• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The PDFium Authors
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 <math.h>
10 #include <stdint.h>
11 
12 #include <algorithm>
13 #include <utility>
14 
15 #include "build/build_config.h"
16 #include "core/fxcrt/fx_2d_size.h"
17 #include "core/fxcrt/fx_safe_types.h"
18 #include "core/fxge/cfx_cliprgn.h"
19 #include "core/fxge/cfx_defaultrenderdevice.h"
20 #include "core/fxge/cfx_graphstatedata.h"
21 #include "core/fxge/cfx_path.h"
22 #include "core/fxge/dib/cfx_dibitmap.h"
23 #include "core/fxge/dib/cfx_imagerenderer.h"
24 #include "core/fxge/dib/cfx_imagestretcher.h"
25 #include "third_party/base/check.h"
26 #include "third_party/base/check_op.h"
27 #include "third_party/base/cxx17_backports.h"
28 #include "third_party/base/notreached.h"
29 #include "third_party/base/span.h"
30 
31 // Ignore fallthrough warnings in agg23 headers.
32 #if defined(__clang__)
33 #pragma GCC diagnostic push
34 #pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
35 #endif
36 #include "third_party/agg23/agg_clip_liang_barsky.h"
37 #include "third_party/agg23/agg_conv_dash.h"
38 #include "third_party/agg23/agg_conv_stroke.h"
39 #include "third_party/agg23/agg_curves.h"
40 #include "third_party/agg23/agg_path_storage.h"
41 #include "third_party/agg23/agg_pixfmt_gray.h"
42 #include "third_party/agg23/agg_rasterizer_scanline_aa.h"
43 #include "third_party/agg23/agg_renderer_scanline.h"
44 #include "third_party/agg23/agg_scanline_u.h"
45 #if defined(__clang__)
46 #pragma GCC diagnostic pop
47 #endif
48 
49 namespace pdfium {
50 namespace {
51 
52 const float kMaxPos = 32000.0f;
53 
HardClip(const CFX_PointF & pos)54 CFX_PointF HardClip(const CFX_PointF& pos) {
55   return CFX_PointF(pdfium::clamp(pos.x, -kMaxPos, kMaxPos),
56                     pdfium::clamp(pos.y, -kMaxPos, kMaxPos));
57 }
58 
RgbByteOrderCompositeRect(const RetainPtr<CFX_DIBitmap> & pBitmap,int left,int top,int width,int height,FX_ARGB argb)59 void RgbByteOrderCompositeRect(const RetainPtr<CFX_DIBitmap>& pBitmap,
60                                int left,
61                                int top,
62                                int width,
63                                int height,
64                                FX_ARGB argb) {
65   int src_alpha = FXARGB_A(argb);
66   if (src_alpha == 0)
67     return;
68 
69   FX_RECT rect(left, top, left + width, top + height);
70   rect.Intersect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight());
71   width = rect.Width();
72   int src_r = FXARGB_R(argb);
73   int src_g = FXARGB_G(argb);
74   int src_b = FXARGB_B(argb);
75   int Bpp = pBitmap->GetBPP() / 8;
76   int dib_argb = FXARGB_TOBGRORDERDIB(argb);
77   pdfium::span<uint8_t> pBuffer = pBitmap->GetBuffer();
78   if (src_alpha == 255) {
79     for (int row = rect.top; row < rect.bottom; row++) {
80       uint8_t* dest_scan =
81           pBuffer.subspan(row * pBitmap->GetPitch() + rect.left * Bpp).data();
82       if (Bpp == 4) {
83         std::fill_n(reinterpret_cast<uint32_t*>(dest_scan), width, dib_argb);
84       } else {
85         for (int col = 0; col < width; col++) {
86           *dest_scan++ = src_r;
87           *dest_scan++ = src_g;
88           *dest_scan++ = src_b;
89         }
90       }
91     }
92     return;
93   }
94   bool bAlpha = pBitmap->IsAlphaFormat();
95   for (int row = rect.top; row < rect.bottom; row++) {
96     uint8_t* dest_scan =
97         pBuffer.subspan(row * pBitmap->GetPitch() + rect.left * Bpp).data();
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, argb);
103           dest_scan += 4;
104           continue;
105         }
106         uint8_t dest_alpha =
107             back_alpha + src_alpha - back_alpha * src_alpha / 255;
108         dest_scan[3] = dest_alpha;
109         int alpha_ratio = src_alpha * 255 / dest_alpha;
110         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
111         dest_scan++;
112         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
113         dest_scan++;
114         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
115         dest_scan += 2;
116       }
117       continue;
118     }
119     for (int col = 0; col < width; col++) {
120       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha);
121       dest_scan++;
122       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha);
123       dest_scan++;
124       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha);
125       dest_scan++;
126       if (Bpp == 4)
127         dest_scan++;
128     }
129   }
130 }
131 
RgbByteOrderTransferBitmap(const RetainPtr<CFX_DIBitmap> & pBitmap,int width,int height,const RetainPtr<CFX_DIBBase> & pSrcBitmap,int src_left,int src_top)132 void RgbByteOrderTransferBitmap(const RetainPtr<CFX_DIBitmap>& pBitmap,
133                                 int width,
134                                 int height,
135                                 const RetainPtr<CFX_DIBBase>& pSrcBitmap,
136                                 int src_left,
137                                 int src_top) {
138   int dest_left = 0;
139   int dest_top = 0;
140   if (!pBitmap->GetOverlapRect(dest_left, dest_top, width, height,
141                                pSrcBitmap->GetWidth(), pSrcBitmap->GetHeight(),
142                                src_left, src_top, nullptr)) {
143     return;
144   }
145 
146   const int Bpp = pBitmap->GetBPP() / 8;
147   const FXDIB_Format dest_format = pBitmap->GetFormat();
148   const FXDIB_Format src_format = pSrcBitmap->GetFormat();
149   const int dest_pitch = pBitmap->GetPitch();
150 
151   const size_t dest_x_offset = Fx2DSizeOrDie(dest_left, Bpp);
152   const size_t dest_y_offset = Fx2DSizeOrDie(dest_top, dest_pitch);
153 
154   pdfium::span<uint8_t> dest_span =
155       pBitmap->GetBuffer().subspan(dest_y_offset).subspan(dest_x_offset);
156   if (dest_format == src_format) {
157     const size_t src_x_offset = Fx2DSizeOrDie(src_left, Bpp);
158     for (int row = 0; row < height; row++) {
159       uint8_t* dest_scan = dest_span.data();
160       const uint8_t* src_scan =
161           pSrcBitmap->GetScanline(src_top + row).subspan(src_x_offset).data();
162       if (Bpp == 4) {
163         for (int col = 0; col < width; col++) {
164           FXARGB_SETRGBORDERDIB(dest_scan,
165                                 *reinterpret_cast<const uint32_t*>(src_scan));
166           dest_scan += 4;
167           src_scan += 4;
168         }
169       } else {
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       dest_span = dest_span.subspan(dest_pitch);
178     }
179     return;
180   }
181 
182   if (dest_format == FXDIB_Format::kRgb) {
183     DCHECK_EQ(src_format, FXDIB_Format::kRgb32);
184     const size_t src_x_offset = Fx2DSizeOrDie(src_left, 4);
185     for (int row = 0; row < height; row++) {
186       uint8_t* dest_scan = dest_span.data();
187       const uint8_t* src_scan =
188           pSrcBitmap->GetScanline(src_top + row).subspan(src_x_offset).data();
189       for (int col = 0; col < width; col++) {
190         *dest_scan++ = src_scan[2];
191         *dest_scan++ = src_scan[1];
192         *dest_scan++ = src_scan[0];
193         src_scan += 4;
194       }
195       if (row < height - 1) {
196         // Since `dest_scan` was initialized in a way that takes `dest_x_offset`
197         // and `dest_y_offset` into account, it may go past the end of the span
198         // after processing the last row.
199         dest_span = dest_span.subspan(dest_pitch);
200       }
201     }
202     return;
203   }
204 
205   DCHECK(dest_format == FXDIB_Format::kArgb ||
206          dest_format == FXDIB_Format::kRgb32);
207   if (src_format == FXDIB_Format::kRgb) {
208     const size_t src_x_offset = Fx2DSizeOrDie(src_left, 3);
209     for (int row = 0; row < height; row++) {
210       uint8_t* dest_scan = dest_span.data();
211       const uint8_t* src_scan =
212           pSrcBitmap->GetScanline(src_top + row).subspan(src_x_offset).data();
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       dest_span = dest_span.subspan(dest_pitch);
220     }
221     return;
222   }
223   if (src_format != FXDIB_Format::kRgb32)
224     return;
225   DCHECK_EQ(dest_format, FXDIB_Format::kArgb);
226   const size_t src_x_offset = Fx2DSizeOrDie(src_left, 4);
227   for (int row = 0; row < height; row++) {
228     uint8_t* dest_scan = dest_span.data();
229     const uint8_t* src_scan =
230         pSrcBitmap->GetScanline(src_top + row).subspan(src_x_offset).data();
231     for (int col = 0; col < width; col++) {
232       FXARGB_SETDIB(dest_scan,
233                     ArgbEncode(0xff, src_scan[0], src_scan[1], src_scan[2]));
234       src_scan += 4;
235       dest_scan += 4;
236     }
237     dest_span = dest_span.subspan(dest_pitch);
238   }
239 }
240 
RasterizeStroke(agg::rasterizer_scanline_aa * rasterizer,agg::path_storage * path_data,const CFX_Matrix * pObject2Device,const CFX_GraphStateData * pGraphState,float scale,bool bTextMode)241 void RasterizeStroke(agg::rasterizer_scanline_aa* rasterizer,
242                      agg::path_storage* path_data,
243                      const CFX_Matrix* pObject2Device,
244                      const CFX_GraphStateData* pGraphState,
245                      float scale,
246                      bool bTextMode) {
247   agg::line_cap_e cap;
248   switch (pGraphState->m_LineCap) {
249     case CFX_GraphStateData::LineCap::kRound:
250       cap = agg::round_cap;
251       break;
252     case CFX_GraphStateData::LineCap::kSquare:
253       cap = agg::square_cap;
254       break;
255     default:
256       cap = agg::butt_cap;
257       break;
258   }
259   agg::line_join_e join;
260   switch (pGraphState->m_LineJoin) {
261     case CFX_GraphStateData::LineJoin::kRound:
262       join = agg::round_join;
263       break;
264     case CFX_GraphStateData::LineJoin::kBevel:
265       join = agg::bevel_join;
266       break;
267     default:
268       join = agg::miter_join_revert;
269       break;
270   }
271   float width = pGraphState->m_LineWidth * scale;
272   float unit = 1.0f;
273   if (pObject2Device) {
274     unit =
275         1.0f / ((pObject2Device->GetXUnit() + pObject2Device->GetYUnit()) / 2);
276   }
277   width = std::max(width, unit);
278   if (!pGraphState->m_DashArray.empty()) {
279     using DashConverter = agg::conv_dash<agg::path_storage>;
280     DashConverter dash(*path_data);
281     for (size_t i = 0; i < (pGraphState->m_DashArray.size() + 1) / 2; i++) {
282       float on = pGraphState->m_DashArray[i * 2];
283       if (on <= 0.000001f)
284         on = 0.1f;
285       float off = i * 2 + 1 == pGraphState->m_DashArray.size()
286                       ? on
287                       : pGraphState->m_DashArray[i * 2 + 1];
288       off = std::max(off, 0.0f);
289       dash.add_dash(on * scale, off * scale);
290     }
291     dash.dash_start(pGraphState->m_DashPhase * scale);
292     using DashStroke = agg::conv_stroke<DashConverter>;
293     DashStroke stroke(dash);
294     stroke.line_join(join);
295     stroke.line_cap(cap);
296     stroke.miter_limit(pGraphState->m_MiterLimit);
297     stroke.width(width);
298     rasterizer->add_path_transformed(stroke, pObject2Device);
299     return;
300   }
301   agg::conv_stroke<agg::path_storage> stroke(*path_data);
302   stroke.line_join(join);
303   stroke.line_cap(cap);
304   stroke.miter_limit(pGraphState->m_MiterLimit);
305   stroke.width(width);
306   rasterizer->add_path_transformed(stroke, pObject2Device);
307 }
308 
GetAlternateOrWindingFillType(const CFX_FillRenderOptions & fill_options)309 agg::filling_rule_e GetAlternateOrWindingFillType(
310     const CFX_FillRenderOptions& fill_options) {
311   return fill_options.fill_type == CFX_FillRenderOptions::FillType::kWinding
312              ? agg::fill_non_zero
313              : agg::fill_even_odd;
314 }
315 
GetClipMaskFromRegion(const CFX_ClipRgn * r)316 RetainPtr<CFX_DIBitmap> GetClipMaskFromRegion(const CFX_ClipRgn* r) {
317   return (r && r->GetType() == CFX_ClipRgn::kMaskF) ? r->GetMask() : nullptr;
318 }
319 
GetClipBoxFromRegion(const RetainPtr<CFX_DIBitmap> & device,const CFX_ClipRgn * region)320 FX_RECT GetClipBoxFromRegion(const RetainPtr<CFX_DIBitmap>& device,
321                              const CFX_ClipRgn* region) {
322   if (region)
323     return region->GetBox();
324   return FX_RECT(0, 0, device->GetWidth(), device->GetHeight());
325 }
326 
327 class CFX_Renderer {
328  public:
329   CFX_Renderer(const RetainPtr<CFX_DIBitmap>& pDevice,
330                const RetainPtr<CFX_DIBitmap>& pBackdropDevice,
331                const CFX_ClipRgn* pClipRgn,
332                uint32_t color,
333                bool bFullCover,
334                bool bRgbByteOrder);
335 
336   // Needed for agg caller
prepare(unsigned)337   void prepare(unsigned) {}
338 
339   template <class Scanline>
340   void render(const Scanline& sl);
341 
342  private:
343   using CompositeSpanFunc = void (
344       CFX_Renderer::*)(uint8_t*, int, int, int, uint8_t*, int, int, uint8_t*);
345 
346   void CompositeSpan(uint8_t* dest_scan,
347                      uint8_t* backdrop_scan,
348                      int Bpp,
349                      bool bDestAlpha,
350                      int span_left,
351                      int span_len,
352                      uint8_t* cover_scan,
353                      int clip_left,
354                      int clip_right,
355                      uint8_t* clip_scan);
356 
357   void CompositeSpan1bpp(uint8_t* dest_scan,
358                          int Bpp,
359                          int span_left,
360                          int span_len,
361                          uint8_t* cover_scan,
362                          int clip_left,
363                          int clip_right,
364                          uint8_t* clip_scan);
365 
366   void CompositeSpanGray(uint8_t* dest_scan,
367                          int Bpp,
368                          int span_left,
369                          int span_len,
370                          uint8_t* cover_scan,
371                          int clip_left,
372                          int clip_right,
373                          uint8_t* clip_scan);
374 
375   void CompositeSpanARGB(uint8_t* dest_scan,
376                          int Bpp,
377                          int span_left,
378                          int span_len,
379                          uint8_t* cover_scan,
380                          int clip_left,
381                          int clip_right,
382                          uint8_t* clip_scan);
383 
384   void CompositeSpanRGB(uint8_t* dest_scan,
385                         int Bpp,
386                         int span_left,
387                         int span_len,
388                         uint8_t* cover_scan,
389                         int clip_left,
390                         int clip_right,
391                         uint8_t* clip_scan);
392 
393   void CompositeSpan1bppHelper(uint8_t* dest_scan,
394                                int col_start,
395                                int col_end,
396                                const uint8_t* cover_scan,
397                                const uint8_t* clip_scan,
398                                int span_left);
399 
GetCompositeSpanFunc(const RetainPtr<CFX_DIBitmap> & device)400   static CompositeSpanFunc GetCompositeSpanFunc(
401       const RetainPtr<CFX_DIBitmap>& device) {
402     if (device->GetBPP() == 1)
403       return &CFX_Renderer::CompositeSpan1bpp;
404     if (device->GetBPP() == 8)
405       return &CFX_Renderer::CompositeSpanGray;
406     if (device->GetFormat() == FXDIB_Format::kArgb)
407       return &CFX_Renderer::CompositeSpanARGB;
408     return &CFX_Renderer::CompositeSpanRGB;
409   }
410 
GetSrcAlpha(const uint8_t * clip_scan,int col) const411   inline int GetSrcAlpha(const uint8_t* clip_scan, int col) const {
412     return clip_scan ? m_Alpha * clip_scan[col] / 255 : m_Alpha;
413   }
414 
GetSourceAlpha(const uint8_t * cover_scan,const uint8_t * clip_scan,int col) const415   inline int GetSourceAlpha(const uint8_t* cover_scan,
416                             const uint8_t* clip_scan,
417                             int col) const {
418     return clip_scan ? m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255
419                      : m_Alpha * cover_scan[col] / 255;
420   }
421 
GetColStart(int span_left,int clip_left) const422   inline int GetColStart(int span_left, int clip_left) const {
423     return span_left < clip_left ? clip_left - span_left : 0;
424   }
425 
GetColEnd(int span_left,int span_len,int clip_right) const426   inline int GetColEnd(int span_left, int span_len, int clip_right) const {
427     return span_left + span_len < clip_right ? span_len
428                                              : clip_right - span_left;
429   }
430 
431   int m_Alpha;
432   int m_Red;
433   int m_Green;
434   int m_Blue;
435   int m_Gray;
436   const uint32_t m_Color;
437   const bool m_bFullCover;
438   const bool m_bRgbByteOrder;
439   const FX_RECT m_ClipBox;
440   RetainPtr<CFX_DIBitmap> const m_pBackdropDevice;
441   RetainPtr<CFX_DIBitmap> const m_pClipMask;
442   RetainPtr<CFX_DIBitmap> const m_pDevice;
443   UnownedPtr<const CFX_ClipRgn> m_pClipRgn;
444   const CompositeSpanFunc m_CompositeSpanFunc;
445 };
446 
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)447 void CFX_Renderer::CompositeSpan(uint8_t* dest_scan,
448                                  uint8_t* backdrop_scan,
449                                  int Bpp,
450                                  bool bDestAlpha,
451                                  int span_left,
452                                  int span_len,
453                                  uint8_t* cover_scan,
454                                  int clip_left,
455                                  int clip_right,
456                                  uint8_t* clip_scan) {
457   int col_start = GetColStart(span_left, clip_left);
458   int col_end = GetColEnd(span_left, span_len, clip_right);
459   if (Bpp) {
460     dest_scan += col_start * Bpp;
461     backdrop_scan += col_start * Bpp;
462   } else {
463     dest_scan += col_start / 8;
464     backdrop_scan += col_start / 8;
465   }
466   if (m_bRgbByteOrder) {
467     if (Bpp == 4 && bDestAlpha) {
468       for (int col = col_start; col < col_end; col++) {
469         int src_alpha = GetSrcAlpha(clip_scan, col);
470         uint8_t dest_alpha =
471             backdrop_scan[3] + src_alpha - backdrop_scan[3] * src_alpha / 255;
472         dest_scan[3] = dest_alpha;
473         int alpha_ratio = src_alpha * 255 / dest_alpha;
474         if (m_bFullCover) {
475           *dest_scan++ =
476               FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Red, alpha_ratio);
477           *dest_scan++ =
478               FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, alpha_ratio);
479           *dest_scan++ =
480               FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, alpha_ratio);
481           dest_scan++;
482           backdrop_scan++;
483         } else {
484           int r = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Red, alpha_ratio);
485           int g = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, alpha_ratio);
486           int b = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, alpha_ratio);
487           backdrop_scan++;
488           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]);
489           dest_scan++;
490           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]);
491           dest_scan++;
492           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]);
493           dest_scan += 2;
494         }
495       }
496       return;
497     }
498     if (Bpp == 3 || Bpp == 4) {
499       for (int col = col_start; col < col_end; col++) {
500         int src_alpha = GetSrcAlpha(clip_scan, col);
501         int r = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Red, src_alpha);
502         int g = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, src_alpha);
503         int b = FXDIB_ALPHA_MERGE(*backdrop_scan, m_Blue, src_alpha);
504         backdrop_scan += Bpp - 2;
505         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]);
506         dest_scan++;
507         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]);
508         dest_scan++;
509         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]);
510         dest_scan += Bpp - 2;
511       }
512     }
513     return;
514   }
515   if (Bpp == 4 && bDestAlpha) {
516     for (int col = col_start; col < col_end; col++) {
517       int src_alpha = GetSrcAlpha(clip_scan, col);
518       int src_alpha_covered = src_alpha * cover_scan[col] / 255;
519       if (src_alpha_covered == 0) {
520         dest_scan += 4;
521         continue;
522       }
523       if (cover_scan[col] == 255) {
524         dest_scan[3] = src_alpha_covered;
525         *dest_scan++ = m_Blue;
526         *dest_scan++ = m_Green;
527         *dest_scan = m_Red;
528         dest_scan += 2;
529         continue;
530       }
531       if (dest_scan[3] == 0) {
532         dest_scan[3] = src_alpha_covered;
533         *dest_scan++ = m_Blue;
534         *dest_scan++ = m_Green;
535         *dest_scan = m_Red;
536         dest_scan += 2;
537         continue;
538       }
539       uint8_t cover = cover_scan[col];
540       dest_scan[3] = FXDIB_ALPHA_MERGE(dest_scan[3], src_alpha, cover);
541       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, cover);
542       dest_scan++;
543       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, cover);
544       dest_scan++;
545       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, cover);
546       dest_scan += 2;
547     }
548     return;
549   }
550   if (Bpp == 3 || Bpp == 4) {
551     for (int col = col_start; col < col_end; col++) {
552       int src_alpha = GetSrcAlpha(clip_scan, col);
553       if (m_bFullCover) {
554         *dest_scan++ = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, src_alpha);
555         *dest_scan++ = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, src_alpha);
556         *dest_scan = FXDIB_ALPHA_MERGE(*backdrop_scan, m_Red, src_alpha);
557         dest_scan += Bpp - 2;
558         backdrop_scan += Bpp - 2;
559         continue;
560       }
561       int b = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, src_alpha);
562       int g = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, src_alpha);
563       int r = FXDIB_ALPHA_MERGE(*backdrop_scan, m_Red, src_alpha);
564       backdrop_scan += Bpp - 2;
565       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]);
566       dest_scan++;
567       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]);
568       dest_scan++;
569       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]);
570       dest_scan += Bpp - 2;
571     }
572     return;
573   }
574   if (Bpp == 1) {
575     for (int col = col_start; col < col_end; col++) {
576       int src_alpha = GetSrcAlpha(clip_scan, col);
577       if (m_bFullCover) {
578         *dest_scan = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Gray, src_alpha);
579         continue;
580       }
581       int gray = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Gray, src_alpha);
582       *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, cover_scan[col]);
583       dest_scan++;
584     }
585     return;
586   }
587   CompositeSpan1bppHelper(dest_scan, col_start, col_end, cover_scan, clip_scan,
588                           span_left);
589 }
590 
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)591 void CFX_Renderer::CompositeSpan1bpp(uint8_t* dest_scan,
592                                      int Bpp,
593                                      int span_left,
594                                      int span_len,
595                                      uint8_t* cover_scan,
596                                      int clip_left,
597                                      int clip_right,
598                                      uint8_t* clip_scan) {
599   DCHECK(!m_bRgbByteOrder);
600   int col_start = GetColStart(span_left, clip_left);
601   int col_end = GetColEnd(span_left, span_len, clip_right);
602   dest_scan += col_start / 8;
603   CompositeSpan1bppHelper(dest_scan, col_start, col_end, cover_scan, clip_scan,
604                           span_left);
605 }
606 
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)607 void CFX_Renderer::CompositeSpanGray(uint8_t* dest_scan,
608                                      int Bpp,
609                                      int span_left,
610                                      int span_len,
611                                      uint8_t* cover_scan,
612                                      int clip_left,
613                                      int clip_right,
614                                      uint8_t* clip_scan) {
615   DCHECK(!m_bRgbByteOrder);
616   int col_start = GetColStart(span_left, clip_left);
617   int col_end = GetColEnd(span_left, span_len, clip_right);
618   dest_scan += col_start;
619   for (int col = col_start; col < col_end; col++) {
620     int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col);
621     if (src_alpha) {
622       if (src_alpha == 255)
623         *dest_scan = m_Gray;
624       else
625         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha);
626     }
627     dest_scan++;
628   }
629 }
630 
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)631 void CFX_Renderer::CompositeSpanARGB(uint8_t* dest_scan,
632                                      int Bpp,
633                                      int span_left,
634                                      int span_len,
635                                      uint8_t* cover_scan,
636                                      int clip_left,
637                                      int clip_right,
638                                      uint8_t* clip_scan) {
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 * Bpp;
642   if (m_bRgbByteOrder) {
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           *(reinterpret_cast<uint32_t*>(dest_scan)) = m_Color;
649         } else {
650           uint8_t dest_alpha =
651               dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255;
652           dest_scan[3] = dest_alpha;
653           int alpha_ratio = src_alpha * 255 / dest_alpha;
654           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
655           dest_scan++;
656           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
657           dest_scan++;
658           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
659           dest_scan += 2;
660           continue;
661         }
662       }
663       dest_scan += 4;
664     }
665     return;
666   }
667   for (int col = col_start; col < col_end; col++) {
668     int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col)
669                                  : GetSourceAlpha(cover_scan, clip_scan, col);
670     if (src_alpha) {
671       if (src_alpha == 255) {
672         *(reinterpret_cast<uint32_t*>(dest_scan)) = m_Color;
673       } else {
674         if (dest_scan[3] == 0) {
675           dest_scan[3] = src_alpha;
676           *dest_scan++ = m_Blue;
677           *dest_scan++ = m_Green;
678           *dest_scan = m_Red;
679           dest_scan += 2;
680           continue;
681         }
682         uint8_t dest_alpha =
683             dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255;
684         dest_scan[3] = dest_alpha;
685         int alpha_ratio = src_alpha * 255 / dest_alpha;
686         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
687         dest_scan++;
688         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
689         dest_scan++;
690         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
691         dest_scan += 2;
692         continue;
693       }
694     }
695     dest_scan += Bpp;
696   }
697 }
698 
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)699 void CFX_Renderer::CompositeSpanRGB(uint8_t* dest_scan,
700                                     int Bpp,
701                                     int span_left,
702                                     int span_len,
703                                     uint8_t* cover_scan,
704                                     int clip_left,
705                                     int clip_right,
706                                     uint8_t* clip_scan) {
707   int col_start = GetColStart(span_left, clip_left);
708   int col_end = GetColEnd(span_left, span_len, clip_right);
709   dest_scan += col_start * Bpp;
710   if (m_bRgbByteOrder) {
711     for (int col = col_start; col < col_end; col++) {
712       int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col);
713       if (src_alpha) {
714         if (src_alpha == 255) {
715           if (Bpp == 4) {
716             *(uint32_t*)dest_scan = m_Color;
717           } else if (Bpp == 3) {
718             *dest_scan++ = m_Red;
719             *dest_scan++ = m_Green;
720             *dest_scan++ = m_Blue;
721             continue;
722           }
723         } else {
724           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
725           dest_scan++;
726           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
727           dest_scan++;
728           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
729           dest_scan += Bpp - 2;
730           continue;
731         }
732       }
733       dest_scan += Bpp;
734     }
735     return;
736   }
737   for (int col = col_start; col < col_end; col++) {
738     int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col)
739                                  : GetSourceAlpha(cover_scan, clip_scan, col);
740     if (src_alpha) {
741       if (src_alpha == 255) {
742         if (Bpp == 4) {
743           *(uint32_t*)dest_scan = m_Color;
744         } else if (Bpp == 3) {
745           *dest_scan++ = m_Blue;
746           *dest_scan++ = m_Green;
747           *dest_scan++ = m_Red;
748           continue;
749         }
750       } else {
751         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
752         dest_scan++;
753         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
754         dest_scan++;
755         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
756         dest_scan += Bpp - 2;
757         continue;
758       }
759     }
760     dest_scan += Bpp;
761   }
762 }
763 
CFX_Renderer(const RetainPtr<CFX_DIBitmap> & pDevice,const RetainPtr<CFX_DIBitmap> & pBackdropDevice,const CFX_ClipRgn * pClipRgn,uint32_t color,bool bFullCover,bool bRgbByteOrder)764 CFX_Renderer::CFX_Renderer(const RetainPtr<CFX_DIBitmap>& pDevice,
765                            const RetainPtr<CFX_DIBitmap>& pBackdropDevice,
766                            const CFX_ClipRgn* pClipRgn,
767                            uint32_t color,
768                            bool bFullCover,
769                            bool bRgbByteOrder)
770     : m_Alpha(FXARGB_A(color)),
771       m_Color(bRgbByteOrder ? FXARGB_TOBGRORDERDIB(color) : color),
772       m_bFullCover(bFullCover),
773       m_bRgbByteOrder(bRgbByteOrder),
774       m_ClipBox(GetClipBoxFromRegion(pDevice, pClipRgn)),
775       m_pBackdropDevice(pBackdropDevice),
776       m_pClipMask(GetClipMaskFromRegion(pClipRgn)),
777       m_pDevice(pDevice),
778       m_pClipRgn(pClipRgn),
779       m_CompositeSpanFunc(GetCompositeSpanFunc(m_pDevice)) {
780   if (m_pDevice->GetBPP() == 8) {
781     DCHECK(!m_bRgbByteOrder);
782     if (m_pDevice->IsMaskFormat())
783       m_Gray = 255;
784     else
785       m_Gray = FXRGB2GRAY(FXARGB_R(color), FXARGB_G(color), FXARGB_B(color));
786     return;
787   }
788 
789   std::tie(m_Alpha, m_Red, m_Green, m_Blue) = ArgbDecode(color);
790 }
791 
792 template <class Scanline>
render(const Scanline & sl)793 void CFX_Renderer::render(const Scanline& sl) {
794   int y = sl.y();
795   if (y < m_ClipBox.top || y >= m_ClipBox.bottom)
796     return;
797 
798   uint8_t* dest_scan =
799       m_pDevice->GetBuffer().subspan(m_pDevice->GetPitch() * y).data();
800   uint8_t* backdrop_scan = nullptr;
801   if (m_pBackdropDevice) {
802     backdrop_scan = m_pBackdropDevice->GetBuffer()
803                         .subspan(m_pBackdropDevice->GetPitch() * y)
804                         .data();
805   }
806   int Bpp = m_pDevice->GetBPP() / 8;
807   bool bDestAlpha = m_pDevice->IsAlphaFormat() || m_pDevice->IsMaskFormat();
808   unsigned num_spans = sl.num_spans();
809   typename Scanline::const_iterator span = sl.begin();
810   while (true) {
811     if (span->len <= 0)
812       break;
813 
814     int x = span->x;
815     uint8_t* dest_pos = nullptr;
816     uint8_t* backdrop_pos = nullptr;
817     if (Bpp) {
818       backdrop_pos = backdrop_scan ? backdrop_scan + x * Bpp : nullptr;
819       dest_pos = dest_scan + x * Bpp;
820     } else {
821       dest_pos = dest_scan + x / 8;
822       backdrop_pos = backdrop_scan ? backdrop_scan + x / 8 : nullptr;
823     }
824     uint8_t* clip_pos = nullptr;
825     if (m_pClipMask) {
826       // TODO(crbug.com/1382604): use subspan arithmetic.
827       clip_pos = m_pClipMask->GetBuffer().data() +
828                  (y - m_ClipBox.top) * m_pClipMask->GetPitch() + x -
829                  m_ClipBox.left;
830     }
831     if (backdrop_pos) {
832       CompositeSpan(dest_pos, backdrop_pos, Bpp, bDestAlpha, x, span->len,
833                     span->covers, m_ClipBox.left, m_ClipBox.right, clip_pos);
834     } else {
835       (this->*m_CompositeSpanFunc)(dest_pos, Bpp, x, span->len, span->covers,
836                                    m_ClipBox.left, m_ClipBox.right, clip_pos);
837     }
838     if (--num_spans == 0)
839       break;
840 
841     ++span;
842   }
843 }
844 
CompositeSpan1bppHelper(uint8_t * dest_scan,int col_start,int col_end,const uint8_t * cover_scan,const uint8_t * clip_scan,int span_left)845 void CFX_Renderer::CompositeSpan1bppHelper(uint8_t* dest_scan,
846                                            int col_start,
847                                            int col_end,
848                                            const uint8_t* cover_scan,
849                                            const uint8_t* clip_scan,
850                                            int span_left) {
851   int index = 0;
852   if (m_pDevice->HasPalette()) {
853     for (int i = 0; i < 2; i++) {
854       if (m_pDevice->GetPaletteSpan()[i] == m_Color)
855         index = i;
856     }
857   } else {
858     index = (static_cast<uint8_t>(m_Color) == 0xff) ? 1 : 0;
859   }
860   uint8_t* dest_scan1 = dest_scan;
861   for (int col = col_start; col < col_end; col++) {
862     int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col);
863     if (src_alpha) {
864       if (!index)
865         *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8));
866       else
867         *dest_scan1 |= 1 << (7 - (col + span_left) % 8);
868     }
869     dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8;
870   }
871 }
872 
873 template <class BaseRenderer>
874 class RendererScanLineAaOffset {
875  public:
876   typedef BaseRenderer base_ren_type;
877   typedef typename base_ren_type::color_type color_type;
RendererScanLineAaOffset(base_ren_type & ren,unsigned left,unsigned top)878   RendererScanLineAaOffset(base_ren_type& ren, unsigned left, unsigned top)
879       : m_ren(&ren), m_left(left), m_top(top) {}
color(const color_type & c)880   void color(const color_type& c) { m_color = c; }
color() const881   const color_type& color() const { return m_color; }
prepare(unsigned)882   void prepare(unsigned) {}
883   template <class Scanline>
render(const Scanline & sl)884   void render(const Scanline& sl) {
885     int y = sl.y();
886     unsigned num_spans = sl.num_spans();
887     typename Scanline::const_iterator span = sl.begin();
888     while (true) {
889       int x = span->x;
890       if (span->len > 0) {
891         m_ren->blend_solid_hspan(x - m_left, y - m_top, (unsigned)span->len,
892                                  m_color, span->covers);
893       } else {
894         m_ren->blend_hline(x - m_left, y - m_top, (unsigned)(x - span->len - 1),
895                            m_color, *(span->covers));
896       }
897       if (--num_spans == 0)
898         break;
899 
900       ++span;
901     }
902   }
903 
904  private:
905   base_ren_type* m_ren;
906   color_type m_color;
907   unsigned m_left;
908   unsigned m_top;
909 };
910 
BuildAggPath(const CFX_Path & path,const CFX_Matrix * pObject2Device)911 agg::path_storage BuildAggPath(const CFX_Path& path,
912                                const CFX_Matrix* pObject2Device) {
913   agg::path_storage agg_path;
914   pdfium::span<const CFX_Path::Point> points = path.GetPoints();
915   for (size_t i = 0; i < points.size(); ++i) {
916     CFX_PointF pos = points[i].m_Point;
917     if (pObject2Device)
918       pos = pObject2Device->Transform(pos);
919 
920     pos = HardClip(pos);
921     CFX_Path::Point::Type point_type = points[i].m_Type;
922     if (point_type == CFX_Path::Point::Type::kMove) {
923       agg_path.move_to(pos.x, pos.y);
924     } else if (point_type == CFX_Path::Point::Type::kLine) {
925       if (i > 0 && points[i - 1].IsTypeAndOpen(CFX_Path::Point::Type::kMove) &&
926           (i == points.size() - 1 ||
927            points[i + 1].IsTypeAndOpen(CFX_Path::Point::Type::kMove)) &&
928           points[i].m_Point == points[i - 1].m_Point) {
929         pos.x += 1;
930       }
931       agg_path.line_to(pos.x, pos.y);
932     } else if (point_type == CFX_Path::Point::Type::kBezier) {
933       if (i > 0 && i + 2 < points.size()) {
934         CFX_PointF pos0 = points[i - 1].m_Point;
935         CFX_PointF pos2 = points[i + 1].m_Point;
936         CFX_PointF pos3 = points[i + 2].m_Point;
937         if (pObject2Device) {
938           pos0 = pObject2Device->Transform(pos0);
939           pos2 = pObject2Device->Transform(pos2);
940           pos3 = pObject2Device->Transform(pos3);
941         }
942         pos0 = HardClip(pos0);
943         pos2 = HardClip(pos2);
944         pos3 = HardClip(pos3);
945         agg::curve4 curve(pos0.x, pos0.y, pos.x, pos.y, pos2.x, pos2.y, pos3.x,
946                           pos3.y);
947         i += 2;
948         agg_path.add_path(curve);
949       }
950     }
951     if (points[i].m_CloseFigure)
952       agg_path.end_poly();
953   }
954   return agg_path;
955 }
956 
957 }  // namespace
958 
CFX_AggDeviceDriver(RetainPtr<CFX_DIBitmap> pBitmap,bool bRgbByteOrder,RetainPtr<CFX_DIBitmap> pBackdropBitmap,bool bGroupKnockout)959 CFX_AggDeviceDriver::CFX_AggDeviceDriver(
960     RetainPtr<CFX_DIBitmap> pBitmap,
961     bool bRgbByteOrder,
962     RetainPtr<CFX_DIBitmap> pBackdropBitmap,
963     bool bGroupKnockout)
964     : m_pBitmap(std::move(pBitmap)),
965       m_bRgbByteOrder(bRgbByteOrder),
966       m_bGroupKnockout(bGroupKnockout),
967       m_pBackdropBitmap(std::move(pBackdropBitmap)) {
968   DCHECK(m_pBitmap);
969   DCHECK_NE(m_pBitmap->GetFormat(), FXDIB_Format::k1bppMask);
970   DCHECK_NE(m_pBitmap->GetFormat(), FXDIB_Format::k1bppRgb);
971   InitPlatform();
972 }
973 
~CFX_AggDeviceDriver()974 CFX_AggDeviceDriver::~CFX_AggDeviceDriver() {
975   DestroyPlatform();
976 }
977 
978 #if !BUILDFLAG(IS_APPLE)
InitPlatform()979 void CFX_AggDeviceDriver::InitPlatform() {}
980 
DestroyPlatform()981 void CFX_AggDeviceDriver::DestroyPlatform() {}
982 
DrawDeviceText(pdfium::span<const TextCharPos> pCharPos,CFX_Font * pFont,const CFX_Matrix & mtObject2Device,float font_size,uint32_t color,const CFX_TextRenderOptions & options)983 bool CFX_AggDeviceDriver::DrawDeviceText(
984     pdfium::span<const TextCharPos> pCharPos,
985     CFX_Font* pFont,
986     const CFX_Matrix& mtObject2Device,
987     float font_size,
988     uint32_t color,
989     const CFX_TextRenderOptions& options) {
990   return false;
991 }
992 #endif  // !BUILDFLAG(IS_APPLE)
993 
GetDeviceType() const994 DeviceType CFX_AggDeviceDriver::GetDeviceType() const {
995   return DeviceType::kDisplay;
996 }
997 
GetDeviceCaps(int caps_id) const998 int CFX_AggDeviceDriver::GetDeviceCaps(int caps_id) const {
999   switch (caps_id) {
1000     case FXDC_PIXEL_WIDTH:
1001       return m_pBitmap->GetWidth();
1002     case FXDC_PIXEL_HEIGHT:
1003       return m_pBitmap->GetHeight();
1004     case FXDC_BITS_PIXEL:
1005       return m_pBitmap->GetBPP();
1006     case FXDC_HORZ_SIZE:
1007     case FXDC_VERT_SIZE:
1008       return 0;
1009     case FXDC_RENDER_CAPS: {
1010       int flags = FXRC_GET_BITS | FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE |
1011                   FXRC_BLEND_MODE | FXRC_SOFT_CLIP;
1012       if (m_pBitmap->IsAlphaFormat()) {
1013         flags |= FXRC_ALPHA_OUTPUT;
1014       } else if (m_pBitmap->IsMaskFormat()) {
1015         if (m_pBitmap->GetBPP() == 1)
1016           flags |= FXRC_BITMASK_OUTPUT;
1017         else
1018           flags |= FXRC_BYTEMASK_OUTPUT;
1019       }
1020       return flags;
1021     }
1022     default:
1023       NOTREACHED();
1024       return 0;
1025   }
1026 }
1027 
SaveState()1028 void CFX_AggDeviceDriver::SaveState() {
1029   std::unique_ptr<CFX_ClipRgn> pClip;
1030   if (m_pClipRgn)
1031     pClip = std::make_unique<CFX_ClipRgn>(*m_pClipRgn);
1032   m_StateStack.push_back(std::move(pClip));
1033 }
1034 
RestoreState(bool bKeepSaved)1035 void CFX_AggDeviceDriver::RestoreState(bool bKeepSaved) {
1036   m_pClipRgn.reset();
1037 
1038   if (m_StateStack.empty())
1039     return;
1040 
1041   if (bKeepSaved) {
1042     if (m_StateStack.back())
1043       m_pClipRgn = std::make_unique<CFX_ClipRgn>(*m_StateStack.back());
1044   } else {
1045     m_pClipRgn = std::move(m_StateStack.back());
1046     m_StateStack.pop_back();
1047   }
1048 }
1049 
SetClipMask(agg::rasterizer_scanline_aa & rasterizer)1050 void CFX_AggDeviceDriver::SetClipMask(agg::rasterizer_scanline_aa& rasterizer) {
1051   FX_RECT path_rect(rasterizer.min_x(), rasterizer.min_y(),
1052                     rasterizer.max_x() + 1, rasterizer.max_y() + 1);
1053   path_rect.Intersect(m_pClipRgn->GetBox());
1054   auto pThisLayer = pdfium::MakeRetain<CFX_DIBitmap>();
1055   pThisLayer->Create(path_rect.Width(), path_rect.Height(),
1056                      FXDIB_Format::k8bppMask);
1057   agg::rendering_buffer raw_buf(pThisLayer->GetBuffer().data(),
1058                                 pThisLayer->GetWidth(), pThisLayer->GetHeight(),
1059                                 pThisLayer->GetPitch());
1060   agg::pixfmt_gray8 pixel_buf(raw_buf);
1061   agg::renderer_base<agg::pixfmt_gray8> base_buf(pixel_buf);
1062   RendererScanLineAaOffset<agg::renderer_base<agg::pixfmt_gray8>> final_render(
1063       base_buf, path_rect.left, path_rect.top);
1064   final_render.color(agg::gray8(255));
1065   agg::scanline_u8 scanline;
1066   agg::render_scanlines(rasterizer, scanline, final_render,
1067                         m_FillOptions.aliased_path);
1068   m_pClipRgn->IntersectMaskF(path_rect.left, path_rect.top,
1069                              std::move(pThisLayer));
1070 }
1071 
SetClip_PathFill(const CFX_Path & path,const CFX_Matrix * pObject2Device,const CFX_FillRenderOptions & fill_options)1072 bool CFX_AggDeviceDriver::SetClip_PathFill(
1073     const CFX_Path& path,
1074     const CFX_Matrix* pObject2Device,
1075     const CFX_FillRenderOptions& fill_options) {
1076   DCHECK(fill_options.fill_type != CFX_FillRenderOptions::FillType::kNoFill);
1077 
1078   m_FillOptions = fill_options;
1079   if (!m_pClipRgn) {
1080     m_pClipRgn = std::make_unique<CFX_ClipRgn>(
1081         GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT));
1082   }
1083   absl::optional<CFX_FloatRect> maybe_rectf = path.GetRect(pObject2Device);
1084   if (maybe_rectf.has_value()) {
1085     CFX_FloatRect& rectf = maybe_rectf.value();
1086     rectf.Intersect(
1087         CFX_FloatRect(0, 0, static_cast<float>(GetDeviceCaps(FXDC_PIXEL_WIDTH)),
1088                       static_cast<float>(GetDeviceCaps(FXDC_PIXEL_HEIGHT))));
1089     FX_RECT rect = rectf.GetOuterRect();
1090     m_pClipRgn->IntersectRect(rect);
1091     return true;
1092   }
1093   agg::path_storage path_data = BuildAggPath(path, pObject2Device);
1094   path_data.end_poly();
1095   agg::rasterizer_scanline_aa rasterizer;
1096   rasterizer.clip_box(0.0f, 0.0f,
1097                       static_cast<float>(GetDeviceCaps(FXDC_PIXEL_WIDTH)),
1098                       static_cast<float>(GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
1099   rasterizer.add_path(path_data);
1100   rasterizer.filling_rule(GetAlternateOrWindingFillType(fill_options));
1101   SetClipMask(rasterizer);
1102   return true;
1103 }
1104 
SetClip_PathStroke(const CFX_Path & path,const CFX_Matrix * pObject2Device,const CFX_GraphStateData * pGraphState)1105 bool CFX_AggDeviceDriver::SetClip_PathStroke(
1106     const CFX_Path& path,
1107     const CFX_Matrix* pObject2Device,
1108     const CFX_GraphStateData* pGraphState) {
1109   if (!m_pClipRgn) {
1110     m_pClipRgn = std::make_unique<CFX_ClipRgn>(
1111         GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT));
1112   }
1113   agg::path_storage path_data = BuildAggPath(path, nullptr);
1114   agg::rasterizer_scanline_aa rasterizer;
1115   rasterizer.clip_box(0.0f, 0.0f,
1116                       static_cast<float>(GetDeviceCaps(FXDC_PIXEL_WIDTH)),
1117                       static_cast<float>(GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
1118   RasterizeStroke(&rasterizer, &path_data, pObject2Device, pGraphState, 1.0f,
1119                   false);
1120   rasterizer.filling_rule(agg::fill_non_zero);
1121   SetClipMask(rasterizer);
1122   return true;
1123 }
1124 
GetDriverType() const1125 int CFX_AggDeviceDriver::GetDriverType() const {
1126   return 1;
1127 }
1128 
MultiplyAlpha(float alpha)1129 bool CFX_AggDeviceDriver::MultiplyAlpha(float alpha) {
1130   return m_pBitmap->MultiplyAlpha(static_cast<int32_t>(alpha * 255));
1131 }
1132 
MultiplyAlpha(const RetainPtr<CFX_DIBBase> & mask)1133 bool CFX_AggDeviceDriver::MultiplyAlpha(const RetainPtr<CFX_DIBBase>& mask) {
1134   return m_pBitmap->MultiplyAlpha(mask);
1135 }
1136 
RenderRasterizer(agg::rasterizer_scanline_aa & rasterizer,uint32_t color,bool bFullCover,bool bGroupKnockout)1137 void CFX_AggDeviceDriver::RenderRasterizer(
1138     agg::rasterizer_scanline_aa& rasterizer,
1139     uint32_t color,
1140     bool bFullCover,
1141     bool bGroupKnockout) {
1142   RetainPtr<CFX_DIBitmap> pt = bGroupKnockout ? m_pBackdropBitmap : nullptr;
1143   CFX_Renderer render(m_pBitmap, pt, m_pClipRgn.get(), color, bFullCover,
1144                       m_bRgbByteOrder);
1145   agg::scanline_u8 scanline;
1146   agg::render_scanlines(rasterizer, scanline, render,
1147                         m_FillOptions.aliased_path);
1148 }
1149 
DrawPath(const CFX_Path & path,const CFX_Matrix * pObject2Device,const CFX_GraphStateData * pGraphState,uint32_t fill_color,uint32_t stroke_color,const CFX_FillRenderOptions & fill_options,BlendMode blend_type)1150 bool CFX_AggDeviceDriver::DrawPath(const CFX_Path& path,
1151                                    const CFX_Matrix* pObject2Device,
1152                                    const CFX_GraphStateData* pGraphState,
1153                                    uint32_t fill_color,
1154                                    uint32_t stroke_color,
1155                                    const CFX_FillRenderOptions& fill_options,
1156                                    BlendMode blend_type) {
1157   if (blend_type != BlendMode::kNormal)
1158     return false;
1159 
1160   if (m_pBitmap->GetBuffer().empty())
1161     return true;
1162 
1163   m_FillOptions = fill_options;
1164   if (fill_options.fill_type != CFX_FillRenderOptions::FillType::kNoFill &&
1165       fill_color) {
1166     agg::path_storage path_data = BuildAggPath(path, pObject2Device);
1167     agg::rasterizer_scanline_aa rasterizer;
1168     rasterizer.clip_box(0.0f, 0.0f,
1169                         static_cast<float>(GetDeviceCaps(FXDC_PIXEL_WIDTH)),
1170                         static_cast<float>(GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
1171     rasterizer.add_path(path_data);
1172     rasterizer.filling_rule(GetAlternateOrWindingFillType(fill_options));
1173     RenderRasterizer(rasterizer, fill_color, fill_options.full_cover,
1174                      /*bGroupKnockout=*/false);
1175   }
1176   int stroke_alpha = FXARGB_A(stroke_color);
1177   if (!pGraphState || !stroke_alpha)
1178     return true;
1179 
1180   if (fill_options.zero_area) {
1181     agg::path_storage path_data = BuildAggPath(path, pObject2Device);
1182     agg::rasterizer_scanline_aa rasterizer;
1183     rasterizer.clip_box(0.0f, 0.0f,
1184                         static_cast<float>(GetDeviceCaps(FXDC_PIXEL_WIDTH)),
1185                         static_cast<float>(GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
1186     RasterizeStroke(&rasterizer, &path_data, nullptr, pGraphState, 1,
1187                     fill_options.stroke_text_mode);
1188     RenderRasterizer(rasterizer, stroke_color, fill_options.full_cover,
1189                      m_bGroupKnockout);
1190     return true;
1191   }
1192   CFX_Matrix matrix1;
1193   CFX_Matrix matrix2;
1194   if (pObject2Device) {
1195     matrix1.a = std::max(fabs(pObject2Device->a), fabs(pObject2Device->b));
1196     matrix1.d = matrix1.a;
1197     matrix2 = CFX_Matrix(
1198         pObject2Device->a / matrix1.a, pObject2Device->b / matrix1.a,
1199         pObject2Device->c / matrix1.d, pObject2Device->d / matrix1.d, 0, 0);
1200 
1201     matrix1 = *pObject2Device * matrix2.GetInverse();
1202   }
1203 
1204   agg::path_storage path_data = BuildAggPath(path, &matrix1);
1205   agg::rasterizer_scanline_aa rasterizer;
1206   rasterizer.clip_box(0.0f, 0.0f,
1207                       static_cast<float>(GetDeviceCaps(FXDC_PIXEL_WIDTH)),
1208                       static_cast<float>(GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
1209   RasterizeStroke(&rasterizer, &path_data, &matrix2, pGraphState, matrix1.a,
1210                   fill_options.stroke_text_mode);
1211   RenderRasterizer(rasterizer, stroke_color, fill_options.full_cover,
1212                    m_bGroupKnockout);
1213   return true;
1214 }
1215 
FillRectWithBlend(const FX_RECT & rect,uint32_t fill_color,BlendMode blend_type)1216 bool CFX_AggDeviceDriver::FillRectWithBlend(const FX_RECT& rect,
1217                                             uint32_t fill_color,
1218                                             BlendMode blend_type) {
1219   if (blend_type != BlendMode::kNormal)
1220     return false;
1221 
1222   if (m_pBitmap->GetBuffer().empty())
1223     return true;
1224 
1225   FX_RECT clip_rect;
1226   GetClipBox(&clip_rect);
1227   FX_RECT draw_rect = clip_rect;
1228   draw_rect.Intersect(rect);
1229   if (draw_rect.IsEmpty())
1230     return true;
1231 
1232   if (!m_pClipRgn || m_pClipRgn->GetType() == CFX_ClipRgn::kRectI) {
1233     if (m_bRgbByteOrder) {
1234       RgbByteOrderCompositeRect(m_pBitmap, draw_rect.left, draw_rect.top,
1235                                 draw_rect.Width(), draw_rect.Height(),
1236                                 fill_color);
1237     } else {
1238       m_pBitmap->CompositeRect(draw_rect.left, draw_rect.top, draw_rect.Width(),
1239                                draw_rect.Height(), fill_color);
1240     }
1241     return true;
1242   }
1243   m_pBitmap->CompositeMask(draw_rect.left, draw_rect.top, draw_rect.Width(),
1244                            draw_rect.Height(), m_pClipRgn->GetMask(),
1245                            fill_color, draw_rect.left - clip_rect.left,
1246                            draw_rect.top - clip_rect.top, BlendMode::kNormal,
1247                            nullptr, m_bRgbByteOrder);
1248   return true;
1249 }
1250 
GetClipBox(FX_RECT * pRect)1251 bool CFX_AggDeviceDriver::GetClipBox(FX_RECT* pRect) {
1252   if (!m_pClipRgn) {
1253     pRect->left = pRect->top = 0;
1254     pRect->right = GetDeviceCaps(FXDC_PIXEL_WIDTH);
1255     pRect->bottom = GetDeviceCaps(FXDC_PIXEL_HEIGHT);
1256     return true;
1257   }
1258   *pRect = m_pClipRgn->GetBox();
1259   return true;
1260 }
1261 
GetDIBits(const RetainPtr<CFX_DIBitmap> & pBitmap,int left,int top)1262 bool CFX_AggDeviceDriver::GetDIBits(const RetainPtr<CFX_DIBitmap>& pBitmap,
1263                                     int left,
1264                                     int top) {
1265   if (m_pBitmap->GetBuffer().empty())
1266     return true;
1267 
1268   FX_RECT rect(left, top, left + pBitmap->GetWidth(),
1269                top + pBitmap->GetHeight());
1270   RetainPtr<CFX_DIBitmap> pBack;
1271   if (m_pBackdropBitmap) {
1272     pBack = m_pBackdropBitmap->ClipTo(rect);
1273     if (!pBack)
1274       return true;
1275 
1276     pBack->CompositeBitmap(0, 0, pBack->GetWidth(), pBack->GetHeight(),
1277                            m_pBitmap, 0, 0, BlendMode::kNormal, nullptr, false);
1278   } else {
1279     pBack = m_pBitmap->ClipTo(rect);
1280     if (!pBack)
1281       return true;
1282   }
1283 
1284   left = std::min(left, 0);
1285   top = std::min(top, 0);
1286   if (m_bRgbByteOrder) {
1287     RgbByteOrderTransferBitmap(pBitmap, rect.Width(), rect.Height(), pBack,
1288                                left, top);
1289     return true;
1290   }
1291   return pBitmap->TransferBitmap(0, 0, rect.Width(), rect.Height(), pBack, left,
1292                                  top);
1293 }
1294 
GetBackDrop()1295 RetainPtr<CFX_DIBitmap> CFX_AggDeviceDriver::GetBackDrop() {
1296   return m_pBackdropBitmap;
1297 }
1298 
SetDIBits(const RetainPtr<CFX_DIBBase> & pBitmap,uint32_t argb,const FX_RECT & src_rect,int left,int top,BlendMode blend_type)1299 bool CFX_AggDeviceDriver::SetDIBits(const RetainPtr<CFX_DIBBase>& pBitmap,
1300                                     uint32_t argb,
1301                                     const FX_RECT& src_rect,
1302                                     int left,
1303                                     int top,
1304                                     BlendMode blend_type) {
1305   if (m_pBitmap->GetBuffer().empty())
1306     return true;
1307 
1308   if (pBitmap->IsMaskFormat()) {
1309     return m_pBitmap->CompositeMask(left, top, src_rect.Width(),
1310                                     src_rect.Height(), pBitmap, argb,
1311                                     src_rect.left, src_rect.top, blend_type,
1312                                     m_pClipRgn.get(), m_bRgbByteOrder);
1313   }
1314   return m_pBitmap->CompositeBitmap(
1315       left, top, src_rect.Width(), src_rect.Height(), pBitmap, src_rect.left,
1316       src_rect.top, blend_type, m_pClipRgn.get(), m_bRgbByteOrder);
1317 }
1318 
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)1319 bool CFX_AggDeviceDriver::StretchDIBits(const RetainPtr<CFX_DIBBase>& pSource,
1320                                         uint32_t argb,
1321                                         int dest_left,
1322                                         int dest_top,
1323                                         int dest_width,
1324                                         int dest_height,
1325                                         const FX_RECT* pClipRect,
1326                                         const FXDIB_ResampleOptions& options,
1327                                         BlendMode blend_type) {
1328   if (m_pBitmap->GetBuffer().empty())
1329     return true;
1330 
1331   if (dest_width == pSource->GetWidth() &&
1332       dest_height == pSource->GetHeight()) {
1333     FX_RECT rect(0, 0, dest_width, dest_height);
1334     return SetDIBits(pSource, argb, rect, dest_left, dest_top, blend_type);
1335   }
1336   FX_RECT dest_rect(dest_left, dest_top, dest_left + dest_width,
1337                     dest_top + dest_height);
1338   dest_rect.Normalize();
1339   FX_RECT dest_clip = dest_rect;
1340   dest_clip.Intersect(*pClipRect);
1341   CFX_BitmapComposer composer;
1342   composer.Compose(m_pBitmap, m_pClipRgn.get(), 255, argb, dest_clip, false,
1343                    false, false, m_bRgbByteOrder, blend_type);
1344   dest_clip.Offset(-dest_rect.left, -dest_rect.top);
1345   CFX_ImageStretcher stretcher(&composer, pSource, dest_width, dest_height,
1346                                dest_clip, options);
1347   if (stretcher.Start())
1348     stretcher.Continue(nullptr);
1349   return true;
1350 }
1351 
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)1352 bool CFX_AggDeviceDriver::StartDIBits(
1353     const RetainPtr<CFX_DIBBase>& pSource,
1354     int bitmap_alpha,
1355     uint32_t argb,
1356     const CFX_Matrix& matrix,
1357     const FXDIB_ResampleOptions& options,
1358     std::unique_ptr<CFX_ImageRenderer>* handle,
1359     BlendMode blend_type) {
1360   if (m_pBitmap->GetBuffer().empty())
1361     return true;
1362 
1363   *handle = std::make_unique<CFX_ImageRenderer>(
1364       m_pBitmap, m_pClipRgn.get(), pSource, bitmap_alpha, argb, matrix, options,
1365       m_bRgbByteOrder);
1366   return true;
1367 }
1368 
ContinueDIBits(CFX_ImageRenderer * pHandle,PauseIndicatorIface * pPause)1369 bool CFX_AggDeviceDriver::ContinueDIBits(CFX_ImageRenderer* pHandle,
1370                                          PauseIndicatorIface* pPause) {
1371   return m_pBitmap->GetBuffer().empty() || pHandle->Continue(pPause);
1372 }
1373 
1374 }  // namespace pdfium
1375 
AttachAggImpl(RetainPtr<CFX_DIBitmap> pBitmap,bool bRgbByteOrder,RetainPtr<CFX_DIBitmap> pBackdropBitmap,bool bGroupKnockout)1376 bool CFX_DefaultRenderDevice::AttachAggImpl(
1377     RetainPtr<CFX_DIBitmap> pBitmap,
1378     bool bRgbByteOrder,
1379     RetainPtr<CFX_DIBitmap> pBackdropBitmap,
1380     bool bGroupKnockout) {
1381   if (!pBitmap)
1382     return false;
1383 
1384   SetBitmap(pBitmap);
1385   SetDeviceDriver(std::make_unique<pdfium::CFX_AggDeviceDriver>(
1386       std::move(pBitmap), bRgbByteOrder, std::move(pBackdropBitmap),
1387       bGroupKnockout));
1388   return true;
1389 }
1390 
CreateAgg(int width,int height,FXDIB_Format format,RetainPtr<CFX_DIBitmap> pBackdropBitmap)1391 bool CFX_DefaultRenderDevice::CreateAgg(
1392     int width,
1393     int height,
1394     FXDIB_Format format,
1395     RetainPtr<CFX_DIBitmap> pBackdropBitmap) {
1396   auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1397   if (!pBitmap->Create(width, height, format))
1398     return false;
1399 
1400   SetBitmap(pBitmap);
1401   SetDeviceDriver(std::make_unique<pdfium::CFX_AggDeviceDriver>(
1402       std::move(pBitmap), false, std::move(pBackdropBitmap), false));
1403   return true;
1404 }
1405