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 <memory>
8 
9 #include "fx_path_generator.h"
10 #include "pre.h"
11 
12 class CAGG_Graphics {
13  public:
14   CAGG_Graphics();
15   FX_ERR Create(CFX_Graphics* owner,
16                 int32_t width,
17                 int32_t height,
18                 FXDIB_Format format);
19   virtual ~CAGG_Graphics();
20 
21  private:
22   CFX_Graphics* _owner;
23 };
CFX_Graphics()24 CFX_Graphics::CFX_Graphics() {
25   _type = FX_CONTEXT_None;
26   _info._graphState.SetDashCount(0);
27   _info._isAntialiasing = TRUE;
28   _info._strokeAlignment = FX_STROKEALIGNMENT_Center;
29   _info._CTM.SetIdentity();
30   _info._isActOnDash = FALSE;
31   _info._strokeColor = NULL;
32   _info._fillColor = NULL;
33   _info._font = NULL;
34   _info._fontSize = 40.0;
35   _info._fontHScale = 1.0;
36   _info._fontSpacing = 0.0;
37   _renderDevice = NULL;
38   _aggGraphics = NULL;
39 }
Create(CFX_RenderDevice * renderDevice,FX_BOOL isAntialiasing)40 FX_ERR CFX_Graphics::Create(CFX_RenderDevice* renderDevice,
41                             FX_BOOL isAntialiasing) {
42   _FX_RETURN_VALUE_IF_FAIL(renderDevice, FX_ERR_Parameter_Invalid);
43   if (_type != FX_CONTEXT_None) {
44     return FX_ERR_Property_Invalid;
45   }
46   _type = FX_CONTEXT_Device;
47   _info._isAntialiasing = isAntialiasing;
48   _renderDevice = renderDevice;
49   if (_renderDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP) {
50     return FX_ERR_Succeeded;
51   }
52   return FX_ERR_Indefinite;
53 }
Create(int32_t width,int32_t height,FXDIB_Format format,FX_BOOL isNative,FX_BOOL isAntialiasing)54 FX_ERR CFX_Graphics::Create(int32_t width,
55                             int32_t height,
56                             FXDIB_Format format,
57                             FX_BOOL isNative,
58                             FX_BOOL isAntialiasing) {
59   if (_type != FX_CONTEXT_None) {
60     return FX_ERR_Property_Invalid;
61   }
62   _type = FX_CONTEXT_Device;
63   _info._isAntialiasing = isAntialiasing;
64   {
65     _aggGraphics = new CAGG_Graphics;
66     return _aggGraphics->Create(this, width, height, format);
67   }
68 }
~CFX_Graphics()69 CFX_Graphics::~CFX_Graphics() {
70   if (_aggGraphics) {
71     delete _aggGraphics;
72     _aggGraphics = NULL;
73   }
74   _renderDevice = NULL;
75   _info._graphState.SetDashCount(0);
76   _type = FX_CONTEXT_None;
77 }
GetDeviceCap(const int32_t capID,FX_DeviceCap & capVal)78 FX_ERR CFX_Graphics::GetDeviceCap(const int32_t capID, FX_DeviceCap& capVal) {
79   switch (_type) {
80     case FX_CONTEXT_Device: {
81       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
82       capVal = _renderDevice->GetDeviceCaps(capID);
83       return FX_ERR_Succeeded;
84     }
85     default: { return FX_ERR_Property_Invalid; }
86   }
87 }
IsPrinterDevice(FX_BOOL & isPrinter)88 FX_ERR CFX_Graphics::IsPrinterDevice(FX_BOOL& isPrinter) {
89   switch (_type) {
90     case FX_CONTEXT_Device: {
91       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
92       int32_t deviceClass = _renderDevice->GetDeviceClass();
93       if (deviceClass == FXDC_PRINTER) {
94         isPrinter = TRUE;
95       } else {
96         isPrinter = FALSE;
97       }
98       return FX_ERR_Succeeded;
99     }
100     default: { return FX_ERR_Property_Invalid; }
101   }
102 }
EnableAntialiasing(FX_BOOL isAntialiasing)103 FX_ERR CFX_Graphics::EnableAntialiasing(FX_BOOL isAntialiasing) {
104   switch (_type) {
105     case FX_CONTEXT_Device: {
106       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
107       _info._isAntialiasing = isAntialiasing;
108       return FX_ERR_Succeeded;
109     }
110     default: { return FX_ERR_Property_Invalid; }
111   }
112 }
SaveGraphState()113 FX_ERR CFX_Graphics::SaveGraphState() {
114   switch (_type) {
115     case FX_CONTEXT_Device: {
116       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
117       _renderDevice->SaveState();
118       TInfo* info = new TInfo;
119       info->_graphState.Copy(_info._graphState);
120       info->_isAntialiasing = _info._isAntialiasing;
121       info->_strokeAlignment = _info._strokeAlignment;
122       info->_CTM = _info._CTM;
123       info->_isActOnDash = _info._isActOnDash;
124       info->_strokeColor = _info._strokeColor;
125       info->_fillColor = _info._fillColor;
126       info->_font = _info._font;
127       info->_fontSize = _info._fontSize;
128       info->_fontHScale = _info._fontHScale;
129       info->_fontSpacing = _info._fontSpacing;
130       _infoStack.Add(info);
131       return FX_ERR_Succeeded;
132     }
133     default: { return FX_ERR_Property_Invalid; }
134   }
135 }
RestoreGraphState()136 FX_ERR CFX_Graphics::RestoreGraphState() {
137   switch (_type) {
138     case FX_CONTEXT_Device: {
139       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
140       _renderDevice->RestoreState();
141       int32_t size = _infoStack.GetSize();
142       if (size <= 0) {
143         return FX_ERR_Intermediate_Value_Invalid;
144       }
145       int32_t topIndex = size - 1;
146       TInfo* info = (TInfo*)_infoStack.GetAt(topIndex);
147       _FX_RETURN_VALUE_IF_FAIL(info, FX_ERR_Intermediate_Value_Invalid);
148       _info._graphState.Copy(info->_graphState);
149       _info._isAntialiasing = info->_isAntialiasing;
150       _info._strokeAlignment = info->_strokeAlignment;
151       _info._CTM = info->_CTM;
152       _info._isActOnDash = info->_isActOnDash;
153       _info._strokeColor = info->_strokeColor;
154       _info._fillColor = info->_fillColor;
155       _info._font = info->_font;
156       _info._fontSize = info->_fontSize;
157       _info._fontHScale = info->_fontHScale;
158       _info._fontSpacing = info->_fontSpacing;
159       delete info;
160       info = NULL;
161       _infoStack.RemoveAt(topIndex);
162       return FX_ERR_Succeeded;
163     }
164     default: { return FX_ERR_Property_Invalid; }
165   }
166 }
GetLineCap(CFX_GraphStateData::LineCap & lineCap)167 FX_ERR CFX_Graphics::GetLineCap(CFX_GraphStateData::LineCap& lineCap) {
168   switch (_type) {
169     case FX_CONTEXT_Device: {
170       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
171       lineCap = _info._graphState.m_LineCap;
172       return FX_ERR_Succeeded;
173     }
174     default: { return FX_ERR_Property_Invalid; }
175   }
176 }
SetLineCap(CFX_GraphStateData::LineCap lineCap)177 FX_ERR CFX_Graphics::SetLineCap(CFX_GraphStateData::LineCap lineCap) {
178   switch (_type) {
179     case FX_CONTEXT_Device: {
180       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
181       _info._graphState.m_LineCap = lineCap;
182       return FX_ERR_Succeeded;
183     }
184     default: { return FX_ERR_Property_Invalid; }
185   }
186 }
GetDashCount(int32_t & dashCount)187 FX_ERR CFX_Graphics::GetDashCount(int32_t& dashCount) {
188   switch (_type) {
189     case FX_CONTEXT_Device: {
190       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
191       dashCount = _info._graphState.m_DashCount;
192       return FX_ERR_Succeeded;
193     }
194     default: { return FX_ERR_Property_Invalid; }
195   }
196 }
GetLineDash(FX_FLOAT & dashPhase,FX_FLOAT * dashArray)197 FX_ERR CFX_Graphics::GetLineDash(FX_FLOAT& dashPhase, FX_FLOAT* dashArray) {
198   _FX_RETURN_VALUE_IF_FAIL(dashArray, FX_ERR_Parameter_Invalid);
199   switch (_type) {
200     case FX_CONTEXT_Device: {
201       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
202       dashPhase = _info._graphState.m_DashPhase;
203       FXSYS_memcpy(dashArray, _info._graphState.m_DashArray,
204                    _info._graphState.m_DashCount * sizeof(FX_FLOAT));
205       return FX_ERR_Succeeded;
206     }
207     default: { return FX_ERR_Property_Invalid; }
208   }
209 }
SetLineDash(FX_FLOAT dashPhase,FX_FLOAT * dashArray,int32_t dashCount)210 FX_ERR CFX_Graphics::SetLineDash(FX_FLOAT dashPhase,
211                                  FX_FLOAT* dashArray,
212                                  int32_t dashCount) {
213   if (dashCount > 0 && !dashArray) {
214     return FX_ERR_Parameter_Invalid;
215   }
216   dashCount = dashCount < 0 ? 0 : dashCount;
217   switch (_type) {
218     case FX_CONTEXT_Device: {
219       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
220       FX_FLOAT scale = 1.0;
221       if (_info._isActOnDash) {
222         scale = _info._graphState.m_LineWidth;
223       }
224       _info._graphState.m_DashPhase = dashPhase;
225       _info._graphState.SetDashCount(dashCount);
226       for (int32_t i = 0; i < dashCount; i++) {
227         _info._graphState.m_DashArray[i] = dashArray[i] * scale;
228       }
229       return FX_ERR_Succeeded;
230     }
231     default: { return FX_ERR_Property_Invalid; }
232   }
233 }
SetLineDash(FX_DashStyle dashStyle)234 FX_ERR CFX_Graphics::SetLineDash(FX_DashStyle dashStyle) {
235   switch (_type) {
236     case FX_CONTEXT_Device: {
237       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
238       return RenderDeviceSetLineDash(dashStyle);
239     }
240     default: { return FX_ERR_Property_Invalid; }
241   }
242 }
GetLineJoin(CFX_GraphStateData::LineJoin & lineJoin)243 FX_ERR CFX_Graphics::GetLineJoin(CFX_GraphStateData::LineJoin& lineJoin) {
244   switch (_type) {
245     case FX_CONTEXT_Device: {
246       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
247       lineJoin = _info._graphState.m_LineJoin;
248       return FX_ERR_Succeeded;
249     }
250     default: { return FX_ERR_Property_Invalid; }
251   }
252 }
SetLineJoin(CFX_GraphStateData::LineJoin lineJoin)253 FX_ERR CFX_Graphics::SetLineJoin(CFX_GraphStateData::LineJoin lineJoin) {
254   switch (_type) {
255     case FX_CONTEXT_Device: {
256       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
257       _info._graphState.m_LineJoin = lineJoin;
258       return FX_ERR_Succeeded;
259     }
260     default: { return FX_ERR_Property_Invalid; }
261   }
262 }
GetMiterLimit(FX_FLOAT & miterLimit)263 FX_ERR CFX_Graphics::GetMiterLimit(FX_FLOAT& miterLimit) {
264   switch (_type) {
265     case FX_CONTEXT_Device: {
266       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
267       miterLimit = _info._graphState.m_MiterLimit;
268       return FX_ERR_Succeeded;
269     }
270     default: { return FX_ERR_Property_Invalid; }
271   }
272 }
SetMiterLimit(FX_FLOAT miterLimit)273 FX_ERR CFX_Graphics::SetMiterLimit(FX_FLOAT miterLimit) {
274   switch (_type) {
275     case FX_CONTEXT_Device: {
276       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
277       _info._graphState.m_MiterLimit = miterLimit;
278       return FX_ERR_Succeeded;
279     }
280     default: { return FX_ERR_Property_Invalid; }
281   }
282 }
GetLineWidth(FX_FLOAT & lineWidth)283 FX_ERR CFX_Graphics::GetLineWidth(FX_FLOAT& lineWidth) {
284   switch (_type) {
285     case FX_CONTEXT_Device: {
286       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
287       lineWidth = _info._graphState.m_LineWidth;
288       return FX_ERR_Succeeded;
289     }
290     default: { return FX_ERR_Property_Invalid; }
291   }
292 }
SetLineWidth(FX_FLOAT lineWidth,FX_BOOL isActOnDash)293 FX_ERR CFX_Graphics::SetLineWidth(FX_FLOAT lineWidth, FX_BOOL isActOnDash) {
294   switch (_type) {
295     case FX_CONTEXT_Device: {
296       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
297       _info._graphState.m_LineWidth = lineWidth;
298       _info._isActOnDash = isActOnDash;
299       return FX_ERR_Succeeded;
300     }
301     default: { return FX_ERR_Property_Invalid; }
302   }
303 }
GetStrokeAlignment(FX_StrokeAlignment & strokeAlignment)304 FX_ERR CFX_Graphics::GetStrokeAlignment(FX_StrokeAlignment& strokeAlignment) {
305   switch (_type) {
306     case FX_CONTEXT_Device: {
307       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
308       strokeAlignment = _info._strokeAlignment;
309       return FX_ERR_Succeeded;
310     }
311     default: { return FX_ERR_Property_Invalid; }
312   }
313 }
SetStrokeAlignment(FX_StrokeAlignment strokeAlignment)314 FX_ERR CFX_Graphics::SetStrokeAlignment(FX_StrokeAlignment strokeAlignment) {
315   switch (_type) {
316     case FX_CONTEXT_Device: {
317       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
318       _info._strokeAlignment = strokeAlignment;
319       return FX_ERR_Succeeded;
320     }
321     default: { return FX_ERR_Property_Invalid; }
322   }
323 }
SetStrokeColor(CFX_Color * color)324 FX_ERR CFX_Graphics::SetStrokeColor(CFX_Color* color) {
325   _FX_RETURN_VALUE_IF_FAIL(color, FX_ERR_Parameter_Invalid);
326   switch (_type) {
327     case FX_CONTEXT_Device: {
328       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
329       _info._strokeColor = color;
330       return FX_ERR_Succeeded;
331     }
332     default: { return FX_ERR_Property_Invalid; }
333   }
334 }
SetFillColor(CFX_Color * color)335 FX_ERR CFX_Graphics::SetFillColor(CFX_Color* color) {
336   _FX_RETURN_VALUE_IF_FAIL(color, FX_ERR_Parameter_Invalid);
337   switch (_type) {
338     case FX_CONTEXT_Device: {
339       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
340       _info._fillColor = color;
341       return FX_ERR_Succeeded;
342     }
343     default: { return FX_ERR_Property_Invalid; }
344   }
345 }
StrokePath(CFX_Path * path,CFX_Matrix * matrix)346 FX_ERR CFX_Graphics::StrokePath(CFX_Path* path, CFX_Matrix* matrix) {
347   _FX_RETURN_VALUE_IF_FAIL(path, FX_ERR_Parameter_Invalid);
348   switch (_type) {
349     case FX_CONTEXT_Device: {
350       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
351       return RenderDeviceStrokePath(path, matrix);
352     }
353     default: { return FX_ERR_Property_Invalid; }
354   }
355 }
FillPath(CFX_Path * path,FX_FillMode fillMode,CFX_Matrix * matrix)356 FX_ERR CFX_Graphics::FillPath(CFX_Path* path,
357                               FX_FillMode fillMode,
358                               CFX_Matrix* matrix) {
359   _FX_RETURN_VALUE_IF_FAIL(path, FX_ERR_Parameter_Invalid);
360   switch (_type) {
361     case FX_CONTEXT_Device: {
362       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
363       return RenderDeviceFillPath(path, fillMode, matrix);
364     }
365     default: { return FX_ERR_Property_Invalid; }
366   }
367 }
ClipPath(CFX_Path * path,FX_FillMode fillMode,CFX_Matrix * matrix)368 FX_ERR CFX_Graphics::ClipPath(CFX_Path* path,
369                               FX_FillMode fillMode,
370                               CFX_Matrix* matrix) {
371   _FX_RETURN_VALUE_IF_FAIL(path, FX_ERR_Parameter_Invalid);
372   switch (_type) {
373     case FX_CONTEXT_Device: {
374       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
375       FX_BOOL result = _renderDevice->SetClip_PathFill(
376           path->GetPathData(), (CFX_Matrix*)matrix, fillMode);
377       _FX_RETURN_VALUE_IF_FAIL(result, FX_ERR_Indefinite);
378       return FX_ERR_Succeeded;
379     }
380     default: { return FX_ERR_Property_Invalid; }
381   }
382 }
DrawImage(CFX_DIBSource * source,const CFX_PointF & point,CFX_Matrix * matrix)383 FX_ERR CFX_Graphics::DrawImage(CFX_DIBSource* source,
384                                const CFX_PointF& point,
385                                CFX_Matrix* matrix) {
386   _FX_RETURN_VALUE_IF_FAIL(source, FX_ERR_Parameter_Invalid);
387   switch (_type) {
388     case FX_CONTEXT_Device: {
389       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
390       return RenderDeviceDrawImage(source, point, matrix);
391     }
392     default: { return FX_ERR_Property_Invalid; }
393   }
394 }
StretchImage(CFX_DIBSource * source,const CFX_RectF & rect,CFX_Matrix * matrix)395 FX_ERR CFX_Graphics::StretchImage(CFX_DIBSource* source,
396                                   const CFX_RectF& rect,
397                                   CFX_Matrix* matrix) {
398   _FX_RETURN_VALUE_IF_FAIL(source, FX_ERR_Parameter_Invalid);
399   switch (_type) {
400     case FX_CONTEXT_Device: {
401       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
402       return RenderDeviceStretchImage(source, rect, matrix);
403     }
404     default: { return FX_ERR_Property_Invalid; }
405   }
406 }
ConcatMatrix(const CFX_Matrix * matrix)407 FX_ERR CFX_Graphics::ConcatMatrix(const CFX_Matrix* matrix) {
408   _FX_RETURN_VALUE_IF_FAIL(matrix, FX_ERR_Parameter_Invalid);
409   switch (_type) {
410     case FX_CONTEXT_Device: {
411       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
412       _info._CTM.Concat(*matrix);
413       return FX_ERR_Succeeded;
414     }
415     default: { return FX_ERR_Property_Invalid; }
416   }
417 }
GetMatrix()418 CFX_Matrix* CFX_Graphics::GetMatrix() {
419   switch (_type) {
420     case FX_CONTEXT_Device: {
421       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, NULL);
422       return &_info._CTM;
423     }
424     default: { return NULL; }
425   }
426 }
GetClipRect(CFX_RectF & rect)427 FX_ERR CFX_Graphics::GetClipRect(CFX_RectF& rect) {
428   switch (_type) {
429     case FX_CONTEXT_Device: {
430       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
431       FX_RECT r = _renderDevice->GetClipBox();
432       rect.left = (FX_FLOAT)r.left;
433       rect.top = (FX_FLOAT)r.top;
434       rect.width = (FX_FLOAT)r.Width();
435       rect.height = (FX_FLOAT)r.Height();
436       return FX_ERR_Succeeded;
437     }
438     default: { return FX_ERR_Property_Invalid; }
439   }
440 }
SetClipRect(const CFX_RectF & rect)441 FX_ERR CFX_Graphics::SetClipRect(const CFX_RectF& rect) {
442   switch (_type) {
443     case FX_CONTEXT_Device: {
444       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
445       FX_RECT r(FXSYS_round(rect.left), FXSYS_round(rect.top),
446                 FXSYS_round(rect.right()), FXSYS_round(rect.bottom()));
447       FX_BOOL result = _renderDevice->SetClip_Rect(&r);
448       _FX_RETURN_VALUE_IF_FAIL(result, FX_ERR_Method_Not_Supported);
449       return FX_ERR_Succeeded;
450     }
451     default: { return FX_ERR_Property_Invalid; }
452   }
453 }
ClearClip()454 FX_ERR CFX_Graphics::ClearClip() {
455   switch (_type) {
456     case FX_CONTEXT_Device: {
457       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
458       FX_BOOL result = FX_ERR_Succeeded;
459       _FX_RETURN_VALUE_IF_FAIL(result, FX_ERR_Method_Not_Supported);
460       return FX_ERR_Succeeded;
461     }
462     default: { return FX_ERR_Property_Invalid; }
463   }
464 }
SetFont(CFX_Font * font)465 FX_ERR CFX_Graphics::SetFont(CFX_Font* font) {
466   _FX_RETURN_VALUE_IF_FAIL(font, FX_ERR_Parameter_Invalid);
467   switch (_type) {
468     case FX_CONTEXT_Device: {
469       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
470       _info._font = font;
471       return FX_ERR_Succeeded;
472     }
473     default: { return FX_ERR_Property_Invalid; }
474   }
475 }
SetFontSize(const FX_FLOAT size)476 FX_ERR CFX_Graphics::SetFontSize(const FX_FLOAT size) {
477   FX_FLOAT fontSize = size <= 0 ? 1.0f : size;
478   switch (_type) {
479     case FX_CONTEXT_Device: {
480       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
481       _info._fontSize = fontSize;
482       return FX_ERR_Succeeded;
483     }
484     default: { return FX_ERR_Property_Invalid; }
485   }
486 }
SetFontHScale(const FX_FLOAT scale)487 FX_ERR CFX_Graphics::SetFontHScale(const FX_FLOAT scale) {
488   FX_FLOAT fontHScale = scale <= 0 ? 1.0f : scale;
489   switch (_type) {
490     case FX_CONTEXT_Device: {
491       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
492       _info._fontHScale = fontHScale;
493       return FX_ERR_Succeeded;
494     }
495     default: { return FX_ERR_Property_Invalid; }
496   }
497 }
SetCharSpacing(const FX_FLOAT spacing)498 FX_ERR CFX_Graphics::SetCharSpacing(const FX_FLOAT spacing) {
499   FX_FLOAT fontSpacing = spacing < 0 ? 0 : spacing;
500   switch (_type) {
501     case FX_CONTEXT_Device: {
502       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
503       _info._fontSpacing = fontSpacing;
504       return FX_ERR_Succeeded;
505     }
506     default: { return FX_ERR_Property_Invalid; }
507   }
508 }
SetTextDrawingMode(const int32_t mode)509 FX_ERR CFX_Graphics::SetTextDrawingMode(const int32_t mode) {
510   switch (_type) {
511     case FX_CONTEXT_Device: {
512       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
513       return FX_ERR_Succeeded;
514     }
515     default: { return FX_ERR_Property_Invalid; }
516   }
517 }
ShowText(const CFX_PointF & point,const CFX_WideString & text,CFX_Matrix * matrix)518 FX_ERR CFX_Graphics::ShowText(const CFX_PointF& point,
519                               const CFX_WideString& text,
520                               CFX_Matrix* matrix) {
521   switch (_type) {
522     case FX_CONTEXT_Device: {
523       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
524       return RenderDeviceShowText(point, text, matrix);
525     }
526     default: { return FX_ERR_Property_Invalid; }
527   }
528 }
CalcTextRect(CFX_RectF & rect,const CFX_WideString & text,FX_BOOL isMultiline,CFX_Matrix * matrix)529 FX_ERR CFX_Graphics::CalcTextRect(CFX_RectF& rect,
530                                   const CFX_WideString& text,
531                                   FX_BOOL isMultiline,
532                                   CFX_Matrix* matrix) {
533   switch (_type) {
534     case FX_CONTEXT_Device: {
535       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
536       int32_t length = text.GetLength();
537       FX_DWORD* charCodes = FX_Alloc(FX_DWORD, length);
538       FXTEXT_CHARPOS* charPos = FX_Alloc(FXTEXT_CHARPOS, length);
539       CalcTextInfo(text, charCodes, charPos, rect);
540       FX_Free(charPos);
541       FX_Free(charCodes);
542       return FX_ERR_Succeeded;
543     }
544     default: { return FX_ERR_Property_Invalid; }
545   }
546 }
Transfer(CFX_Graphics * graphics,const CFX_Matrix * matrix)547 FX_ERR CFX_Graphics::Transfer(CFX_Graphics* graphics,
548                               const CFX_Matrix* matrix) {
549   _FX_RETURN_VALUE_IF_FAIL(graphics, FX_ERR_Parameter_Invalid);
550   CFX_Matrix m;
551   m.Set(_info._CTM.a, _info._CTM.b, _info._CTM.c, _info._CTM.d, _info._CTM.e,
552         _info._CTM.f);
553   if (matrix) {
554     m.Concat(*matrix);
555   }
556   switch (_type) {
557     case FX_CONTEXT_Device: {
558       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
559       {
560         _FX_RETURN_VALUE_IF_FAIL(graphics->_renderDevice,
561                                  FX_ERR_Parameter_Invalid);
562         CFX_DIBitmap* bitmap = graphics->_renderDevice->GetBitmap();
563         FX_BOOL result = _renderDevice->SetDIBits(bitmap, 0, 0);
564         _FX_RETURN_VALUE_IF_FAIL(result, FX_ERR_Method_Not_Supported);
565       }
566     }
567     default: { return FX_ERR_Property_Invalid; }
568   }
569 }
Transfer(CFX_Graphics * graphics,FX_FLOAT srcLeft,FX_FLOAT srcTop,const CFX_RectF & dstRect,const CFX_Matrix * matrix)570 FX_ERR CFX_Graphics::Transfer(CFX_Graphics* graphics,
571                               FX_FLOAT srcLeft,
572                               FX_FLOAT srcTop,
573                               const CFX_RectF& dstRect,
574                               const CFX_Matrix* matrix) {
575   _FX_RETURN_VALUE_IF_FAIL(graphics, FX_ERR_Parameter_Invalid);
576   CFX_Matrix m;
577   m.Set(_info._CTM.a, _info._CTM.b, _info._CTM.c, _info._CTM.d, _info._CTM.e,
578         _info._CTM.f);
579   if (matrix) {
580     m.Concat(*matrix);
581   }
582   switch (_type) {
583     case FX_CONTEXT_Device: {
584       _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
585       {
586         _FX_RETURN_VALUE_IF_FAIL(graphics->_renderDevice,
587                                  FX_ERR_Parameter_Invalid);
588         CFX_DIBitmap* bitmap = graphics->_renderDevice->GetBitmap();
589         FX_BOOL result = FX_ERR_Indefinite;
590         CFX_DIBitmap bmp;
591         result = bmp.Create((int32_t)dstRect.width, (int32_t)dstRect.height,
592                             bitmap->GetFormat());
593         _FX_RETURN_VALUE_IF_FAIL(result, FX_ERR_Intermediate_Value_Invalid);
594         result = graphics->_renderDevice->GetDIBits(&bmp, (int32_t)srcLeft,
595                                                     (int32_t)srcTop);
596         _FX_RETURN_VALUE_IF_FAIL(result, FX_ERR_Method_Not_Supported);
597         result = _renderDevice->SetDIBits(&bmp, (int32_t)dstRect.left,
598                                           (int32_t)dstRect.top);
599         _FX_RETURN_VALUE_IF_FAIL(result, FX_ERR_Method_Not_Supported);
600         return FX_ERR_Succeeded;
601       }
602     }
603     default: { return FX_ERR_Property_Invalid; }
604   }
605 }
GetRenderDevice()606 CFX_RenderDevice* CFX_Graphics::GetRenderDevice() {
607   return _renderDevice;
608 }
InverseRect(const CFX_RectF & rect)609 FX_ERR CFX_Graphics::InverseRect(const CFX_RectF& rect) {
610   _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
611   CFX_DIBitmap* bitmap = _renderDevice->GetBitmap();
612   _FX_RETURN_VALUE_IF_FAIL(bitmap, FX_ERR_Property_Invalid);
613   CFX_RectF temp(rect);
614   _info._CTM.TransformRect(temp);
615   CFX_RectF r;
616   r.Set(0, 0, (FX_FLOAT)bitmap->GetWidth(), (FX_FLOAT)bitmap->GetWidth());
617   r.Intersect(temp);
618   if (r.IsEmpty()) {
619     return FX_ERR_Parameter_Invalid;
620   }
621   FX_ARGB* pBuf =
622       (FX_ARGB*)(bitmap->GetBuffer() + int32_t(r.top) * bitmap->GetPitch());
623   int32_t bottom = (int32_t)r.bottom();
624   int32_t right = (int32_t)r.right();
625   for (int32_t i = (int32_t)r.top; i < bottom; i++) {
626     FX_ARGB* pLine = pBuf + (int32_t)r.left;
627     for (int32_t j = (int32_t)r.left; j < right; j++) {
628       FX_ARGB c = *pLine;
629       *pLine++ = (c & 0xFF000000) | (0xFFFFFF - (c & 0x00FFFFFF));
630     }
631     pBuf = (FX_ARGB*)((uint8_t*)pBuf + bitmap->GetPitch());
632   }
633   return FX_ERR_Succeeded;
634 }
XorDIBitmap(const CFX_DIBitmap * srcBitmap,const CFX_RectF & rect)635 FX_ERR CFX_Graphics::XorDIBitmap(const CFX_DIBitmap* srcBitmap,
636                                  const CFX_RectF& rect) {
637   _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
638   CFX_DIBitmap* dst = _renderDevice->GetBitmap();
639   _FX_RETURN_VALUE_IF_FAIL(dst, FX_ERR_Property_Invalid);
640   CFX_RectF temp(rect);
641   _info._CTM.TransformRect(temp);
642   CFX_RectF r;
643   r.Set(0, 0, (FX_FLOAT)dst->GetWidth(), (FX_FLOAT)dst->GetWidth());
644   r.Intersect(temp);
645   if (r.IsEmpty()) {
646     return FX_ERR_Parameter_Invalid;
647   }
648   FX_ARGB* pSrcBuf = (FX_ARGB*)(srcBitmap->GetBuffer() +
649                                 int32_t(r.top) * srcBitmap->GetPitch());
650   FX_ARGB* pDstBuf =
651       (FX_ARGB*)(dst->GetBuffer() + int32_t(r.top) * dst->GetPitch());
652   int32_t bottom = (int32_t)r.bottom();
653   int32_t right = (int32_t)r.right();
654   for (int32_t i = (int32_t)r.top; i < bottom; i++) {
655     FX_ARGB* pSrcLine = pSrcBuf + (int32_t)r.left;
656     FX_ARGB* pDstLine = pDstBuf + (int32_t)r.left;
657     for (int32_t j = (int32_t)r.left; j < right; j++) {
658       FX_ARGB c = *pDstLine;
659       *pDstLine++ =
660           ArgbEncode(FXARGB_A(c), (c & 0xFFFFFF) ^ (*pSrcLine & 0xFFFFFF));
661       pSrcLine++;
662     }
663     pSrcBuf = (FX_ARGB*)((uint8_t*)pSrcBuf + srcBitmap->GetPitch());
664     pDstBuf = (FX_ARGB*)((uint8_t*)pDstBuf + dst->GetPitch());
665   }
666   return FX_ERR_Succeeded;
667 }
EqvDIBitmap(const CFX_DIBitmap * srcBitmap,const CFX_RectF & rect)668 FX_ERR CFX_Graphics::EqvDIBitmap(const CFX_DIBitmap* srcBitmap,
669                                  const CFX_RectF& rect) {
670   _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid);
671   CFX_DIBitmap* dst = _renderDevice->GetBitmap();
672   _FX_RETURN_VALUE_IF_FAIL(dst, FX_ERR_Property_Invalid);
673   CFX_RectF temp(rect);
674   _info._CTM.TransformRect(temp);
675   CFX_RectF r;
676   r.Set(0, 0, (FX_FLOAT)dst->GetWidth(), (FX_FLOAT)dst->GetWidth());
677   r.Intersect(temp);
678   if (r.IsEmpty()) {
679     return FX_ERR_Parameter_Invalid;
680   }
681   FX_ARGB* pSrcBuf = (FX_ARGB*)(srcBitmap->GetBuffer() +
682                                 int32_t(r.top) * srcBitmap->GetPitch());
683   FX_ARGB* pDstBuf =
684       (FX_ARGB*)(dst->GetBuffer() + int32_t(r.top) * dst->GetPitch());
685   int32_t bottom = (int32_t)r.bottom();
686   int32_t right = (int32_t)r.right();
687   for (int32_t i = (int32_t)r.top; i < bottom; i++) {
688     FX_ARGB* pSrcLine = pSrcBuf + (int32_t)r.left;
689     FX_ARGB* pDstLine = pDstBuf + (int32_t)r.left;
690     for (int32_t j = (int32_t)r.left; j < right; j++) {
691       FX_ARGB c = *pDstLine;
692       *pDstLine++ =
693           ArgbEncode(FXARGB_A(c), ~((c & 0xFFFFFF) ^ (*pSrcLine & 0xFFFFFF)));
694       pSrcLine++;
695     }
696     pSrcBuf = (FX_ARGB*)((uint8_t*)pSrcBuf + srcBitmap->GetPitch());
697     pDstBuf = (FX_ARGB*)((uint8_t*)pDstBuf + dst->GetPitch());
698   }
699   return FX_ERR_Succeeded;
700 }
RenderDeviceSetLineDash(FX_DashStyle dashStyle)701 FX_ERR CFX_Graphics::RenderDeviceSetLineDash(FX_DashStyle dashStyle) {
702   switch (dashStyle) {
703     case FX_DASHSTYLE_Solid: {
704       _info._graphState.SetDashCount(0);
705       return FX_ERR_Succeeded;
706     }
707     case FX_DASHSTYLE_Dash: {
708       FX_FLOAT dashArray[] = {3, 1};
709       SetLineDash(0, dashArray, 2);
710       return FX_ERR_Succeeded;
711     }
712     case FX_DASHSTYLE_Dot: {
713       FX_FLOAT dashArray[] = {1, 1};
714       SetLineDash(0, dashArray, 2);
715       return FX_ERR_Succeeded;
716     }
717     case FX_DASHSTYLE_DashDot: {
718       FX_FLOAT dashArray[] = {3, 1, 1, 1};
719       SetLineDash(0, dashArray, 4);
720       return FX_ERR_Succeeded;
721     }
722     case FX_DASHSTYLE_DashDotDot: {
723       FX_FLOAT dashArray[] = {4, 1, 2, 1, 2, 1};
724       SetLineDash(0, dashArray, 6);
725       return FX_ERR_Succeeded;
726     }
727     default: { return FX_ERR_Parameter_Invalid; }
728   }
729 }
RenderDeviceStrokePath(CFX_Path * path,CFX_Matrix * matrix)730 FX_ERR CFX_Graphics::RenderDeviceStrokePath(CFX_Path* path,
731                                             CFX_Matrix* matrix) {
732   _FX_RETURN_VALUE_IF_FAIL(_info._strokeColor, FX_ERR_Property_Invalid);
733   CFX_Matrix m;
734   m.Set(_info._CTM.a, _info._CTM.b, _info._CTM.c, _info._CTM.d, _info._CTM.e,
735         _info._CTM.f);
736   if (matrix) {
737     m.Concat(*matrix);
738   }
739   switch (_info._strokeColor->_type) {
740     case FX_COLOR_Solid: {
741       FX_BOOL result = _renderDevice->DrawPath(
742           path->GetPathData(), (CFX_Matrix*)&m, &_info._graphState, 0x0,
743           _info._strokeColor->_argb, 0);
744       _FX_RETURN_VALUE_IF_FAIL(result, FX_ERR_Indefinite);
745       return FX_ERR_Succeeded;
746     }
747     case FX_COLOR_Pattern: {
748       return StrokePathWithPattern(path, &m);
749     }
750     case FX_COLOR_Shading: {
751       return StrokePathWithShading(path, &m);
752     }
753     default: { return FX_ERR_Property_Invalid; }
754   }
755 }
RenderDeviceFillPath(CFX_Path * path,FX_FillMode fillMode,CFX_Matrix * matrix)756 FX_ERR CFX_Graphics::RenderDeviceFillPath(CFX_Path* path,
757                                           FX_FillMode fillMode,
758                                           CFX_Matrix* matrix) {
759   _FX_RETURN_VALUE_IF_FAIL(_info._fillColor, FX_ERR_Property_Invalid);
760   CFX_Matrix m;
761   m.Set(_info._CTM.a, _info._CTM.b, _info._CTM.c, _info._CTM.d, _info._CTM.e,
762         _info._CTM.f);
763   if (matrix) {
764     m.Concat(*matrix);
765   }
766   switch (_info._fillColor->_type) {
767     case FX_COLOR_Solid: {
768       FX_BOOL result = _renderDevice->DrawPath(
769           path->GetPathData(), (CFX_Matrix*)&m, &_info._graphState,
770           _info._fillColor->_argb, 0x0, fillMode);
771       _FX_RETURN_VALUE_IF_FAIL(result, FX_ERR_Indefinite);
772       return FX_ERR_Succeeded;
773     }
774     case FX_COLOR_Pattern: {
775       { return FillPathWithPattern(path, fillMode, &m); }
776     }
777     case FX_COLOR_Shading: {
778       { return FillPathWithShading(path, fillMode, &m); }
779     }
780     default: { return FX_ERR_Property_Invalid; }
781   }
782 }
RenderDeviceDrawImage(CFX_DIBSource * source,const CFX_PointF & point,CFX_Matrix * matrix)783 FX_ERR CFX_Graphics::RenderDeviceDrawImage(CFX_DIBSource* source,
784                                            const CFX_PointF& point,
785                                            CFX_Matrix* matrix) {
786   CFX_Matrix m1;
787   m1.Set(_info._CTM.a, _info._CTM.b, _info._CTM.c, _info._CTM.d, _info._CTM.e,
788          _info._CTM.f);
789   if (matrix) {
790     m1.Concat(*matrix);
791   }
792   CFX_Matrix m2;
793   m2.Set((FX_FLOAT)source->GetWidth(), 0.0, 0.0, (FX_FLOAT)source->GetHeight(),
794          point.x, point.y);
795   m2.Concat(m1);
796   int32_t left, top;
797   CFX_DIBitmap* bmp1 = source->FlipImage(FALSE, TRUE);
798   CFX_DIBitmap* bmp2 = bmp1->TransformTo((CFX_Matrix*)&m2, left, top);
799   CFX_RectF r;
800   GetClipRect(r);
801   FX_ERR result = FX_ERR_Indefinite;
802   {
803     CFX_DIBitmap* bitmap = _renderDevice->GetBitmap();
804     CFX_DIBitmap bmp;
805     bmp.Create(bitmap->GetWidth(), bitmap->GetHeight(), FXDIB_Argb);
806     _renderDevice->GetDIBits(&bmp, 0, 0);
807     bmp.TransferBitmap(FXSYS_round(r.left), FXSYS_round(r.top),
808                        FXSYS_round(r.Width()), FXSYS_round(r.Height()), bmp2,
809                        FXSYS_round(r.left - left), FXSYS_round(r.top - top));
810     _renderDevice->SetDIBits(&bmp, 0, 0);
811     result = FX_ERR_Succeeded;
812   }
813   if (bmp2) {
814     delete bmp2;
815     bmp2 = NULL;
816   }
817   if (bmp1) {
818     delete bmp1;
819     bmp1 = NULL;
820   }
821   return result;
822 }
RenderDeviceStretchImage(CFX_DIBSource * source,const CFX_RectF & rect,CFX_Matrix * matrix)823 FX_ERR CFX_Graphics::RenderDeviceStretchImage(CFX_DIBSource* source,
824                                               const CFX_RectF& rect,
825                                               CFX_Matrix* matrix) {
826   CFX_Matrix m1;
827   m1.Set(_info._CTM.a, _info._CTM.b, _info._CTM.c, _info._CTM.d, _info._CTM.e,
828          _info._CTM.f);
829   if (matrix) {
830     m1.Concat(*matrix);
831   }
832   CFX_DIBitmap* bmp1 =
833       source->StretchTo((int32_t)rect.Width(), (int32_t)rect.Height());
834   CFX_Matrix m2;
835   m2.Set(rect.Width(), 0.0, 0.0, rect.Height(), rect.left, rect.top);
836   m2.Concat(m1);
837   int32_t left, top;
838   CFX_DIBitmap* bmp2 = bmp1->FlipImage(FALSE, TRUE);
839   CFX_DIBitmap* bmp3 = bmp2->TransformTo((CFX_Matrix*)&m2, left, top);
840   CFX_RectF r;
841   GetClipRect(r);
842   FX_ERR result = FX_ERR_Indefinite;
843   {
844     CFX_DIBitmap* bitmap = _renderDevice->GetBitmap();
845     bitmap->CompositeBitmap(FXSYS_round(r.left), FXSYS_round(r.top),
846                             FXSYS_round(r.Width()), FXSYS_round(r.Height()),
847                             bmp3, FXSYS_round(r.left - left),
848                             FXSYS_round(r.top - top));
849     result = FX_ERR_Succeeded;
850   }
851   if (bmp3) {
852     delete bmp3;
853     bmp3 = NULL;
854   }
855   if (bmp2) {
856     delete bmp2;
857     bmp2 = NULL;
858   }
859   if (bmp1) {
860     delete bmp1;
861     bmp1 = NULL;
862   }
863   return result;
864 }
RenderDeviceShowText(const CFX_PointF & point,const CFX_WideString & text,CFX_Matrix * matrix)865 FX_ERR CFX_Graphics::RenderDeviceShowText(const CFX_PointF& point,
866                                           const CFX_WideString& text,
867                                           CFX_Matrix* matrix) {
868   int32_t length = text.GetLength();
869   FX_DWORD* charCodes = FX_Alloc(FX_DWORD, length);
870   FXTEXT_CHARPOS* charPos = FX_Alloc(FXTEXT_CHARPOS, length);
871   CFX_RectF rect;
872   rect.Set(point.x, point.y, 0, 0);
873   CalcTextInfo(text, charCodes, charPos, rect);
874   CFX_Matrix m;
875   m.Set(_info._CTM.a, _info._CTM.b, _info._CTM.c, _info._CTM.d, _info._CTM.e,
876         _info._CTM.f);
877   m.Translate(0, _info._fontSize * _info._fontHScale);
878   if (matrix) {
879     m.Concat(*matrix);
880   }
881   FX_BOOL result = _renderDevice->DrawNormalText(
882       length, charPos, _info._font, CFX_GEModule::Get()->GetFontCache(),
883       -_info._fontSize * _info._fontHScale, (CFX_Matrix*)&m,
884       _info._fillColor->_argb, FXTEXT_CLEARTYPE);
885   _FX_RETURN_VALUE_IF_FAIL(result, FX_ERR_Indefinite);
886   FX_Free(charPos);
887   FX_Free(charCodes);
888   return FX_ERR_Succeeded;
889 }
StrokePathWithPattern(CFX_Path * path,CFX_Matrix * matrix)890 FX_ERR CFX_Graphics::StrokePathWithPattern(CFX_Path* path, CFX_Matrix* matrix) {
891   return FX_ERR_Method_Not_Supported;
892 }
StrokePathWithShading(CFX_Path * path,CFX_Matrix * matrix)893 FX_ERR CFX_Graphics::StrokePathWithShading(CFX_Path* path, CFX_Matrix* matrix) {
894   return FX_ERR_Method_Not_Supported;
895 }
FillPathWithPattern(CFX_Path * path,FX_FillMode fillMode,CFX_Matrix * matrix)896 FX_ERR CFX_Graphics::FillPathWithPattern(CFX_Path* path,
897                                          FX_FillMode fillMode,
898                                          CFX_Matrix* matrix) {
899   CFX_Pattern* pattern = _info._fillColor->_pattern;
900   CFX_DIBitmap* bitmap = _renderDevice->GetBitmap();
901   int32_t width = bitmap->GetWidth();
902   int32_t height = bitmap->GetHeight();
903   CFX_DIBitmap bmp;
904   bmp.Create(width, height, FXDIB_Argb);
905   _renderDevice->GetDIBits(&bmp, 0, 0);
906   switch (pattern->_type) {
907     case FX_PATTERN_Bitmap: {
908       int32_t xStep = FXSYS_round(pattern->_x1Step);
909       int32_t yStep = FXSYS_round(pattern->_y1Step);
910       int32_t xCount = width / xStep + 1;
911       int32_t yCount = height / yStep + 1;
912       for (int32_t i = 0; i <= yCount; i++) {
913         for (int32_t j = 0; j <= xCount; j++) {
914           bmp.TransferBitmap(j * xStep, i * yStep, xStep, yStep,
915                              pattern->_bitmap, 0, 0);
916         }
917       }
918       break;
919     }
920     case FX_PATTERN_Hatch: {
921       FX_HatchStyle hatchStyle = _info._fillColor->_pattern->_hatchStyle;
922       if (hatchStyle < FX_HATCHSTYLE_Horizontal ||
923           hatchStyle > FX_HATCHSTYLE_SolidDiamond) {
924         return FX_ERR_Intermediate_Value_Invalid;
925       }
926       const FX_HATCHDATA& data = hatchBitmapData[hatchStyle];
927       CFX_DIBitmap mask;
928       mask.Create(data.width, data.height, FXDIB_1bppMask);
929       FXSYS_memcpy(mask.GetBuffer(), data.maskBits,
930                    mask.GetPitch() * data.height);
931       CFX_FloatRect rectf = path->GetPathData()->GetBoundingBox();
932       if (matrix) {
933         rectf.Transform((const CFX_Matrix*)matrix);
934       }
935       FX_RECT rect(FXSYS_round(rectf.left), FXSYS_round(rectf.top),
936                    FXSYS_round(rectf.right), FXSYS_round(rectf.bottom));
937       CFX_FxgeDevice device;
938       device.Attach(&bmp);
939       device.FillRect(&rect, _info._fillColor->_pattern->_backArgb);
940       for (int32_t j = rect.bottom; j < rect.top; j += mask.GetHeight()) {
941         for (int32_t i = rect.left; i < rect.right; i += mask.GetWidth()) {
942           device.SetBitMask(&mask, i, j, _info._fillColor->_pattern->_foreArgb);
943         }
944       }
945       break;
946     }
947   }
948   _renderDevice->SaveState();
949   _renderDevice->SetClip_PathFill(path->GetPathData(), (CFX_Matrix*)matrix,
950                                   fillMode);
951   SetDIBitsWithMatrix(&bmp, &pattern->_matrix);
952   _renderDevice->RestoreState();
953   return FX_ERR_Succeeded;
954 }
FillPathWithShading(CFX_Path * path,FX_FillMode fillMode,CFX_Matrix * matrix)955 FX_ERR CFX_Graphics::FillPathWithShading(CFX_Path* path,
956                                          FX_FillMode fillMode,
957                                          CFX_Matrix* matrix) {
958   CFX_DIBitmap* bitmap = _renderDevice->GetBitmap();
959   int32_t width = bitmap->GetWidth();
960   int32_t height = bitmap->GetHeight();
961   FX_FLOAT start_x = _info._fillColor->_shading->_beginPoint.x;
962   FX_FLOAT start_y = _info._fillColor->_shading->_beginPoint.y;
963   FX_FLOAT end_x = _info._fillColor->_shading->_endPoint.x;
964   FX_FLOAT end_y = _info._fillColor->_shading->_endPoint.y;
965   CFX_DIBitmap bmp;
966   bmp.Create(width, height, FXDIB_Argb);
967   _renderDevice->GetDIBits(&bmp, 0, 0);
968   int32_t pitch = bmp.GetPitch();
969   FX_BOOL result = FALSE;
970   switch (_info._fillColor->_shading->_type) {
971     case FX_SHADING_Axial: {
972       FX_FLOAT x_span = end_x - start_x;
973       FX_FLOAT y_span = end_y - start_y;
974       FX_FLOAT axis_len_square =
975           FXSYS_Mul(x_span, x_span) + FXSYS_Mul(y_span, y_span);
976       for (int32_t row = 0; row < height; row++) {
977         FX_DWORD* dib_buf = (FX_DWORD*)(bmp.GetBuffer() + row * pitch);
978         for (int32_t column = 0; column < width; column++) {
979           FX_FLOAT x = (FX_FLOAT)(column);
980           FX_FLOAT y = (FX_FLOAT)(row);
981           FX_FLOAT scale = FXSYS_Div(
982               FXSYS_Mul(x - start_x, x_span) + FXSYS_Mul(y - start_y, y_span),
983               axis_len_square);
984           if (scale < 0) {
985             if (!_info._fillColor->_shading->_isExtendedBegin) {
986               continue;
987             }
988             scale = 0;
989           } else if (scale > 1.0f) {
990             if (!_info._fillColor->_shading->_isExtendedEnd) {
991               continue;
992             }
993             scale = 1.0f;
994           }
995           int32_t index = (int32_t)(scale * (FX_SHADING_Steps - 1));
996           dib_buf[column] = _info._fillColor->_shading->_argbArray[index];
997         }
998       }
999       result = TRUE;
1000       break;
1001     }
1002     case FX_SHADING_Radial: {
1003       FX_FLOAT start_r = _info._fillColor->_shading->_beginRadius;
1004       FX_FLOAT end_r = _info._fillColor->_shading->_endRadius;
1005       FX_FLOAT a = FXSYS_Mul(start_x - end_x, start_x - end_x) +
1006                    FXSYS_Mul(start_y - end_y, start_y - end_y) -
1007                    FXSYS_Mul(start_r - end_r, start_r - end_r);
1008       for (int32_t row = 0; row < height; row++) {
1009         FX_DWORD* dib_buf = (FX_DWORD*)(bmp.GetBuffer() + row * pitch);
1010         for (int32_t column = 0; column < width; column++) {
1011           FX_FLOAT x = (FX_FLOAT)(column);
1012           FX_FLOAT y = (FX_FLOAT)(row);
1013           FX_FLOAT b = -2 * (FXSYS_Mul(x - start_x, end_x - start_x) +
1014                              FXSYS_Mul(y - start_y, end_y - start_y) +
1015                              FXSYS_Mul(start_r, end_r - start_r));
1016           FX_FLOAT c = FXSYS_Mul(x - start_x, x - start_x) +
1017                        FXSYS_Mul(y - start_y, y - start_y) -
1018                        FXSYS_Mul(start_r, start_r);
1019           FX_FLOAT s;
1020           if (a == 0) {
1021             s = (FXSYS_Div(-c, b));
1022           } else {
1023             FX_FLOAT b2_4ac = FXSYS_Mul(b, b) - 4 * FXSYS_Mul(a, c);
1024             if (b2_4ac < 0) {
1025               continue;
1026             }
1027             FX_FLOAT root = (FXSYS_sqrt(b2_4ac));
1028             FX_FLOAT s1, s2;
1029             if (a > 0) {
1030               s1 = FXSYS_Div(-b - root, 2 * a);
1031               s2 = FXSYS_Div(-b + root, 2 * a);
1032             } else {
1033               s2 = FXSYS_Div(-b - root, 2 * a);
1034               s1 = FXSYS_Div(-b + root, 2 * a);
1035             }
1036             if (s2 <= 1.0f || _info._fillColor->_shading->_isExtendedEnd) {
1037               s = (s2);
1038             } else {
1039               s = (s1);
1040             }
1041             if ((start_r) + s * (end_r - start_r) < 0) {
1042               continue;
1043             }
1044           }
1045           if (s < 0) {
1046             if (!_info._fillColor->_shading->_isExtendedBegin) {
1047               continue;
1048             }
1049             s = 0;
1050           }
1051           if (s > 1.0f) {
1052             if (!_info._fillColor->_shading->_isExtendedEnd) {
1053               continue;
1054             }
1055             s = 1.0f;
1056           }
1057           int index = (int32_t)(s * (FX_SHADING_Steps - 1));
1058           dib_buf[column] = _info._fillColor->_shading->_argbArray[index];
1059         }
1060       }
1061       result = TRUE;
1062       break;
1063     }
1064     default: { result = FALSE; }
1065   }
1066   if (result) {
1067     _renderDevice->SaveState();
1068     _renderDevice->SetClip_PathFill(path->GetPathData(), (CFX_Matrix*)matrix,
1069                                     fillMode);
1070     SetDIBitsWithMatrix(&bmp, matrix);
1071     _renderDevice->RestoreState();
1072   }
1073   return result;
1074 }
SetDIBitsWithMatrix(CFX_DIBSource * source,CFX_Matrix * matrix)1075 FX_ERR CFX_Graphics::SetDIBitsWithMatrix(CFX_DIBSource* source,
1076                                          CFX_Matrix* matrix) {
1077   if (matrix->IsIdentity()) {
1078     _renderDevice->SetDIBits(source, 0, 0);
1079   } else {
1080     CFX_Matrix m;
1081     m.Set((FX_FLOAT)source->GetWidth(), 0, 0, (FX_FLOAT)source->GetHeight(), 0,
1082           0);
1083     m.Concat(*matrix);
1084     int32_t left, top;
1085     CFX_DIBitmap* bmp1 = source->FlipImage(FALSE, TRUE);
1086     CFX_DIBitmap* bmp2 = bmp1->TransformTo((CFX_Matrix*)&m, left, top);
1087     _renderDevice->SetDIBits(bmp2, left, top);
1088     if (bmp2) {
1089       delete bmp2;
1090       bmp2 = NULL;
1091     }
1092     if (bmp1) {
1093       delete bmp1;
1094       bmp1 = NULL;
1095     }
1096   }
1097   return FX_ERR_Succeeded;
1098 }
CalcTextInfo(const CFX_WideString & text,FX_DWORD * charCodes,FXTEXT_CHARPOS * charPos,CFX_RectF & rect)1099 FX_ERR CFX_Graphics::CalcTextInfo(const CFX_WideString& text,
1100                                   FX_DWORD* charCodes,
1101                                   FXTEXT_CHARPOS* charPos,
1102                                   CFX_RectF& rect) {
1103   std::unique_ptr<CFX_UnicodeEncoding> encoding(
1104       new CFX_UnicodeEncoding(_info._font));
1105   int32_t length = text.GetLength();
1106   FX_FLOAT penX = (FX_FLOAT)rect.left;
1107   FX_FLOAT penY = (FX_FLOAT)rect.top;
1108   FX_FLOAT left = (FX_FLOAT)(0);
1109   FX_FLOAT top = (FX_FLOAT)(0);
1110   charCodes[0] = text.GetAt(0);
1111   charPos[0].m_OriginX = penX + left;
1112   charPos[0].m_OriginY = penY + top;
1113   charPos[0].m_GlyphIndex = encoding->GlyphFromCharCode(charCodes[0]);
1114   charPos[0].m_FontCharWidth = FXSYS_round(
1115       _info._font->GetGlyphWidth(charPos[0].m_GlyphIndex) * _info._fontHScale);
1116   charPos[0].m_bGlyphAdjust = TRUE;
1117   charPos[0].m_AdjustMatrix[0] = -1;
1118   charPos[0].m_AdjustMatrix[1] = 0;
1119   charPos[0].m_AdjustMatrix[2] = 0;
1120   charPos[0].m_AdjustMatrix[3] = 1;
1121   penX += (FX_FLOAT)(charPos[0].m_FontCharWidth) * _info._fontSize / 1000 +
1122           _info._fontSpacing;
1123   for (int32_t i = 1; i < length; i++) {
1124     charCodes[i] = text.GetAt(i);
1125     charPos[i].m_OriginX = penX + left;
1126     charPos[i].m_OriginY = penY + top;
1127     charPos[i].m_GlyphIndex = encoding->GlyphFromCharCode(charCodes[i]);
1128     charPos[i].m_FontCharWidth =
1129         FXSYS_round(_info._font->GetGlyphWidth(charPos[i].m_GlyphIndex) *
1130                     _info._fontHScale);
1131     charPos[i].m_bGlyphAdjust = TRUE;
1132     charPos[i].m_AdjustMatrix[0] = -1;
1133     charPos[i].m_AdjustMatrix[1] = 0;
1134     charPos[i].m_AdjustMatrix[2] = 0;
1135     charPos[i].m_AdjustMatrix[3] = 1;
1136     penX += (FX_FLOAT)(charPos[i].m_FontCharWidth) * _info._fontSize / 1000 +
1137             _info._fontSpacing;
1138   }
1139   rect.width = (FX_FLOAT)penX - rect.left;
1140   rect.height = rect.top + _info._fontSize * _info._fontHScale - rect.top;
1141   return FX_ERR_Succeeded;
1142 }
CAGG_Graphics()1143 CAGG_Graphics::CAGG_Graphics() {
1144   _owner = NULL;
1145 }
Create(CFX_Graphics * owner,int32_t width,int32_t height,FXDIB_Format format)1146 FX_ERR CAGG_Graphics::Create(CFX_Graphics* owner,
1147                              int32_t width,
1148                              int32_t height,
1149                              FXDIB_Format format) {
1150   if (owner->_renderDevice) {
1151     return FX_ERR_Parameter_Invalid;
1152   }
1153   if (_owner) {
1154     return FX_ERR_Property_Invalid;
1155   }
1156   CFX_FxgeDevice* device = new CFX_FxgeDevice;
1157   device->Create(width, height, format);
1158   _owner = owner;
1159   _owner->_renderDevice = device;
1160   _owner->_renderDevice->GetBitmap()->Clear(0xFFFFFFFF);
1161   return FX_ERR_Succeeded;
1162 }
~CAGG_Graphics()1163 CAGG_Graphics::~CAGG_Graphics() {
1164   if (_owner->_renderDevice) {
1165     delete (CFX_FxgeDevice*)_owner->_renderDevice;
1166   }
1167   _owner = NULL;
1168 }
CFX_Path()1169 CFX_Path::CFX_Path() {
1170   _generator = NULL;
1171 }
Create()1172 FX_ERR CFX_Path::Create() {
1173   if (_generator) {
1174     return FX_ERR_Property_Invalid;
1175   }
1176   _generator = new CFX_PathGenerator;
1177   _generator->Create();
1178   return FX_ERR_Succeeded;
1179 }
~CFX_Path()1180 CFX_Path::~CFX_Path() {
1181   if (_generator) {
1182     delete _generator;
1183     _generator = NULL;
1184   }
1185 }
MoveTo(FX_FLOAT x,FX_FLOAT y)1186 FX_ERR CFX_Path::MoveTo(FX_FLOAT x, FX_FLOAT y) {
1187   _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid);
1188   _generator->MoveTo(x, y);
1189   return FX_ERR_Succeeded;
1190 }
LineTo(FX_FLOAT x,FX_FLOAT y)1191 FX_ERR CFX_Path::LineTo(FX_FLOAT x, FX_FLOAT y) {
1192   _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid);
1193   _generator->LineTo(x, y);
1194   return FX_ERR_Succeeded;
1195 }
BezierTo(FX_FLOAT ctrlX1,FX_FLOAT ctrlY1,FX_FLOAT ctrlX2,FX_FLOAT ctrlY2,FX_FLOAT toX,FX_FLOAT toY)1196 FX_ERR CFX_Path::BezierTo(FX_FLOAT ctrlX1,
1197                           FX_FLOAT ctrlY1,
1198                           FX_FLOAT ctrlX2,
1199                           FX_FLOAT ctrlY2,
1200                           FX_FLOAT toX,
1201                           FX_FLOAT toY) {
1202   _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid);
1203   _generator->BezierTo(ctrlX1, ctrlY1, ctrlX2, ctrlY2, toX, toY);
1204   return FX_ERR_Succeeded;
1205 }
ArcTo(FX_FLOAT left,FX_FLOAT top,FX_FLOAT width,FX_FLOAT height,FX_FLOAT startAngle,FX_FLOAT sweepAngle)1206 FX_ERR CFX_Path::ArcTo(FX_FLOAT left,
1207                        FX_FLOAT top,
1208                        FX_FLOAT width,
1209                        FX_FLOAT height,
1210                        FX_FLOAT startAngle,
1211                        FX_FLOAT sweepAngle) {
1212   _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid);
1213   _generator->ArcTo(left + width / 2, top + height / 2, width / 2, height / 2,
1214                     startAngle, sweepAngle);
1215   return FX_ERR_Succeeded;
1216 }
Close()1217 FX_ERR CFX_Path::Close() {
1218   _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid);
1219   _generator->Close();
1220   return FX_ERR_Succeeded;
1221 }
AddLine(FX_FLOAT x1,FX_FLOAT y1,FX_FLOAT x2,FX_FLOAT y2)1222 FX_ERR CFX_Path::AddLine(FX_FLOAT x1, FX_FLOAT y1, FX_FLOAT x2, FX_FLOAT y2) {
1223   _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid);
1224   _generator->AddLine(x1, y1, x2, y2);
1225   return FX_ERR_Succeeded;
1226 }
AddBezier(FX_FLOAT startX,FX_FLOAT startY,FX_FLOAT ctrlX1,FX_FLOAT ctrlY1,FX_FLOAT ctrlX2,FX_FLOAT ctrlY2,FX_FLOAT endX,FX_FLOAT endY)1227 FX_ERR CFX_Path::AddBezier(FX_FLOAT startX,
1228                            FX_FLOAT startY,
1229                            FX_FLOAT ctrlX1,
1230                            FX_FLOAT ctrlY1,
1231                            FX_FLOAT ctrlX2,
1232                            FX_FLOAT ctrlY2,
1233                            FX_FLOAT endX,
1234                            FX_FLOAT endY) {
1235   _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid);
1236   _generator->AddBezier(startX, startY, ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX,
1237                         endY);
1238   return FX_ERR_Succeeded;
1239 }
AddRectangle(FX_FLOAT left,FX_FLOAT top,FX_FLOAT width,FX_FLOAT height)1240 FX_ERR CFX_Path::AddRectangle(FX_FLOAT left,
1241                               FX_FLOAT top,
1242                               FX_FLOAT width,
1243                               FX_FLOAT height) {
1244   _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid);
1245   _generator->AddRectangle(left, top, left + width, top + height);
1246   return FX_ERR_Succeeded;
1247 }
AddEllipse(FX_FLOAT left,FX_FLOAT top,FX_FLOAT width,FX_FLOAT height)1248 FX_ERR CFX_Path::AddEllipse(FX_FLOAT left,
1249                             FX_FLOAT top,
1250                             FX_FLOAT width,
1251                             FX_FLOAT height) {
1252   _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid);
1253   _generator->AddEllipse(left + width / 2, top + height / 2, width / 2,
1254                          height / 2);
1255   return FX_ERR_Succeeded;
1256 }
AddEllipse(const CFX_RectF & rect)1257 FX_ERR CFX_Path::AddEllipse(const CFX_RectF& rect) {
1258   _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid);
1259   _generator->AddEllipse(rect.left + rect.Width() / 2,
1260                          rect.top + rect.Height() / 2, rect.Width() / 2,
1261                          rect.Height() / 2);
1262   return FX_ERR_Succeeded;
1263 }
AddArc(FX_FLOAT left,FX_FLOAT top,FX_FLOAT width,FX_FLOAT height,FX_FLOAT startAngle,FX_FLOAT sweepAngle)1264 FX_ERR CFX_Path::AddArc(FX_FLOAT left,
1265                         FX_FLOAT top,
1266                         FX_FLOAT width,
1267                         FX_FLOAT height,
1268                         FX_FLOAT startAngle,
1269                         FX_FLOAT sweepAngle) {
1270   _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid);
1271   _generator->AddArc(left + width / 2, top + height / 2, width / 2, height / 2,
1272                      startAngle, sweepAngle);
1273   return FX_ERR_Succeeded;
1274 }
AddPie(FX_FLOAT left,FX_FLOAT top,FX_FLOAT width,FX_FLOAT height,FX_FLOAT startAngle,FX_FLOAT sweepAngle)1275 FX_ERR CFX_Path::AddPie(FX_FLOAT left,
1276                         FX_FLOAT top,
1277                         FX_FLOAT width,
1278                         FX_FLOAT height,
1279                         FX_FLOAT startAngle,
1280                         FX_FLOAT sweepAngle) {
1281   _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid);
1282   _generator->AddPie(left + width / 2, top + height / 2, width / 2, height / 2,
1283                      startAngle, sweepAngle);
1284   return FX_ERR_Succeeded;
1285 }
AddSubpath(CFX_Path * path)1286 FX_ERR CFX_Path::AddSubpath(CFX_Path* path) {
1287   _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid);
1288   _generator->AddPathData(path->GetPathData());
1289   return FX_ERR_Succeeded;
1290 }
Clear()1291 FX_ERR CFX_Path::Clear() {
1292   _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid);
1293   _generator->GetPathData()->SetPointCount(0);
1294   return FX_ERR_Succeeded;
1295 }
IsEmpty()1296 FX_BOOL CFX_Path::IsEmpty() {
1297   _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid);
1298   if (_generator->GetPathData()->GetPointCount() == 0) {
1299     return TRUE;
1300   }
1301   return FALSE;
1302 }
GetPathData()1303 CFX_PathData* CFX_Path::GetPathData() {
1304   _FX_RETURN_VALUE_IF_FAIL(_generator, NULL);
1305   return _generator->GetPathData();
1306 }
CFX_Color()1307 CFX_Color::CFX_Color() {
1308   _type = FX_COLOR_None;
1309 }
CFX_Color(const FX_ARGB argb)1310 CFX_Color::CFX_Color(const FX_ARGB argb) {
1311   _type = FX_COLOR_None;
1312   Set(argb);
1313 }
CFX_Color(CFX_Pattern * pattern,const FX_ARGB argb)1314 CFX_Color::CFX_Color(CFX_Pattern* pattern, const FX_ARGB argb) {
1315   _type = FX_COLOR_None;
1316   Set(pattern, argb);
1317 }
CFX_Color(CFX_Shading * shading)1318 CFX_Color::CFX_Color(CFX_Shading* shading) {
1319   _type = FX_COLOR_None;
1320   Set(shading);
1321 }
~CFX_Color()1322 CFX_Color::~CFX_Color() {
1323   _type = FX_COLOR_None;
1324 }
Set(const FX_ARGB argb)1325 FX_ERR CFX_Color::Set(const FX_ARGB argb) {
1326   _type = FX_COLOR_Solid;
1327   _argb = argb;
1328   _pattern = NULL;
1329   return FX_ERR_Succeeded;
1330 }
Set(CFX_Pattern * pattern,const FX_ARGB argb)1331 FX_ERR CFX_Color::Set(CFX_Pattern* pattern, const FX_ARGB argb) {
1332   _FX_RETURN_VALUE_IF_FAIL(pattern, FX_ERR_Parameter_Invalid);
1333   _type = FX_COLOR_Pattern;
1334   _argb = argb;
1335   _pattern = pattern;
1336   return FX_ERR_Succeeded;
1337 }
Set(CFX_Shading * shading)1338 FX_ERR CFX_Color::Set(CFX_Shading* shading) {
1339   _FX_RETURN_VALUE_IF_FAIL(shading, FX_ERR_Parameter_Invalid);
1340   _type = FX_COLOR_Shading;
1341   _shading = shading;
1342   return FX_ERR_Succeeded;
1343 }
CFX_Pattern()1344 CFX_Pattern::CFX_Pattern() {
1345   _type = FX_PATTERN_None;
1346   _matrix.SetIdentity();
1347 }
Create(CFX_DIBitmap * bitmap,const FX_FLOAT xStep,const FX_FLOAT yStep,CFX_Matrix * matrix)1348 FX_ERR CFX_Pattern::Create(CFX_DIBitmap* bitmap,
1349                            const FX_FLOAT xStep,
1350                            const FX_FLOAT yStep,
1351                            CFX_Matrix* matrix) {
1352   _FX_RETURN_VALUE_IF_FAIL(bitmap, FX_ERR_Parameter_Invalid);
1353   if (_type != FX_PATTERN_None) {
1354     return FX_ERR_Property_Invalid;
1355   }
1356   _type = FX_PATTERN_Bitmap;
1357   _bitmap = bitmap;
1358   _x1Step = xStep;
1359   _y1Step = yStep;
1360   if (matrix) {
1361     _matrix.Set(matrix->a, matrix->b, matrix->c, matrix->d, matrix->e,
1362                 matrix->f);
1363   }
1364   return FX_ERR_Succeeded;
1365 }
Create(FX_HatchStyle hatchStyle,const FX_ARGB foreArgb,const FX_ARGB backArgb,CFX_Matrix * matrix)1366 FX_ERR CFX_Pattern::Create(FX_HatchStyle hatchStyle,
1367                            const FX_ARGB foreArgb,
1368                            const FX_ARGB backArgb,
1369                            CFX_Matrix* matrix) {
1370   if (hatchStyle < FX_HATCHSTYLE_Horizontal ||
1371       hatchStyle > FX_HATCHSTYLE_SolidDiamond) {
1372     return FX_ERR_Parameter_Invalid;
1373   }
1374   if (_type != FX_PATTERN_None) {
1375     return FX_ERR_Property_Invalid;
1376   }
1377   _type = FX_PATTERN_Hatch;
1378   _hatchStyle = hatchStyle;
1379   _foreArgb = foreArgb;
1380   _backArgb = backArgb;
1381   if (matrix) {
1382     _matrix.Set(matrix->a, matrix->b, matrix->c, matrix->d, matrix->e,
1383                 matrix->f);
1384   }
1385   return FX_ERR_Succeeded;
1386 }
~CFX_Pattern()1387 CFX_Pattern::~CFX_Pattern() {
1388   _type = FX_PATTERN_None;
1389 }
CFX_Shading()1390 CFX_Shading::CFX_Shading() {
1391   _type = FX_SHADING_None;
1392 }
CreateAxial(const CFX_PointF & beginPoint,const CFX_PointF & endPoint,FX_BOOL isExtendedBegin,FX_BOOL isExtendedEnd,const FX_ARGB beginArgb,const FX_ARGB endArgb)1393 FX_ERR CFX_Shading::CreateAxial(const CFX_PointF& beginPoint,
1394                                 const CFX_PointF& endPoint,
1395                                 FX_BOOL isExtendedBegin,
1396                                 FX_BOOL isExtendedEnd,
1397                                 const FX_ARGB beginArgb,
1398                                 const FX_ARGB endArgb) {
1399   if (_type != FX_SHADING_None) {
1400     return FX_ERR_Property_Invalid;
1401   }
1402   _type = FX_SHADING_Axial;
1403   _beginPoint = beginPoint;
1404   _endPoint = endPoint;
1405   _isExtendedBegin = isExtendedBegin;
1406   _isExtendedEnd = isExtendedEnd;
1407   _beginArgb = beginArgb;
1408   _endArgb = endArgb;
1409   return InitArgbArray();
1410 }
CreateRadial(const CFX_PointF & beginPoint,const CFX_PointF & endPoint,const FX_FLOAT beginRadius,const FX_FLOAT endRadius,FX_BOOL isExtendedBegin,FX_BOOL isExtendedEnd,const FX_ARGB beginArgb,const FX_ARGB endArgb)1411 FX_ERR CFX_Shading::CreateRadial(const CFX_PointF& beginPoint,
1412                                  const CFX_PointF& endPoint,
1413                                  const FX_FLOAT beginRadius,
1414                                  const FX_FLOAT endRadius,
1415                                  FX_BOOL isExtendedBegin,
1416                                  FX_BOOL isExtendedEnd,
1417                                  const FX_ARGB beginArgb,
1418                                  const FX_ARGB endArgb) {
1419   if (_type != FX_SHADING_None) {
1420     return FX_ERR_Property_Invalid;
1421   }
1422   _type = FX_SHADING_Radial;
1423   _beginPoint = beginPoint;
1424   _endPoint = endPoint;
1425   _beginRadius = beginRadius;
1426   _endRadius = endRadius;
1427   _isExtendedBegin = isExtendedBegin;
1428   _isExtendedEnd = isExtendedEnd;
1429   _beginArgb = beginArgb;
1430   _endArgb = endArgb;
1431   return InitArgbArray();
1432 }
~CFX_Shading()1433 CFX_Shading::~CFX_Shading() {
1434   _type = FX_SHADING_None;
1435 }
InitArgbArray()1436 FX_ERR CFX_Shading::InitArgbArray() {
1437   int32_t a1, r1, g1, b1;
1438   ArgbDecode(_beginArgb, a1, r1, g1, b1);
1439   int32_t a2, r2, g2, b2;
1440   ArgbDecode(_endArgb, a2, r2, g2, b2);
1441   FX_FLOAT f = (FX_FLOAT)(FX_SHADING_Steps - 1);
1442   FX_FLOAT aScale = (FX_FLOAT)(1.0 * (a2 - a1) / f);
1443   FX_FLOAT rScale = (FX_FLOAT)(1.0 * (r2 - r1) / f);
1444   FX_FLOAT gScale = (FX_FLOAT)(1.0 * (g2 - g1) / f);
1445   FX_FLOAT bScale = (FX_FLOAT)(1.0 * (b2 - b1) / f);
1446   int32_t a3, r3, g3, b3;
1447   for (int32_t i = 0; i < FX_SHADING_Steps; i++) {
1448     a3 = (int32_t)(i * aScale);
1449     r3 = (int32_t)(i * rScale);
1450     g3 = (int32_t)(i * gScale);
1451     b3 = (int32_t)(i * bScale);
1452     _argbArray[i] =
1453         FXARGB_TODIB(FXARGB_MAKE((a1 + a3), (r1 + r3), (g1 + g3), (b1 + b3)));
1454   }
1455   return FX_ERR_Succeeded;
1456 }
1457 class CFX_Pause : public IFX_Pause {
1458  public:
NeedToPauseNow()1459   virtual FX_BOOL NeedToPauseNow() { return TRUE; }
1460 };
1461