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