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