1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "fpdfsdk/pdfwindow/PWL_Utils.h"
8
9 #include <algorithm>
10 #include <memory>
11
12 #include "core/fpdfdoc/cpvt_word.h"
13 #include "core/fxge/cfx_graphstatedata.h"
14 #include "core/fxge/cfx_pathdata.h"
15 #include "core/fxge/cfx_renderdevice.h"
16 #include "fpdfsdk/fxedit/fxet_edit.h"
17 #include "fpdfsdk/pdfwindow/PWL_Icon.h"
18 #include "fpdfsdk/pdfwindow/PWL_Wnd.h"
19
OffsetRect(const CFX_FloatRect & rect,FX_FLOAT x,FX_FLOAT y)20 CFX_FloatRect CPWL_Utils::OffsetRect(const CFX_FloatRect& rect,
21 FX_FLOAT x,
22 FX_FLOAT y) {
23 return CFX_FloatRect(rect.left + x, rect.bottom + y, rect.right + x,
24 rect.top + y);
25 }
26
OverlapWordRange(const CPVT_WordRange & wr1,const CPVT_WordRange & wr2)27 CPVT_WordRange CPWL_Utils::OverlapWordRange(const CPVT_WordRange& wr1,
28 const CPVT_WordRange& wr2) {
29 CPVT_WordRange wrRet;
30
31 if (wr2.EndPos.WordCmp(wr1.BeginPos) < 0 ||
32 wr2.BeginPos.WordCmp(wr1.EndPos) > 0)
33 return wrRet;
34 if (wr1.EndPos.WordCmp(wr2.BeginPos) < 0 ||
35 wr1.BeginPos.WordCmp(wr2.EndPos) > 0)
36 return wrRet;
37
38 if (wr1.BeginPos.WordCmp(wr2.BeginPos) < 0) {
39 wrRet.BeginPos = wr2.BeginPos;
40 } else {
41 wrRet.BeginPos = wr1.BeginPos;
42 }
43
44 if (wr1.EndPos.WordCmp(wr2.EndPos) < 0) {
45 wrRet.EndPos = wr1.EndPos;
46 } else {
47 wrRet.EndPos = wr2.EndPos;
48 }
49
50 return wrRet;
51 }
52
GetAP_Check(const CFX_FloatRect & crBBox)53 CFX_ByteString CPWL_Utils::GetAP_Check(const CFX_FloatRect& crBBox) {
54 const FX_FLOAT fWidth = crBBox.right - crBBox.left;
55 const FX_FLOAT fHeight = crBBox.top - crBBox.bottom;
56
57 CFX_PointF pts[8][3] = {{CFX_PointF(0.28f, 0.52f), CFX_PointF(0.27f, 0.48f),
58 CFX_PointF(0.29f, 0.40f)},
59 {CFX_PointF(0.30f, 0.33f), CFX_PointF(0.31f, 0.29f),
60 CFX_PointF(0.31f, 0.28f)},
61 {CFX_PointF(0.39f, 0.28f), CFX_PointF(0.49f, 0.29f),
62 CFX_PointF(0.77f, 0.67f)},
63 {CFX_PointF(0.76f, 0.68f), CFX_PointF(0.78f, 0.69f),
64 CFX_PointF(0.76f, 0.75f)},
65 {CFX_PointF(0.76f, 0.75f), CFX_PointF(0.73f, 0.80f),
66 CFX_PointF(0.68f, 0.75f)},
67 {CFX_PointF(0.68f, 0.74f), CFX_PointF(0.68f, 0.74f),
68 CFX_PointF(0.44f, 0.47f)},
69 {CFX_PointF(0.43f, 0.47f), CFX_PointF(0.40f, 0.47f),
70 CFX_PointF(0.41f, 0.58f)},
71 {CFX_PointF(0.40f, 0.60f), CFX_PointF(0.28f, 0.66f),
72 CFX_PointF(0.30f, 0.56f)}};
73
74 for (size_t i = 0; i < FX_ArraySize(pts); ++i) {
75 for (size_t j = 0; j < FX_ArraySize(pts[0]); ++j) {
76 pts[i][j].x = pts[i][j].x * fWidth + crBBox.left;
77 pts[i][j].y *= pts[i][j].y * fHeight + crBBox.bottom;
78 }
79 }
80
81 CFX_ByteTextBuf csAP;
82 csAP << pts[0][0].x << " " << pts[0][0].y << " m\n";
83
84 for (size_t i = 0; i < FX_ArraySize(pts); ++i) {
85 size_t nNext = i < FX_ArraySize(pts) - 1 ? i + 1 : 0;
86
87 FX_FLOAT px1 = pts[i][1].x - pts[i][0].x;
88 FX_FLOAT py1 = pts[i][1].y - pts[i][0].y;
89 FX_FLOAT px2 = pts[i][2].x - pts[nNext][0].x;
90 FX_FLOAT py2 = pts[i][2].y - pts[nNext][0].y;
91
92 csAP << pts[i][0].x + px1 * FX_BEZIER << " "
93 << pts[i][0].y + py1 * FX_BEZIER << " "
94 << pts[nNext][0].x + px2 * FX_BEZIER << " "
95 << pts[nNext][0].y + py2 * FX_BEZIER << " " << pts[nNext][0].x << " "
96 << pts[nNext][0].y << " c\n";
97 }
98
99 return csAP.MakeString();
100 }
101
GetAP_Circle(const CFX_FloatRect & crBBox)102 CFX_ByteString CPWL_Utils::GetAP_Circle(const CFX_FloatRect& crBBox) {
103 CFX_ByteTextBuf csAP;
104
105 FX_FLOAT fWidth = crBBox.right - crBBox.left;
106 FX_FLOAT fHeight = crBBox.top - crBBox.bottom;
107
108 CFX_PointF pt1(crBBox.left, crBBox.bottom + fHeight / 2);
109 CFX_PointF pt2(crBBox.left + fWidth / 2, crBBox.top);
110 CFX_PointF pt3(crBBox.right, crBBox.bottom + fHeight / 2);
111 CFX_PointF pt4(crBBox.left + fWidth / 2, crBBox.bottom);
112
113 csAP << pt1.x << " " << pt1.y << " m\n";
114
115 FX_FLOAT px = pt2.x - pt1.x;
116 FX_FLOAT py = pt2.y - pt1.y;
117
118 csAP << pt1.x << " " << pt1.y + py * FX_BEZIER << " "
119 << pt2.x - px * FX_BEZIER << " " << pt2.y << " " << pt2.x << " " << pt2.y
120 << " c\n";
121
122 px = pt3.x - pt2.x;
123 py = pt2.y - pt3.y;
124
125 csAP << pt2.x + px * FX_BEZIER << " " << pt2.y << " " << pt3.x << " "
126 << pt3.y + py * FX_BEZIER << " " << pt3.x << " " << pt3.y << " c\n";
127
128 px = pt3.x - pt4.x;
129 py = pt3.y - pt4.y;
130
131 csAP << pt3.x << " " << pt3.y - py * FX_BEZIER << " "
132 << pt4.x + px * FX_BEZIER << " " << pt4.y << " " << pt4.x << " " << pt4.y
133 << " c\n";
134
135 px = pt4.x - pt1.x;
136 py = pt1.y - pt4.y;
137
138 csAP << pt4.x - px * FX_BEZIER << " " << pt4.y << " " << pt1.x << " "
139 << pt1.y - py * FX_BEZIER << " " << pt1.x << " " << pt1.y << " c\n";
140
141 return csAP.MakeString();
142 }
143
GetAP_Cross(const CFX_FloatRect & crBBox)144 CFX_ByteString CPWL_Utils::GetAP_Cross(const CFX_FloatRect& crBBox) {
145 CFX_ByteTextBuf csAP;
146
147 csAP << crBBox.left << " " << crBBox.top << " m\n";
148 csAP << crBBox.right << " " << crBBox.bottom << " l\n";
149 csAP << crBBox.left << " " << crBBox.bottom << " m\n";
150 csAP << crBBox.right << " " << crBBox.top << " l\n";
151
152 return csAP.MakeString();
153 }
154
GetAP_Diamond(const CFX_FloatRect & crBBox)155 CFX_ByteString CPWL_Utils::GetAP_Diamond(const CFX_FloatRect& crBBox) {
156 CFX_ByteTextBuf csAP;
157
158 FX_FLOAT fWidth = crBBox.right - crBBox.left;
159 FX_FLOAT fHeight = crBBox.top - crBBox.bottom;
160
161 CFX_PointF pt1(crBBox.left, crBBox.bottom + fHeight / 2);
162 CFX_PointF pt2(crBBox.left + fWidth / 2, crBBox.top);
163 CFX_PointF pt3(crBBox.right, crBBox.bottom + fHeight / 2);
164 CFX_PointF pt4(crBBox.left + fWidth / 2, crBBox.bottom);
165
166 csAP << pt1.x << " " << pt1.y << " m\n";
167 csAP << pt2.x << " " << pt2.y << " l\n";
168 csAP << pt3.x << " " << pt3.y << " l\n";
169 csAP << pt4.x << " " << pt4.y << " l\n";
170 csAP << pt1.x << " " << pt1.y << " l\n";
171
172 return csAP.MakeString();
173 }
174
GetAP_Square(const CFX_FloatRect & crBBox)175 CFX_ByteString CPWL_Utils::GetAP_Square(const CFX_FloatRect& crBBox) {
176 CFX_ByteTextBuf csAP;
177
178 csAP << crBBox.left << " " << crBBox.top << " m\n";
179 csAP << crBBox.right << " " << crBBox.top << " l\n";
180 csAP << crBBox.right << " " << crBBox.bottom << " l\n";
181 csAP << crBBox.left << " " << crBBox.bottom << " l\n";
182 csAP << crBBox.left << " " << crBBox.top << " l\n";
183
184 return csAP.MakeString();
185 }
186
GetAP_Star(const CFX_FloatRect & crBBox)187 CFX_ByteString CPWL_Utils::GetAP_Star(const CFX_FloatRect& crBBox) {
188 CFX_ByteTextBuf csAP;
189
190 FX_FLOAT fRadius =
191 (crBBox.top - crBBox.bottom) / (1 + (FX_FLOAT)cos(FX_PI / 5.0f));
192 CFX_PointF ptCenter = CFX_PointF((crBBox.left + crBBox.right) / 2.0f,
193 (crBBox.top + crBBox.bottom) / 2.0f);
194
195 FX_FLOAT px[5], py[5];
196
197 FX_FLOAT fAngel = FX_PI / 10.0f;
198
199 for (int32_t i = 0; i < 5; i++) {
200 px[i] = ptCenter.x + fRadius * (FX_FLOAT)cos(fAngel);
201 py[i] = ptCenter.y + fRadius * (FX_FLOAT)sin(fAngel);
202
203 fAngel += FX_PI * 2 / 5.0f;
204 }
205
206 csAP << px[0] << " " << py[0] << " m\n";
207
208 int32_t nNext = 0;
209 for (int32_t j = 0; j < 5; j++) {
210 nNext += 2;
211 if (nNext >= 5)
212 nNext -= 5;
213 csAP << px[nNext] << " " << py[nNext] << " l\n";
214 }
215
216 return csAP.MakeString();
217 }
218
GetAP_HalfCircle(const CFX_FloatRect & crBBox,FX_FLOAT fRotate)219 CFX_ByteString CPWL_Utils::GetAP_HalfCircle(const CFX_FloatRect& crBBox,
220 FX_FLOAT fRotate) {
221 CFX_ByteTextBuf csAP;
222
223 FX_FLOAT fWidth = crBBox.right - crBBox.left;
224 FX_FLOAT fHeight = crBBox.top - crBBox.bottom;
225
226 CFX_PointF pt1(-fWidth / 2, 0);
227 CFX_PointF pt2(0, fHeight / 2);
228 CFX_PointF pt3(fWidth / 2, 0);
229
230 FX_FLOAT px, py;
231
232 csAP << cos(fRotate) << " " << sin(fRotate) << " " << -sin(fRotate) << " "
233 << cos(fRotate) << " " << crBBox.left + fWidth / 2 << " "
234 << crBBox.bottom + fHeight / 2 << " cm\n";
235
236 csAP << pt1.x << " " << pt1.y << " m\n";
237
238 px = pt2.x - pt1.x;
239 py = pt2.y - pt1.y;
240
241 csAP << pt1.x << " " << pt1.y + py * FX_BEZIER << " "
242 << pt2.x - px * FX_BEZIER << " " << pt2.y << " " << pt2.x << " " << pt2.y
243 << " c\n";
244
245 px = pt3.x - pt2.x;
246 py = pt2.y - pt3.y;
247
248 csAP << pt2.x + px * FX_BEZIER << " " << pt2.y << " " << pt3.x << " "
249 << pt3.y + py * FX_BEZIER << " " << pt3.x << " " << pt3.y << " c\n";
250
251 return csAP.MakeString();
252 }
253
InflateRect(const CFX_FloatRect & rcRect,FX_FLOAT fSize)254 CFX_FloatRect CPWL_Utils::InflateRect(const CFX_FloatRect& rcRect,
255 FX_FLOAT fSize) {
256 if (rcRect.IsEmpty())
257 return rcRect;
258
259 CFX_FloatRect rcNew(rcRect.left - fSize, rcRect.bottom - fSize,
260 rcRect.right + fSize, rcRect.top + fSize);
261 rcNew.Normalize();
262 return rcNew;
263 }
264
DeflateRect(const CFX_FloatRect & rcRect,FX_FLOAT fSize)265 CFX_FloatRect CPWL_Utils::DeflateRect(const CFX_FloatRect& rcRect,
266 FX_FLOAT fSize) {
267 if (rcRect.IsEmpty())
268 return rcRect;
269
270 CFX_FloatRect rcNew(rcRect.left + fSize, rcRect.bottom + fSize,
271 rcRect.right - fSize, rcRect.top - fSize);
272 rcNew.Normalize();
273 return rcNew;
274 }
275
ScaleRect(const CFX_FloatRect & rcRect,FX_FLOAT fScale)276 CFX_FloatRect CPWL_Utils::ScaleRect(const CFX_FloatRect& rcRect,
277 FX_FLOAT fScale) {
278 FX_FLOAT fHalfWidth = (rcRect.right - rcRect.left) / 2.0f;
279 FX_FLOAT fHalfHeight = (rcRect.top - rcRect.bottom) / 2.0f;
280
281 CFX_PointF ptCenter = CFX_PointF((rcRect.left + rcRect.right) / 2,
282 (rcRect.top + rcRect.bottom) / 2);
283
284 return CFX_FloatRect(
285 ptCenter.x - fHalfWidth * fScale, ptCenter.y - fHalfHeight * fScale,
286 ptCenter.x + fHalfWidth * fScale, ptCenter.y + fHalfHeight * fScale);
287 }
288
GetRectFillAppStream(const CFX_FloatRect & rect,const CPWL_Color & color)289 CFX_ByteString CPWL_Utils::GetRectFillAppStream(const CFX_FloatRect& rect,
290 const CPWL_Color& color) {
291 CFX_ByteTextBuf sAppStream;
292 CFX_ByteString sColor = GetColorAppStream(color, true);
293 if (sColor.GetLength() > 0) {
294 sAppStream << "q\n" << sColor;
295 sAppStream << rect.left << " " << rect.bottom << " "
296 << rect.right - rect.left << " " << rect.top - rect.bottom
297 << " re f\nQ\n";
298 }
299
300 return sAppStream.MakeString();
301 }
302
GetCircleFillAppStream(const CFX_FloatRect & rect,const CPWL_Color & color)303 CFX_ByteString CPWL_Utils::GetCircleFillAppStream(const CFX_FloatRect& rect,
304 const CPWL_Color& color) {
305 CFX_ByteTextBuf sAppStream;
306 CFX_ByteString sColor = GetColorAppStream(color, true);
307 if (sColor.GetLength() > 0) {
308 sAppStream << "q\n" << sColor << CPWL_Utils::GetAP_Circle(rect) << "f\nQ\n";
309 }
310 return sAppStream.MakeString();
311 }
312
GetCenterSquare(const CFX_FloatRect & rect)313 CFX_FloatRect CPWL_Utils::GetCenterSquare(const CFX_FloatRect& rect) {
314 FX_FLOAT fWidth = rect.right - rect.left;
315 FX_FLOAT fHeight = rect.top - rect.bottom;
316
317 FX_FLOAT fCenterX = (rect.left + rect.right) / 2.0f;
318 FX_FLOAT fCenterY = (rect.top + rect.bottom) / 2.0f;
319
320 FX_FLOAT fRadius = (fWidth > fHeight) ? fHeight / 2 : fWidth / 2;
321
322 return CFX_FloatRect(fCenterX - fRadius, fCenterY - fRadius,
323 fCenterX + fRadius, fCenterY + fRadius);
324 }
325
GetEditAppStream(CFX_Edit * pEdit,const CFX_PointF & ptOffset,const CPVT_WordRange * pRange,bool bContinuous,uint16_t SubWord)326 CFX_ByteString CPWL_Utils::GetEditAppStream(CFX_Edit* pEdit,
327 const CFX_PointF& ptOffset,
328 const CPVT_WordRange* pRange,
329 bool bContinuous,
330 uint16_t SubWord) {
331 return CFX_Edit::GetEditAppearanceStream(pEdit, ptOffset, pRange, bContinuous,
332 SubWord);
333 }
334
GetEditSelAppStream(CFX_Edit * pEdit,const CFX_PointF & ptOffset,const CPVT_WordRange * pRange)335 CFX_ByteString CPWL_Utils::GetEditSelAppStream(CFX_Edit* pEdit,
336 const CFX_PointF& ptOffset,
337 const CPVT_WordRange* pRange) {
338 return CFX_Edit::GetSelectAppearanceStream(pEdit, ptOffset, pRange);
339 }
340
GetPushButtonAppStream(const CFX_FloatRect & rcBBox,IPVT_FontMap * pFontMap,CPDF_Stream * pIconStream,CPDF_IconFit & IconFit,const CFX_WideString & sLabel,const CPWL_Color & crText,FX_FLOAT fFontSize,int32_t nLayOut)341 CFX_ByteString CPWL_Utils::GetPushButtonAppStream(const CFX_FloatRect& rcBBox,
342 IPVT_FontMap* pFontMap,
343 CPDF_Stream* pIconStream,
344 CPDF_IconFit& IconFit,
345 const CFX_WideString& sLabel,
346 const CPWL_Color& crText,
347 FX_FLOAT fFontSize,
348 int32_t nLayOut) {
349 const FX_FLOAT fAutoFontScale = 1.0f / 3.0f;
350
351 std::unique_ptr<CFX_Edit> pEdit(new CFX_Edit);
352 pEdit->SetFontMap(pFontMap);
353 pEdit->SetAlignmentH(1, true);
354 pEdit->SetAlignmentV(1, true);
355 pEdit->SetMultiLine(false, true);
356 pEdit->SetAutoReturn(false, true);
357 if (IsFloatZero(fFontSize))
358 pEdit->SetAutoFontSize(true, true);
359 else
360 pEdit->SetFontSize(fFontSize);
361
362 pEdit->Initialize();
363 pEdit->SetText(sLabel);
364
365 CFX_FloatRect rcLabelContent = pEdit->GetContentRect();
366 CPWL_Icon Icon;
367 PWL_CREATEPARAM cp;
368 cp.dwFlags = PWS_VISIBLE;
369 Icon.Create(cp);
370 Icon.SetIconFit(&IconFit);
371 Icon.SetPDFStream(pIconStream);
372
373 CFX_FloatRect rcLabel = CFX_FloatRect(0, 0, 0, 0);
374 CFX_FloatRect rcIcon = CFX_FloatRect(0, 0, 0, 0);
375 FX_FLOAT fWidth = 0.0f;
376 FX_FLOAT fHeight = 0.0f;
377
378 switch (nLayOut) {
379 case PPBL_LABEL:
380 rcLabel = rcBBox;
381 rcIcon = CFX_FloatRect(0, 0, 0, 0);
382 break;
383 case PPBL_ICON:
384 rcIcon = rcBBox;
385 rcLabel = CFX_FloatRect(0, 0, 0, 0);
386 break;
387 case PPBL_ICONTOPLABELBOTTOM:
388
389 if (pIconStream) {
390 if (IsFloatZero(fFontSize)) {
391 fHeight = rcBBox.top - rcBBox.bottom;
392 rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right,
393 rcBBox.bottom + fHeight * fAutoFontScale);
394 rcIcon =
395 CFX_FloatRect(rcBBox.left, rcLabel.top, rcBBox.right, rcBBox.top);
396 } else {
397 fHeight = rcLabelContent.Height();
398
399 if (rcBBox.bottom + fHeight > rcBBox.top) {
400 rcIcon = CFX_FloatRect(0, 0, 0, 0);
401 rcLabel = rcBBox;
402 } else {
403 rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right,
404 rcBBox.bottom + fHeight);
405 rcIcon = CFX_FloatRect(rcBBox.left, rcLabel.top, rcBBox.right,
406 rcBBox.top);
407 }
408 }
409 } else {
410 rcLabel = rcBBox;
411 rcIcon = CFX_FloatRect(0, 0, 0, 0);
412 }
413
414 break;
415 case PPBL_LABELTOPICONBOTTOM:
416
417 if (pIconStream) {
418 if (IsFloatZero(fFontSize)) {
419 fHeight = rcBBox.top - rcBBox.bottom;
420 rcLabel =
421 CFX_FloatRect(rcBBox.left, rcBBox.top - fHeight * fAutoFontScale,
422 rcBBox.right, rcBBox.top);
423 rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right,
424 rcLabel.bottom);
425 } else {
426 fHeight = rcLabelContent.Height();
427
428 if (rcBBox.bottom + fHeight > rcBBox.top) {
429 rcIcon = CFX_FloatRect(0, 0, 0, 0);
430 rcLabel = rcBBox;
431 } else {
432 rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.top - fHeight,
433 rcBBox.right, rcBBox.top);
434 rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right,
435 rcLabel.bottom);
436 }
437 }
438 } else {
439 rcLabel = rcBBox;
440 rcIcon = CFX_FloatRect(0, 0, 0, 0);
441 }
442
443 break;
444 case PPBL_ICONLEFTLABELRIGHT:
445
446 if (pIconStream) {
447 if (IsFloatZero(fFontSize)) {
448 fWidth = rcBBox.right - rcBBox.left;
449 rcLabel = CFX_FloatRect(rcBBox.right - fWidth * fAutoFontScale,
450 rcBBox.bottom, rcBBox.right, rcBBox.top);
451 rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left,
452 rcBBox.top);
453
454 if (rcLabelContent.Width() < fWidth * fAutoFontScale) {
455 } else {
456 if (rcLabelContent.Width() < fWidth) {
457 rcLabel = CFX_FloatRect(rcBBox.right - rcLabelContent.Width(),
458 rcBBox.bottom, rcBBox.right, rcBBox.top);
459 rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left,
460 rcBBox.top);
461 } else {
462 rcLabel = rcBBox;
463 rcIcon = CFX_FloatRect(0, 0, 0, 0);
464 }
465 }
466 } else {
467 fWidth = rcLabelContent.Width();
468
469 if (rcBBox.left + fWidth > rcBBox.right) {
470 rcLabel = rcBBox;
471 rcIcon = CFX_FloatRect(0, 0, 0, 0);
472 } else {
473 rcLabel = CFX_FloatRect(rcBBox.right - fWidth, rcBBox.bottom,
474 rcBBox.right, rcBBox.top);
475 rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left,
476 rcBBox.top);
477 }
478 }
479 } else {
480 rcLabel = rcBBox;
481 rcIcon = CFX_FloatRect(0, 0, 0, 0);
482 }
483
484 break;
485 case PPBL_LABELLEFTICONRIGHT:
486
487 if (pIconStream) {
488 if (IsFloatZero(fFontSize)) {
489 fWidth = rcBBox.right - rcBBox.left;
490 rcLabel =
491 CFX_FloatRect(rcBBox.left, rcBBox.bottom,
492 rcBBox.left + fWidth * fAutoFontScale, rcBBox.top);
493 rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right,
494 rcBBox.top);
495
496 if (rcLabelContent.Width() < fWidth * fAutoFontScale) {
497 } else {
498 if (rcLabelContent.Width() < fWidth) {
499 rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom,
500 rcBBox.left + rcLabelContent.Width(),
501 rcBBox.top);
502 rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right,
503 rcBBox.top);
504 } else {
505 rcLabel = rcBBox;
506 rcIcon = CFX_FloatRect(0, 0, 0, 0);
507 }
508 }
509 } else {
510 fWidth = rcLabelContent.Width();
511
512 if (rcBBox.left + fWidth > rcBBox.right) {
513 rcLabel = rcBBox;
514 rcIcon = CFX_FloatRect(0, 0, 0, 0);
515 } else {
516 rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom,
517 rcBBox.left + fWidth, rcBBox.top);
518 rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right,
519 rcBBox.top);
520 }
521 }
522 } else {
523 rcLabel = rcBBox;
524 rcIcon = CFX_FloatRect(0, 0, 0, 0);
525 }
526
527 break;
528 case PPBL_LABELOVERICON:
529 rcLabel = rcBBox;
530 rcIcon = rcBBox;
531 break;
532 }
533
534 CFX_ByteTextBuf sAppStream, sTemp;
535
536 if (!rcIcon.IsEmpty()) {
537 Icon.Move(rcIcon, false, false);
538 sTemp << Icon.GetImageAppStream();
539 }
540
541 Icon.Destroy();
542
543 if (!rcLabel.IsEmpty()) {
544 pEdit->SetPlateRect(rcLabel);
545 CFX_ByteString sEdit =
546 CPWL_Utils::GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, 0.0f));
547 if (sEdit.GetLength() > 0) {
548 sTemp << "BT\n"
549 << CPWL_Utils::GetColorAppStream(crText) << sEdit << "ET\n";
550 }
551 }
552
553 if (sTemp.GetSize() > 0) {
554 sAppStream << "q\n"
555 << rcBBox.left << " " << rcBBox.bottom << " "
556 << rcBBox.right - rcBBox.left << " "
557 << rcBBox.top - rcBBox.bottom << " re W n\n";
558 sAppStream << sTemp << "Q\n";
559 }
560 return sAppStream.MakeString();
561 }
562
GetColorAppStream(const CPWL_Color & color,const bool & bFillOrStroke)563 CFX_ByteString CPWL_Utils::GetColorAppStream(const CPWL_Color& color,
564 const bool& bFillOrStroke) {
565 CFX_ByteTextBuf sColorStream;
566
567 switch (color.nColorType) {
568 case COLORTYPE_RGB:
569 sColorStream << color.fColor1 << " " << color.fColor2 << " "
570 << color.fColor3 << " " << (bFillOrStroke ? "rg" : "RG")
571 << "\n";
572 break;
573 case COLORTYPE_GRAY:
574 sColorStream << color.fColor1 << " " << (bFillOrStroke ? "g" : "G")
575 << "\n";
576 break;
577 case COLORTYPE_CMYK:
578 sColorStream << color.fColor1 << " " << color.fColor2 << " "
579 << color.fColor3 << " " << color.fColor4 << " "
580 << (bFillOrStroke ? "k" : "K") << "\n";
581 break;
582 }
583
584 return sColorStream.MakeString();
585 }
586
GetBorderAppStream(const CFX_FloatRect & rect,FX_FLOAT fWidth,const CPWL_Color & color,const CPWL_Color & crLeftTop,const CPWL_Color & crRightBottom,BorderStyle nStyle,const CPWL_Dash & dash)587 CFX_ByteString CPWL_Utils::GetBorderAppStream(const CFX_FloatRect& rect,
588 FX_FLOAT fWidth,
589 const CPWL_Color& color,
590 const CPWL_Color& crLeftTop,
591 const CPWL_Color& crRightBottom,
592 BorderStyle nStyle,
593 const CPWL_Dash& dash) {
594 CFX_ByteTextBuf sAppStream;
595 CFX_ByteString sColor;
596
597 FX_FLOAT fLeft = rect.left;
598 FX_FLOAT fRight = rect.right;
599 FX_FLOAT fTop = rect.top;
600 FX_FLOAT fBottom = rect.bottom;
601
602 if (fWidth > 0.0f) {
603 FX_FLOAT fHalfWidth = fWidth / 2.0f;
604
605 sAppStream << "q\n";
606
607 switch (nStyle) {
608 default:
609 case BorderStyle::SOLID:
610 sColor = CPWL_Utils::GetColorAppStream(color, true);
611 if (sColor.GetLength() > 0) {
612 sAppStream << sColor;
613 sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " "
614 << fTop - fBottom << " re\n";
615 sAppStream << fLeft + fWidth << " " << fBottom + fWidth << " "
616 << fRight - fLeft - fWidth * 2 << " "
617 << fTop - fBottom - fWidth * 2 << " re\n";
618 sAppStream << "f*\n";
619 }
620 break;
621 case BorderStyle::DASH:
622 sColor = CPWL_Utils::GetColorAppStream(color, false);
623 if (sColor.GetLength() > 0) {
624 sAppStream << sColor;
625 sAppStream << fWidth << " w"
626 << " [" << dash.nDash << " " << dash.nGap << "] "
627 << dash.nPhase << " d\n";
628 sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2
629 << " m\n";
630 sAppStream << fLeft + fWidth / 2 << " " << fTop - fWidth / 2
631 << " l\n";
632 sAppStream << fRight - fWidth / 2 << " " << fTop - fWidth / 2
633 << " l\n";
634 sAppStream << fRight - fWidth / 2 << " " << fBottom + fWidth / 2
635 << " l\n";
636 sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2
637 << " l S\n";
638 }
639 break;
640 case BorderStyle::BEVELED:
641 case BorderStyle::INSET:
642 sColor = CPWL_Utils::GetColorAppStream(crLeftTop, true);
643 if (sColor.GetLength() > 0) {
644 sAppStream << sColor;
645 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth
646 << " m\n";
647 sAppStream << fLeft + fHalfWidth << " " << fTop - fHalfWidth
648 << " l\n";
649 sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth
650 << " l\n";
651 sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2
652 << " l\n";
653 sAppStream << fLeft + fHalfWidth * 2 << " " << fTop - fHalfWidth * 2
654 << " l\n";
655 sAppStream << fLeft + fHalfWidth * 2 << " "
656 << fBottom + fHalfWidth * 2 << " l f\n";
657 }
658
659 sColor = CPWL_Utils::GetColorAppStream(crRightBottom, true);
660 if (sColor.GetLength() > 0) {
661 sAppStream << sColor;
662 sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth
663 << " m\n";
664 sAppStream << fRight - fHalfWidth << " " << fBottom + fHalfWidth
665 << " l\n";
666 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth
667 << " l\n";
668 sAppStream << fLeft + fHalfWidth * 2 << " "
669 << fBottom + fHalfWidth * 2 << " l\n";
670 sAppStream << fRight - fHalfWidth * 2 << " "
671 << fBottom + fHalfWidth * 2 << " l\n";
672 sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2
673 << " l f\n";
674 }
675
676 sColor = CPWL_Utils::GetColorAppStream(color, true);
677 if (sColor.GetLength() > 0) {
678 sAppStream << sColor;
679 sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " "
680 << fTop - fBottom << " re\n";
681 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " "
682 << fRight - fLeft - fHalfWidth * 2 << " "
683 << fTop - fBottom - fHalfWidth * 2 << " re f*\n";
684 }
685 break;
686 case BorderStyle::UNDERLINE:
687 sColor = CPWL_Utils::GetColorAppStream(color, false);
688 if (sColor.GetLength() > 0) {
689 sAppStream << sColor;
690 sAppStream << fWidth << " w\n";
691 sAppStream << fLeft << " " << fBottom + fWidth / 2 << " m\n";
692 sAppStream << fRight << " " << fBottom + fWidth / 2 << " l S\n";
693 }
694 break;
695 }
696
697 sAppStream << "Q\n";
698 }
699
700 return sAppStream.MakeString();
701 }
702
GetCircleBorderAppStream(const CFX_FloatRect & rect,FX_FLOAT fWidth,const CPWL_Color & color,const CPWL_Color & crLeftTop,const CPWL_Color & crRightBottom,BorderStyle nStyle,const CPWL_Dash & dash)703 CFX_ByteString CPWL_Utils::GetCircleBorderAppStream(
704 const CFX_FloatRect& rect,
705 FX_FLOAT fWidth,
706 const CPWL_Color& color,
707 const CPWL_Color& crLeftTop,
708 const CPWL_Color& crRightBottom,
709 BorderStyle nStyle,
710 const CPWL_Dash& dash) {
711 CFX_ByteTextBuf sAppStream;
712 CFX_ByteString sColor;
713
714 if (fWidth > 0.0f) {
715 sAppStream << "q\n";
716
717 switch (nStyle) {
718 default:
719 case BorderStyle::SOLID:
720 case BorderStyle::UNDERLINE: {
721 sColor = CPWL_Utils::GetColorAppStream(color, false);
722 if (sColor.GetLength() > 0) {
723 sAppStream << "q\n" << fWidth << " w\n" << sColor
724 << CPWL_Utils::GetAP_Circle(
725 CPWL_Utils::DeflateRect(rect, fWidth / 2.0f))
726 << " S\nQ\n";
727 }
728 } break;
729 case BorderStyle::DASH: {
730 sColor = CPWL_Utils::GetColorAppStream(color, false);
731 if (sColor.GetLength() > 0) {
732 sAppStream << "q\n" << fWidth << " w\n"
733 << "[" << dash.nDash << " " << dash.nGap << "] "
734 << dash.nPhase << " d\n" << sColor
735 << CPWL_Utils::GetAP_Circle(
736 CPWL_Utils::DeflateRect(rect, fWidth / 2.0f))
737 << " S\nQ\n";
738 }
739 } break;
740 case BorderStyle::BEVELED: {
741 FX_FLOAT fHalfWidth = fWidth / 2.0f;
742
743 sColor = CPWL_Utils::GetColorAppStream(color, false);
744 if (sColor.GetLength() > 0) {
745 sAppStream << "q\n" << fHalfWidth << " w\n" << sColor
746 << CPWL_Utils::GetAP_Circle(rect) << " S\nQ\n";
747 }
748
749 sColor = CPWL_Utils::GetColorAppStream(crLeftTop, false);
750 if (sColor.GetLength() > 0) {
751 sAppStream << "q\n" << fHalfWidth << " w\n" << sColor
752 << CPWL_Utils::GetAP_HalfCircle(
753 CPWL_Utils::DeflateRect(rect, fHalfWidth * 0.75f),
754 FX_PI / 4.0f)
755 << " S\nQ\n";
756 }
757
758 sColor = CPWL_Utils::GetColorAppStream(crRightBottom, false);
759 if (sColor.GetLength() > 0) {
760 sAppStream << "q\n" << fHalfWidth << " w\n" << sColor
761 << CPWL_Utils::GetAP_HalfCircle(
762 CPWL_Utils::DeflateRect(rect, fHalfWidth * 0.75f),
763 FX_PI * 5 / 4.0f)
764 << " S\nQ\n";
765 }
766 } break;
767 case BorderStyle::INSET: {
768 FX_FLOAT fHalfWidth = fWidth / 2.0f;
769
770 sColor = CPWL_Utils::GetColorAppStream(color, false);
771 if (sColor.GetLength() > 0) {
772 sAppStream << "q\n" << fHalfWidth << " w\n" << sColor
773 << CPWL_Utils::GetAP_Circle(rect) << " S\nQ\n";
774 }
775
776 sColor = CPWL_Utils::GetColorAppStream(crLeftTop, false);
777 if (sColor.GetLength() > 0) {
778 sAppStream << "q\n" << fHalfWidth << " w\n" << sColor
779 << CPWL_Utils::GetAP_HalfCircle(
780 CPWL_Utils::DeflateRect(rect, fHalfWidth * 0.75f),
781 FX_PI / 4.0f)
782 << " S\nQ\n";
783 }
784
785 sColor = CPWL_Utils::GetColorAppStream(crRightBottom, false);
786 if (sColor.GetLength() > 0) {
787 sAppStream << "q\n" << fHalfWidth << " w\n" << sColor
788 << CPWL_Utils::GetAP_HalfCircle(
789 CPWL_Utils::DeflateRect(rect, fHalfWidth * 0.75f),
790 FX_PI * 5 / 4.0f)
791 << " S\nQ\n";
792 }
793 } break;
794 }
795
796 sAppStream << "Q\n";
797 }
798
799 return sAppStream.MakeString();
800 }
801
GetAppStream_Check(const CFX_FloatRect & rcBBox,const CPWL_Color & crText)802 CFX_ByteString CPWL_Utils::GetAppStream_Check(const CFX_FloatRect& rcBBox,
803 const CPWL_Color& crText) {
804 CFX_ByteTextBuf sAP;
805 sAP << "q\n"
806 << CPWL_Utils::GetColorAppStream(crText, true)
807 << CPWL_Utils::GetAP_Check(rcBBox) << "f\nQ\n";
808 return sAP.MakeString();
809 }
810
GetAppStream_Circle(const CFX_FloatRect & rcBBox,const CPWL_Color & crText)811 CFX_ByteString CPWL_Utils::GetAppStream_Circle(const CFX_FloatRect& rcBBox,
812 const CPWL_Color& crText) {
813 CFX_ByteTextBuf sAP;
814 sAP << "q\n"
815 << CPWL_Utils::GetColorAppStream(crText, true)
816 << CPWL_Utils::GetAP_Circle(rcBBox) << "f\nQ\n";
817 return sAP.MakeString();
818 }
819
GetAppStream_Cross(const CFX_FloatRect & rcBBox,const CPWL_Color & crText)820 CFX_ByteString CPWL_Utils::GetAppStream_Cross(const CFX_FloatRect& rcBBox,
821 const CPWL_Color& crText) {
822 CFX_ByteTextBuf sAP;
823 sAP << "q\n"
824 << CPWL_Utils::GetColorAppStream(crText, false)
825 << CPWL_Utils::GetAP_Cross(rcBBox) << "S\nQ\n";
826 return sAP.MakeString();
827 }
828
GetAppStream_Diamond(const CFX_FloatRect & rcBBox,const CPWL_Color & crText)829 CFX_ByteString CPWL_Utils::GetAppStream_Diamond(const CFX_FloatRect& rcBBox,
830 const CPWL_Color& crText) {
831 CFX_ByteTextBuf sAP;
832 sAP << "q\n1 w\n"
833 << CPWL_Utils::GetColorAppStream(crText, true)
834 << CPWL_Utils::GetAP_Diamond(rcBBox) << "f\nQ\n";
835 return sAP.MakeString();
836 }
837
GetAppStream_Square(const CFX_FloatRect & rcBBox,const CPWL_Color & crText)838 CFX_ByteString CPWL_Utils::GetAppStream_Square(const CFX_FloatRect& rcBBox,
839 const CPWL_Color& crText) {
840 CFX_ByteTextBuf sAP;
841 sAP << "q\n"
842 << CPWL_Utils::GetColorAppStream(crText, true)
843 << CPWL_Utils::GetAP_Square(rcBBox) << "f\nQ\n";
844 return sAP.MakeString();
845 }
846
GetAppStream_Star(const CFX_FloatRect & rcBBox,const CPWL_Color & crText)847 CFX_ByteString CPWL_Utils::GetAppStream_Star(const CFX_FloatRect& rcBBox,
848 const CPWL_Color& crText) {
849 CFX_ByteTextBuf sAP;
850 sAP << "q\n"
851 << CPWL_Utils::GetColorAppStream(crText, true)
852 << CPWL_Utils::GetAP_Star(rcBBox) << "f\nQ\n";
853 return sAP.MakeString();
854 }
855
GetCheckBoxAppStream(const CFX_FloatRect & rcBBox,int32_t nStyle,const CPWL_Color & crText)856 CFX_ByteString CPWL_Utils::GetCheckBoxAppStream(const CFX_FloatRect& rcBBox,
857 int32_t nStyle,
858 const CPWL_Color& crText) {
859 CFX_FloatRect rcCenter = GetCenterSquare(rcBBox);
860 switch (nStyle) {
861 default:
862 case PCS_CHECK:
863 return GetAppStream_Check(rcCenter, crText);
864 case PCS_CIRCLE:
865 return GetAppStream_Circle(ScaleRect(rcCenter, 2.0f / 3.0f), crText);
866 case PCS_CROSS:
867 return GetAppStream_Cross(rcCenter, crText);
868 case PCS_DIAMOND:
869 return GetAppStream_Diamond(ScaleRect(rcCenter, 2.0f / 3.0f), crText);
870 case PCS_SQUARE:
871 return GetAppStream_Square(ScaleRect(rcCenter, 2.0f / 3.0f), crText);
872 case PCS_STAR:
873 return GetAppStream_Star(ScaleRect(rcCenter, 2.0f / 3.0f), crText);
874 }
875 }
876
GetRadioButtonAppStream(const CFX_FloatRect & rcBBox,int32_t nStyle,const CPWL_Color & crText)877 CFX_ByteString CPWL_Utils::GetRadioButtonAppStream(const CFX_FloatRect& rcBBox,
878 int32_t nStyle,
879 const CPWL_Color& crText) {
880 CFX_FloatRect rcCenter = GetCenterSquare(rcBBox);
881 switch (nStyle) {
882 default:
883 case PCS_CHECK:
884 return GetAppStream_Check(rcCenter, crText);
885 case PCS_CIRCLE:
886 return GetAppStream_Circle(ScaleRect(rcCenter, 1.0f / 2.0f), crText);
887 case PCS_CROSS:
888 return GetAppStream_Cross(rcCenter, crText);
889 case PCS_DIAMOND:
890 return GetAppStream_Diamond(ScaleRect(rcCenter, 2.0f / 3.0f), crText);
891 case PCS_SQUARE:
892 return GetAppStream_Square(ScaleRect(rcCenter, 2.0f / 3.0f), crText);
893 case PCS_STAR:
894 return GetAppStream_Star(ScaleRect(rcCenter, 2.0f / 3.0f), crText);
895 }
896 }
897
GetDropButtonAppStream(const CFX_FloatRect & rcBBox)898 CFX_ByteString CPWL_Utils::GetDropButtonAppStream(const CFX_FloatRect& rcBBox) {
899 CFX_ByteTextBuf sAppStream;
900
901 if (!rcBBox.IsEmpty()) {
902 sAppStream << "q\n"
903 << CPWL_Utils::GetColorAppStream(
904 CPWL_Color(COLORTYPE_RGB, 220.0f / 255.0f,
905 220.0f / 255.0f, 220.0f / 255.0f),
906 true);
907 sAppStream << rcBBox.left << " " << rcBBox.bottom << " "
908 << rcBBox.right - rcBBox.left << " "
909 << rcBBox.top - rcBBox.bottom << " re f\n";
910 sAppStream << "Q\n";
911
912 sAppStream << "q\n"
913 << CPWL_Utils::GetBorderAppStream(
914 rcBBox, 2, CPWL_Color(COLORTYPE_GRAY, 0),
915 CPWL_Color(COLORTYPE_GRAY, 1),
916 CPWL_Color(COLORTYPE_GRAY, 0.5), BorderStyle::BEVELED,
917 CPWL_Dash(3, 0, 0))
918 << "Q\n";
919
920 CFX_PointF ptCenter = CFX_PointF((rcBBox.left + rcBBox.right) / 2,
921 (rcBBox.top + rcBBox.bottom) / 2);
922 if (IsFloatBigger(rcBBox.right - rcBBox.left, 6) &&
923 IsFloatBigger(rcBBox.top - rcBBox.bottom, 6)) {
924 sAppStream << "q\n"
925 << " 0 g\n";
926 sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " m\n";
927 sAppStream << ptCenter.x + 3 << " " << ptCenter.y + 1.5f << " l\n";
928 sAppStream << ptCenter.x << " " << ptCenter.y - 1.5f << " l\n";
929 sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " l f\n";
930 sAppStream << "Q\n";
931 }
932 }
933
934 return sAppStream.MakeString();
935 }
936
DrawFillRect(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device,const CFX_FloatRect & rect,const FX_COLORREF & color)937 void CPWL_Utils::DrawFillRect(CFX_RenderDevice* pDevice,
938 CFX_Matrix* pUser2Device,
939 const CFX_FloatRect& rect,
940 const FX_COLORREF& color) {
941 CFX_PathData path;
942 CFX_FloatRect rcTemp(rect);
943 path.AppendRect(rcTemp.left, rcTemp.bottom, rcTemp.right, rcTemp.top);
944 pDevice->DrawPath(&path, pUser2Device, nullptr, color, 0, FXFILL_WINDING);
945 }
946
DrawFillArea(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device,const CFX_PointF * pPts,int32_t nCount,const FX_COLORREF & color)947 void CPWL_Utils::DrawFillArea(CFX_RenderDevice* pDevice,
948 CFX_Matrix* pUser2Device,
949 const CFX_PointF* pPts,
950 int32_t nCount,
951 const FX_COLORREF& color) {
952 CFX_PathData path;
953 path.AppendPoint(pPts[0], FXPT_TYPE::MoveTo, false);
954 for (int32_t i = 1; i < nCount; i++)
955 path.AppendPoint(pPts[i], FXPT_TYPE::LineTo, false);
956
957 pDevice->DrawPath(&path, pUser2Device, nullptr, color, 0, FXFILL_ALTERNATE);
958 }
959
DrawStrokeRect(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device,const CFX_FloatRect & rect,const FX_COLORREF & color,FX_FLOAT fWidth)960 void CPWL_Utils::DrawStrokeRect(CFX_RenderDevice* pDevice,
961 CFX_Matrix* pUser2Device,
962 const CFX_FloatRect& rect,
963 const FX_COLORREF& color,
964 FX_FLOAT fWidth) {
965 CFX_PathData path;
966 CFX_FloatRect rcTemp(rect);
967 path.AppendRect(rcTemp.left, rcTemp.bottom, rcTemp.right, rcTemp.top);
968
969 CFX_GraphStateData gsd;
970 gsd.m_LineWidth = fWidth;
971
972 pDevice->DrawPath(&path, pUser2Device, &gsd, 0, color, FXFILL_ALTERNATE);
973 }
974
DrawStrokeLine(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device,const CFX_PointF & ptMoveTo,const CFX_PointF & ptLineTo,const FX_COLORREF & color,FX_FLOAT fWidth)975 void CPWL_Utils::DrawStrokeLine(CFX_RenderDevice* pDevice,
976 CFX_Matrix* pUser2Device,
977 const CFX_PointF& ptMoveTo,
978 const CFX_PointF& ptLineTo,
979 const FX_COLORREF& color,
980 FX_FLOAT fWidth) {
981 CFX_PathData path;
982 path.AppendPoint(ptMoveTo, FXPT_TYPE::MoveTo, false);
983 path.AppendPoint(ptLineTo, FXPT_TYPE::LineTo, false);
984
985 CFX_GraphStateData gsd;
986 gsd.m_LineWidth = fWidth;
987
988 pDevice->DrawPath(&path, pUser2Device, &gsd, 0, color, FXFILL_ALTERNATE);
989 }
990
DrawFillRect(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device,const CFX_FloatRect & rect,const CPWL_Color & color,int32_t nTransparency)991 void CPWL_Utils::DrawFillRect(CFX_RenderDevice* pDevice,
992 CFX_Matrix* pUser2Device,
993 const CFX_FloatRect& rect,
994 const CPWL_Color& color,
995 int32_t nTransparency) {
996 CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rect,
997 color.ToFXColor(nTransparency));
998 }
999
DrawShadow(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device,bool bVertical,bool bHorizontal,CFX_FloatRect rect,int32_t nTransparency,int32_t nStartGray,int32_t nEndGray)1000 void CPWL_Utils::DrawShadow(CFX_RenderDevice* pDevice,
1001 CFX_Matrix* pUser2Device,
1002 bool bVertical,
1003 bool bHorizontal,
1004 CFX_FloatRect rect,
1005 int32_t nTransparency,
1006 int32_t nStartGray,
1007 int32_t nEndGray) {
1008 FX_FLOAT fStepGray = 1.0f;
1009
1010 if (bVertical) {
1011 fStepGray = (nEndGray - nStartGray) / rect.Height();
1012
1013 for (FX_FLOAT fy = rect.bottom + 0.5f; fy <= rect.top - 0.5f; fy += 1.0f) {
1014 int32_t nGray = nStartGray + (int32_t)(fStepGray * (fy - rect.bottom));
1015 CPWL_Utils::DrawStrokeLine(
1016 pDevice, pUser2Device, CFX_PointF(rect.left, fy),
1017 CFX_PointF(rect.right, fy),
1018 ArgbEncode(nTransparency, nGray, nGray, nGray), 1.5f);
1019 }
1020 }
1021
1022 if (bHorizontal) {
1023 fStepGray = (nEndGray - nStartGray) / rect.Width();
1024
1025 for (FX_FLOAT fx = rect.left + 0.5f; fx <= rect.right - 0.5f; fx += 1.0f) {
1026 int32_t nGray = nStartGray + (int32_t)(fStepGray * (fx - rect.left));
1027 CPWL_Utils::DrawStrokeLine(
1028 pDevice, pUser2Device, CFX_PointF(fx, rect.bottom),
1029 CFX_PointF(fx, rect.top),
1030 ArgbEncode(nTransparency, nGray, nGray, nGray), 1.5f);
1031 }
1032 }
1033 }
1034
DrawBorder(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device,const CFX_FloatRect & rect,FX_FLOAT fWidth,const CPWL_Color & color,const CPWL_Color & crLeftTop,const CPWL_Color & crRightBottom,BorderStyle nStyle,int32_t nTransparency)1035 void CPWL_Utils::DrawBorder(CFX_RenderDevice* pDevice,
1036 CFX_Matrix* pUser2Device,
1037 const CFX_FloatRect& rect,
1038 FX_FLOAT fWidth,
1039 const CPWL_Color& color,
1040 const CPWL_Color& crLeftTop,
1041 const CPWL_Color& crRightBottom,
1042 BorderStyle nStyle,
1043 int32_t nTransparency) {
1044 FX_FLOAT fLeft = rect.left;
1045 FX_FLOAT fRight = rect.right;
1046 FX_FLOAT fTop = rect.top;
1047 FX_FLOAT fBottom = rect.bottom;
1048
1049 if (fWidth > 0.0f) {
1050 FX_FLOAT fHalfWidth = fWidth / 2.0f;
1051
1052 switch (nStyle) {
1053 default:
1054 case BorderStyle::SOLID: {
1055 CFX_PathData path;
1056 path.AppendRect(fLeft, fBottom, fRight, fTop);
1057 path.AppendRect(fLeft + fWidth, fBottom + fWidth, fRight - fWidth,
1058 fTop - fWidth);
1059 pDevice->DrawPath(&path, pUser2Device, nullptr,
1060 color.ToFXColor(nTransparency), 0, FXFILL_ALTERNATE);
1061 break;
1062 }
1063 case BorderStyle::DASH: {
1064 CFX_PathData path;
1065 path.AppendPoint(
1066 CFX_PointF(fLeft + fWidth / 2.0f, fBottom + fWidth / 2.0f),
1067 FXPT_TYPE::MoveTo, false);
1068 path.AppendPoint(
1069 CFX_PointF(fLeft + fWidth / 2.0f, fTop - fWidth / 2.0f),
1070 FXPT_TYPE::LineTo, false);
1071 path.AppendPoint(
1072 CFX_PointF(fRight - fWidth / 2.0f, fTop - fWidth / 2.0f),
1073 FXPT_TYPE::LineTo, false);
1074 path.AppendPoint(
1075 CFX_PointF(fRight - fWidth / 2.0f, fBottom + fWidth / 2.0f),
1076 FXPT_TYPE::LineTo, false);
1077 path.AppendPoint(
1078 CFX_PointF(fLeft + fWidth / 2.0f, fBottom + fWidth / 2.0f),
1079 FXPT_TYPE::LineTo, false);
1080
1081 CFX_GraphStateData gsd;
1082 gsd.SetDashCount(2);
1083 gsd.m_DashArray[0] = 3.0f;
1084 gsd.m_DashArray[1] = 3.0f;
1085 gsd.m_DashPhase = 0;
1086
1087 gsd.m_LineWidth = fWidth;
1088 pDevice->DrawPath(&path, pUser2Device, &gsd, 0,
1089 color.ToFXColor(nTransparency), FXFILL_WINDING);
1090 break;
1091 }
1092 case BorderStyle::BEVELED:
1093 case BorderStyle::INSET: {
1094 CFX_GraphStateData gsd;
1095 gsd.m_LineWidth = fHalfWidth;
1096
1097 CFX_PathData pathLT;
1098
1099 pathLT.AppendPoint(CFX_PointF(fLeft + fHalfWidth, fBottom + fHalfWidth),
1100 FXPT_TYPE::MoveTo, false);
1101 pathLT.AppendPoint(CFX_PointF(fLeft + fHalfWidth, fTop - fHalfWidth),
1102 FXPT_TYPE::LineTo, false);
1103 pathLT.AppendPoint(CFX_PointF(fRight - fHalfWidth, fTop - fHalfWidth),
1104 FXPT_TYPE::LineTo, false);
1105 pathLT.AppendPoint(
1106 CFX_PointF(fRight - fHalfWidth * 2, fTop - fHalfWidth * 2),
1107 FXPT_TYPE::LineTo, false);
1108 pathLT.AppendPoint(
1109 CFX_PointF(fLeft + fHalfWidth * 2, fTop - fHalfWidth * 2),
1110 FXPT_TYPE::LineTo, false);
1111 pathLT.AppendPoint(
1112 CFX_PointF(fLeft + fHalfWidth * 2, fBottom + fHalfWidth * 2),
1113 FXPT_TYPE::LineTo, false);
1114 pathLT.AppendPoint(CFX_PointF(fLeft + fHalfWidth, fBottom + fHalfWidth),
1115 FXPT_TYPE::LineTo, false);
1116
1117 pDevice->DrawPath(&pathLT, pUser2Device, &gsd,
1118 crLeftTop.ToFXColor(nTransparency), 0,
1119 FXFILL_ALTERNATE);
1120
1121 CFX_PathData pathRB;
1122 pathRB.AppendPoint(CFX_PointF(fRight - fHalfWidth, fTop - fHalfWidth),
1123 FXPT_TYPE::MoveTo, false);
1124 pathRB.AppendPoint(
1125 CFX_PointF(fRight - fHalfWidth, fBottom + fHalfWidth),
1126 FXPT_TYPE::LineTo, false);
1127 pathRB.AppendPoint(CFX_PointF(fLeft + fHalfWidth, fBottom + fHalfWidth),
1128 FXPT_TYPE::LineTo, false);
1129 pathRB.AppendPoint(
1130 CFX_PointF(fLeft + fHalfWidth * 2, fBottom + fHalfWidth * 2),
1131 FXPT_TYPE::LineTo, false);
1132 pathRB.AppendPoint(
1133 CFX_PointF(fRight - fHalfWidth * 2, fBottom + fHalfWidth * 2),
1134 FXPT_TYPE::LineTo, false);
1135 pathRB.AppendPoint(
1136 CFX_PointF(fRight - fHalfWidth * 2, fTop - fHalfWidth * 2),
1137 FXPT_TYPE::LineTo, false);
1138 pathRB.AppendPoint(CFX_PointF(fRight - fHalfWidth, fTop - fHalfWidth),
1139 FXPT_TYPE::LineTo, false);
1140
1141 pDevice->DrawPath(&pathRB, pUser2Device, &gsd,
1142 crRightBottom.ToFXColor(nTransparency), 0,
1143 FXFILL_ALTERNATE);
1144
1145 CFX_PathData path;
1146
1147 path.AppendRect(fLeft, fBottom, fRight, fTop);
1148 path.AppendRect(fLeft + fHalfWidth, fBottom + fHalfWidth,
1149 fRight - fHalfWidth, fTop - fHalfWidth);
1150
1151 pDevice->DrawPath(&path, pUser2Device, &gsd,
1152 color.ToFXColor(nTransparency), 0, FXFILL_ALTERNATE);
1153 break;
1154 }
1155 case BorderStyle::UNDERLINE: {
1156 CFX_PathData path;
1157 path.AppendPoint(CFX_PointF(fLeft, fBottom + fWidth / 2),
1158 FXPT_TYPE::MoveTo, false);
1159 path.AppendPoint(CFX_PointF(fRight, fBottom + fWidth / 2),
1160 FXPT_TYPE::LineTo, false);
1161
1162 CFX_GraphStateData gsd;
1163 gsd.m_LineWidth = fWidth;
1164
1165 pDevice->DrawPath(&path, pUser2Device, &gsd, 0,
1166 color.ToFXColor(nTransparency), FXFILL_ALTERNATE);
1167 break;
1168 }
1169 }
1170 }
1171 }
1172
1173