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 "core/fxge/agg/fx_agg_driver.h"
8
9 #include <algorithm>
10 #include <utility>
11
12 #include "core/fxge/cfx_cliprgn.h"
13 #include "core/fxge/cfx_defaultrenderdevice.h"
14 #include "core/fxge/cfx_graphstatedata.h"
15 #include "core/fxge/cfx_pathdata.h"
16 #include "core/fxge/dib/cfx_imagerenderer.h"
17 #include "core/fxge/dib/cfx_imagestretcher.h"
18 #include "third_party/agg23/agg_conv_dash.h"
19 #include "third_party/agg23/agg_conv_stroke.h"
20 #include "third_party/agg23/agg_curves.h"
21 #include "third_party/agg23/agg_path_storage.h"
22 #include "third_party/agg23/agg_pixfmt_gray.h"
23 #include "third_party/agg23/agg_rasterizer_scanline_aa.h"
24 #include "third_party/agg23/agg_renderer_scanline.h"
25 #include "third_party/agg23/agg_scanline_u.h"
26 #include "third_party/base/ptr_util.h"
27 #include "third_party/base/stl_util.h"
28
29 namespace {
30
31 const float kMaxPos = 32000.0f;
32
HardClip(const CFX_PointF & pos)33 CFX_PointF HardClip(const CFX_PointF& pos) {
34 return CFX_PointF(pdfium::clamp(pos.x, -kMaxPos, kMaxPos),
35 pdfium::clamp(pos.y, -kMaxPos, kMaxPos));
36 }
37
RgbByteOrderSetPixel(const RetainPtr<CFX_DIBitmap> & pBitmap,int x,int y,uint32_t argb)38 void RgbByteOrderSetPixel(const RetainPtr<CFX_DIBitmap>& pBitmap,
39 int x,
40 int y,
41 uint32_t argb) {
42 if (x < 0 || x >= pBitmap->GetWidth() || y < 0 || y >= pBitmap->GetHeight())
43 return;
44
45 uint8_t* pos = pBitmap->GetBuffer() + y * pBitmap->GetPitch() +
46 x * pBitmap->GetBPP() / 8;
47 if (pBitmap->GetFormat() == FXDIB_Argb) {
48 FXARGB_SETRGBORDERDIB(pos, argb);
49 return;
50 }
51
52 int alpha = FXARGB_A(argb);
53 pos[0] = (FXARGB_R(argb) * alpha + pos[0] * (255 - alpha)) / 255;
54 pos[1] = (FXARGB_G(argb) * alpha + pos[1] * (255 - alpha)) / 255;
55 pos[2] = (FXARGB_B(argb) * alpha + pos[2] * (255 - alpha)) / 255;
56 }
57
RgbByteOrderCompositeRect(const RetainPtr<CFX_DIBitmap> & pBitmap,int left,int top,int width,int height,FX_ARGB argb)58 void RgbByteOrderCompositeRect(const RetainPtr<CFX_DIBitmap>& pBitmap,
59 int left,
60 int top,
61 int width,
62 int height,
63 FX_ARGB argb) {
64 int src_alpha = FXARGB_A(argb);
65 if (src_alpha == 0)
66 return;
67
68 FX_RECT rect(left, top, left + width, top + height);
69 rect.Intersect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight());
70 width = rect.Width();
71 int src_r = FXARGB_R(argb);
72 int src_g = FXARGB_G(argb);
73 int src_b = FXARGB_B(argb);
74 int Bpp = pBitmap->GetBPP() / 8;
75 int dib_argb = FXARGB_TOBGRORDERDIB(argb);
76 uint8_t* pBuffer = pBitmap->GetBuffer();
77 if (src_alpha == 255) {
78 for (int row = rect.top; row < rect.bottom; row++) {
79 uint8_t* dest_scan =
80 pBuffer + row * pBitmap->GetPitch() + rect.left * Bpp;
81 if (Bpp == 4) {
82 uint32_t* scan = reinterpret_cast<uint32_t*>(dest_scan);
83 for (int col = 0; col < width; col++)
84 *scan++ = dib_argb;
85 } else {
86 for (int col = 0; col < width; col++) {
87 *dest_scan++ = src_r;
88 *dest_scan++ = src_g;
89 *dest_scan++ = src_b;
90 }
91 }
92 }
93 return;
94 }
95 bool bAlpha = pBitmap->HasAlpha();
96 for (int row = rect.top; row < rect.bottom; row++) {
97 uint8_t* dest_scan = pBuffer + row * pBitmap->GetPitch() + rect.left * Bpp;
98 if (bAlpha) {
99 for (int col = 0; col < width; col++) {
100 uint8_t back_alpha = dest_scan[3];
101 if (back_alpha == 0) {
102 FXARGB_SETRGBORDERDIB(dest_scan,
103 FXARGB_MAKE(src_alpha, src_r, src_g, src_b));
104 dest_scan += 4;
105 continue;
106 }
107 uint8_t dest_alpha =
108 back_alpha + src_alpha - back_alpha * src_alpha / 255;
109 dest_scan[3] = dest_alpha;
110 int alpha_ratio = src_alpha * 255 / dest_alpha;
111 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
112 dest_scan++;
113 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
114 dest_scan++;
115 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
116 dest_scan += 2;
117 }
118 continue;
119 }
120 for (int col = 0; col < width; col++) {
121 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha);
122 dest_scan++;
123 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha);
124 dest_scan++;
125 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha);
126 dest_scan++;
127 if (Bpp == 4)
128 dest_scan++;
129 }
130 }
131 }
132
RgbByteOrderTransferBitmap(const RetainPtr<CFX_DIBitmap> & pBitmap,int dest_left,int dest_top,int width,int height,const RetainPtr<CFX_DIBSource> & pSrcBitmap,int src_left,int src_top)133 void RgbByteOrderTransferBitmap(const RetainPtr<CFX_DIBitmap>& pBitmap,
134 int dest_left,
135 int dest_top,
136 int width,
137 int height,
138 const RetainPtr<CFX_DIBSource>& pSrcBitmap,
139 int src_left,
140 int src_top) {
141 if (!pBitmap)
142 return;
143
144 pBitmap->GetOverlapRect(dest_left, dest_top, width, height,
145 pSrcBitmap->GetWidth(), pSrcBitmap->GetHeight(),
146 src_left, src_top, nullptr);
147 if (width == 0 || height == 0)
148 return;
149
150 int Bpp = pBitmap->GetBPP() / 8;
151 FXDIB_Format dest_format = pBitmap->GetFormat();
152 FXDIB_Format src_format = pSrcBitmap->GetFormat();
153 int pitch = pBitmap->GetPitch();
154 uint8_t* buffer = pBitmap->GetBuffer();
155 if (dest_format == src_format) {
156 for (int row = 0; row < height; row++) {
157 uint8_t* dest_scan = buffer + (dest_top + row) * pitch + dest_left * Bpp;
158 uint8_t* src_scan =
159 const_cast<uint8_t*>(pSrcBitmap->GetScanline(src_top + row)) +
160 src_left * Bpp;
161 if (Bpp == 4) {
162 for (int col = 0; col < width; col++) {
163 FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_scan[3], src_scan[0],
164 src_scan[1], src_scan[2]));
165 dest_scan += 4;
166 src_scan += 4;
167 }
168 continue;
169 }
170 for (int col = 0; col < width; col++) {
171 *dest_scan++ = src_scan[2];
172 *dest_scan++ = src_scan[1];
173 *dest_scan++ = src_scan[0];
174 src_scan += 3;
175 }
176 }
177 return;
178 }
179
180 uint8_t* dest_buf = buffer + dest_top * pitch + dest_left * Bpp;
181 if (dest_format == FXDIB_Rgb) {
182 ASSERT(src_format == FXDIB_Rgb32);
183 for (int row = 0; row < height; row++) {
184 uint8_t* dest_scan = dest_buf + row * pitch;
185 uint8_t* src_scan =
186 const_cast<uint8_t*>(pSrcBitmap->GetScanline(src_top + row)) +
187 src_left * 4;
188 for (int col = 0; col < width; col++) {
189 *dest_scan++ = src_scan[2];
190 *dest_scan++ = src_scan[1];
191 *dest_scan++ = src_scan[0];
192 src_scan += 4;
193 }
194 }
195 return;
196 }
197
198 ASSERT(dest_format == FXDIB_Argb || dest_format == FXDIB_Rgb32);
199 if (src_format == FXDIB_Rgb) {
200 for (int row = 0; row < height; row++) {
201 uint8_t* dest_scan = dest_buf + row * pitch;
202 uint8_t* src_scan =
203 const_cast<uint8_t*>(pSrcBitmap->GetScanline(src_top + row)) +
204 src_left * 3;
205 for (int col = 0; col < width; col++) {
206 FXARGB_SETDIB(dest_scan,
207 FXARGB_MAKE(0xff, src_scan[0], src_scan[1], src_scan[2]));
208 dest_scan += 4;
209 src_scan += 3;
210 }
211 }
212 return;
213 }
214 if (src_format != FXDIB_Rgb32)
215 return;
216 ASSERT(dest_format == FXDIB_Argb);
217 for (int row = 0; row < height; row++) {
218 uint8_t* dest_scan = dest_buf + row * pitch;
219 uint8_t* src_scan =
220 const_cast<uint8_t*>(pSrcBitmap->GetScanline(src_top + row)) +
221 src_left * 4;
222 for (int col = 0; col < width; col++) {
223 FXARGB_SETDIB(dest_scan,
224 FXARGB_MAKE(0xff, src_scan[0], src_scan[1], src_scan[2]));
225 src_scan += 4;
226 dest_scan += 4;
227 }
228 }
229 }
230
DibSetPixel(const RetainPtr<CFX_DIBitmap> & pDevice,int x,int y,uint32_t color)231 bool DibSetPixel(const RetainPtr<CFX_DIBitmap>& pDevice,
232 int x,
233 int y,
234 uint32_t color) {
235 int alpha = FXARGB_A(color);
236 if (pDevice->IsCmykImage())
237 return false;
238
239 pDevice->SetPixel(x, y, color);
240 if (pDevice->m_pAlphaMask)
241 pDevice->m_pAlphaMask->SetPixel(x, y, alpha << 24);
242 return true;
243 }
244
RasterizeStroke(agg::rasterizer_scanline_aa * rasterizer,agg::path_storage * path_data,const CFX_Matrix * pObject2Device,const CFX_GraphStateData * pGraphState,float scale,bool bStrokeAdjust,bool bTextMode)245 void RasterizeStroke(agg::rasterizer_scanline_aa* rasterizer,
246 agg::path_storage* path_data,
247 const CFX_Matrix* pObject2Device,
248 const CFX_GraphStateData* pGraphState,
249 float scale,
250 bool bStrokeAdjust,
251 bool bTextMode) {
252 agg::line_cap_e cap;
253 switch (pGraphState->m_LineCap) {
254 case CFX_GraphStateData::LineCapRound:
255 cap = agg::round_cap;
256 break;
257 case CFX_GraphStateData::LineCapSquare:
258 cap = agg::square_cap;
259 break;
260 default:
261 cap = agg::butt_cap;
262 break;
263 }
264 agg::line_join_e join;
265 switch (pGraphState->m_LineJoin) {
266 case CFX_GraphStateData::LineJoinRound:
267 join = agg::round_join;
268 break;
269 case CFX_GraphStateData::LineJoinBevel:
270 join = agg::bevel_join;
271 break;
272 default:
273 join = agg::miter_join_revert;
274 break;
275 }
276 float width = pGraphState->m_LineWidth * scale;
277 float unit = 1.0f;
278 if (pObject2Device) {
279 unit =
280 1.0f / ((pObject2Device->GetXUnit() + pObject2Device->GetYUnit()) / 2);
281 }
282 width = std::max(width, unit);
283 if (pGraphState->m_DashArray) {
284 typedef agg::conv_dash<agg::path_storage> dash_converter;
285 dash_converter dash(*path_data);
286 for (int i = 0; i < (pGraphState->m_DashCount + 1) / 2; i++) {
287 float on = pGraphState->m_DashArray[i * 2];
288 if (on <= 0.000001f)
289 on = 1.0f / 10;
290 float off = i * 2 + 1 == pGraphState->m_DashCount
291 ? on
292 : pGraphState->m_DashArray[i * 2 + 1];
293 off = std::max(off, 0.0f);
294 dash.add_dash(on * scale, off * scale);
295 }
296 dash.dash_start(pGraphState->m_DashPhase * scale);
297 typedef agg::conv_stroke<dash_converter> dash_stroke;
298 dash_stroke stroke(dash);
299 stroke.line_join(join);
300 stroke.line_cap(cap);
301 stroke.miter_limit(pGraphState->m_MiterLimit);
302 stroke.width(width);
303 rasterizer->add_path_transformed(stroke, pObject2Device);
304 return;
305 }
306 agg::conv_stroke<agg::path_storage> stroke(*path_data);
307 stroke.line_join(join);
308 stroke.line_cap(cap);
309 stroke.miter_limit(pGraphState->m_MiterLimit);
310 stroke.width(width);
311 rasterizer->add_path_transformed(stroke, pObject2Device);
312 }
313
314 class CFX_Renderer {
315 public:
316 // Needed for agg caller
prepare(unsigned)317 void prepare(unsigned) {}
318
319 void CompositeSpan(uint8_t* dest_scan,
320 uint8_t* ori_scan,
321 int Bpp,
322 bool bDestAlpha,
323 int span_left,
324 int span_len,
325 uint8_t* cover_scan,
326 int clip_left,
327 int clip_right,
328 uint8_t* clip_scan);
329
330 void CompositeSpan1bpp(uint8_t* dest_scan,
331 int Bpp,
332 int span_left,
333 int span_len,
334 uint8_t* cover_scan,
335 int clip_left,
336 int clip_right,
337 uint8_t* clip_scan,
338 uint8_t* dest_extra_alpha_scan);
339
340 void CompositeSpanGray(uint8_t* dest_scan,
341 int Bpp,
342 int span_left,
343 int span_len,
344 uint8_t* cover_scan,
345 int clip_left,
346 int clip_right,
347 uint8_t* clip_scan,
348 uint8_t* dest_extra_alpha_scan);
349
350 void CompositeSpanARGB(uint8_t* dest_scan,
351 int Bpp,
352 int span_left,
353 int span_len,
354 uint8_t* cover_scan,
355 int clip_left,
356 int clip_right,
357 uint8_t* clip_scan,
358 uint8_t* dest_extra_alpha_scan);
359
360 void CompositeSpanRGB(uint8_t* dest_scan,
361 int Bpp,
362 int span_left,
363 int span_len,
364 uint8_t* cover_scan,
365 int clip_left,
366 int clip_right,
367 uint8_t* clip_scan,
368 uint8_t* dest_extra_alpha_scan);
369
370 void CompositeSpanCMYK(uint8_t* dest_scan,
371 int Bpp,
372 int span_left,
373 int span_len,
374 uint8_t* cover_scan,
375 int clip_left,
376 int clip_right,
377 uint8_t* clip_scan,
378 uint8_t* dest_extra_alpha_scan);
379
380 bool Init(const RetainPtr<CFX_DIBitmap>& pDevice,
381 const RetainPtr<CFX_DIBitmap>& pOriDevice,
382 const CFX_ClipRgn* pClipRgn,
383 uint32_t color,
384 bool bFullCover,
385 bool bRgbByteOrder);
386
387 template <class Scanline>
388 void render(const Scanline& sl);
389
390 private:
391 void (CFX_Renderer::*composite_span)(uint8_t*,
392 int,
393 int,
394 int,
395 uint8_t*,
396 int,
397 int,
398 uint8_t*,
399 uint8_t*);
400
401 void CompositeSpan1bppHelper(uint8_t* dest_scan,
402 int col_start,
403 int col_end,
404 const uint8_t* cover_scan,
405 const uint8_t* clip_scan,
406 int span_left);
407
GetSrcAlpha(const uint8_t * clip_scan,int col) const408 inline int GetSrcAlpha(const uint8_t* clip_scan, int col) const {
409 return clip_scan ? m_Alpha * clip_scan[col] / 255 : m_Alpha;
410 }
411
GetSourceAlpha(const uint8_t * cover_scan,const uint8_t * clip_scan,int col) const412 inline int GetSourceAlpha(const uint8_t* cover_scan,
413 const uint8_t* clip_scan,
414 int col) const {
415 return clip_scan ? m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255
416 : m_Alpha * cover_scan[col] / 255;
417 }
418
GetColStart(int span_left,int clip_left) const419 inline int GetColStart(int span_left, int clip_left) const {
420 return span_left < clip_left ? clip_left - span_left : 0;
421 }
422
GetColEnd(int span_left,int span_len,int clip_right) const423 inline int GetColEnd(int span_left, int span_len, int clip_right) const {
424 return span_left + span_len < clip_right ? span_len
425 : clip_right - span_left;
426 }
427
428 int m_Alpha;
429 int m_Red;
430 int m_Green;
431 int m_Blue;
432 int m_Gray;
433 uint32_t m_Color;
434 bool m_bFullCover;
435 bool m_bRgbByteOrder;
436 FX_RECT m_ClipBox;
437 RetainPtr<CFX_DIBitmap> m_pOriDevice;
438 RetainPtr<CFX_DIBitmap> m_pClipMask;
439 RetainPtr<CFX_DIBitmap> m_pDevice;
440 UnownedPtr<const CFX_ClipRgn> m_pClipRgn;
441 };
442
CompositeSpan(uint8_t * dest_scan,uint8_t * ori_scan,int Bpp,bool bDestAlpha,int span_left,int span_len,uint8_t * cover_scan,int clip_left,int clip_right,uint8_t * clip_scan)443 void CFX_Renderer::CompositeSpan(uint8_t* dest_scan,
444 uint8_t* ori_scan,
445 int Bpp,
446 bool bDestAlpha,
447 int span_left,
448 int span_len,
449 uint8_t* cover_scan,
450 int clip_left,
451 int clip_right,
452 uint8_t* clip_scan) {
453 ASSERT(!m_pDevice->IsCmykImage());
454 int col_start = GetColStart(span_left, clip_left);
455 int col_end = GetColEnd(span_left, span_len, clip_right);
456 if (Bpp) {
457 dest_scan += col_start * Bpp;
458 ori_scan += col_start * Bpp;
459 } else {
460 dest_scan += col_start / 8;
461 ori_scan += col_start / 8;
462 }
463 if (m_bRgbByteOrder) {
464 if (Bpp == 4 && bDestAlpha) {
465 for (int col = col_start; col < col_end; col++) {
466 int src_alpha = GetSrcAlpha(clip_scan, col);
467 uint8_t dest_alpha =
468 ori_scan[3] + src_alpha - ori_scan[3] * src_alpha / 255;
469 dest_scan[3] = dest_alpha;
470 int alpha_ratio = src_alpha * 255 / dest_alpha;
471 if (m_bFullCover) {
472 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio);
473 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio);
474 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio);
475 dest_scan++;
476 ori_scan++;
477 } else {
478 int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio);
479 int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio);
480 int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio);
481 ori_scan++;
482 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]);
483 dest_scan++;
484 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]);
485 dest_scan++;
486 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]);
487 dest_scan += 2;
488 }
489 }
490 return;
491 }
492 if (Bpp == 3 || Bpp == 4) {
493 for (int col = col_start; col < col_end; col++) {
494 int src_alpha = GetSrcAlpha(clip_scan, col);
495 int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, src_alpha);
496 int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha);
497 int b = FXDIB_ALPHA_MERGE(*ori_scan, m_Blue, src_alpha);
498 ori_scan += Bpp - 2;
499 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]);
500 dest_scan++;
501 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]);
502 dest_scan++;
503 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]);
504 dest_scan += Bpp - 2;
505 }
506 }
507 return;
508 }
509 if (Bpp == 4 && bDestAlpha) {
510 for (int col = col_start; col < col_end; col++) {
511 int src_alpha = GetSrcAlpha(clip_scan, col);
512 int src_alpha_covered = src_alpha * cover_scan[col] / 255;
513 if (src_alpha_covered == 0) {
514 dest_scan += 4;
515 continue;
516 }
517 if (cover_scan[col] == 255) {
518 dest_scan[3] = src_alpha_covered;
519 *dest_scan++ = m_Blue;
520 *dest_scan++ = m_Green;
521 *dest_scan = m_Red;
522 dest_scan += 2;
523 continue;
524 }
525 if (dest_scan[3] == 0) {
526 dest_scan[3] = src_alpha_covered;
527 *dest_scan++ = m_Blue;
528 *dest_scan++ = m_Green;
529 *dest_scan = m_Red;
530 dest_scan += 2;
531 continue;
532 }
533 uint8_t cover = cover_scan[col];
534 dest_scan[3] = FXDIB_ALPHA_MERGE(dest_scan[3], src_alpha, cover);
535 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, cover);
536 dest_scan++;
537 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, cover);
538 dest_scan++;
539 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, cover);
540 dest_scan += 2;
541 }
542 return;
543 }
544 if (Bpp == 3 || Bpp == 4) {
545 for (int col = col_start; col < col_end; col++) {
546 int src_alpha = GetSrcAlpha(clip_scan, col);
547 if (m_bFullCover) {
548 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha);
549 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha);
550 *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha);
551 dest_scan += Bpp - 2;
552 ori_scan += Bpp - 2;
553 continue;
554 }
555 int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha);
556 int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha);
557 int r = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha);
558 ori_scan += Bpp - 2;
559 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]);
560 dest_scan++;
561 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]);
562 dest_scan++;
563 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]);
564 dest_scan += Bpp - 2;
565 continue;
566 }
567 return;
568 }
569 if (Bpp == 1) {
570 for (int col = col_start; col < col_end; col++) {
571 int src_alpha = GetSrcAlpha(clip_scan, col);
572 if (m_bFullCover) {
573 *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha);
574 continue;
575 }
576 int gray = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha);
577 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, cover_scan[col]);
578 dest_scan++;
579 }
580 return;
581 }
582 CompositeSpan1bppHelper(dest_scan, col_start, col_end, cover_scan, clip_scan,
583 span_left);
584 }
585
CompositeSpan1bpp(uint8_t * dest_scan,int Bpp,int span_left,int span_len,uint8_t * cover_scan,int clip_left,int clip_right,uint8_t * clip_scan,uint8_t * dest_extra_alpha_scan)586 void CFX_Renderer::CompositeSpan1bpp(uint8_t* dest_scan,
587 int Bpp,
588 int span_left,
589 int span_len,
590 uint8_t* cover_scan,
591 int clip_left,
592 int clip_right,
593 uint8_t* clip_scan,
594 uint8_t* dest_extra_alpha_scan) {
595 ASSERT(!m_bRgbByteOrder);
596 ASSERT(!m_pDevice->IsCmykImage());
597 int col_start = GetColStart(span_left, clip_left);
598 int col_end = GetColEnd(span_left, span_len, clip_right);
599 dest_scan += col_start / 8;
600 CompositeSpan1bppHelper(dest_scan, col_start, col_end, cover_scan, clip_scan,
601 span_left);
602 }
603
CompositeSpanGray(uint8_t * dest_scan,int Bpp,int span_left,int span_len,uint8_t * cover_scan,int clip_left,int clip_right,uint8_t * clip_scan,uint8_t * dest_extra_alpha_scan)604 void CFX_Renderer::CompositeSpanGray(uint8_t* dest_scan,
605 int Bpp,
606 int span_left,
607 int span_len,
608 uint8_t* cover_scan,
609 int clip_left,
610 int clip_right,
611 uint8_t* clip_scan,
612 uint8_t* dest_extra_alpha_scan) {
613 ASSERT(!m_bRgbByteOrder);
614 int col_start = GetColStart(span_left, clip_left);
615 int col_end = GetColEnd(span_left, span_len, clip_right);
616 dest_scan += col_start;
617 if (dest_extra_alpha_scan) {
618 for (int col = col_start; col < col_end; col++) {
619 int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col)
620 : GetSourceAlpha(cover_scan, clip_scan, col);
621 if (src_alpha) {
622 if (src_alpha == 255) {
623 *dest_scan = m_Gray;
624 *dest_extra_alpha_scan = m_Alpha;
625 } else {
626 uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha -
627 (*dest_extra_alpha_scan) * src_alpha / 255;
628 *dest_extra_alpha_scan++ = dest_alpha;
629 int alpha_ratio = src_alpha * 255 / dest_alpha;
630 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio);
631 dest_scan++;
632 continue;
633 }
634 }
635 dest_extra_alpha_scan++;
636 dest_scan++;
637 }
638 return;
639 }
640 for (int col = col_start; col < col_end; col++) {
641 int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col);
642 if (src_alpha) {
643 if (src_alpha == 255)
644 *dest_scan = m_Gray;
645 else
646 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha);
647 }
648 dest_scan++;
649 }
650 }
651
CompositeSpanARGB(uint8_t * dest_scan,int Bpp,int span_left,int span_len,uint8_t * cover_scan,int clip_left,int clip_right,uint8_t * clip_scan,uint8_t * dest_extra_alpha_scan)652 void CFX_Renderer::CompositeSpanARGB(uint8_t* dest_scan,
653 int Bpp,
654 int span_left,
655 int span_len,
656 uint8_t* cover_scan,
657 int clip_left,
658 int clip_right,
659 uint8_t* clip_scan,
660 uint8_t* dest_extra_alpha_scan) {
661 int col_start = GetColStart(span_left, clip_left);
662 int col_end = GetColEnd(span_left, span_len, clip_right);
663 dest_scan += col_start * Bpp;
664 if (m_bRgbByteOrder) {
665 for (int col = col_start; col < col_end; col++) {
666 int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col)
667 : GetSourceAlpha(cover_scan, clip_scan, col);
668 if (src_alpha) {
669 if (src_alpha == 255) {
670 *(reinterpret_cast<uint32_t*>(dest_scan)) = m_Color;
671 } else {
672 uint8_t dest_alpha =
673 dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255;
674 dest_scan[3] = dest_alpha;
675 int alpha_ratio = src_alpha * 255 / dest_alpha;
676 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
677 dest_scan++;
678 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
679 dest_scan++;
680 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
681 dest_scan += 2;
682 continue;
683 }
684 }
685 dest_scan += 4;
686 }
687 return;
688 }
689 for (int col = col_start; col < col_end; col++) {
690 int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col)
691 : GetSourceAlpha(cover_scan, clip_scan, col);
692 if (src_alpha) {
693 if (src_alpha == 255) {
694 *(reinterpret_cast<uint32_t*>(dest_scan)) = m_Color;
695 } else {
696 if (dest_scan[3] == 0) {
697 dest_scan[3] = src_alpha;
698 *dest_scan++ = m_Blue;
699 *dest_scan++ = m_Green;
700 *dest_scan = m_Red;
701 dest_scan += 2;
702 continue;
703 }
704 uint8_t dest_alpha =
705 dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255;
706 dest_scan[3] = dest_alpha;
707 int alpha_ratio = src_alpha * 255 / dest_alpha;
708 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
709 dest_scan++;
710 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
711 dest_scan++;
712 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
713 dest_scan += 2;
714 continue;
715 }
716 }
717 dest_scan += Bpp;
718 }
719 }
720
CompositeSpanRGB(uint8_t * dest_scan,int Bpp,int span_left,int span_len,uint8_t * cover_scan,int clip_left,int clip_right,uint8_t * clip_scan,uint8_t * dest_extra_alpha_scan)721 void CFX_Renderer::CompositeSpanRGB(uint8_t* dest_scan,
722 int Bpp,
723 int span_left,
724 int span_len,
725 uint8_t* cover_scan,
726 int clip_left,
727 int clip_right,
728 uint8_t* clip_scan,
729 uint8_t* dest_extra_alpha_scan) {
730 int col_start = GetColStart(span_left, clip_left);
731 int col_end = GetColEnd(span_left, span_len, clip_right);
732 dest_scan += col_start * Bpp;
733 if (m_bRgbByteOrder) {
734 for (int col = col_start; col < col_end; col++) {
735 int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col);
736 if (src_alpha) {
737 if (src_alpha == 255) {
738 if (Bpp == 4) {
739 *(uint32_t*)dest_scan = m_Color;
740 } else if (Bpp == 3) {
741 *dest_scan++ = m_Red;
742 *dest_scan++ = m_Green;
743 *dest_scan++ = m_Blue;
744 continue;
745 }
746 } else {
747 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
748 dest_scan++;
749 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
750 dest_scan++;
751 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
752 dest_scan += Bpp - 2;
753 continue;
754 }
755 }
756 dest_scan += Bpp;
757 }
758 return;
759 }
760 if (Bpp == 3 && dest_extra_alpha_scan) {
761 for (int col = col_start; col < col_end; col++) {
762 int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col)
763 : GetSourceAlpha(cover_scan, clip_scan, col);
764 if (src_alpha) {
765 if (src_alpha == 255) {
766 *dest_scan++ = static_cast<uint8_t>(m_Blue);
767 *dest_scan++ = static_cast<uint8_t>(m_Green);
768 *dest_scan++ = static_cast<uint8_t>(m_Red);
769 *dest_extra_alpha_scan++ = static_cast<uint8_t>(m_Alpha);
770 continue;
771 }
772 uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha -
773 (*dest_extra_alpha_scan) * src_alpha / 255;
774 *dest_extra_alpha_scan++ = dest_alpha;
775 int alpha_ratio = src_alpha * 255 / dest_alpha;
776 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
777 dest_scan++;
778 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
779 dest_scan++;
780 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
781 dest_scan++;
782 continue;
783 }
784 dest_extra_alpha_scan++;
785 dest_scan += Bpp;
786 }
787 return;
788 }
789 for (int col = col_start; col < col_end; col++) {
790 int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col)
791 : GetSourceAlpha(cover_scan, clip_scan, col);
792 if (src_alpha) {
793 if (src_alpha == 255) {
794 if (Bpp == 4) {
795 *(uint32_t*)dest_scan = m_Color;
796 } else if (Bpp == 3) {
797 *dest_scan++ = m_Blue;
798 *dest_scan++ = m_Green;
799 *dest_scan++ = m_Red;
800 continue;
801 }
802 } else {
803 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
804 dest_scan++;
805 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
806 dest_scan++;
807 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
808 dest_scan += Bpp - 2;
809 continue;
810 }
811 }
812 dest_scan += Bpp;
813 }
814 }
815
CompositeSpanCMYK(uint8_t * dest_scan,int Bpp,int span_left,int span_len,uint8_t * cover_scan,int clip_left,int clip_right,uint8_t * clip_scan,uint8_t * dest_extra_alpha_scan)816 void CFX_Renderer::CompositeSpanCMYK(uint8_t* dest_scan,
817 int Bpp,
818 int span_left,
819 int span_len,
820 uint8_t* cover_scan,
821 int clip_left,
822 int clip_right,
823 uint8_t* clip_scan,
824 uint8_t* dest_extra_alpha_scan) {
825 ASSERT(!m_bRgbByteOrder);
826 int col_start = GetColStart(span_left, clip_left);
827 int col_end = GetColEnd(span_left, span_len, clip_right);
828 dest_scan += col_start * 4;
829 if (dest_extra_alpha_scan) {
830 for (int col = col_start; col < col_end; col++) {
831 int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col)
832 : GetSourceAlpha(cover_scan, clip_scan, col);
833 if (src_alpha) {
834 if (src_alpha == 255) {
835 *(reinterpret_cast<FX_CMYK*>(dest_scan)) = m_Color;
836 *dest_extra_alpha_scan = static_cast<uint8_t>(m_Alpha);
837 } else {
838 uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha -
839 (*dest_extra_alpha_scan) * src_alpha / 255;
840 *dest_extra_alpha_scan++ = dest_alpha;
841 int alpha_ratio = src_alpha * 255 / dest_alpha;
842 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
843 dest_scan++;
844 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
845 dest_scan++;
846 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
847 dest_scan++;
848 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio);
849 dest_scan++;
850 continue;
851 }
852 }
853 dest_extra_alpha_scan++;
854 dest_scan += 4;
855 }
856 return;
857 }
858 for (int col = col_start; col < col_end; col++) {
859 int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col);
860 if (src_alpha) {
861 if (src_alpha == 255) {
862 *(reinterpret_cast<FX_CMYK*>(dest_scan)) = m_Color;
863 } else {
864 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
865 dest_scan++;
866 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
867 dest_scan++;
868 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
869 dest_scan++;
870 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha);
871 dest_scan++;
872 continue;
873 }
874 }
875 dest_scan += 4;
876 }
877 }
878
Init(const RetainPtr<CFX_DIBitmap> & pDevice,const RetainPtr<CFX_DIBitmap> & pOriDevice,const CFX_ClipRgn * pClipRgn,uint32_t color,bool bFullCover,bool bRgbByteOrder)879 bool CFX_Renderer::Init(const RetainPtr<CFX_DIBitmap>& pDevice,
880 const RetainPtr<CFX_DIBitmap>& pOriDevice,
881 const CFX_ClipRgn* pClipRgn,
882 uint32_t color,
883 bool bFullCover,
884 bool bRgbByteOrder) {
885 m_pDevice = pDevice;
886 m_pClipRgn = pClipRgn;
887 composite_span = nullptr;
888 m_bRgbByteOrder = bRgbByteOrder;
889 m_pOriDevice = pOriDevice;
890 if (m_pClipRgn) {
891 m_ClipBox = m_pClipRgn->GetBox();
892 } else {
893 m_ClipBox.left = m_ClipBox.top = 0;
894 m_ClipBox.right = m_pDevice->GetWidth();
895 m_ClipBox.bottom = m_pDevice->GetHeight();
896 }
897 m_pClipMask = nullptr;
898 if (m_pClipRgn && m_pClipRgn->GetType() == CFX_ClipRgn::MaskF)
899 m_pClipMask = m_pClipRgn->GetMask();
900 m_bFullCover = bFullCover;
901 bool bDeviceCMYK = pDevice->IsCmykImage();
902 m_Alpha = FXARGB_A(color);
903 if (m_pDevice->GetBPP() == 8) {
904 ASSERT(!m_bRgbByteOrder);
905 composite_span = &CFX_Renderer::CompositeSpanGray;
906 if (m_pDevice->IsAlphaMask())
907 m_Gray = 255;
908 else
909 m_Gray = FXRGB2GRAY(FXARGB_R(color), FXARGB_G(color), FXARGB_B(color));
910 return true;
911 }
912 if (bDeviceCMYK) {
913 ASSERT(!m_bRgbByteOrder);
914 composite_span = &CFX_Renderer::CompositeSpanCMYK;
915 return false;
916 }
917 composite_span = (pDevice->GetFormat() == FXDIB_Argb)
918 ? &CFX_Renderer::CompositeSpanARGB
919 : &CFX_Renderer::CompositeSpanRGB;
920 if (m_bRgbByteOrder)
921 m_Color = FXARGB_TOBGRORDERDIB(color);
922 else
923 m_Color = FXARGB_TODIB(color);
924 std::tie(m_Alpha, m_Red, m_Green, m_Blue) = ArgbDecode(color);
925 if (m_pDevice->GetBPP() == 1)
926 composite_span = &CFX_Renderer::CompositeSpan1bpp;
927 return true;
928 }
929
930 template <class Scanline>
render(const Scanline & sl)931 void CFX_Renderer::render(const Scanline& sl) {
932 if (!m_pOriDevice && !composite_span)
933 return;
934
935 int y = sl.y();
936 if (y < m_ClipBox.top || y >= m_ClipBox.bottom)
937 return;
938
939 uint8_t* dest_scan = m_pDevice->GetBuffer() + m_pDevice->GetPitch() * y;
940 uint8_t* dest_scan_extra_alpha = nullptr;
941 RetainPtr<CFX_DIBitmap> pAlphaMask = m_pDevice->m_pAlphaMask;
942 if (pAlphaMask) {
943 dest_scan_extra_alpha =
944 pAlphaMask->GetBuffer() + pAlphaMask->GetPitch() * y;
945 }
946 uint8_t* ori_scan = nullptr;
947 if (m_pOriDevice)
948 ori_scan = m_pOriDevice->GetBuffer() + m_pOriDevice->GetPitch() * y;
949 int Bpp = m_pDevice->GetBPP() / 8;
950 bool bDestAlpha = m_pDevice->HasAlpha() || m_pDevice->IsAlphaMask();
951 unsigned num_spans = sl.num_spans();
952 typename Scanline::const_iterator span = sl.begin();
953 while (1) {
954 if (span->len <= 0)
955 break;
956
957 int x = span->x;
958 uint8_t* dest_pos = nullptr;
959 uint8_t* dest_extra_alpha_pos = nullptr;
960 uint8_t* ori_pos = nullptr;
961 if (Bpp) {
962 ori_pos = ori_scan ? ori_scan + x * Bpp : nullptr;
963 dest_pos = dest_scan + x * Bpp;
964 dest_extra_alpha_pos =
965 dest_scan_extra_alpha ? dest_scan_extra_alpha + x : nullptr;
966 } else {
967 dest_pos = dest_scan + x / 8;
968 ori_pos = ori_scan ? ori_scan + x / 8 : nullptr;
969 }
970 uint8_t* clip_pos = nullptr;
971 if (m_pClipMask) {
972 clip_pos = m_pClipMask->GetBuffer() +
973 (y - m_ClipBox.top) * m_pClipMask->GetPitch() + x -
974 m_ClipBox.left;
975 }
976 if (ori_pos) {
977 CompositeSpan(dest_pos, ori_pos, Bpp, bDestAlpha, x, span->len,
978 span->covers, m_ClipBox.left, m_ClipBox.right, clip_pos);
979 } else {
980 (this->*composite_span)(dest_pos, Bpp, x, span->len, span->covers,
981 m_ClipBox.left, m_ClipBox.right, clip_pos,
982 dest_extra_alpha_pos);
983 }
984 if (--num_spans == 0)
985 break;
986
987 ++span;
988 }
989 }
990
CompositeSpan1bppHelper(uint8_t * dest_scan,int col_start,int col_end,const uint8_t * cover_scan,const uint8_t * clip_scan,int span_left)991 void CFX_Renderer::CompositeSpan1bppHelper(uint8_t* dest_scan,
992 int col_start,
993 int col_end,
994 const uint8_t* cover_scan,
995 const uint8_t* clip_scan,
996 int span_left) {
997 int index = 0;
998 if (m_pDevice->GetPalette()) {
999 for (int i = 0; i < 2; i++) {
1000 if (FXARGB_TODIB(m_pDevice->GetPalette()[i]) == m_Color)
1001 index = i;
1002 }
1003 } else {
1004 index = (static_cast<uint8_t>(m_Color) == 0xff) ? 1 : 0;
1005 }
1006 uint8_t* dest_scan1 = dest_scan;
1007 for (int col = col_start; col < col_end; col++) {
1008 int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col);
1009 if (src_alpha) {
1010 if (!index)
1011 *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8));
1012 else
1013 *dest_scan1 |= 1 << (7 - (col + span_left) % 8);
1014 }
1015 dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8;
1016 }
1017 }
1018
1019 } // namespace
1020
1021 namespace agg {
1022
1023 template <class BaseRenderer>
1024 class renderer_scanline_aa_offset {
1025 public:
1026 typedef BaseRenderer base_ren_type;
1027 typedef typename base_ren_type::color_type color_type;
renderer_scanline_aa_offset(base_ren_type & ren,unsigned left,unsigned top)1028 renderer_scanline_aa_offset(base_ren_type& ren, unsigned left, unsigned top)
1029 : m_ren(&ren), m_left(left), m_top(top) {}
color(const color_type & c)1030 void color(const color_type& c) { m_color = c; }
color() const1031 const color_type& color() const { return m_color; }
prepare(unsigned)1032 void prepare(unsigned) {}
1033 template <class Scanline>
render(const Scanline & sl)1034 void render(const Scanline& sl) {
1035 int y = sl.y();
1036 unsigned num_spans = sl.num_spans();
1037 typename Scanline::const_iterator span = sl.begin();
1038 while (1) {
1039 int x = span->x;
1040 if (span->len > 0) {
1041 m_ren->blend_solid_hspan(x - m_left, y - m_top, (unsigned)span->len,
1042 m_color, span->covers);
1043 } else {
1044 m_ren->blend_hline(x - m_left, y - m_top, (unsigned)(x - span->len - 1),
1045 m_color, *(span->covers));
1046 }
1047 if (--num_spans == 0)
1048 break;
1049
1050 ++span;
1051 }
1052 }
1053
1054 private:
1055 base_ren_type* m_ren;
1056 color_type m_color;
1057 unsigned m_left, m_top;
1058 };
1059
1060 } // namespace agg
1061
BuildPath(const CFX_PathData * pPathData,const CFX_Matrix * pObject2Device)1062 void CAgg_PathData::BuildPath(const CFX_PathData* pPathData,
1063 const CFX_Matrix* pObject2Device) {
1064 const std::vector<FX_PATHPOINT>& pPoints = pPathData->GetPoints();
1065 for (size_t i = 0; i < pPoints.size(); i++) {
1066 CFX_PointF pos = pPoints[i].m_Point;
1067 if (pObject2Device)
1068 pos = pObject2Device->Transform(pos);
1069
1070 pos = HardClip(pos);
1071 FXPT_TYPE point_type = pPoints[i].m_Type;
1072 if (point_type == FXPT_TYPE::MoveTo) {
1073 m_PathData.move_to(pos.x, pos.y);
1074 } else if (point_type == FXPT_TYPE::LineTo) {
1075 if (i > 0 && pPoints[i - 1].IsTypeAndOpen(FXPT_TYPE::MoveTo) &&
1076 (i == pPoints.size() - 1 ||
1077 pPoints[i + 1].IsTypeAndOpen(FXPT_TYPE::MoveTo)) &&
1078 pPoints[i].m_Point == pPoints[i - 1].m_Point) {
1079 pos.x += 1;
1080 }
1081 m_PathData.line_to(pos.x, pos.y);
1082 } else if (point_type == FXPT_TYPE::BezierTo) {
1083 if (i > 0 && i + 2 < pPoints.size()) {
1084 CFX_PointF pos0 = pPoints[i - 1].m_Point;
1085 CFX_PointF pos2 = pPoints[i + 1].m_Point;
1086 CFX_PointF pos3 = pPoints[i + 2].m_Point;
1087 if (pObject2Device) {
1088 pos0 = pObject2Device->Transform(pos0);
1089 pos2 = pObject2Device->Transform(pos2);
1090 pos3 = pObject2Device->Transform(pos3);
1091 }
1092 pos0 = HardClip(pos0);
1093 pos2 = HardClip(pos2);
1094 pos3 = HardClip(pos3);
1095 agg::curve4 curve(pos0.x, pos0.y, pos.x, pos.y, pos2.x, pos2.y, pos3.x,
1096 pos3.y);
1097 i += 2;
1098 m_PathData.add_path_curve(curve);
1099 }
1100 }
1101 if (pPoints[i].m_CloseFigure)
1102 m_PathData.end_poly();
1103 }
1104 }
1105
CFX_AggDeviceDriver(const RetainPtr<CFX_DIBitmap> & pBitmap,bool bRgbByteOrder,const RetainPtr<CFX_DIBitmap> & pOriDevice,bool bGroupKnockout)1106 CFX_AggDeviceDriver::CFX_AggDeviceDriver(
1107 const RetainPtr<CFX_DIBitmap>& pBitmap,
1108 bool bRgbByteOrder,
1109 const RetainPtr<CFX_DIBitmap>& pOriDevice,
1110 bool bGroupKnockout)
1111 : m_pBitmap(pBitmap),
1112 #if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
1113 m_pPlatformGraphics(nullptr),
1114 #endif
1115 m_FillFlags(0),
1116 m_bRgbByteOrder(bRgbByteOrder),
1117 m_pOriDevice(pOriDevice),
1118 m_bGroupKnockout(bGroupKnockout) {
1119 InitPlatform();
1120 }
1121
~CFX_AggDeviceDriver()1122 CFX_AggDeviceDriver::~CFX_AggDeviceDriver() {
1123 DestroyPlatform();
1124 }
1125
GetBuffer() const1126 uint8_t* CFX_AggDeviceDriver::GetBuffer() const {
1127 return m_pBitmap->GetBuffer();
1128 }
1129
1130 #if _FX_PLATFORM_ != _FX_PLATFORM_APPLE_
InitPlatform()1131 void CFX_AggDeviceDriver::InitPlatform() {}
1132
DestroyPlatform()1133 void CFX_AggDeviceDriver::DestroyPlatform() {}
1134
DrawDeviceText(int nChars,const FXTEXT_CHARPOS * pCharPos,CFX_Font * pFont,const CFX_Matrix * pObject2Device,float font_size,uint32_t color)1135 bool CFX_AggDeviceDriver::DrawDeviceText(int nChars,
1136 const FXTEXT_CHARPOS* pCharPos,
1137 CFX_Font* pFont,
1138 const CFX_Matrix* pObject2Device,
1139 float font_size,
1140 uint32_t color) {
1141 return false;
1142 }
1143 #endif // _FX_PLATFORM_ != _FX_PLATFORM_APPLE_
1144
GetDeviceCaps(int caps_id) const1145 int CFX_AggDeviceDriver::GetDeviceCaps(int caps_id) const {
1146 switch (caps_id) {
1147 case FXDC_DEVICE_CLASS:
1148 return FXDC_DISPLAY;
1149 case FXDC_PIXEL_WIDTH:
1150 return m_pBitmap->GetWidth();
1151 case FXDC_PIXEL_HEIGHT:
1152 return m_pBitmap->GetHeight();
1153 case FXDC_BITS_PIXEL:
1154 return m_pBitmap->GetBPP();
1155 case FXDC_HORZ_SIZE:
1156 case FXDC_VERT_SIZE:
1157 return 0;
1158 case FXDC_RENDER_CAPS: {
1159 int flags = FXRC_GET_BITS | FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE |
1160 FXRC_BLEND_MODE | FXRC_SOFT_CLIP;
1161 if (m_pBitmap->HasAlpha()) {
1162 flags |= FXRC_ALPHA_OUTPUT;
1163 } else if (m_pBitmap->IsAlphaMask()) {
1164 if (m_pBitmap->GetBPP() == 1)
1165 flags |= FXRC_BITMASK_OUTPUT;
1166 else
1167 flags |= FXRC_BYTEMASK_OUTPUT;
1168 }
1169 if (m_pBitmap->IsCmykImage())
1170 flags |= FXRC_CMYK_OUTPUT;
1171 return flags;
1172 }
1173 default:
1174 return 0;
1175 }
1176 }
1177
SaveState()1178 void CFX_AggDeviceDriver::SaveState() {
1179 std::unique_ptr<CFX_ClipRgn> pClip;
1180 if (m_pClipRgn)
1181 pClip = pdfium::MakeUnique<CFX_ClipRgn>(*m_pClipRgn);
1182 m_StateStack.push_back(std::move(pClip));
1183 }
1184
RestoreState(bool bKeepSaved)1185 void CFX_AggDeviceDriver::RestoreState(bool bKeepSaved) {
1186 m_pClipRgn.reset();
1187
1188 if (m_StateStack.empty())
1189 return;
1190
1191 if (bKeepSaved) {
1192 if (m_StateStack.back())
1193 m_pClipRgn = pdfium::MakeUnique<CFX_ClipRgn>(*m_StateStack.back());
1194 } else {
1195 m_pClipRgn = std::move(m_StateStack.back());
1196 m_StateStack.pop_back();
1197 }
1198 }
1199
SetClipMask(agg::rasterizer_scanline_aa & rasterizer)1200 void CFX_AggDeviceDriver::SetClipMask(agg::rasterizer_scanline_aa& rasterizer) {
1201 FX_RECT path_rect(rasterizer.min_x(), rasterizer.min_y(),
1202 rasterizer.max_x() + 1, rasterizer.max_y() + 1);
1203 path_rect.Intersect(m_pClipRgn->GetBox());
1204 auto pThisLayer = pdfium::MakeRetain<CFX_DIBitmap>();
1205 pThisLayer->Create(path_rect.Width(), path_rect.Height(), FXDIB_8bppMask);
1206 pThisLayer->Clear(0);
1207 agg::rendering_buffer raw_buf(pThisLayer->GetBuffer(), pThisLayer->GetWidth(),
1208 pThisLayer->GetHeight(),
1209 pThisLayer->GetPitch());
1210 agg::pixfmt_gray8 pixel_buf(raw_buf);
1211 agg::renderer_base<agg::pixfmt_gray8> base_buf(pixel_buf);
1212 agg::renderer_scanline_aa_offset<agg::renderer_base<agg::pixfmt_gray8> >
1213 final_render(base_buf, path_rect.left, path_rect.top);
1214 final_render.color(agg::gray8(255));
1215 agg::scanline_u8 scanline;
1216 agg::render_scanlines(rasterizer, scanline, final_render,
1217 (m_FillFlags & FXFILL_NOPATHSMOOTH) != 0);
1218 m_pClipRgn->IntersectMaskF(path_rect.left, path_rect.top, pThisLayer);
1219 }
1220
SetClip_PathFill(const CFX_PathData * pPathData,const CFX_Matrix * pObject2Device,int fill_mode)1221 bool CFX_AggDeviceDriver::SetClip_PathFill(const CFX_PathData* pPathData,
1222 const CFX_Matrix* pObject2Device,
1223 int fill_mode) {
1224 m_FillFlags = fill_mode;
1225 if (!m_pClipRgn) {
1226 m_pClipRgn = pdfium::MakeUnique<CFX_ClipRgn>(
1227 GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT));
1228 }
1229 size_t size = pPathData->GetPoints().size();
1230 if (size == 5 || size == 4) {
1231 CFX_FloatRect rectf;
1232 if (pPathData->IsRect(pObject2Device, &rectf)) {
1233 rectf.Intersect(CFX_FloatRect(
1234 0, 0, static_cast<float>(GetDeviceCaps(FXDC_PIXEL_WIDTH)),
1235 static_cast<float>(GetDeviceCaps(FXDC_PIXEL_HEIGHT))));
1236 FX_RECT rect = rectf.GetOuterRect();
1237 m_pClipRgn->IntersectRect(rect);
1238 return true;
1239 }
1240 }
1241 CAgg_PathData path_data;
1242 path_data.BuildPath(pPathData, pObject2Device);
1243 path_data.m_PathData.end_poly();
1244 agg::rasterizer_scanline_aa rasterizer;
1245 rasterizer.clip_box(0.0f, 0.0f,
1246 static_cast<float>(GetDeviceCaps(FXDC_PIXEL_WIDTH)),
1247 static_cast<float>(GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
1248 rasterizer.add_path(path_data.m_PathData);
1249 rasterizer.filling_rule((fill_mode & 3) == FXFILL_WINDING
1250 ? agg::fill_non_zero
1251 : agg::fill_even_odd);
1252 SetClipMask(rasterizer);
1253 return true;
1254 }
1255
SetClip_PathStroke(const CFX_PathData * pPathData,const CFX_Matrix * pObject2Device,const CFX_GraphStateData * pGraphState)1256 bool CFX_AggDeviceDriver::SetClip_PathStroke(
1257 const CFX_PathData* pPathData,
1258 const CFX_Matrix* pObject2Device,
1259 const CFX_GraphStateData* pGraphState) {
1260 if (!m_pClipRgn) {
1261 m_pClipRgn = pdfium::MakeUnique<CFX_ClipRgn>(
1262 GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT));
1263 }
1264 CAgg_PathData path_data;
1265 path_data.BuildPath(pPathData, nullptr);
1266 agg::rasterizer_scanline_aa rasterizer;
1267 rasterizer.clip_box(0.0f, 0.0f,
1268 static_cast<float>(GetDeviceCaps(FXDC_PIXEL_WIDTH)),
1269 static_cast<float>(GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
1270 RasterizeStroke(&rasterizer, &path_data.m_PathData, pObject2Device,
1271 pGraphState, 1.0f, false, false);
1272 rasterizer.filling_rule(agg::fill_non_zero);
1273 SetClipMask(rasterizer);
1274 return true;
1275 }
1276
GetDriverType() const1277 int CFX_AggDeviceDriver::GetDriverType() const {
1278 return 1;
1279 }
1280
RenderRasterizer(agg::rasterizer_scanline_aa & rasterizer,uint32_t color,bool bFullCover,bool bGroupKnockout)1281 bool CFX_AggDeviceDriver::RenderRasterizer(
1282 agg::rasterizer_scanline_aa& rasterizer,
1283 uint32_t color,
1284 bool bFullCover,
1285 bool bGroupKnockout) {
1286 RetainPtr<CFX_DIBitmap> pt = bGroupKnockout ? m_pOriDevice : nullptr;
1287 CFX_Renderer render;
1288 if (!render.Init(m_pBitmap, pt, m_pClipRgn.get(), color, bFullCover,
1289 m_bRgbByteOrder)) {
1290 return false;
1291 }
1292 agg::scanline_u8 scanline;
1293 agg::render_scanlines(rasterizer, scanline, render,
1294 (m_FillFlags & FXFILL_NOPATHSMOOTH) != 0);
1295 return true;
1296 }
1297
DrawPath(const CFX_PathData * pPathData,const CFX_Matrix * pObject2Device,const CFX_GraphStateData * pGraphState,uint32_t fill_color,uint32_t stroke_color,int fill_mode,int blend_type)1298 bool CFX_AggDeviceDriver::DrawPath(const CFX_PathData* pPathData,
1299 const CFX_Matrix* pObject2Device,
1300 const CFX_GraphStateData* pGraphState,
1301 uint32_t fill_color,
1302 uint32_t stroke_color,
1303 int fill_mode,
1304 int blend_type) {
1305 if (blend_type != FXDIB_BLEND_NORMAL)
1306 return false;
1307
1308 if (!GetBuffer())
1309 return true;
1310
1311 m_FillFlags = fill_mode;
1312 if ((fill_mode & 3) && fill_color) {
1313 CAgg_PathData path_data;
1314 path_data.BuildPath(pPathData, pObject2Device);
1315 agg::rasterizer_scanline_aa rasterizer;
1316 rasterizer.clip_box(0.0f, 0.0f,
1317 static_cast<float>(GetDeviceCaps(FXDC_PIXEL_WIDTH)),
1318 static_cast<float>(GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
1319 rasterizer.add_path(path_data.m_PathData);
1320 rasterizer.filling_rule((fill_mode & 3) == FXFILL_WINDING
1321 ? agg::fill_non_zero
1322 : agg::fill_even_odd);
1323 if (!RenderRasterizer(rasterizer, fill_color,
1324 !!(fill_mode & FXFILL_FULLCOVER), false)) {
1325 return false;
1326 }
1327 }
1328 int stroke_alpha = FXARGB_A(stroke_color);
1329 if (!pGraphState || !stroke_alpha)
1330 return true;
1331
1332 if (fill_mode & FX_ZEROAREA_FILL) {
1333 CAgg_PathData path_data;
1334 path_data.BuildPath(pPathData, pObject2Device);
1335 agg::rasterizer_scanline_aa rasterizer;
1336 rasterizer.clip_box(0.0f, 0.0f,
1337 static_cast<float>(GetDeviceCaps(FXDC_PIXEL_WIDTH)),
1338 static_cast<float>(GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
1339 RasterizeStroke(&rasterizer, &path_data.m_PathData, nullptr, pGraphState, 1,
1340 false, !!(fill_mode & FX_STROKE_TEXT_MODE));
1341 return RenderRasterizer(rasterizer, stroke_color,
1342 !!(fill_mode & FXFILL_FULLCOVER), m_bGroupKnockout);
1343 }
1344 CFX_Matrix matrix1;
1345 CFX_Matrix matrix2;
1346 if (pObject2Device) {
1347 matrix1.a = std::max(fabs(pObject2Device->a), fabs(pObject2Device->b));
1348 matrix1.d = matrix1.a;
1349 matrix2 = CFX_Matrix(
1350 pObject2Device->a / matrix1.a, pObject2Device->b / matrix1.a,
1351 pObject2Device->c / matrix1.d, pObject2Device->d / matrix1.d, 0, 0);
1352
1353 matrix1 = *pObject2Device;
1354 matrix1.Concat(matrix2.GetInverse());
1355 }
1356
1357 CAgg_PathData path_data;
1358 path_data.BuildPath(pPathData, &matrix1);
1359 agg::rasterizer_scanline_aa rasterizer;
1360 rasterizer.clip_box(0.0f, 0.0f,
1361 static_cast<float>(GetDeviceCaps(FXDC_PIXEL_WIDTH)),
1362 static_cast<float>(GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
1363 RasterizeStroke(&rasterizer, &path_data.m_PathData, &matrix2, pGraphState,
1364 matrix1.a, false, !!(fill_mode & FX_STROKE_TEXT_MODE));
1365 return RenderRasterizer(rasterizer, stroke_color,
1366 !!(fill_mode & FXFILL_FULLCOVER), m_bGroupKnockout);
1367 }
1368
SetPixel(int x,int y,uint32_t color)1369 bool CFX_AggDeviceDriver::SetPixel(int x, int y, uint32_t color) {
1370 if (!m_pBitmap->GetBuffer())
1371 return true;
1372
1373 if (!m_pClipRgn) {
1374 if (!m_bRgbByteOrder)
1375 return DibSetPixel(m_pBitmap, x, y, color);
1376 RgbByteOrderSetPixel(m_pBitmap, x, y, color);
1377 return true;
1378 }
1379 if (!m_pClipRgn->GetBox().Contains(x, y))
1380 return true;
1381
1382 if (m_pClipRgn->GetType() == CFX_ClipRgn::RectI) {
1383 if (!m_bRgbByteOrder)
1384 return DibSetPixel(m_pBitmap, x, y, color);
1385 RgbByteOrderSetPixel(m_pBitmap, x, y, color);
1386 return true;
1387 }
1388 if (m_pClipRgn->GetType() != CFX_ClipRgn::MaskF)
1389 return true;
1390
1391 int new_alpha =
1392 FXARGB_A(color) * m_pClipRgn->GetMask()->GetScanline(y)[x] / 255;
1393 color = (color & 0xffffff) | (new_alpha << 24);
1394 if (m_bRgbByteOrder) {
1395 RgbByteOrderSetPixel(m_pBitmap, x, y, color);
1396 return true;
1397 }
1398 return DibSetPixel(m_pBitmap, x, y, color);
1399 }
1400
FillRectWithBlend(const FX_RECT * pRect,uint32_t fill_color,int blend_type)1401 bool CFX_AggDeviceDriver::FillRectWithBlend(const FX_RECT* pRect,
1402 uint32_t fill_color,
1403 int blend_type) {
1404 if (blend_type != FXDIB_BLEND_NORMAL)
1405 return false;
1406
1407 if (!m_pBitmap->GetBuffer())
1408 return true;
1409
1410 FX_RECT clip_rect;
1411 GetClipBox(&clip_rect);
1412 FX_RECT draw_rect = clip_rect;
1413 if (pRect)
1414 draw_rect.Intersect(*pRect);
1415 if (draw_rect.IsEmpty())
1416 return true;
1417
1418 if (!m_pClipRgn || m_pClipRgn->GetType() == CFX_ClipRgn::RectI) {
1419 if (m_bRgbByteOrder) {
1420 RgbByteOrderCompositeRect(m_pBitmap, draw_rect.left, draw_rect.top,
1421 draw_rect.Width(), draw_rect.Height(),
1422 fill_color);
1423 } else {
1424 m_pBitmap->CompositeRect(draw_rect.left, draw_rect.top, draw_rect.Width(),
1425 draw_rect.Height(), fill_color, 0);
1426 }
1427 return true;
1428 }
1429 m_pBitmap->CompositeMask(draw_rect.left, draw_rect.top, draw_rect.Width(),
1430 draw_rect.Height(), m_pClipRgn->GetMask(),
1431 fill_color, draw_rect.left - clip_rect.left,
1432 draw_rect.top - clip_rect.top, FXDIB_BLEND_NORMAL,
1433 nullptr, m_bRgbByteOrder, 0);
1434 return true;
1435 }
1436
GetClipBox(FX_RECT * pRect)1437 bool CFX_AggDeviceDriver::GetClipBox(FX_RECT* pRect) {
1438 if (!m_pClipRgn) {
1439 pRect->left = pRect->top = 0;
1440 pRect->right = GetDeviceCaps(FXDC_PIXEL_WIDTH);
1441 pRect->bottom = GetDeviceCaps(FXDC_PIXEL_HEIGHT);
1442 return true;
1443 }
1444 *pRect = m_pClipRgn->GetBox();
1445 return true;
1446 }
1447
GetDIBits(const RetainPtr<CFX_DIBitmap> & pBitmap,int left,int top)1448 bool CFX_AggDeviceDriver::GetDIBits(const RetainPtr<CFX_DIBitmap>& pBitmap,
1449 int left,
1450 int top) {
1451 if (!m_pBitmap || !m_pBitmap->GetBuffer())
1452 return true;
1453
1454 FX_RECT rect(left, top, left + pBitmap->GetWidth(),
1455 top + pBitmap->GetHeight());
1456 RetainPtr<CFX_DIBitmap> pBack;
1457 if (m_pOriDevice) {
1458 pBack = m_pOriDevice->Clone(&rect);
1459 if (!pBack)
1460 return true;
1461
1462 pBack->CompositeBitmap(0, 0, pBack->GetWidth(), pBack->GetHeight(),
1463 m_pBitmap, 0, 0);
1464 } else {
1465 pBack = m_pBitmap->Clone(&rect);
1466 if (!pBack)
1467 return true;
1468 }
1469
1470 left = std::min(left, 0);
1471 top = std::min(top, 0);
1472 if (m_bRgbByteOrder) {
1473 RgbByteOrderTransferBitmap(pBitmap, 0, 0, rect.Width(), rect.Height(),
1474 pBack, left, top);
1475 return true;
1476 }
1477 return pBitmap->TransferBitmap(0, 0, rect.Width(), rect.Height(), pBack, left,
1478 top);
1479 }
1480
GetBackDrop()1481 RetainPtr<CFX_DIBitmap> CFX_AggDeviceDriver::GetBackDrop() {
1482 return m_pOriDevice;
1483 }
1484
SetDIBits(const RetainPtr<CFX_DIBSource> & pBitmap,uint32_t argb,const FX_RECT * pSrcRect,int left,int top,int blend_type)1485 bool CFX_AggDeviceDriver::SetDIBits(const RetainPtr<CFX_DIBSource>& pBitmap,
1486 uint32_t argb,
1487 const FX_RECT* pSrcRect,
1488 int left,
1489 int top,
1490 int blend_type) {
1491 if (!m_pBitmap->GetBuffer())
1492 return true;
1493
1494 if (pBitmap->IsAlphaMask()) {
1495 return m_pBitmap->CompositeMask(left, top, pSrcRect->Width(),
1496 pSrcRect->Height(), pBitmap, argb,
1497 pSrcRect->left, pSrcRect->top, blend_type,
1498 m_pClipRgn.get(), m_bRgbByteOrder, 0);
1499 }
1500 return m_pBitmap->CompositeBitmap(
1501 left, top, pSrcRect->Width(), pSrcRect->Height(), pBitmap, pSrcRect->left,
1502 pSrcRect->top, blend_type, m_pClipRgn.get(), m_bRgbByteOrder);
1503 }
1504
StretchDIBits(const RetainPtr<CFX_DIBSource> & pSource,uint32_t argb,int dest_left,int dest_top,int dest_width,int dest_height,const FX_RECT * pClipRect,uint32_t flags,int blend_type)1505 bool CFX_AggDeviceDriver::StretchDIBits(const RetainPtr<CFX_DIBSource>& pSource,
1506 uint32_t argb,
1507 int dest_left,
1508 int dest_top,
1509 int dest_width,
1510 int dest_height,
1511 const FX_RECT* pClipRect,
1512 uint32_t flags,
1513 int blend_type) {
1514 if (!m_pBitmap->GetBuffer())
1515 return true;
1516
1517 if (dest_width == pSource->GetWidth() &&
1518 dest_height == pSource->GetHeight()) {
1519 FX_RECT rect(0, 0, dest_width, dest_height);
1520 return SetDIBits(pSource, argb, &rect, dest_left, dest_top, blend_type);
1521 }
1522 FX_RECT dest_rect(dest_left, dest_top, dest_left + dest_width,
1523 dest_top + dest_height);
1524 dest_rect.Normalize();
1525 FX_RECT dest_clip = dest_rect;
1526 dest_clip.Intersect(*pClipRect);
1527 CFX_BitmapComposer composer;
1528 composer.Compose(m_pBitmap, m_pClipRgn.get(), 255, argb, dest_clip, false,
1529 false, false, m_bRgbByteOrder, 0, blend_type);
1530 dest_clip.Offset(-dest_rect.left, -dest_rect.top);
1531 CFX_ImageStretcher stretcher(&composer, pSource, dest_width, dest_height,
1532 dest_clip, flags);
1533 if (stretcher.Start())
1534 stretcher.Continue(nullptr);
1535 return true;
1536 }
1537
StartDIBits(const RetainPtr<CFX_DIBSource> & pSource,int bitmap_alpha,uint32_t argb,const CFX_Matrix * pMatrix,uint32_t render_flags,std::unique_ptr<CFX_ImageRenderer> * handle,int blend_type)1538 bool CFX_AggDeviceDriver::StartDIBits(
1539 const RetainPtr<CFX_DIBSource>& pSource,
1540 int bitmap_alpha,
1541 uint32_t argb,
1542 const CFX_Matrix* pMatrix,
1543 uint32_t render_flags,
1544 std::unique_ptr<CFX_ImageRenderer>* handle,
1545 int blend_type) {
1546 if (!m_pBitmap->GetBuffer())
1547 return true;
1548
1549 *handle = pdfium::MakeUnique<CFX_ImageRenderer>(
1550 m_pBitmap, m_pClipRgn.get(), pSource, bitmap_alpha, argb, pMatrix,
1551 render_flags, m_bRgbByteOrder);
1552 return true;
1553 }
1554
ContinueDIBits(CFX_ImageRenderer * pHandle,IFX_PauseIndicator * pPause)1555 bool CFX_AggDeviceDriver::ContinueDIBits(CFX_ImageRenderer* pHandle,
1556 IFX_PauseIndicator* pPause) {
1557 return m_pBitmap->GetBuffer() ? pHandle->Continue(pPause) : true;
1558 }
1559
1560 #ifndef _SKIA_SUPPORT_
CFX_DefaultRenderDevice()1561 CFX_DefaultRenderDevice::CFX_DefaultRenderDevice() {}
1562
~CFX_DefaultRenderDevice()1563 CFX_DefaultRenderDevice::~CFX_DefaultRenderDevice() {}
1564
Attach(const RetainPtr<CFX_DIBitmap> & pBitmap,bool bRgbByteOrder,const RetainPtr<CFX_DIBitmap> & pOriDevice,bool bGroupKnockout)1565 bool CFX_DefaultRenderDevice::Attach(const RetainPtr<CFX_DIBitmap>& pBitmap,
1566 bool bRgbByteOrder,
1567 const RetainPtr<CFX_DIBitmap>& pOriDevice,
1568 bool bGroupKnockout) {
1569 if (!pBitmap)
1570 return false;
1571
1572 SetBitmap(pBitmap);
1573 SetDeviceDriver(pdfium::MakeUnique<CFX_AggDeviceDriver>(
1574 pBitmap, bRgbByteOrder, pOriDevice, bGroupKnockout));
1575 return true;
1576 }
1577
Create(int width,int height,FXDIB_Format format,const RetainPtr<CFX_DIBitmap> & pOriDevice)1578 bool CFX_DefaultRenderDevice::Create(
1579 int width,
1580 int height,
1581 FXDIB_Format format,
1582 const RetainPtr<CFX_DIBitmap>& pOriDevice) {
1583 auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1584 if (!pBitmap->Create(width, height, format))
1585 return false;
1586
1587 SetBitmap(pBitmap);
1588 SetDeviceDriver(pdfium::MakeUnique<CFX_AggDeviceDriver>(pBitmap, false,
1589 pOriDevice, false));
1590 return true;
1591 }
1592
1593 #endif
1594