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