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