• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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