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