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