Home | History | Annotate | Download | only in skia
      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 #include <algorithm>
      6 #include <utility>
      7 #include <vector>
      8 
      9 #include "core/fpdfapi/page/cpdf_meshstream.h"
     10 #include "core/fpdfapi/page/cpdf_shadingpattern.h"
     11 #include "core/fpdfapi/page/pageint.h"
     12 #include "core/fpdfapi/parser/cpdf_array.h"
     13 #include "core/fpdfapi/parser/cpdf_dictionary.h"
     14 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
     15 #include "core/fxcodec/fx_codec.h"
     16 #include "core/fxcrt/fx_memory.h"
     17 #include "core/fxge/cfx_fxgedevice.h"
     18 #include "core/fxge/cfx_gemodule.h"
     19 #include "core/fxge/cfx_graphstatedata.h"
     20 #include "core/fxge/cfx_pathdata.h"
     21 #include "core/fxge/cfx_renderdevice.h"
     22 #include "core/fxge/skia/fx_skia_device.h"
     23 
     24 #ifdef _SKIA_SUPPORT_PATHS_
     25 #include "core/fxge/ge/cfx_cliprgn.h"
     26 #endif  // _SKIA_SUPPORT_PATHS_
     27 
     28 #include "third_party/base/ptr_util.h"
     29 
     30 #include "third_party/skia/include/core/SkCanvas.h"
     31 #include "third_party/skia/include/core/SkClipOp.h"
     32 #include "third_party/skia/include/core/SkPaint.h"
     33 #include "third_party/skia/include/core/SkPath.h"
     34 #include "third_party/skia/include/core/SkShader.h"
     35 #include "third_party/skia/include/core/SkStream.h"
     36 #include "third_party/skia/include/core/SkTypeface.h"
     37 #include "third_party/skia/include/effects/SkDashPathEffect.h"
     38 #include "third_party/skia/include/effects/SkGradientShader.h"
     39 #include "third_party/skia/include/pathops/SkPathOps.h"
     40 
     41 #ifdef _SKIA_SUPPORT_
     42 #include "third_party/skia/include/core/SkColorFilter.h"
     43 #include "third_party/skia/include/core/SkColorPriv.h"
     44 #include "third_party/skia/include/core/SkMaskFilter.h"
     45 #include "third_party/skia/include/core/SkPictureRecorder.h"
     46 #endif  // _SKIA_SUPPORT_
     47 
     48 namespace {
     49 
     50 #ifdef _SKIA_SUPPORT_PATHS_
     51 void RgbByteOrderTransferBitmap(CFX_DIBitmap* pBitmap,
     52                                 int dest_left,
     53                                 int dest_top,
     54                                 int width,
     55                                 int height,
     56                                 const CFX_DIBSource* pSrcBitmap,
     57                                 int src_left,
     58                                 int src_top) {
     59   if (!pBitmap)
     60     return;
     61 
     62   pBitmap->GetOverlapRect(dest_left, dest_top, width, height,
     63                           pSrcBitmap->GetWidth(), pSrcBitmap->GetHeight(),
     64                           src_left, src_top, nullptr);
     65   if (width == 0 || height == 0)
     66     return;
     67 
     68   int Bpp = pBitmap->GetBPP() / 8;
     69   FXDIB_Format dest_format = pBitmap->GetFormat();
     70   FXDIB_Format src_format = pSrcBitmap->GetFormat();
     71   int pitch = pBitmap->GetPitch();
     72   uint8_t* buffer = pBitmap->GetBuffer();
     73   if (dest_format == src_format) {
     74     for (int row = 0; row < height; row++) {
     75       uint8_t* dest_scan = buffer + (dest_top + row) * pitch + dest_left * Bpp;
     76       uint8_t* src_scan =
     77           (uint8_t*)pSrcBitmap->GetScanline(src_top + row) + src_left * Bpp;
     78       if (Bpp == 4) {
     79         for (int col = 0; col < width; col++) {
     80           FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_scan[3], src_scan[0],
     81                                                src_scan[1], src_scan[2]));
     82           dest_scan += 4;
     83           src_scan += 4;
     84         }
     85       } else {
     86         for (int col = 0; col < width; col++) {
     87           *dest_scan++ = src_scan[2];
     88           *dest_scan++ = src_scan[1];
     89           *dest_scan++ = src_scan[0];
     90           src_scan += 3;
     91         }
     92       }
     93     }
     94     return;
     95   }
     96 
     97   uint8_t* dest_buf = buffer + dest_top * pitch + dest_left * Bpp;
     98   if (dest_format == FXDIB_Rgb) {
     99     if (src_format == FXDIB_Rgb32) {
    100       for (int row = 0; row < height; row++) {
    101         uint8_t* dest_scan = dest_buf + row * pitch;
    102         uint8_t* src_scan =
    103             (uint8_t*)pSrcBitmap->GetScanline(src_top + row) + src_left * 4;
    104         for (int col = 0; col < width; col++) {
    105           *dest_scan++ = src_scan[2];
    106           *dest_scan++ = src_scan[1];
    107           *dest_scan++ = src_scan[0];
    108           src_scan += 4;
    109         }
    110       }
    111     } else {
    112       ASSERT(false);
    113     }
    114     return;
    115   }
    116 
    117   if (dest_format == FXDIB_Argb || dest_format == FXDIB_Rgb32) {
    118     if (src_format == FXDIB_Rgb) {
    119       for (int row = 0; row < height; row++) {
    120         uint8_t* dest_scan = (uint8_t*)(dest_buf + row * pitch);
    121         uint8_t* src_scan =
    122             (uint8_t*)pSrcBitmap->GetScanline(src_top + row) + src_left * 3;
    123         for (int col = 0; col < width; col++) {
    124           FXARGB_SETDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[0], src_scan[1],
    125                                                src_scan[2]));
    126           dest_scan += 4;
    127           src_scan += 3;
    128         }
    129       }
    130     } else if (src_format == FXDIB_Rgb32) {
    131       ASSERT(dest_format == FXDIB_Argb);
    132       for (int row = 0; row < height; row++) {
    133         uint8_t* dest_scan = dest_buf + row * pitch;
    134         uint8_t* src_scan =
    135             (uint8_t*)(pSrcBitmap->GetScanline(src_top + row) + src_left * 4);
    136         for (int col = 0; col < width; col++) {
    137           FXARGB_SETDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[0], src_scan[1],
    138                                                src_scan[2]));
    139           src_scan += 4;
    140           dest_scan += 4;
    141         }
    142       }
    143     }
    144     return;
    145   }
    146 
    147   ASSERT(false);
    148 }
    149 
    150 #endif  // _SKIA_SUPPORT_PATHS_
    151 
    152 #define SHOW_SKIA_PATH 0  // set to 1 to print the path contents
    153 #define DRAW_SKIA_CLIP 0  // set to 1 to draw a green rectangle around the clip
    154 
    155 #if SHOW_SKIA_PATH
    156 void DebugShowSkiaPaint(const SkPaint& paint) {
    157   if (SkPaint::kFill_Style == paint.getStyle()) {
    158     printf("fill 0x%08x\n", paint.getColor());
    159   } else {
    160     printf("stroke 0x%08x width %g\n", paint.getColor(),
    161            paint.getStrokeWidth());
    162   }
    163 }
    164 
    165 void DebugShowCanvasMatrix(const SkCanvas* canvas) {
    166   SkMatrix matrix = canvas->getTotalMatrix();
    167   SkScalar m[9];
    168   matrix.get9(m);
    169   printf("matrix (%g,%g,%g) (%g,%g,%g) (%g,%g,%g)\n", m[0], m[1], m[2], m[3],
    170          m[4], m[5], m[6], m[7], m[8]);
    171 }
    172 #endif  // SHOW_SKIA_PATH
    173 
    174 void DebugShowSkiaPath(const SkPath& path) {
    175 #if SHOW_SKIA_PATH
    176   char buffer[4096];
    177   sk_bzero(buffer, sizeof(buffer));
    178   SkMemoryWStream stream(buffer, sizeof(buffer));
    179   path.dump(&stream, false, false);
    180   printf("%s", buffer);
    181 #endif  // SHOW_SKIA_PATH
    182 }
    183 
    184 void DebugShowCanvasClip(const SkCanvas* canvas) {
    185 #if SHOW_SKIA_PATH
    186   SkRect local;
    187   SkIRect device;
    188   canvas->getClipBounds(&local);
    189   printf("local bounds %g %g %g %g\n", local.fLeft, local.fTop, local.fRight,
    190          local.fBottom);
    191   canvas->getClipDeviceBounds(&device);
    192   printf("device bounds %d %d %d %d\n", device.fLeft, device.fTop,
    193          device.fRight, device.fBottom);
    194 #endif  // SHOW_SKIA_PATH
    195 }
    196 
    197 #if SHOW_SKIA_PATH
    198 void DebugShowSkiaPaint(const SkPaint& paint) {
    199   if (SkPaint::kFill_Style == paint.getStyle()) {
    200     printf("fill 0x%08x\n", paint.getColor());
    201   } else {
    202     printf("stroke 0x%08x width %g\n", paint.getColor(),
    203            paint.getStrokeWidth());
    204   }
    205 }
    206 #endif  // SHOW_SKIA_PATH
    207 
    208 void DebugShowSkiaDrawPath(const SkCanvas* canvas,
    209                            const SkPaint& paint,
    210                            const SkPath& path) {
    211 #if SHOW_SKIA_PATH
    212   DebugShowSkiaPaint(paint);
    213   DebugShowCanvasMatrix(canvas);
    214   DebugShowCanvasClip(canvas);
    215   DebugShowSkiaPath(path);
    216   printf("\n");
    217 #endif  // SHOW_SKIA_PATH
    218 }
    219 
    220 void DebugShowSkiaDrawRect(const SkCanvas* canvas,
    221                            const SkPaint& paint,
    222                            const SkRect& rect) {
    223 #if SHOW_SKIA_PATH
    224   DebugShowSkiaPaint(paint);
    225   DebugShowCanvasMatrix(canvas);
    226   DebugShowCanvasClip(canvas);
    227   printf("rect %g %g %g %g\n", rect.fLeft, rect.fTop, rect.fRight,
    228          rect.fBottom);
    229 #endif  // SHOW_SKIA_PATH
    230 }
    231 
    232 #if DRAW_SKIA_CLIP
    233 
    234 SkPaint DebugClipPaint() {
    235   SkPaint paint;
    236   paint.setAntiAlias(true);
    237   paint.setColor(SK_ColorGREEN);
    238   paint.setStyle(SkPaint::kStroke_Style);
    239   return paint;
    240 }
    241 
    242 void DebugDrawSkiaClipRect(SkCanvas* canvas, const SkRect& rect) {
    243   SkPaint paint = DebugClipPaint();
    244   canvas->drawRect(rect, paint);
    245 }
    246 
    247 void DebugDrawSkiaClipPath(SkCanvas* canvas, const SkPath& path) {
    248   SkPaint paint = DebugClipPaint();
    249   canvas->drawPath(path, paint);
    250 }
    251 
    252 #else  // DRAW_SKIA_CLIP
    253 
    254 void DebugDrawSkiaClipRect(SkCanvas* canvas, const SkRect& rect) {}
    255 
    256 void DebugDrawSkiaClipPath(SkCanvas* canvas, const SkPath& path) {}
    257 
    258 #endif  // DRAW_SKIA_CLIP
    259 
    260 #ifdef _SKIA_SUPPORT_
    261 static void DebugValidate(const CFX_DIBitmap* bitmap,
    262                           const CFX_DIBitmap* device) {
    263   if (bitmap) {
    264     SkASSERT(bitmap->GetBPP() == 8 || bitmap->GetBPP() == 32);
    265     if (bitmap->GetBPP() == 32) {
    266       bitmap->DebugVerifyBitmapIsPreMultiplied();
    267     }
    268   }
    269   if (device) {
    270     SkASSERT(device->GetBPP() == 8 || device->GetBPP() == 32);
    271     if (device->GetBPP() == 32) {
    272       device->DebugVerifyBitmapIsPreMultiplied();
    273     }
    274   }
    275 }
    276 #endif  // _SKIA_SUPPORT_
    277 
    278 SkPath BuildPath(const CFX_PathData* pPathData) {
    279   SkPath skPath;
    280   const CFX_PathData* pFPath = pPathData;
    281   const std::vector<FX_PATHPOINT>& pPoints = pFPath->GetPoints();
    282   for (size_t i = 0; i < pPoints.size(); i++) {
    283     CFX_PointF point = pPoints[i].m_Point;
    284     FXPT_TYPE point_type = pPoints[i].m_Type;
    285     if (point_type == FXPT_TYPE::MoveTo) {
    286       skPath.moveTo(point.x, point.y);
    287     } else if (point_type == FXPT_TYPE::LineTo) {
    288       skPath.lineTo(point.x, point.y);
    289     } else if (point_type == FXPT_TYPE::BezierTo) {
    290       CFX_PointF point2 = pPoints[i + 1].m_Point;
    291       CFX_PointF point3 = pPoints[i + 2].m_Point;
    292       skPath.cubicTo(point.x, point.y, point2.x, point2.y, point3.x, point3.y);
    293       i += 2;
    294     }
    295     if (pPoints[i].m_CloseFigure)
    296       skPath.close();
    297   }
    298   return skPath;
    299 }
    300 
    301 SkMatrix ToSkMatrix(const CFX_Matrix& m) {
    302   SkMatrix skMatrix;
    303   skMatrix.setAll(m.a, m.c, m.e, m.b, m.d, m.f, 0, 0, 1);
    304   return skMatrix;
    305 }
    306 
    307 // use when pdf's y-axis points up instead of down
    308 SkMatrix ToFlippedSkMatrix(const CFX_Matrix& m, SkScalar flip) {
    309   SkMatrix skMatrix;
    310   skMatrix.setAll(m.a * flip, -m.c * flip, m.e, m.b * flip, -m.d * flip, m.f, 0,
    311                   0, 1);
    312   return skMatrix;
    313 }
    314 
    315 SkBlendMode GetSkiaBlendMode(int blend_type) {
    316   switch (blend_type) {
    317     case FXDIB_BLEND_MULTIPLY:
    318       return SkBlendMode::kMultiply;
    319     case FXDIB_BLEND_SCREEN:
    320       return SkBlendMode::kScreen;
    321     case FXDIB_BLEND_OVERLAY:
    322       return SkBlendMode::kOverlay;
    323     case FXDIB_BLEND_DARKEN:
    324       return SkBlendMode::kDarken;
    325     case FXDIB_BLEND_LIGHTEN:
    326       return SkBlendMode::kLighten;
    327     case FXDIB_BLEND_COLORDODGE:
    328       return SkBlendMode::kColorDodge;
    329     case FXDIB_BLEND_COLORBURN:
    330       return SkBlendMode::kColorBurn;
    331     case FXDIB_BLEND_HARDLIGHT:
    332       return SkBlendMode::kHardLight;
    333     case FXDIB_BLEND_SOFTLIGHT:
    334       return SkBlendMode::kSoftLight;
    335     case FXDIB_BLEND_DIFFERENCE:
    336       return SkBlendMode::kDifference;
    337     case FXDIB_BLEND_EXCLUSION:
    338       return SkBlendMode::kExclusion;
    339     case FXDIB_BLEND_HUE:
    340       return SkBlendMode::kHue;
    341     case FXDIB_BLEND_SATURATION:
    342       return SkBlendMode::kSaturation;
    343     case FXDIB_BLEND_COLOR:
    344       return SkBlendMode::kColor;
    345     case FXDIB_BLEND_LUMINOSITY:
    346       return SkBlendMode::kLuminosity;
    347     case FXDIB_BLEND_NORMAL:
    348     default:
    349       return SkBlendMode::kSrcOver;
    350   }
    351 }
    352 
    353 bool AddColors(const CPDF_ExpIntFunc* pFunc, SkTDArray<SkColor>* skColors) {
    354   if (pFunc->CountInputs() != 1)
    355     return false;
    356   if (pFunc->m_Exponent != 1)
    357     return false;
    358   if (pFunc->m_nOrigOutputs != 3)
    359     return false;
    360   skColors->push(
    361       SkColorSetARGB(0xFF, SkUnitScalarClampToByte(pFunc->m_pBeginValues[0]),
    362                      SkUnitScalarClampToByte(pFunc->m_pBeginValues[1]),
    363                      SkUnitScalarClampToByte(pFunc->m_pBeginValues[2])));
    364   skColors->push(
    365       SkColorSetARGB(0xFF, SkUnitScalarClampToByte(pFunc->m_pEndValues[0]),
    366                      SkUnitScalarClampToByte(pFunc->m_pEndValues[1]),
    367                      SkUnitScalarClampToByte(pFunc->m_pEndValues[2])));
    368   return true;
    369 }
    370 
    371 uint8_t FloatToByte(FX_FLOAT f) {
    372   ASSERT(0 <= f && f <= 1);
    373   return (uint8_t)(f * 255.99f);
    374 }
    375 
    376 bool AddSamples(const CPDF_SampledFunc* pFunc,
    377                 SkTDArray<SkColor>* skColors,
    378                 SkTDArray<SkScalar>* skPos) {
    379   if (pFunc->CountInputs() != 1)
    380     return false;
    381   if (pFunc->CountOutputs() != 3)  // expect rgb
    382     return false;
    383   if (pFunc->GetEncodeInfo().empty())
    384     return false;
    385   const CPDF_SampledFunc::SampleEncodeInfo& encodeInfo =
    386       pFunc->GetEncodeInfo()[0];
    387   if (encodeInfo.encode_min != 0)
    388     return false;
    389   if (encodeInfo.encode_max != encodeInfo.sizes - 1)
    390     return false;
    391   uint32_t sampleSize = pFunc->GetBitsPerSample();
    392   uint32_t sampleCount = encodeInfo.sizes;
    393   if (sampleCount != 1U << sampleSize)
    394     return false;
    395   if (pFunc->GetSampleStream()->GetSize() < sampleCount * 3 * sampleSize / 8)
    396     return false;
    397 
    398   FX_FLOAT colorsMin[3];
    399   FX_FLOAT colorsMax[3];
    400   for (int i = 0; i < 3; ++i) {
    401     colorsMin[i] = pFunc->GetRange(i * 2);
    402     colorsMax[i] = pFunc->GetRange(i * 2 + 1);
    403   }
    404   const uint8_t* pSampleData = pFunc->GetSampleStream()->GetData();
    405   for (uint32_t i = 0; i < sampleCount; ++i) {
    406     FX_FLOAT floatColors[3];
    407     for (uint32_t j = 0; j < 3; ++j) {
    408       int sample = GetBits32(pSampleData, (i * 3 + j) * sampleSize, sampleSize);
    409       FX_FLOAT interp = (FX_FLOAT)sample / (sampleCount - 1);
    410       floatColors[j] = colorsMin[j] + (colorsMax[j] - colorsMin[j]) * interp;
    411     }
    412     SkColor color =
    413         SkPackARGB32(0xFF, FloatToByte(floatColors[0]),
    414                      FloatToByte(floatColors[1]), FloatToByte(floatColors[2]));
    415     skColors->push(color);
    416     skPos->push((FX_FLOAT)i / (sampleCount - 1));
    417   }
    418   return true;
    419 }
    420 
    421 bool AddStitching(const CPDF_StitchFunc* pFunc,
    422                   SkTDArray<SkColor>* skColors,
    423                   SkTDArray<SkScalar>* skPos) {
    424   FX_FLOAT boundsStart = pFunc->GetDomain(0);
    425 
    426   const auto& subFunctions = pFunc->GetSubFunctions();
    427   int subFunctionCount = subFunctions.size();
    428   for (int i = 0; i < subFunctionCount; ++i) {
    429     const CPDF_ExpIntFunc* pSubFunc = subFunctions[i]->ToExpIntFunc();
    430     if (!pSubFunc)
    431       return false;
    432     if (!AddColors(pSubFunc, skColors))
    433       return false;
    434     FX_FLOAT boundsEnd =
    435         i < subFunctionCount - 1 ? pFunc->GetBound(i + 1) : pFunc->GetDomain(1);
    436     skPos->push(boundsStart);
    437     skPos->push(boundsEnd);
    438     boundsStart = boundsEnd;
    439   }
    440   return true;
    441 }
    442 
    443 // see https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
    444 SkScalar LineSide(const SkPoint line[2], const SkPoint& pt) {
    445   return (line[1].fY - line[0].fY) * pt.fX - (line[1].fX - line[0].fX) * pt.fY +
    446          line[1].fX * line[0].fY - line[1].fY * line[0].fX;
    447 }
    448 
    449 SkPoint IntersectSides(const SkPoint& parallelPt,
    450                        const SkVector& paraRay,
    451                        const SkPoint& perpendicularPt) {
    452   SkVector perpRay = {paraRay.fY, -paraRay.fX};
    453   SkScalar denom = perpRay.fY * paraRay.fX - paraRay.fY * perpRay.fX;
    454   if (!denom) {
    455     SkPoint zeroPt = {0, 0};
    456     return zeroPt;
    457   }
    458   SkVector ab0 = parallelPt - perpendicularPt;
    459   SkScalar numerA = ab0.fY * perpRay.fX - perpRay.fY * ab0.fX;
    460   numerA /= denom;
    461   SkPoint result = {parallelPt.fX + paraRay.fX * numerA,
    462                     parallelPt.fY + paraRay.fY * numerA};
    463   return result;
    464 }
    465 
    466 void ClipAngledGradient(const SkPoint pts[2],
    467                         SkPoint rectPts[4],
    468                         bool clipStart,
    469                         bool clipEnd,
    470                         SkPath* clip) {
    471   // find the corners furthest from the gradient perpendiculars
    472   SkScalar minPerpDist = SK_ScalarMax;
    473   SkScalar maxPerpDist = SK_ScalarMin;
    474   int minPerpPtIndex = -1;
    475   int maxPerpPtIndex = -1;
    476   SkVector slope = pts[1] - pts[0];
    477   SkPoint startPerp[2] = {pts[0], {pts[0].fX + slope.fY, pts[0].fY - slope.fX}};
    478   SkPoint endPerp[2] = {pts[1], {pts[1].fX + slope.fY, pts[1].fY - slope.fX}};
    479   for (int i = 0; i < 4; ++i) {
    480     SkScalar sDist = LineSide(startPerp, rectPts[i]);
    481     SkScalar eDist = LineSide(endPerp, rectPts[i]);
    482     if (sDist * eDist <= 0)  // if the signs are different,
    483       continue;              // the point is inside the gradient
    484     if (sDist < 0) {
    485       SkScalar smaller = SkTMin(sDist, eDist);
    486       if (minPerpDist > smaller) {
    487         minPerpDist = smaller;
    488         minPerpPtIndex = i;
    489       }
    490     } else {
    491       SkScalar larger = SkTMax(sDist, eDist);
    492       if (maxPerpDist < larger) {
    493         maxPerpDist = larger;
    494         maxPerpPtIndex = i;
    495       }
    496     }
    497   }
    498   if (minPerpPtIndex < 0 && maxPerpPtIndex < 0)  // nothing's outside
    499     return;
    500   // determine if negative distances are before start or after end
    501   SkPoint beforeStart = {pts[0].fX * 2 - pts[1].fX, pts[0].fY * 2 - pts[1].fY};
    502   bool beforeNeg = LineSide(startPerp, beforeStart) < 0;
    503   const SkPoint& startEdgePt =
    504       clipStart ? pts[0] : beforeNeg ? rectPts[minPerpPtIndex]
    505                                      : rectPts[maxPerpPtIndex];
    506   const SkPoint& endEdgePt = clipEnd ? pts[1] : beforeNeg
    507                                                     ? rectPts[maxPerpPtIndex]
    508                                                     : rectPts[minPerpPtIndex];
    509   // find the corners that bound the gradient
    510   SkScalar minDist = SK_ScalarMax;
    511   SkScalar maxDist = SK_ScalarMin;
    512   int minBounds = -1;
    513   int maxBounds = -1;
    514   for (int i = 0; i < 4; ++i) {
    515     SkScalar dist = LineSide(pts, rectPts[i]);
    516     if (minDist > dist) {
    517       minDist = dist;
    518       minBounds = i;
    519     }
    520     if (maxDist < dist) {
    521       maxDist = dist;
    522       maxBounds = i;
    523     }
    524   }
    525   ASSERT(minBounds >= 0);
    526   ASSERT(maxBounds != minBounds && maxBounds >= 0);
    527   // construct a clip parallel to the gradient that goes through
    528   // rectPts[minBounds] and rectPts[maxBounds] and perpendicular to the
    529   // gradient that goes through startEdgePt, endEdgePt.
    530   clip->moveTo(IntersectSides(rectPts[minBounds], slope, startEdgePt));
    531   clip->lineTo(IntersectSides(rectPts[minBounds], slope, endEdgePt));
    532   clip->lineTo(IntersectSides(rectPts[maxBounds], slope, endEdgePt));
    533   clip->lineTo(IntersectSides(rectPts[maxBounds], slope, startEdgePt));
    534 }
    535 
    536 #ifdef _SKIA_SUPPORT_
    537 void SetBitmapMatrix(const CFX_Matrix* pMatrix,
    538                      int width,
    539                      int height,
    540                      SkMatrix* skMatrix) {
    541   const CFX_Matrix& m = *pMatrix;
    542   skMatrix->setAll(m.a / width, -m.c / height, m.c + m.e, m.b / width,
    543                    -m.d / height, m.d + m.f, 0, 0, 1);
    544 }
    545 
    546 void SetBitmapPaint(bool isAlphaMask,
    547                     uint32_t argb,
    548                     int bitmap_alpha,
    549                     int blend_type,
    550                     SkPaint* paint) {
    551   paint->setAntiAlias(true);
    552   if (isAlphaMask) {
    553     paint->setColorFilter(
    554         SkColorFilter::MakeModeFilter(argb, SkBlendMode::kSrc));
    555   }
    556   // paint->setFilterQuality(kHigh_SkFilterQuality);
    557   paint->setBlendMode(GetSkiaBlendMode(blend_type));
    558   paint->setAlpha(bitmap_alpha);
    559 }
    560 
    561 bool Upsample(const CFX_DIBSource* pSource,
    562               std::unique_ptr<uint8_t, FxFreeDeleter>& dst8Storage,
    563               std::unique_ptr<uint32_t, FxFreeDeleter>& dst32Storage,
    564               SkColorTable** ctPtr,
    565               SkBitmap* skBitmap,
    566               int* widthPtr,
    567               int* heightPtr,
    568               bool forceAlpha) {
    569   void* buffer = pSource->GetBuffer();
    570   if (!buffer)
    571     return false;
    572   SkColorType colorType = forceAlpha || pSource->IsAlphaMask()
    573                               ? SkColorType::kAlpha_8_SkColorType
    574                               : SkColorType::kGray_8_SkColorType;
    575   SkAlphaType alphaType =
    576       pSource->IsAlphaMask() ? kPremul_SkAlphaType : kOpaque_SkAlphaType;
    577   int width = pSource->GetWidth();
    578   int height = pSource->GetHeight();
    579   int rowBytes = pSource->GetPitch();
    580   switch (pSource->GetBPP()) {
    581     case 1: {
    582       dst8Storage.reset(FX_Alloc2D(uint8_t, width, height));
    583       uint8_t* dst8Pixels = dst8Storage.get();
    584       for (int y = 0; y < height; ++y) {
    585         const uint8_t* srcRow =
    586             static_cast<const uint8_t*>(buffer) + y * rowBytes;
    587         uint8_t* dstRow = dst8Pixels + y * width;
    588         for (int x = 0; x < width; ++x)
    589           dstRow[x] = srcRow[x >> 3] & (1 << (~x & 0x07)) ? 0xFF : 0x00;
    590       }
    591       buffer = dst8Storage.get();
    592       rowBytes = width;
    593       break;
    594     }
    595     case 8:
    596       // we upscale ctables to 32bit.
    597       if (pSource->GetPalette()) {
    598         dst32Storage.reset(FX_Alloc2D(uint32_t, width, height));
    599         SkPMColor* dst32Pixels = dst32Storage.get();
    600         const SkPMColor* ctable = pSource->GetPalette();
    601         const unsigned ctableSize = pSource->GetPaletteSize();
    602         for (int y = 0; y < height; ++y) {
    603           const uint8_t* srcRow =
    604               static_cast<const uint8_t*>(buffer) + y * rowBytes;
    605           uint32_t* dstRow = dst32Pixels + y * width;
    606           for (int x = 0; x < width; ++x) {
    607             unsigned index = srcRow[x];
    608             if (index >= ctableSize) {
    609               index = 0;
    610             }
    611             dstRow[x] = ctable[index];
    612           }
    613         }
    614         buffer = dst32Storage.get();
    615         rowBytes = width * sizeof(uint32_t);
    616         colorType = SkColorType::kN32_SkColorType;
    617       }
    618       break;
    619     case 24: {
    620       dst32Storage.reset(FX_Alloc2D(uint32_t, width, height));
    621       uint32_t* dst32Pixels = dst32Storage.get();
    622       for (int y = 0; y < height; ++y) {
    623         const uint8_t* srcRow =
    624             static_cast<const uint8_t*>(buffer) + y * rowBytes;
    625         uint32_t* dstRow = dst32Pixels + y * width;
    626         for (int x = 0; x < width; ++x) {
    627           dstRow[x] = SkPackARGB32(0xFF, srcRow[x * 3 + 2], srcRow[x * 3 + 1],
    628                                    srcRow[x * 3 + 0]);
    629         }
    630       }
    631       buffer = dst32Storage.get();
    632       rowBytes = width * sizeof(uint32_t);
    633       colorType = SkColorType::kN32_SkColorType;
    634       alphaType = kOpaque_SkAlphaType;
    635       break;
    636     }
    637     case 32:
    638       colorType = SkColorType::kN32_SkColorType;
    639       alphaType = kPremul_SkAlphaType;
    640       pSource->DebugVerifyBitmapIsPreMultiplied(buffer);
    641       break;
    642     default:
    643       SkASSERT(0);  // TODO(caryclark) ensure that all cases are covered
    644       colorType = SkColorType::kUnknown_SkColorType;
    645   }
    646   SkImageInfo imageInfo =
    647       SkImageInfo::Make(width, height, colorType, alphaType);
    648   skBitmap->installPixels(imageInfo, buffer, rowBytes, *ctPtr, nullptr,
    649                           nullptr);
    650   *widthPtr = width;
    651   *heightPtr = height;
    652   return true;
    653 }
    654 #endif  // _SKIA_SUPPORT_
    655 
    656 }  // namespace
    657 
    658 // Encapsulate the state used for successive text and path draws so that
    659 // they can be combined.
    660 class SkiaState {
    661  public:
    662   enum class Clip {
    663     kSave,
    664     kPath,
    665   };
    666 
    667   enum class Accumulator {
    668     kNone,
    669     kPath,
    670     kText,
    671     kOther,
    672   };
    673 
    674   // mark all cached state as uninitialized
    675   explicit SkiaState(CFX_SkiaDeviceDriver* pDriver)
    676       : m_pDriver(pDriver),
    677         m_pFont(nullptr),
    678         m_fontSize(0),
    679         m_fillColor(0),
    680         m_strokeColor(0),
    681         m_blendType(0),
    682         m_commandIndex(0),
    683         m_drawIndex(INT_MAX),
    684         m_clipIndex(0),
    685         m_type(Accumulator::kNone),
    686         m_fillFullCover(false),
    687         m_fillPath(false),
    688         m_groupKnockout(false),
    689         m_debugDisable(false)
    690 #if SHOW_SKIA_PATH
    691         ,
    692         m_debugSaveCounter(0)
    693 #endif
    694   {
    695   }
    696 
    697   bool DrawPath(const CFX_PathData* pPathData,
    698                 const CFX_Matrix* pMatrix,
    699                 const CFX_GraphStateData* pDrawState,
    700                 uint32_t fill_color,
    701                 uint32_t stroke_color,
    702                 int fill_mode,
    703                 int blend_type) {
    704     if (m_debugDisable)
    705       return false;
    706     Dump(__func__);
    707     int drawIndex = SkTMin(m_drawIndex, m_commands.count());
    708     if (Accumulator::kText == m_type || drawIndex != m_commandIndex ||
    709         (Accumulator::kPath == m_type &&
    710          DrawChanged(pMatrix, pDrawState, fill_color, stroke_color, fill_mode,
    711                      blend_type, m_pDriver->m_bGroupKnockout))) {
    712       Flush();
    713     }
    714     if (Accumulator::kPath != m_type) {
    715       m_skPath.reset();
    716       m_fillFullCover = !!(fill_mode & FXFILL_FULLCOVER);
    717       m_fillPath = (fill_mode & 3) && fill_color;
    718       m_skPath.setFillType((fill_mode & 3) == FXFILL_ALTERNATE
    719                                ? SkPath::kEvenOdd_FillType
    720                                : SkPath::kWinding_FillType);
    721       if (pDrawState)
    722         m_drawState.Copy(*pDrawState);
    723       m_fillColor = fill_color;
    724       m_strokeColor = stroke_color;
    725       m_blendType = blend_type;
    726       m_groupKnockout = m_pDriver->m_bGroupKnockout;
    727       if (pMatrix)
    728         m_drawMatrix = *pMatrix;
    729       m_drawIndex = m_commandIndex;
    730       m_type = Accumulator::kPath;
    731     }
    732     SkPath skPath = BuildPath(pPathData);
    733     SkPoint delta;
    734     if (MatrixOffset(pMatrix, &delta))
    735       skPath.offset(delta.fX, delta.fY);
    736     m_skPath.addPath(skPath);
    737     return true;
    738   }
    739 
    740   void FlushPath() {
    741     Dump(__func__);
    742     SkMatrix skMatrix = ToSkMatrix(m_drawMatrix);
    743     SkPaint skPaint;
    744     skPaint.setAntiAlias(true);
    745     if (m_fillFullCover)
    746       skPaint.setBlendMode(SkBlendMode::kPlus);
    747     int stroke_alpha = FXARGB_A(m_strokeColor);
    748     if (stroke_alpha)
    749       m_pDriver->PaintStroke(&skPaint, &m_drawState, skMatrix);
    750     SkCanvas* skCanvas = m_pDriver->SkiaCanvas();
    751     skCanvas->save();
    752     skCanvas->concat(skMatrix);
    753     if (m_fillPath) {
    754       SkPath strokePath;
    755       const SkPath* fillPath = &m_skPath;
    756       if (stroke_alpha) {
    757         if (m_groupKnockout) {
    758           skPaint.getFillPath(m_skPath, &strokePath);
    759           if (Op(m_skPath, strokePath, SkPathOp::kDifference_SkPathOp,
    760                  &strokePath)) {
    761             fillPath = &strokePath;
    762           }
    763         }
    764       }
    765       skPaint.setStyle(SkPaint::kFill_Style);
    766       skPaint.setColor(m_fillColor);
    767 #ifdef _SKIA_SUPPORT_PATHS_
    768       m_pDriver->PreMultiply();
    769 #endif  // _SKIA_SUPPORT_PATHS_
    770       DebugShowSkiaDrawPath(skCanvas, skPaint, *fillPath);
    771       skCanvas->drawPath(*fillPath, skPaint);
    772     }
    773     if (stroke_alpha) {
    774       skPaint.setStyle(SkPaint::kStroke_Style);
    775       skPaint.setColor(m_strokeColor);
    776 #ifdef _SKIA_SUPPORT_PATHS_
    777       m_pDriver->PreMultiply();
    778 #endif  // _SKIA_SUPPORT_PATHS_
    779       DebugShowSkiaDrawPath(skCanvas, skPaint, m_skPath);
    780       skCanvas->drawPath(m_skPath, skPaint);
    781     }
    782     skCanvas->restore();
    783     m_drawIndex = INT_MAX;
    784     m_type = Accumulator::kNone;
    785   }
    786 
    787   bool DrawText(int nChars,
    788                 const FXTEXT_CHARPOS* pCharPos,
    789                 CFX_Font* pFont,
    790                 const CFX_Matrix* pMatrix,
    791                 FX_FLOAT font_size,
    792                 uint32_t color) {
    793     if (m_debugDisable)
    794       return false;
    795     Dump(__func__);
    796     int drawIndex = SkTMin(m_drawIndex, m_commands.count());
    797     if (Accumulator::kPath == m_type || drawIndex != m_commandIndex ||
    798         (Accumulator::kText == m_type &&
    799          FontChanged(pFont, pMatrix, font_size, color))) {
    800       Flush();
    801     }
    802     if (Accumulator::kText != m_type) {
    803       m_positions.setCount(0);
    804       m_glyphs.setCount(0);
    805       m_pFont = pFont;
    806       m_fontSize = font_size;
    807       m_fillColor = color;
    808       m_drawMatrix = *pMatrix;
    809       m_drawIndex = m_commandIndex;
    810       m_type = Accumulator::kText;
    811     }
    812     int count = m_positions.count();
    813     m_positions.setCount(nChars + count);
    814     m_glyphs.setCount(nChars + count);
    815     SkScalar flip = m_fontSize < 0 ? -1 : 1;
    816     SkScalar vFlip = flip;
    817     if (pFont->IsVertical())
    818       vFlip *= -1;
    819     for (int index = 0; index < nChars; ++index) {
    820       const FXTEXT_CHARPOS& cp = pCharPos[index];
    821       m_positions[index + count] = {cp.m_Origin.x * flip,
    822                                     cp.m_Origin.y * vFlip};
    823       m_glyphs[index + count] = static_cast<uint16_t>(cp.m_GlyphIndex);
    824     }
    825     SkPoint delta;
    826     if (MatrixOffset(pMatrix, &delta)) {
    827       for (int index = 0; index < nChars; ++index)
    828         m_positions[index + count].offset(delta.fX * flip, -delta.fY * flip);
    829     }
    830     return true;
    831   }
    832 
    833   void FlushText() {
    834     Dump(__func__);
    835     SkPaint skPaint;
    836     skPaint.setAntiAlias(true);
    837     skPaint.setColor(m_fillColor);
    838     if (m_pFont->GetFace()) {  // exclude placeholder test fonts
    839       sk_sp<SkTypeface> typeface(SkSafeRef(m_pFont->GetDeviceCache()));
    840       skPaint.setTypeface(typeface);
    841     }
    842     skPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    843     skPaint.setHinting(SkPaint::kNo_Hinting);
    844     skPaint.setTextSize(SkTAbs(m_fontSize));
    845     skPaint.setSubpixelText(true);
    846     SkCanvas* skCanvas = m_pDriver->SkiaCanvas();
    847     skCanvas->save();
    848     SkScalar flip = m_fontSize < 0 ? -1 : 1;
    849     SkMatrix skMatrix = ToFlippedSkMatrix(m_drawMatrix, flip);
    850     skCanvas->concat(skMatrix);
    851 #ifdef _SKIA_SUPPORT_PATHS_
    852     m_pDriver->PreMultiply();
    853 #endif  // _SKIA_SUPPORT_PATHS_
    854     skCanvas->drawPosText(m_glyphs.begin(), m_glyphs.count() * 2,
    855                           m_positions.begin(), skPaint);
    856     skCanvas->restore();
    857     m_drawIndex = INT_MAX;
    858     m_type = Accumulator::kNone;
    859   }
    860 
    861   bool SetClipFill(const CFX_PathData* pPathData,
    862                    const CFX_Matrix* pMatrix,
    863                    int fill_mode) {
    864     if (m_debugDisable)
    865       return false;
    866     Dump(__func__);
    867     SkPath skClipPath = BuildPath(pPathData);
    868     skClipPath.setFillType((fill_mode & 3) == FXFILL_ALTERNATE
    869                                ? SkPath::kEvenOdd_FillType
    870                                : SkPath::kWinding_FillType);
    871     SkMatrix skMatrix = ToSkMatrix(*pMatrix);
    872     skClipPath.transform(skMatrix);
    873     return SetClip(skClipPath);
    874   }
    875 
    876   bool SetClip(const SkPath& skClipPath) {
    877     // if a pending draw depends on clip state that is cached, flush it and draw
    878     if (m_commandIndex < m_commands.count()) {
    879       if (m_commands[m_commandIndex] == Clip::kPath &&
    880           m_clips[m_commandIndex] == skClipPath) {
    881         ++m_commandIndex;
    882         return true;
    883       }
    884       Flush();
    885     }
    886     while (m_clipIndex > m_commandIndex) {
    887       do {
    888         --m_clipIndex;
    889         SkASSERT(m_clipIndex >= 0);
    890       } while (m_commands[m_clipIndex] != Clip::kSave);
    891       m_pDriver->SkiaCanvas()->restore();
    892     }
    893     if (m_commandIndex < m_commands.count()) {
    894       m_commands[m_commandIndex] = Clip::kPath;
    895       m_clips[m_commandIndex] = skClipPath;
    896     } else {
    897       m_commands.push(Clip::kPath);
    898       m_clips.push_back(skClipPath);
    899     }
    900     ++m_commandIndex;
    901     return true;
    902   }
    903 
    904   bool SetClipStroke(const CFX_PathData* pPathData,
    905                      const CFX_Matrix* pMatrix,
    906                      const CFX_GraphStateData* pGraphState) {
    907     if (m_debugDisable)
    908       return false;
    909     Dump(__func__);
    910     SkPath skPath = BuildPath(pPathData);
    911     SkMatrix skMatrix = ToSkMatrix(*pMatrix);
    912     SkPaint skPaint;
    913     m_pDriver->PaintStroke(&skPaint, pGraphState, skMatrix);
    914     SkPath dst_path;
    915     skPaint.getFillPath(skPath, &dst_path);
    916     dst_path.transform(skMatrix);
    917     return SetClip(dst_path);
    918   }
    919 
    920   bool MatrixOffset(const CFX_Matrix* pMatrix, SkPoint* delta) {
    921     CFX_Matrix identityMatrix;
    922     if (!pMatrix)
    923       pMatrix = &identityMatrix;
    924     delta->set(pMatrix->e - m_drawMatrix.e, pMatrix->f - m_drawMatrix.f);
    925     if (!delta->fX && !delta->fY)
    926       return true;
    927     SkMatrix drawMatrix = ToSkMatrix(m_drawMatrix);
    928     if (!(drawMatrix.getType() & ~SkMatrix::kTranslate_Mask))
    929       return true;
    930     SkMatrix invDrawMatrix;
    931     if (!drawMatrix.invert(&invDrawMatrix))
    932       return false;
    933     SkMatrix invNewMatrix;
    934     SkMatrix newMatrix = ToSkMatrix(*pMatrix);
    935     if (!newMatrix.invert(&invNewMatrix))
    936       return false;
    937     delta->set(invDrawMatrix.getTranslateX() - invNewMatrix.getTranslateX(),
    938                invDrawMatrix.getTranslateY() - invNewMatrix.getTranslateY());
    939     return true;
    940   }
    941 
    942   // returns true if caller should apply command to skia canvas
    943   bool ClipSave() {
    944     if (m_debugDisable)
    945       return false;
    946     Dump(__func__);
    947     int count = m_commands.count();
    948     if (m_commandIndex < count - 1) {
    949       if (Clip::kSave == m_commands[m_commandIndex + 1]) {
    950         ++m_commandIndex;
    951         return true;
    952       }
    953       Flush();
    954       AdjustClip(m_commandIndex);
    955       m_commands[++m_commandIndex] = Clip::kSave;
    956       m_clips[m_commandIndex] = m_skEmptyPath;
    957     } else {
    958       AdjustClip(m_commandIndex);
    959       m_commands.push(Clip::kSave);
    960       m_clips.push_back(m_skEmptyPath);
    961       ++m_commandIndex;
    962     }
    963     return true;
    964   }
    965 
    966   bool ClipRestore() {
    967     if (m_debugDisable)
    968       return false;
    969     Dump(__func__);
    970     while (Clip::kSave != m_commands[--m_commandIndex]) {
    971       SkASSERT(m_commandIndex > 0);
    972     }
    973     return true;
    974   }
    975 
    976   bool DrawChanged(const CFX_Matrix* pMatrix,
    977                    const CFX_GraphStateData* pState,
    978                    uint32_t fill_color,
    979                    uint32_t stroke_color,
    980                    int fill_mode,
    981                    int blend_type,
    982                    bool group_knockout) const {
    983     return MatrixChanged(pMatrix, m_drawMatrix) ||
    984            StateChanged(pState, m_drawState) || fill_color != m_fillColor ||
    985            stroke_color != m_strokeColor ||
    986            ((fill_mode & 3) == FXFILL_ALTERNATE) !=
    987                (m_skPath.getFillType() == SkPath::kEvenOdd_FillType) ||
    988            blend_type != m_blendType || group_knockout != m_groupKnockout;
    989   }
    990 
    991   bool FontChanged(CFX_Font* pFont,
    992                    const CFX_Matrix* pMatrix,
    993                    FX_FLOAT font_size,
    994                    uint32_t color) const {
    995     return pFont != m_pFont || MatrixChanged(pMatrix, m_drawMatrix) ||
    996            font_size != m_fontSize || color != m_fillColor;
    997   }
    998 
    999   bool MatrixChanged(const CFX_Matrix* pMatrix,
   1000                      const CFX_Matrix& refMatrix) const {
   1001     CFX_Matrix identityMatrix;
   1002     if (!pMatrix)
   1003       pMatrix = &identityMatrix;
   1004     return pMatrix->a != refMatrix.a || pMatrix->b != refMatrix.b ||
   1005            pMatrix->c != refMatrix.c || pMatrix->d != refMatrix.d;
   1006   }
   1007 
   1008   bool StateChanged(const CFX_GraphStateData* pState,
   1009                     const CFX_GraphStateData& refState) const {
   1010     CFX_GraphStateData identityState;
   1011     if (!pState)
   1012       pState = &identityState;
   1013     return pState->m_LineWidth != refState.m_LineWidth ||
   1014            pState->m_LineCap != refState.m_LineCap ||
   1015            pState->m_LineJoin != refState.m_LineJoin ||
   1016            pState->m_MiterLimit != refState.m_MiterLimit ||
   1017            DashChanged(pState, refState);
   1018   }
   1019 
   1020   bool DashChanged(const CFX_GraphStateData* pState,
   1021                    const CFX_GraphStateData& refState) const {
   1022     bool dashArray = pState && pState->m_DashArray;
   1023     if (!dashArray && !refState.m_DashArray)
   1024       return false;
   1025     if (!dashArray || !refState.m_DashArray)
   1026       return true;
   1027     if (pState->m_DashPhase != refState.m_DashPhase ||
   1028         pState->m_DashCount != refState.m_DashCount) {
   1029       return true;
   1030     }
   1031     for (int index = 0; index < pState->m_DashCount; ++index) {
   1032       if (pState->m_DashArray[index] != refState.m_DashArray[index])
   1033         return true;
   1034     }
   1035     return true;
   1036   }
   1037 
   1038   void AdjustClip(int limit) {
   1039     while (m_clipIndex > limit) {
   1040       do {
   1041         --m_clipIndex;
   1042         SkASSERT(m_clipIndex >= 0);
   1043       } while (m_commands[m_clipIndex] != Clip::kSave);
   1044       m_pDriver->SkiaCanvas()->restore();
   1045     }
   1046     while (m_clipIndex < limit) {
   1047       if (Clip::kSave == m_commands[m_clipIndex]) {
   1048         m_pDriver->SkiaCanvas()->save();
   1049       } else {
   1050         SkASSERT(Clip::kPath == m_commands[m_clipIndex]);
   1051         m_pDriver->SkiaCanvas()->clipPath(m_clips[m_clipIndex],
   1052                                           SkClipOp::kIntersect, true);
   1053       }
   1054       ++m_clipIndex;
   1055     }
   1056   }
   1057 
   1058   void Flush() {
   1059     if (m_debugDisable)
   1060       return;
   1061     Dump(__func__);
   1062     if (Accumulator::kPath == m_type || Accumulator::kText == m_type) {
   1063       AdjustClip(SkTMin(m_drawIndex, m_commands.count()));
   1064       Accumulator::kPath == m_type ? FlushPath() : FlushText();
   1065     }
   1066   }
   1067 
   1068   void FlushForDraw() {
   1069     if (m_debugDisable)
   1070       return;
   1071     Flush();                     // draw any pending text or path
   1072     AdjustClip(m_commandIndex);  // set up clip stack with any pending state
   1073   }
   1074 
   1075 #if SHOW_SKIA_PATH
   1076   void DumpPrefix(int index) const {
   1077     if (index != m_commandIndex && index != m_drawIndex &&
   1078         index != m_clipIndex) {
   1079       printf("     ");
   1080       return;
   1081     }
   1082     printf("%c%c%c> ", index == m_commandIndex ? 'x' : '-',
   1083            index == m_drawIndex ? 'd' : '-', index == m_clipIndex ? 'c' : '-');
   1084   }
   1085 
   1086   void DumpEndPrefix() const {
   1087     int index = m_commands.count();
   1088     if (index != m_commandIndex && index > m_drawIndex && index != m_clipIndex)
   1089       return;
   1090     printf("%c%c%c>\n", index == m_commandIndex ? 'x' : '-',
   1091            index <= m_drawIndex ? 'd' : '-', index == m_clipIndex ? 'c' : '-');
   1092   }
   1093 #endif  // SHOW_SKIA_PATH
   1094 
   1095   void Dump(const char* where) const {
   1096 #if SHOW_SKIA_PATH
   1097     printf("\n%s\nSkia Save Count %d:\n", where,
   1098            m_pDriver->m_pCanvas->getSaveCount());
   1099     printf("Cache:\n");
   1100     for (int index = 0; index < m_commands.count(); ++index) {
   1101       DumpPrefix(index);
   1102       switch (m_commands[index]) {
   1103         case Clip::kSave:
   1104           printf("Save %d\n", ++m_debugSaveCounter);
   1105           break;
   1106         case Clip::kPath:
   1107           m_clips[index].dump();
   1108           break;
   1109         default:
   1110           printf("unknown\n");
   1111       }
   1112     }
   1113     DumpEndPrefix();
   1114 #endif  // SHOW_SKIA_PATH
   1115 #ifdef SK_DEBUG
   1116     int skCanvasSaveCount = m_pDriver->m_pCanvas->getSaveCount();
   1117     int cacheSaveCount = 1;
   1118     SkASSERT(m_clipIndex <= m_commands.count());
   1119     for (int index = 0; index < m_clipIndex; ++index)
   1120       cacheSaveCount += Clip::kSave == m_commands[index];
   1121     SkASSERT(skCanvasSaveCount == cacheSaveCount);
   1122 #endif
   1123   }
   1124 
   1125  private:
   1126   SkTArray<SkPath> m_clips;        // stack of clips that may be reused
   1127   SkTDArray<Clip> m_commands;      // stack of clip-related commands
   1128   SkTDArray<SkPoint> m_positions;  // accumulator for text positions
   1129   SkTDArray<uint16_t> m_glyphs;    // accumulator for text glyphs
   1130   SkPath m_skPath;                 // accumulator for path contours
   1131   SkPath m_skEmptyPath;            // used as placehold in the clips array
   1132   CFX_Matrix m_drawMatrix;
   1133   CFX_GraphStateData m_clipState;
   1134   CFX_GraphStateData m_drawState;
   1135   CFX_Matrix m_clipMatrix;
   1136   CFX_SkiaDeviceDriver* m_pDriver;
   1137   CFX_Font* m_pFont;
   1138   FX_FLOAT m_fontSize;
   1139   uint32_t m_fillColor;
   1140   uint32_t m_strokeColor;
   1141   int m_blendType;
   1142   int m_commandIndex;  // active position in clip command stack
   1143   int m_drawIndex;     // position of the pending path or text draw
   1144   int m_clipIndex;     // position reflecting depth of canvas clip stacck
   1145   Accumulator m_type;  // type of pending draw
   1146   bool m_fillFullCover;
   1147   bool m_fillPath;
   1148   bool m_groupKnockout;
   1149   bool m_debugDisable;  // turn off cache for debugging
   1150 #if SHOW_SKIA_PATH
   1151   mutable int m_debugSaveCounter;
   1152 #endif
   1153 };
   1154 
   1155 // convert a stroking path to scanlines
   1156 void CFX_SkiaDeviceDriver::PaintStroke(SkPaint* spaint,
   1157                                        const CFX_GraphStateData* pGraphState,
   1158                                        const SkMatrix& matrix) {
   1159   SkPaint::Cap cap;
   1160   switch (pGraphState->m_LineCap) {
   1161     case CFX_GraphStateData::LineCapRound:
   1162       cap = SkPaint::kRound_Cap;
   1163       break;
   1164     case CFX_GraphStateData::LineCapSquare:
   1165       cap = SkPaint::kSquare_Cap;
   1166       break;
   1167     default:
   1168       cap = SkPaint::kButt_Cap;
   1169       break;
   1170   }
   1171   SkPaint::Join join;
   1172   switch (pGraphState->m_LineJoin) {
   1173     case CFX_GraphStateData::LineJoinRound:
   1174       join = SkPaint::kRound_Join;
   1175       break;
   1176     case CFX_GraphStateData::LineJoinBevel:
   1177       join = SkPaint::kBevel_Join;
   1178       break;
   1179     default:
   1180       join = SkPaint::kMiter_Join;
   1181       break;
   1182   }
   1183   SkMatrix inverse;
   1184   if (!matrix.invert(&inverse))
   1185     return;  // give up if the matrix is degenerate, and not invertable
   1186   inverse.set(SkMatrix::kMTransX, 0);
   1187   inverse.set(SkMatrix::kMTransY, 0);
   1188   SkVector deviceUnits[2] = {{0, 1}, {1, 0}};
   1189   inverse.mapPoints(deviceUnits, SK_ARRAY_COUNT(deviceUnits));
   1190   FX_FLOAT width =
   1191       SkTMax(pGraphState->m_LineWidth,
   1192              SkTMin(deviceUnits[0].length(), deviceUnits[1].length()));
   1193   if (pGraphState->m_DashArray) {
   1194     int count = (pGraphState->m_DashCount + 1) / 2;
   1195     SkScalar* intervals = FX_Alloc2D(SkScalar, count, sizeof(SkScalar));
   1196     // Set dash pattern
   1197     for (int i = 0; i < count; i++) {
   1198       FX_FLOAT on = pGraphState->m_DashArray[i * 2];
   1199       if (on <= 0.000001f)
   1200         on = 1.f / 10;
   1201       FX_FLOAT off = i * 2 + 1 == pGraphState->m_DashCount
   1202                          ? on
   1203                          : pGraphState->m_DashArray[i * 2 + 1];
   1204       if (off < 0)
   1205         off = 0;
   1206       intervals[i * 2] = on;
   1207       intervals[i * 2 + 1] = off;
   1208     }
   1209     spaint->setPathEffect(
   1210         SkDashPathEffect::Make(intervals, count * 2, pGraphState->m_DashPhase));
   1211   }
   1212   spaint->setStyle(SkPaint::kStroke_Style);
   1213   spaint->setAntiAlias(true);
   1214   spaint->setStrokeWidth(width);
   1215   spaint->setStrokeMiter(pGraphState->m_MiterLimit);
   1216   spaint->setStrokeCap(cap);
   1217   spaint->setStrokeJoin(join);
   1218 }
   1219 
   1220 CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(CFX_DIBitmap* pBitmap,
   1221                                            bool bRgbByteOrder,
   1222                                            CFX_DIBitmap* pOriDevice,
   1223                                            bool bGroupKnockout)
   1224     : m_pBitmap(pBitmap),
   1225       m_pOriDevice(pOriDevice),
   1226       m_pRecorder(nullptr),
   1227       m_pCache(new SkiaState(this)),
   1228 #ifdef _SKIA_SUPPORT_PATHS_
   1229       m_pClipRgn(nullptr),
   1230       m_FillFlags(0),
   1231       m_bRgbByteOrder(bRgbByteOrder),
   1232 #endif  // _SKIA_SUPPORT_PATHS_
   1233       m_bGroupKnockout(bGroupKnockout) {
   1234   SkBitmap skBitmap;
   1235   SkASSERT(pBitmap->GetBPP() == 8 || pBitmap->GetBPP() == 32);
   1236   SkImageInfo imageInfo = SkImageInfo::Make(
   1237       pBitmap->GetWidth(), pBitmap->GetHeight(),
   1238       pBitmap->GetBPP() == 8 ? kAlpha_8_SkColorType : kN32_SkColorType,
   1239       kOpaque_SkAlphaType);
   1240   skBitmap.installPixels(imageInfo, pBitmap->GetBuffer(), pBitmap->GetPitch(),
   1241                          nullptr,  // FIXME(caryclark) set color table
   1242                          nullptr, nullptr);
   1243   m_pCanvas = new SkCanvas(skBitmap);
   1244 }
   1245 
   1246 #ifdef _SKIA_SUPPORT_
   1247 CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(int size_x, int size_y)
   1248     : m_pBitmap(nullptr),
   1249       m_pOriDevice(nullptr),
   1250       m_pRecorder(new SkPictureRecorder),
   1251       m_pCache(new SkiaState(this)),
   1252       m_bGroupKnockout(false) {
   1253   m_pRecorder->beginRecording(SkIntToScalar(size_x), SkIntToScalar(size_y));
   1254   m_pCanvas = m_pRecorder->getRecordingCanvas();
   1255 }
   1256 
   1257 CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(SkPictureRecorder* recorder)
   1258     : m_pBitmap(nullptr),
   1259       m_pOriDevice(nullptr),
   1260       m_pRecorder(recorder),
   1261       m_pCache(new SkiaState(this)),
   1262       m_bGroupKnockout(false) {
   1263   m_pCanvas = m_pRecorder->getRecordingCanvas();
   1264 }
   1265 #endif  // _SKIA_SUPPORT_
   1266 
   1267 CFX_SkiaDeviceDriver::~CFX_SkiaDeviceDriver() {
   1268   Flush();
   1269   if (!m_pRecorder)
   1270     delete m_pCanvas;
   1271 }
   1272 
   1273 void CFX_SkiaDeviceDriver::Flush() {
   1274   m_pCache->Flush();
   1275 }
   1276 
   1277 bool CFX_SkiaDeviceDriver::DrawDeviceText(int nChars,
   1278                                           const FXTEXT_CHARPOS* pCharPos,
   1279                                           CFX_Font* pFont,
   1280                                           const CFX_Matrix* pObject2Device,
   1281                                           FX_FLOAT font_size,
   1282                                           uint32_t color) {
   1283   if (m_pCache->DrawText(nChars, pCharPos, pFont, pObject2Device, font_size,
   1284                          color)) {
   1285     return true;
   1286   }
   1287   sk_sp<SkTypeface> typeface(SkSafeRef(pFont->GetDeviceCache()));
   1288   SkPaint paint;
   1289   paint.setAntiAlias(true);
   1290   paint.setColor(color);
   1291   paint.setTypeface(typeface);
   1292   paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
   1293   paint.setHinting(SkPaint::kNo_Hinting);
   1294   paint.setTextSize(SkTAbs(font_size));
   1295   paint.setSubpixelText(true);
   1296   m_pCanvas->save();
   1297   SkScalar flip = font_size < 0 ? -1 : 1;
   1298   SkScalar vFlip = flip;
   1299   if (pFont->IsVertical())
   1300     vFlip *= -1;
   1301   SkMatrix skMatrix = ToFlippedSkMatrix(*pObject2Device, flip);
   1302   m_pCanvas->concat(skMatrix);
   1303   SkTDArray<SkPoint> positions;
   1304   positions.setCount(nChars);
   1305   SkTDArray<uint16_t> glyphs;
   1306   glyphs.setCount(nChars);
   1307   for (int index = 0; index < nChars; ++index) {
   1308     const FXTEXT_CHARPOS& cp = pCharPos[index];
   1309     positions[index] = {cp.m_Origin.x * flip, cp.m_Origin.y * vFlip};
   1310     glyphs[index] = static_cast<uint16_t>(cp.m_GlyphIndex);
   1311   }
   1312 #ifdef _SKIA_SUPPORT_PATHS_
   1313   m_pBitmap->PreMultiply();
   1314 #endif  // _SKIA_SUPPORT_PATHS_
   1315   m_pCanvas->drawPosText(glyphs.begin(), nChars * 2, positions.begin(), paint);
   1316   m_pCanvas->restore();
   1317 
   1318   return true;
   1319 }
   1320 
   1321 int CFX_SkiaDeviceDriver::GetDeviceCaps(int caps_id) const {
   1322   switch (caps_id) {
   1323     case FXDC_DEVICE_CLASS:
   1324       return FXDC_DISPLAY;
   1325 #ifdef _SKIA_SUPPORT_
   1326     case FXDC_PIXEL_WIDTH:
   1327       return m_pCanvas->imageInfo().width();
   1328     case FXDC_PIXEL_HEIGHT:
   1329       return m_pCanvas->imageInfo().height();
   1330     case FXDC_BITS_PIXEL:
   1331       return 32;
   1332     case FXDC_HORZ_SIZE:
   1333     case FXDC_VERT_SIZE:
   1334       return 0;
   1335     case FXDC_RENDER_CAPS:
   1336       return FXRC_GET_BITS | FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE |
   1337              FXRC_BLEND_MODE | FXRC_SOFT_CLIP | FXRC_ALPHA_OUTPUT |
   1338              FXRC_FILLSTROKE_PATH | FXRC_SHADING;
   1339 #endif  // _SKIA_SUPPORT_
   1340 
   1341 #ifdef _SKIA_SUPPORT_PATHS_
   1342     case FXDC_PIXEL_WIDTH:
   1343       return m_pBitmap->GetWidth();
   1344     case FXDC_PIXEL_HEIGHT:
   1345       return m_pBitmap->GetHeight();
   1346     case FXDC_BITS_PIXEL:
   1347       return m_pBitmap->GetBPP();
   1348     case FXDC_HORZ_SIZE:
   1349     case FXDC_VERT_SIZE:
   1350       return 0;
   1351     case FXDC_RENDER_CAPS: {
   1352       int flags = FXRC_GET_BITS | FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE |
   1353                   FXRC_BLEND_MODE | FXRC_SOFT_CLIP | FXRC_SHADING;
   1354       if (m_pBitmap->HasAlpha()) {
   1355         flags |= FXRC_ALPHA_OUTPUT;
   1356       } else if (m_pBitmap->IsAlphaMask()) {
   1357         if (m_pBitmap->GetBPP() == 1) {
   1358           flags |= FXRC_BITMASK_OUTPUT;
   1359         } else {
   1360           flags |= FXRC_BYTEMASK_OUTPUT;
   1361         }
   1362       }
   1363       if (m_pBitmap->IsCmykImage()) {
   1364         flags |= FXRC_CMYK_OUTPUT;
   1365       }
   1366       return flags;
   1367     }
   1368 #endif  // _SKIA_SUPPORT_PATHS_
   1369   }
   1370   return 0;
   1371 }
   1372 
   1373 void CFX_SkiaDeviceDriver::SaveState() {
   1374   if (!m_pCache->ClipSave())
   1375     m_pCanvas->save();
   1376 
   1377 #ifdef _SKIA_SUPPORT_PATHS_
   1378   std::unique_ptr<CFX_ClipRgn> pClip;
   1379   if (m_pClipRgn)
   1380     pClip = pdfium::MakeUnique<CFX_ClipRgn>(*m_pClipRgn);
   1381   m_StateStack.push_back(std::move(pClip));
   1382 #endif  // _SKIA_SUPPORT_PATHS_
   1383 }
   1384 
   1385 void CFX_SkiaDeviceDriver::RestoreState(bool bKeepSaved) {
   1386   if (!m_pCache->ClipRestore())
   1387     m_pCanvas->restore();
   1388   if (bKeepSaved && !m_pCache->ClipSave())
   1389     m_pCanvas->save();
   1390 #ifdef _SKIA_SUPPORT_PATHS_
   1391   m_pClipRgn.reset();
   1392 
   1393   if (m_StateStack.empty())
   1394     return;
   1395 
   1396   if (bKeepSaved) {
   1397     if (m_StateStack.back())
   1398       m_pClipRgn = pdfium::MakeUnique<CFX_ClipRgn>(*m_StateStack.back());
   1399   } else {
   1400     m_pClipRgn = std::move(m_StateStack.back());
   1401     m_StateStack.pop_back();
   1402   }
   1403 #endif  // _SKIA_SUPPORT_PATHS_
   1404 }
   1405 
   1406 #ifdef _SKIA_SUPPORT_PATHS_
   1407 void CFX_SkiaDeviceDriver::SetClipMask(const FX_RECT& clipBox,
   1408                                        const SkPath& path) {
   1409   FX_RECT path_rect(clipBox.left, clipBox.top, clipBox.right + 1,
   1410                     clipBox.bottom + 1);
   1411   path_rect.Intersect(m_pClipRgn->GetBox());
   1412   CFX_DIBitmapRef mask;
   1413   CFX_DIBitmap* pThisLayer = mask.Emplace();
   1414   pThisLayer->Create(path_rect.Width(), path_rect.Height(), FXDIB_8bppMask);
   1415   pThisLayer->Clear(0);
   1416 
   1417   SkImageInfo imageInfo =
   1418       SkImageInfo::Make(pThisLayer->GetWidth(), pThisLayer->GetHeight(),
   1419                         SkColorType::kAlpha_8_SkColorType, kOpaque_SkAlphaType);
   1420   SkBitmap bitmap;
   1421   bitmap.installPixels(imageInfo, pThisLayer->GetBuffer(),
   1422                        pThisLayer->GetPitch(), nullptr, nullptr, nullptr);
   1423   SkCanvas* canvas = new SkCanvas(bitmap);
   1424   canvas->translate(
   1425       -path_rect.left,
   1426       -path_rect.top);  // FIXME(caryclark) wrong sign(s)? upside down?
   1427   SkPaint paint;
   1428   paint.setAntiAlias((m_FillFlags & FXFILL_NOPATHSMOOTH) == 0);
   1429   canvas->drawPath(path, paint);
   1430   m_pClipRgn->IntersectMaskF(path_rect.left, path_rect.top, mask);
   1431   delete canvas;
   1432 }
   1433 #endif  // _SKIA_SUPPORT_PATHS_
   1434 
   1435 bool CFX_SkiaDeviceDriver::SetClip_PathFill(
   1436     const CFX_PathData* pPathData,     // path info
   1437     const CFX_Matrix* pObject2Device,  // flips object's y-axis
   1438     int fill_mode                      // fill mode, WINDING or ALTERNATE
   1439     ) {
   1440   CFX_Matrix identity;
   1441   const CFX_Matrix* deviceMatrix = pObject2Device ? pObject2Device : &identity;
   1442   bool cached = m_pCache->SetClipFill(pPathData, deviceMatrix, fill_mode);
   1443 
   1444 #ifdef _SKIA_SUPPORT_PATHS_
   1445   m_FillFlags = fill_mode;
   1446   if (!m_pClipRgn) {
   1447     m_pClipRgn = pdfium::MakeUnique<CFX_ClipRgn>(
   1448         GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT));
   1449   }
   1450 #endif  // _SKIA_SUPPORT_PATHS_
   1451   if (pPathData->GetPoints().size() == 5 ||
   1452       pPathData->GetPoints().size() == 4) {
   1453     CFX_FloatRect rectf;
   1454     if (pPathData->IsRect(deviceMatrix, &rectf)) {
   1455       rectf.Intersect(
   1456           CFX_FloatRect(0, 0, (FX_FLOAT)GetDeviceCaps(FXDC_PIXEL_WIDTH),
   1457                         (FX_FLOAT)GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
   1458       // note that PDF's y-axis goes up; Skia's y-axis goes down
   1459       if (!cached) {
   1460         SkRect skClipRect =
   1461             SkRect::MakeLTRB(rectf.left, rectf.bottom, rectf.right, rectf.top);
   1462         DebugDrawSkiaClipRect(m_pCanvas, skClipRect);
   1463         m_pCanvas->clipRect(skClipRect, SkClipOp::kIntersect, true);
   1464       }
   1465 
   1466 #ifdef _SKIA_SUPPORT_PATHS_
   1467       FX_RECT rect = rectf.GetOuterRect();
   1468       m_pClipRgn->IntersectRect(rect);
   1469 #endif  // _SKIA_SUPPORT_PATHS_
   1470       DebugShowCanvasClip(m_pCanvas);
   1471       return true;
   1472     }
   1473   }
   1474   SkPath skClipPath = BuildPath(pPathData);
   1475   skClipPath.setFillType((fill_mode & 3) == FXFILL_ALTERNATE
   1476                              ? SkPath::kEvenOdd_FillType
   1477                              : SkPath::kWinding_FillType);
   1478   SkMatrix skMatrix = ToSkMatrix(*deviceMatrix);
   1479   skClipPath.transform(skMatrix);
   1480   DebugShowSkiaPath(skClipPath);
   1481   if (!cached) {
   1482     DebugDrawSkiaClipPath(m_pCanvas, skClipPath);
   1483     m_pCanvas->clipPath(skClipPath, SkClipOp::kIntersect, true);
   1484   }
   1485 #ifdef _SKIA_SUPPORT_PATHS_
   1486   FX_RECT clipBox(0, 0, GetDeviceCaps(FXDC_PIXEL_WIDTH),
   1487                   GetDeviceCaps(FXDC_PIXEL_HEIGHT));
   1488   SetClipMask(clipBox, skClipPath);
   1489 #endif  // _SKIA_SUPPORT_PATHS_
   1490   DebugShowCanvasClip(m_pCanvas);
   1491   return true;
   1492 }
   1493 
   1494 bool CFX_SkiaDeviceDriver::SetClip_PathStroke(
   1495     const CFX_PathData* pPathData,         // path info
   1496     const CFX_Matrix* pObject2Device,      // optional transformation
   1497     const CFX_GraphStateData* pGraphState  // graphic state, for pen attributes
   1498     ) {
   1499   bool cached = m_pCache->SetClipStroke(pPathData, pObject2Device, pGraphState);
   1500 
   1501 #ifdef _SKIA_SUPPORT_PATHS_
   1502   if (!m_pClipRgn) {
   1503     m_pClipRgn = pdfium::MakeUnique<CFX_ClipRgn>(
   1504         GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT));
   1505   }
   1506 #endif  // _SKIA_SUPPORT_PATHS_
   1507   // build path data
   1508   SkPath skPath = BuildPath(pPathData);
   1509   SkMatrix skMatrix = ToSkMatrix(*pObject2Device);
   1510   SkPaint skPaint;
   1511   PaintStroke(&skPaint, pGraphState, skMatrix);
   1512   SkPath dst_path;
   1513   skPaint.getFillPath(skPath, &dst_path);
   1514   dst_path.transform(skMatrix);
   1515   if (!cached) {
   1516     DebugDrawSkiaClipPath(m_pCanvas, dst_path);
   1517     m_pCanvas->clipPath(dst_path, SkClipOp::kIntersect, true);
   1518   }
   1519 #ifdef _SKIA_SUPPORT_PATHS_
   1520   FX_RECT clipBox(0, 0, GetDeviceCaps(FXDC_PIXEL_WIDTH),
   1521                   GetDeviceCaps(FXDC_PIXEL_HEIGHT));
   1522   SetClipMask(clipBox, dst_path);
   1523 #endif  // _SKIA_SUPPORT_PATHS_
   1524   DebugShowCanvasClip(m_pCanvas);
   1525   return true;
   1526 }
   1527 
   1528 bool CFX_SkiaDeviceDriver::DrawPath(
   1529     const CFX_PathData* pPathData,          // path info
   1530     const CFX_Matrix* pObject2Device,       // optional transformation
   1531     const CFX_GraphStateData* pGraphState,  // graphic state, for pen attributes
   1532     uint32_t fill_color,                    // fill color
   1533     uint32_t stroke_color,                  // stroke color
   1534     int fill_mode,  // fill mode, WINDING or ALTERNATE. 0 for not filled
   1535     int blend_type) {
   1536   if (fill_mode & FX_ZEROAREA_FILL)
   1537     return true;
   1538   if (m_pCache->DrawPath(pPathData, pObject2Device, pGraphState, fill_color,
   1539                          stroke_color, fill_mode, blend_type)) {
   1540     return true;
   1541   }
   1542   SkMatrix skMatrix;
   1543   if (pObject2Device)
   1544     skMatrix = ToSkMatrix(*pObject2Device);
   1545   else
   1546     skMatrix.setIdentity();
   1547   SkPaint skPaint;
   1548   skPaint.setAntiAlias(true);
   1549   if (fill_mode & FXFILL_FULLCOVER)
   1550     skPaint.setBlendMode(SkBlendMode::kPlus);
   1551   int stroke_alpha = FXARGB_A(stroke_color);
   1552   if (pGraphState && stroke_alpha)
   1553     PaintStroke(&skPaint, pGraphState, skMatrix);
   1554   SkPath skPath = BuildPath(pPathData);
   1555   m_pCanvas->save();
   1556   m_pCanvas->concat(skMatrix);
   1557   if ((fill_mode & 3) && fill_color) {
   1558     skPath.setFillType((fill_mode & 3) == FXFILL_ALTERNATE
   1559                            ? SkPath::kEvenOdd_FillType
   1560                            : SkPath::kWinding_FillType);
   1561     SkPath strokePath;
   1562     const SkPath* fillPath = &skPath;
   1563     if (pGraphState && stroke_alpha) {
   1564       if (m_bGroupKnockout) {
   1565         skPaint.getFillPath(skPath, &strokePath);
   1566         if (Op(skPath, strokePath, SkPathOp::kDifference_SkPathOp,
   1567                &strokePath)) {
   1568           fillPath = &strokePath;
   1569         }
   1570       }
   1571     }
   1572     skPaint.setStyle(SkPaint::kFill_Style);
   1573     skPaint.setColor(fill_color);
   1574 #ifdef _SKIA_SUPPORT_PATHS_
   1575     m_pBitmap->PreMultiply();
   1576 #endif  // _SKIA_SUPPORT_PATHS_
   1577     DebugShowSkiaDrawPath(m_pCanvas, skPaint, *fillPath);
   1578     m_pCanvas->drawPath(*fillPath, skPaint);
   1579   }
   1580   if (pGraphState && stroke_alpha) {
   1581     skPaint.setStyle(SkPaint::kStroke_Style);
   1582     skPaint.setColor(stroke_color);
   1583 #ifdef _SKIA_SUPPORT_PATHS_
   1584     m_pBitmap->PreMultiply();
   1585 #endif  // _SKIA_SUPPORT_PATHS_
   1586     DebugShowSkiaDrawPath(m_pCanvas, skPaint, skPath);
   1587     m_pCanvas->drawPath(skPath, skPaint);
   1588   }
   1589   m_pCanvas->restore();
   1590   return true;
   1591 }
   1592 
   1593 bool CFX_SkiaDeviceDriver::DrawCosmeticLine(FX_FLOAT x1,
   1594                                             FX_FLOAT y1,
   1595                                             FX_FLOAT x2,
   1596                                             FX_FLOAT y2,
   1597                                             uint32_t color,
   1598                                             int blend_type) {
   1599   return false;
   1600 }
   1601 
   1602 bool CFX_SkiaDeviceDriver::FillRectWithBlend(const FX_RECT* pRect,
   1603                                              uint32_t fill_color,
   1604                                              int blend_type) {
   1605   m_pCache->FlushForDraw();
   1606   SkPaint spaint;
   1607   spaint.setAntiAlias(true);
   1608   spaint.setColor(fill_color);
   1609   spaint.setBlendMode(GetSkiaBlendMode(blend_type));
   1610   SkRect rect =
   1611       SkRect::MakeLTRB(pRect->left, SkTMin(pRect->top, pRect->bottom),
   1612                        pRect->right, SkTMax(pRect->bottom, pRect->top));
   1613   DebugShowSkiaDrawRect(m_pCanvas, spaint, rect);
   1614   m_pCanvas->drawRect(rect, spaint);
   1615   return true;
   1616 }
   1617 
   1618 bool CFX_SkiaDeviceDriver::DrawShading(const CPDF_ShadingPattern* pPattern,
   1619                                        const CFX_Matrix* pMatrix,
   1620                                        const FX_RECT& clip_rect,
   1621                                        int alpha,
   1622                                        bool bAlphaMode) {
   1623   m_pCache->FlushForDraw();
   1624   ShadingType shadingType = pPattern->GetShadingType();
   1625   if (kAxialShading != shadingType && kRadialShading != shadingType &&
   1626       kCoonsPatchMeshShading != shadingType) {
   1627     // TODO(caryclark) more types
   1628     return false;
   1629   }
   1630   int csFamily = pPattern->GetCS()->GetFamily();
   1631   if (PDFCS_DEVICERGB != csFamily && PDFCS_DEVICEGRAY != csFamily)
   1632     return false;
   1633   const std::vector<std::unique_ptr<CPDF_Function>>& pFuncs =
   1634       pPattern->GetFuncs();
   1635   int nFuncs = pFuncs.size();
   1636   if (nFuncs > 1)  // TODO(caryclark) remove this restriction
   1637     return false;
   1638   CPDF_Dictionary* pDict = pPattern->GetShadingObject()->GetDict();
   1639   CPDF_Array* pCoords = pDict->GetArrayFor("Coords");
   1640   if (!pCoords && kCoonsPatchMeshShading != shadingType)
   1641     return false;
   1642   // TODO(caryclark) Respect Domain[0], Domain[1]. (Don't know what they do
   1643   // yet.)
   1644   SkTDArray<SkColor> skColors;
   1645   SkTDArray<SkScalar> skPos;
   1646   for (int j = 0; j < nFuncs; j++) {
   1647     if (!pFuncs[j])
   1648       continue;
   1649 
   1650     if (const CPDF_SampledFunc* pSampledFunc = pFuncs[j]->ToSampledFunc()) {
   1651       /* TODO(caryclark)
   1652          Type 0 Sampled Functions in PostScript can also have an Order integer
   1653          in the dictionary. PDFium doesn't appear to check for this anywhere.
   1654        */
   1655       if (!AddSamples(pSampledFunc, &skColors, &skPos))
   1656         return false;
   1657     } else if (const CPDF_ExpIntFunc* pExpIntFuc = pFuncs[j]->ToExpIntFunc()) {
   1658       if (!AddColors(pExpIntFuc, &skColors))
   1659         return false;
   1660       skPos.push(0);
   1661       skPos.push(1);
   1662     } else if (const CPDF_StitchFunc* pStitchFunc = pFuncs[j]->ToStitchFunc()) {
   1663       if (!AddStitching(pStitchFunc, &skColors, &skPos))
   1664         return false;
   1665     } else {
   1666       return false;
   1667     }
   1668   }
   1669   CPDF_Array* pArray = pDict->GetArrayFor("Extend");
   1670   bool clipStart = !pArray || !pArray->GetIntegerAt(0);
   1671   bool clipEnd = !pArray || !pArray->GetIntegerAt(1);
   1672   SkPaint paint;
   1673   paint.setAntiAlias(true);
   1674   paint.setAlpha(alpha);
   1675   SkMatrix skMatrix = ToSkMatrix(*pMatrix);
   1676   SkRect skRect = SkRect::MakeLTRB(clip_rect.left, clip_rect.top,
   1677                                    clip_rect.right, clip_rect.bottom);
   1678   SkPath skClip;
   1679   SkPath skPath;
   1680   if (kAxialShading == shadingType) {
   1681     FX_FLOAT start_x = pCoords->GetNumberAt(0);
   1682     FX_FLOAT start_y = pCoords->GetNumberAt(1);
   1683     FX_FLOAT end_x = pCoords->GetNumberAt(2);
   1684     FX_FLOAT end_y = pCoords->GetNumberAt(3);
   1685     SkPoint pts[] = {{start_x, start_y}, {end_x, end_y}};
   1686     skMatrix.mapPoints(pts, SK_ARRAY_COUNT(pts));
   1687     paint.setShader(SkGradientShader::MakeLinear(
   1688         pts, skColors.begin(), skPos.begin(), skColors.count(),
   1689         SkShader::kClamp_TileMode));
   1690     if (clipStart || clipEnd) {
   1691       // if the gradient is horizontal or vertical, modify the draw rectangle
   1692       if (pts[0].fX == pts[1].fX) {  // vertical
   1693         if (pts[0].fY > pts[1].fY) {
   1694           SkTSwap(pts[0].fY, pts[1].fY);
   1695           SkTSwap(clipStart, clipEnd);
   1696         }
   1697         if (clipStart)
   1698           skRect.fTop = SkTMax(skRect.fTop, pts[0].fY);
   1699         if (clipEnd)
   1700           skRect.fBottom = SkTMin(skRect.fBottom, pts[1].fY);
   1701       } else if (pts[0].fY == pts[1].fY) {  // horizontal
   1702         if (pts[0].fX > pts[1].fX) {
   1703           SkTSwap(pts[0].fX, pts[1].fX);
   1704           SkTSwap(clipStart, clipEnd);
   1705         }
   1706         if (clipStart)
   1707           skRect.fLeft = SkTMax(skRect.fLeft, pts[0].fX);
   1708         if (clipEnd)
   1709           skRect.fRight = SkTMin(skRect.fRight, pts[1].fX);
   1710       } else {  // if the gradient is angled and contained by the rect, clip
   1711         SkPoint rectPts[4] = {{skRect.fLeft, skRect.fTop},
   1712                               {skRect.fRight, skRect.fTop},
   1713                               {skRect.fRight, skRect.fBottom},
   1714                               {skRect.fLeft, skRect.fBottom}};
   1715         ClipAngledGradient(pts, rectPts, clipStart, clipEnd, &skClip);
   1716       }
   1717     }
   1718     skPath.addRect(skRect);
   1719     skMatrix.setIdentity();
   1720   } else if (kRadialShading == shadingType) {
   1721     FX_FLOAT start_x = pCoords->GetNumberAt(0);
   1722     FX_FLOAT start_y = pCoords->GetNumberAt(1);
   1723     FX_FLOAT start_r = pCoords->GetNumberAt(2);
   1724     FX_FLOAT end_x = pCoords->GetNumberAt(3);
   1725     FX_FLOAT end_y = pCoords->GetNumberAt(4);
   1726     FX_FLOAT end_r = pCoords->GetNumberAt(5);
   1727     SkPoint pts[] = {{start_x, start_y}, {end_x, end_y}};
   1728 
   1729     paint.setShader(SkGradientShader::MakeTwoPointConical(
   1730         pts[0], start_r, pts[1], end_r, skColors.begin(), skPos.begin(),
   1731         skColors.count(), SkShader::kClamp_TileMode));
   1732     if (clipStart || clipEnd) {
   1733       if (clipStart && start_r)
   1734         skClip.addCircle(pts[0].fX, pts[0].fY, start_r);
   1735       if (clipEnd)
   1736         skClip.addCircle(pts[1].fX, pts[1].fY, end_r, SkPath::kCCW_Direction);
   1737       else
   1738         skClip.setFillType(SkPath::kInverseWinding_FillType);
   1739       skClip.transform(skMatrix);
   1740     }
   1741     SkMatrix inverse;
   1742     if (!skMatrix.invert(&inverse))
   1743       return false;
   1744     skPath.addRect(skRect);
   1745     skPath.transform(inverse);
   1746   } else {
   1747     ASSERT(kCoonsPatchMeshShading == shadingType);
   1748     CPDF_Stream* pStream = ToStream(pPattern->GetShadingObject());
   1749     if (!pStream)
   1750       return false;
   1751     CPDF_MeshStream stream(shadingType, pPattern->GetFuncs(), pStream,
   1752                            pPattern->GetCS());
   1753     if (!stream.Load())
   1754       return false;
   1755     SkPoint cubics[12];
   1756     SkColor colors[4];
   1757     m_pCanvas->save();
   1758     if (!skClip.isEmpty())
   1759       m_pCanvas->clipPath(skClip, SkClipOp::kIntersect, true);
   1760     m_pCanvas->concat(skMatrix);
   1761     while (!stream.BitStream()->IsEOF()) {
   1762       uint32_t flag = stream.ReadFlag();
   1763       int iStartPoint = flag ? 4 : 0;
   1764       int iStartColor = flag ? 2 : 0;
   1765       if (flag) {
   1766         SkPoint tempCubics[4];
   1767         for (int i = 0; i < (int)SK_ARRAY_COUNT(tempCubics); i++)
   1768           tempCubics[i] = cubics[(flag * 3 + i) % 12];
   1769         FXSYS_memcpy(cubics, tempCubics, sizeof(tempCubics));
   1770         SkColor tempColors[2];
   1771         tempColors[0] = colors[flag];
   1772         tempColors[1] = colors[(flag + 1) % 4];
   1773         FXSYS_memcpy(colors, tempColors, sizeof(tempColors));
   1774       }
   1775       for (int i = iStartPoint; i < (int)SK_ARRAY_COUNT(cubics); i++) {
   1776         CFX_PointF point = stream.ReadCoords();
   1777         cubics[i].fX = point.x;
   1778         cubics[i].fY = point.y;
   1779       }
   1780       for (int i = iStartColor; i < (int)SK_ARRAY_COUNT(colors); i++) {
   1781         FX_FLOAT r;
   1782         FX_FLOAT g;
   1783         FX_FLOAT b;
   1784         std::tie(r, g, b) = stream.ReadColor();
   1785         colors[i] = SkColorSetARGBInline(0xFF, (U8CPU)(r * 255),
   1786                                          (U8CPU)(g * 255), (U8CPU)(b * 255));
   1787       }
   1788       m_pCanvas->drawPatch(cubics, colors, nullptr, paint);
   1789     }
   1790     m_pCanvas->restore();
   1791     return true;
   1792   }
   1793   m_pCanvas->save();
   1794   if (!skClip.isEmpty())
   1795     m_pCanvas->clipPath(skClip, SkClipOp::kIntersect, true);
   1796   m_pCanvas->concat(skMatrix);
   1797   m_pCanvas->drawPath(skPath, paint);
   1798   m_pCanvas->restore();
   1799   return true;
   1800 }
   1801 
   1802 uint8_t* CFX_SkiaDeviceDriver::GetBuffer() const {
   1803   return m_pBitmap->GetBuffer();
   1804 }
   1805 
   1806 bool CFX_SkiaDeviceDriver::GetClipBox(FX_RECT* pRect) {
   1807   // TODO(caryclark) call m_canvas->getClipDeviceBounds() instead
   1808   pRect->left = 0;
   1809   pRect->top = 0;
   1810   const SkImageInfo& canvasSize = m_pCanvas->imageInfo();
   1811   pRect->right = canvasSize.width();
   1812   pRect->bottom = canvasSize.height();
   1813   return true;
   1814 }
   1815 
   1816 bool CFX_SkiaDeviceDriver::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) {
   1817   if (!m_pBitmap)
   1818     return true;
   1819   uint8_t* srcBuffer = m_pBitmap->GetBuffer();
   1820   if (!srcBuffer)
   1821     return true;
   1822 #ifdef _SKIA_SUPPORT_
   1823   m_pCache->FlushForDraw();
   1824   int srcWidth = m_pBitmap->GetWidth();
   1825   int srcHeight = m_pBitmap->GetHeight();
   1826   int srcRowBytes = srcWidth * sizeof(uint32_t);
   1827   SkImageInfo srcImageInfo = SkImageInfo::Make(
   1828       srcWidth, srcHeight, SkColorType::kN32_SkColorType, kPremul_SkAlphaType);
   1829   SkBitmap skSrcBitmap;
   1830   skSrcBitmap.installPixels(srcImageInfo, srcBuffer, srcRowBytes, nullptr,
   1831                             nullptr, nullptr);
   1832   SkASSERT(pBitmap);
   1833   uint8_t* dstBuffer = pBitmap->GetBuffer();
   1834   SkASSERT(dstBuffer);
   1835   int dstWidth = pBitmap->GetWidth();
   1836   int dstHeight = pBitmap->GetHeight();
   1837   int dstRowBytes = dstWidth * sizeof(uint32_t);
   1838   SkImageInfo dstImageInfo = SkImageInfo::Make(
   1839       dstWidth, dstHeight, SkColorType::kN32_SkColorType, kPremul_SkAlphaType);
   1840   SkBitmap skDstBitmap;
   1841   skDstBitmap.installPixels(dstImageInfo, dstBuffer, dstRowBytes, nullptr,
   1842                             nullptr, nullptr);
   1843   SkCanvas canvas(skDstBitmap);
   1844   canvas.drawBitmap(skSrcBitmap, left, top, nullptr);
   1845   return true;
   1846 #endif  // _SKIA_SUPPORT_
   1847 
   1848 #ifdef _SKIA_SUPPORT_PATHS_
   1849   Flush();
   1850   m_pBitmap->UnPreMultiply();
   1851   FX_RECT rect(left, top, left + pBitmap->GetWidth(),
   1852                top + pBitmap->GetHeight());
   1853   std::unique_ptr<CFX_DIBitmap> pBack;
   1854   if (m_pOriDevice) {
   1855     pBack = m_pOriDevice->Clone(&rect);
   1856     if (!pBack)
   1857       return true;
   1858 
   1859     pBack->CompositeBitmap(0, 0, pBack->GetWidth(), pBack->GetHeight(),
   1860                            m_pBitmap, 0, 0);
   1861   } else {
   1862     pBack = m_pBitmap->Clone(&rect);
   1863     if (!pBack)
   1864       return true;
   1865   }
   1866 
   1867   bool bRet = true;
   1868   left = std::min(left, 0);
   1869   top = std::min(top, 0);
   1870   if (m_bRgbByteOrder) {
   1871     RgbByteOrderTransferBitmap(pBitmap, 0, 0, rect.Width(), rect.Height(),
   1872                                pBack.get(), left, top);
   1873   } else {
   1874     bRet = pBitmap->TransferBitmap(0, 0, rect.Width(), rect.Height(),
   1875                                    pBack.get(), left, top);
   1876   }
   1877   return bRet;
   1878 #endif  // _SKIA_SUPPORT_PATHS_
   1879 }
   1880 
   1881 CFX_DIBitmap* CFX_SkiaDeviceDriver::GetBackDrop() {
   1882   return m_pOriDevice;
   1883 }
   1884 
   1885 bool CFX_SkiaDeviceDriver::SetDIBits(const CFX_DIBSource* pBitmap,
   1886                                      uint32_t argb,
   1887                                      const FX_RECT* pSrcRect,
   1888                                      int left,
   1889                                      int top,
   1890                                      int blend_type) {
   1891   if (!m_pBitmap || !m_pBitmap->GetBuffer())
   1892     return true;
   1893 
   1894 #ifdef _SKIA_SUPPORT_
   1895   CFX_Matrix m(pBitmap->GetWidth(), 0, 0, -pBitmap->GetHeight(), left,
   1896                top + pBitmap->GetHeight());
   1897   void* dummy;
   1898   return StartDIBits(pBitmap, 0xFF, argb, &m, 0, dummy, blend_type);
   1899 #endif  // _SKIA_SUPPORT_
   1900 
   1901 #ifdef _SKIA_SUPPORT_PATHS_
   1902   Flush();
   1903   if (pBitmap->IsAlphaMask()) {
   1904     return m_pBitmap->CompositeMask(
   1905         left, top, pSrcRect->Width(), pSrcRect->Height(), pBitmap, argb,
   1906         pSrcRect->left, pSrcRect->top, blend_type, m_pClipRgn.get(),
   1907         m_bRgbByteOrder, 0, nullptr);
   1908   }
   1909   return m_pBitmap->CompositeBitmap(
   1910       left, top, pSrcRect->Width(), pSrcRect->Height(), pBitmap, pSrcRect->left,
   1911       pSrcRect->top, blend_type, m_pClipRgn.get(), m_bRgbByteOrder, nullptr);
   1912 #endif  // _SKIA_SUPPORT_PATHS_
   1913 }
   1914 
   1915 bool CFX_SkiaDeviceDriver::StretchDIBits(const CFX_DIBSource* pSource,
   1916                                          uint32_t argb,
   1917                                          int dest_left,
   1918                                          int dest_top,
   1919                                          int dest_width,
   1920                                          int dest_height,
   1921                                          const FX_RECT* pClipRect,
   1922                                          uint32_t flags,
   1923                                          int blend_type) {
   1924 #ifdef _SKIA_SUPPORT_
   1925   m_pCache->FlushForDraw();
   1926   if (!m_pBitmap->GetBuffer())
   1927     return true;
   1928   CFX_Matrix m(dest_width, 0, 0, -dest_height, dest_left,
   1929                dest_top + dest_height);
   1930 
   1931   m_pCanvas->save();
   1932   SkRect skClipRect = SkRect::MakeLTRB(pClipRect->left, pClipRect->bottom,
   1933                                        pClipRect->right, pClipRect->top);
   1934   m_pCanvas->clipRect(skClipRect, SkClipOp::kIntersect, true);
   1935   void* dummy;
   1936   bool result = StartDIBits(pSource, 0xFF, argb, &m, 0, dummy, blend_type);
   1937   m_pCanvas->restore();
   1938 
   1939   return result;
   1940 #endif  // _SKIA_SUPPORT_
   1941 
   1942 #ifdef _SKIA_SUPPORT_PATHS_
   1943   if (dest_width == pSource->GetWidth() &&
   1944       dest_height == pSource->GetHeight()) {
   1945     FX_RECT rect(0, 0, dest_width, dest_height);
   1946     return SetDIBits(pSource, argb, &rect, dest_left, dest_top, blend_type);
   1947   }
   1948   Flush();
   1949   FX_RECT dest_rect(dest_left, dest_top, dest_left + dest_width,
   1950                     dest_top + dest_height);
   1951   dest_rect.Normalize();
   1952   FX_RECT dest_clip = dest_rect;
   1953   dest_clip.Intersect(*pClipRect);
   1954   CFX_BitmapComposer composer;
   1955   composer.Compose(m_pBitmap, m_pClipRgn.get(), 255, argb, dest_clip, false,
   1956                    false, false, m_bRgbByteOrder, 0, nullptr, blend_type);
   1957   dest_clip.Offset(-dest_rect.left, -dest_rect.top);
   1958   CFX_ImageStretcher stretcher(&composer, pSource, dest_width, dest_height,
   1959                                dest_clip, flags);
   1960   if (stretcher.Start())
   1961     stretcher.Continue(nullptr);
   1962   return true;
   1963 #endif  // _SKIA_SUPPORT_PATHS_
   1964 }
   1965 
   1966 bool CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource,
   1967                                        int bitmap_alpha,
   1968                                        uint32_t argb,
   1969                                        const CFX_Matrix* pMatrix,
   1970                                        uint32_t render_flags,
   1971                                        void*& handle,
   1972                                        int blend_type) {
   1973 #ifdef _SKIA_SUPPORT_
   1974   m_pCache->FlushForDraw();
   1975   DebugValidate(m_pBitmap, m_pOriDevice);
   1976   SkColorTable* ct = nullptr;
   1977   std::unique_ptr<uint8_t, FxFreeDeleter> dst8Storage;
   1978   std::unique_ptr<uint32_t, FxFreeDeleter> dst32Storage;
   1979   SkBitmap skBitmap;
   1980   int width, height;
   1981   if (!Upsample(pSource, dst8Storage, dst32Storage, &ct, &skBitmap, &width,
   1982                 &height, false)) {
   1983     return false;
   1984   }
   1985   m_pCanvas->save();
   1986   SkMatrix skMatrix;
   1987   SetBitmapMatrix(pMatrix, width, height, &skMatrix);
   1988   m_pCanvas->concat(skMatrix);
   1989   SkPaint paint;
   1990   SetBitmapPaint(pSource->IsAlphaMask(), argb, bitmap_alpha, blend_type,
   1991                  &paint);
   1992   // TODO(caryclark) Once Skia supports 8 bit src to 8 bit dst remove this
   1993   if (m_pBitmap && m_pBitmap->GetBPP() == 8 && pSource->GetBPP() == 8) {
   1994     SkMatrix inv;
   1995     SkAssertResult(skMatrix.invert(&inv));
   1996     for (int y = 0; y < m_pBitmap->GetHeight(); ++y) {
   1997       for (int x = 0; x < m_pBitmap->GetWidth(); ++x) {
   1998         SkPoint src = {x + 0.5f, y + 0.5f};
   1999         inv.mapPoints(&src, 1);
   2000         // TODO(caryclark) Why does the matrix map require clamping?
   2001         src.fX = SkTMax(0.5f, SkTMin(src.fX, width - 0.5f));
   2002         src.fY = SkTMax(0.5f, SkTMin(src.fY, height - 0.5f));
   2003         m_pBitmap->SetPixel(x, y, skBitmap.getColor(src.fX, src.fY));
   2004       }
   2005     }
   2006   } else {
   2007     m_pCanvas->drawBitmap(skBitmap, 0, 0, &paint);
   2008   }
   2009   m_pCanvas->restore();
   2010   if (ct)
   2011     ct->unref();
   2012   DebugValidate(m_pBitmap, m_pOriDevice);
   2013 #endif  // _SKIA_SUPPORT_
   2014 
   2015 #ifdef _SKIA_SUPPORT_PATHS_
   2016   Flush();
   2017   if (!m_pBitmap->GetBuffer())
   2018     return true;
   2019   m_pBitmap->UnPreMultiply();
   2020   CFX_ImageRenderer* pRenderer = new CFX_ImageRenderer;
   2021   pRenderer->Start(m_pBitmap, m_pClipRgn.get(), pSource, bitmap_alpha, argb,
   2022                    pMatrix, render_flags, m_bRgbByteOrder, 0, nullptr);
   2023   handle = pRenderer;
   2024 #endif  // _SKIA_SUPPORT_PATHS_
   2025   return true;
   2026 }
   2027 
   2028 bool CFX_SkiaDeviceDriver::ContinueDIBits(void* handle, IFX_Pause* pPause) {
   2029 #ifdef _SKIA_SUPPORT_
   2030   m_pCache->FlushForDraw();
   2031   return false;
   2032 #endif  // _SKIA_SUPPORT_
   2033 
   2034 #ifdef _SKIA_SUPPORT_PATHS_
   2035   Flush();
   2036   if (!m_pBitmap->GetBuffer()) {
   2037     return true;
   2038   }
   2039   return static_cast<CFX_ImageRenderer*>(handle)->Continue(pPause);
   2040 #endif  // _SKIA_SUPPORT_PATHS_
   2041 }
   2042 
   2043 #if defined _SKIA_SUPPORT_
   2044 void CFX_SkiaDeviceDriver::PreMultiply(CFX_DIBitmap* pDIBitmap) {
   2045   pDIBitmap->PreMultiply();
   2046 }
   2047 #endif  // _SKIA_SUPPORT_
   2048 
   2049 void CFX_DIBitmap::PreMultiply() {
   2050   if (this->GetBPP() != 32)
   2051     return;
   2052   void* buffer = this->GetBuffer();
   2053   if (!buffer)
   2054     return;
   2055 #if defined _SKIA_SUPPORT_PATHS_
   2056   Format priorFormat = m_nFormat;
   2057   m_nFormat = Format::kPreMultiplied;
   2058   if (priorFormat != Format::kUnPreMultiplied)
   2059     return;
   2060 #endif
   2061   int height = this->GetHeight();
   2062   int width = this->GetWidth();
   2063   int rowBytes = this->GetPitch();
   2064   SkImageInfo unpremultipliedInfo =
   2065       SkImageInfo::Make(width, height, kN32_SkColorType, kUnpremul_SkAlphaType);
   2066   SkPixmap unpremultiplied(unpremultipliedInfo, buffer, rowBytes);
   2067   SkImageInfo premultipliedInfo =
   2068       SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType);
   2069   SkPixmap premultiplied(premultipliedInfo, buffer, rowBytes);
   2070   unpremultiplied.readPixels(premultiplied);
   2071   this->DebugVerifyBitmapIsPreMultiplied();
   2072 }
   2073 
   2074 #ifdef _SKIA_SUPPORT_PATHS_
   2075 void CFX_DIBitmap::UnPreMultiply() {
   2076   if (this->GetBPP() != 32)
   2077     return;
   2078   void* buffer = this->GetBuffer();
   2079   if (!buffer)
   2080     return;
   2081   Format priorFormat = m_nFormat;
   2082   m_nFormat = Format::kUnPreMultiplied;
   2083   if (priorFormat != Format::kPreMultiplied)
   2084     return;
   2085   this->DebugVerifyBitmapIsPreMultiplied();
   2086   int height = this->GetHeight();
   2087   int width = this->GetWidth();
   2088   int rowBytes = this->GetPitch();
   2089   SkImageInfo premultipliedInfo =
   2090       SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType);
   2091   SkPixmap premultiplied(premultipliedInfo, buffer, rowBytes);
   2092   SkImageInfo unpremultipliedInfo =
   2093       SkImageInfo::Make(width, height, kN32_SkColorType, kUnpremul_SkAlphaType);
   2094   SkPixmap unpremultiplied(unpremultipliedInfo, buffer, rowBytes);
   2095   premultiplied.readPixels(unpremultiplied);
   2096 }
   2097 #endif  // _SKIA_SUPPORT_PATHS_
   2098 
   2099 #ifdef _SKIA_SUPPORT_
   2100 bool CFX_SkiaDeviceDriver::DrawBitsWithMask(const CFX_DIBSource* pSource,
   2101                                             const CFX_DIBSource* pMask,
   2102                                             int bitmap_alpha,
   2103                                             const CFX_Matrix* pMatrix,
   2104                                             int blend_type) {
   2105   DebugValidate(m_pBitmap, m_pOriDevice);
   2106   SkColorTable* srcCt = nullptr;
   2107   SkColorTable* maskCt = nullptr;
   2108   std::unique_ptr<uint8_t, FxFreeDeleter> src8Storage, mask8Storage;
   2109   std::unique_ptr<uint32_t, FxFreeDeleter> src32Storage, mask32Storage;
   2110   SkBitmap skBitmap, skMask;
   2111   int srcWidth, srcHeight, maskWidth, maskHeight;
   2112   if (!Upsample(pSource, src8Storage, src32Storage, &srcCt, &skBitmap,
   2113                 &srcWidth, &srcHeight, false)) {
   2114     return false;
   2115   }
   2116   if (!Upsample(pMask, mask8Storage, mask32Storage, &maskCt, &skMask,
   2117                 &maskWidth, &maskHeight, true)) {
   2118     return false;
   2119   }
   2120   m_pCanvas->save();
   2121   SkMatrix skMatrix;
   2122   SetBitmapMatrix(pMatrix, srcWidth, srcHeight, &skMatrix);
   2123   m_pCanvas->concat(skMatrix);
   2124   SkPaint paint;
   2125   SetBitmapPaint(pSource->IsAlphaMask(), 0xFFFFFFFF, bitmap_alpha, blend_type,
   2126                  &paint);
   2127   sk_sp<SkImage> skSrc = SkImage::MakeFromBitmap(skBitmap);
   2128   sk_sp<SkShader> skSrcShader =
   2129       skSrc->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
   2130   sk_sp<SkImage> skMaskImage = SkImage::MakeFromBitmap(skMask);
   2131   sk_sp<SkShader> skMaskShader = skMaskImage->makeShader(
   2132       SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
   2133   paint.setShader(SkShader::MakeComposeShader(skMaskShader, skSrcShader,
   2134                                               SkBlendMode::kSrcIn));
   2135   SkRect r = {0, 0, SkIntToScalar(srcWidth), SkIntToScalar(srcHeight)};
   2136   m_pCanvas->drawRect(r, paint);
   2137   m_pCanvas->restore();
   2138   if (srcCt)
   2139     srcCt->unref();
   2140   DebugValidate(m_pBitmap, m_pOriDevice);
   2141   return true;
   2142 }
   2143 
   2144 bool CFX_SkiaDeviceDriver::SetBitsWithMask(const CFX_DIBSource* pBitmap,
   2145                                            const CFX_DIBSource* pMask,
   2146                                            int dest_left,
   2147                                            int dest_top,
   2148                                            int bitmap_alpha,
   2149                                            int blend_type) {
   2150   if (!m_pBitmap || !m_pBitmap->GetBuffer())
   2151     return true;
   2152   CFX_Matrix m(pBitmap->GetWidth(), 0, 0, -pBitmap->GetHeight(), dest_left,
   2153                dest_top + pBitmap->GetHeight());
   2154   return DrawBitsWithMask(pBitmap, pMask, bitmap_alpha, &m, blend_type);
   2155 }
   2156 
   2157 void CFX_SkiaDeviceDriver::Clear(uint32_t color) {
   2158   m_pCanvas->clear(color);
   2159 }
   2160 #endif  // _SKIA_SUPPORT_
   2161 
   2162 void CFX_SkiaDeviceDriver::Dump() const {
   2163 #if SHOW_SKIA_PATH && defined _SKIA_SUPPORT_
   2164   if (m_pCache)
   2165     m_pCache->Dump(this);
   2166 #endif  // SHOW_SKIA_PATH && defined _SKIA_SUPPORT_
   2167 }
   2168 
   2169 #ifdef _SKIA_SUPPORT_
   2170 void CFX_SkiaDeviceDriver::DebugVerifyBitmapIsPreMultiplied() const {
   2171   if (m_pOriDevice)
   2172     m_pOriDevice->DebugVerifyBitmapIsPreMultiplied();
   2173 }
   2174 #endif  // _SKIA_SUPPORT_
   2175 
   2176 CFX_FxgeDevice::CFX_FxgeDevice() {
   2177 #ifdef _SKIA_SUPPORT_
   2178   m_bOwnedBitmap = false;
   2179 #endif  // _SKIA_SUPPORT_
   2180 }
   2181 
   2182 #ifdef _SKIA_SUPPORT_
   2183 void CFX_FxgeDevice::Clear(uint32_t color) {
   2184   CFX_SkiaDeviceDriver* skDriver =
   2185       static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver());
   2186   skDriver->Clear(color);
   2187 }
   2188 
   2189 SkPictureRecorder* CFX_FxgeDevice::CreateRecorder(int size_x, int size_y) {
   2190   CFX_SkiaDeviceDriver* skDriver = new CFX_SkiaDeviceDriver(size_x, size_y);
   2191   SetDeviceDriver(pdfium::WrapUnique(skDriver));
   2192   return skDriver->GetRecorder();
   2193 }
   2194 #endif  // _SKIA_SUPPORT_
   2195 
   2196 bool CFX_FxgeDevice::Attach(CFX_DIBitmap* pBitmap,
   2197                             bool bRgbByteOrder,
   2198                             CFX_DIBitmap* pOriDevice,
   2199                             bool bGroupKnockout) {
   2200   if (!pBitmap)
   2201     return false;
   2202   SetBitmap(pBitmap);
   2203   SetDeviceDriver(pdfium::MakeUnique<CFX_SkiaDeviceDriver>(
   2204       pBitmap, bRgbByteOrder, pOriDevice, bGroupKnockout));
   2205   return true;
   2206 }
   2207 
   2208 #ifdef _SKIA_SUPPORT_
   2209 bool CFX_FxgeDevice::AttachRecorder(SkPictureRecorder* recorder) {
   2210   if (!recorder)
   2211     return false;
   2212   SetDeviceDriver(pdfium::MakeUnique<CFX_SkiaDeviceDriver>(recorder));
   2213   return true;
   2214 }
   2215 #endif  // _SKIA_SUPPORT_
   2216 
   2217 bool CFX_FxgeDevice::Create(int width,
   2218                             int height,
   2219                             FXDIB_Format format,
   2220                             CFX_DIBitmap* pOriDevice) {
   2221   m_bOwnedBitmap = true;
   2222   CFX_DIBitmap* pBitmap = new CFX_DIBitmap;
   2223   if (!pBitmap->Create(width, height, format)) {
   2224     delete pBitmap;
   2225     return false;
   2226   }
   2227   SetBitmap(pBitmap);
   2228   SetDeviceDriver(pdfium::MakeUnique<CFX_SkiaDeviceDriver>(pBitmap, false,
   2229                                                            pOriDevice, false));
   2230   return true;
   2231 }
   2232 
   2233 CFX_FxgeDevice::~CFX_FxgeDevice() {
   2234 #ifdef _SKIA_SUPPORT_
   2235   Flush();
   2236   // call destructor of CFX_RenderDevice / CFX_SkiaDeviceDriver immediately
   2237   if (m_bOwnedBitmap && GetBitmap())
   2238     delete GetBitmap();
   2239 #endif  // _SKIA_SUPPORT_
   2240 }
   2241 
   2242 #ifdef _SKIA_SUPPORT_
   2243 void CFX_FxgeDevice::DebugVerifyBitmapIsPreMultiplied() const {
   2244 #ifdef SK_DEBUG
   2245   CFX_SkiaDeviceDriver* skDriver =
   2246       static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver());
   2247   if (skDriver)
   2248     skDriver->DebugVerifyBitmapIsPreMultiplied();
   2249 #endif  // SK_DEBUG
   2250 }
   2251 
   2252 bool CFX_FxgeDevice::SetBitsWithMask(const CFX_DIBSource* pBitmap,
   2253                                      const CFX_DIBSource* pMask,
   2254                                      int left,
   2255                                      int top,
   2256                                      int bitmap_alpha,
   2257                                      int blend_type) {
   2258   CFX_SkiaDeviceDriver* skDriver =
   2259       static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver());
   2260   if (skDriver)
   2261     return skDriver->SetBitsWithMask(pBitmap, pMask, left, top, bitmap_alpha,
   2262                                      blend_type);
   2263   return false;
   2264 }
   2265 #endif  // _SKIA_SUPPORT_
   2266 
   2267 void CFX_DIBSource::DebugVerifyBitmapIsPreMultiplied(void* opt) const {
   2268 #ifdef SK_DEBUG
   2269   SkASSERT(32 == GetBPP());
   2270   const uint32_t* buffer = (const uint32_t*)(opt ? opt : GetBuffer());
   2271   int width = GetWidth();
   2272   int height = GetHeight();
   2273   // verify that input is really premultiplied
   2274   for (int y = 0; y < height; ++y) {
   2275     const uint32_t* srcRow = buffer + y * width;
   2276     for (int x = 0; x < width; ++x) {
   2277       uint8_t a = SkGetPackedA32(srcRow[x]);
   2278       uint8_t r = SkGetPackedR32(srcRow[x]);
   2279       uint8_t g = SkGetPackedG32(srcRow[x]);
   2280       uint8_t b = SkGetPackedB32(srcRow[x]);
   2281       SkA32Assert(a);
   2282       SkASSERT(r <= a);
   2283       SkASSERT(g <= a);
   2284       SkASSERT(b <= a);
   2285     }
   2286   }
   2287 #endif  // SK_DEBUG
   2288 }
   2289 
   2290 #ifdef _SKIA_SUPPORT_PATHS_
   2291 class CFX_Renderer {
   2292  private:
   2293   int m_Alpha, m_Red, m_Green, m_Blue, m_Gray;
   2294   uint32_t m_Color;
   2295   bool m_bFullCover;
   2296   bool m_bRgbByteOrder;
   2297   CFX_DIBitmap* m_pOriDevice;
   2298   FX_RECT m_ClipBox;
   2299   const CFX_DIBitmap* m_pClipMask;
   2300   CFX_DIBitmap* m_pDevice;
   2301   const CFX_ClipRgn* m_pClipRgn;
   2302   void (CFX_Renderer::*composite_span)(uint8_t*,
   2303                                        int,
   2304                                        int,
   2305                                        int,
   2306                                        uint8_t*,
   2307                                        int,
   2308                                        int,
   2309                                        uint8_t*,
   2310                                        uint8_t*);
   2311 
   2312  public:
   2313   void prepare(unsigned) {}
   2314 
   2315   void CompositeSpan(uint8_t* dest_scan,
   2316                      uint8_t* ori_scan,
   2317                      int Bpp,
   2318                      bool bDestAlpha,
   2319                      int span_left,
   2320                      int span_len,
   2321                      uint8_t* cover_scan,
   2322                      int clip_left,
   2323                      int clip_right,
   2324                      uint8_t* clip_scan) {
   2325     ASSERT(!m_pDevice->IsCmykImage());
   2326     int col_start = span_left < clip_left ? clip_left - span_left : 0;
   2327     int col_end = (span_left + span_len) < clip_right
   2328                       ? span_len
   2329                       : (clip_right - span_left);
   2330     if (Bpp) {
   2331       dest_scan += col_start * Bpp;
   2332       ori_scan += col_start * Bpp;
   2333     } else {
   2334       dest_scan += col_start / 8;
   2335       ori_scan += col_start / 8;
   2336     }
   2337     if (m_bRgbByteOrder) {
   2338       if (Bpp == 4 && bDestAlpha) {
   2339         for (int col = col_start; col < col_end; col++) {
   2340           int src_alpha;
   2341           if (clip_scan) {
   2342             src_alpha = m_Alpha * clip_scan[col] / 255;
   2343           } else {
   2344             src_alpha = m_Alpha;
   2345           }
   2346           uint8_t dest_alpha =
   2347               ori_scan[3] + src_alpha - ori_scan[3] * src_alpha / 255;
   2348           dest_scan[3] = dest_alpha;
   2349           int alpha_ratio = src_alpha * 255 / dest_alpha;
   2350           if (m_bFullCover) {
   2351             *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio);
   2352             *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio);
   2353             *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio);
   2354             dest_scan++;
   2355             ori_scan++;
   2356           } else {
   2357             int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio);
   2358             int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio);
   2359             int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio);
   2360             ori_scan++;
   2361             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]);
   2362             dest_scan++;
   2363             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]);
   2364             dest_scan++;
   2365             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]);
   2366             dest_scan += 2;
   2367           }
   2368         }
   2369         return;
   2370       }
   2371       if (Bpp == 3 || Bpp == 4) {
   2372         for (int col = col_start; col < col_end; col++) {
   2373           int src_alpha;
   2374           if (clip_scan) {
   2375             src_alpha = m_Alpha * clip_scan[col] / 255;
   2376           } else {
   2377             src_alpha = m_Alpha;
   2378           }
   2379           int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, src_alpha);
   2380           int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha);
   2381           int b = FXDIB_ALPHA_MERGE(*ori_scan, m_Blue, src_alpha);
   2382           ori_scan += Bpp - 2;
   2383           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]);
   2384           dest_scan++;
   2385           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]);
   2386           dest_scan++;
   2387           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]);
   2388           dest_scan += Bpp - 2;
   2389         }
   2390       }
   2391       return;
   2392     }
   2393     if (Bpp == 4 && bDestAlpha) {
   2394       for (int col = col_start; col < col_end; col++) {
   2395         int src_alpha;
   2396         if (clip_scan) {
   2397           src_alpha = m_Alpha * clip_scan[col] / 255;
   2398         } else {
   2399           src_alpha = m_Alpha;
   2400         }
   2401         int src_alpha_covered = src_alpha * cover_scan[col] / 255;
   2402         if (src_alpha_covered == 0) {
   2403           dest_scan += 4;
   2404           continue;
   2405         }
   2406         if (cover_scan[col] == 255) {
   2407           dest_scan[3] = src_alpha_covered;
   2408           *dest_scan++ = m_Blue;
   2409           *dest_scan++ = m_Green;
   2410           *dest_scan = m_Red;
   2411           dest_scan += 2;
   2412           continue;
   2413         } else {
   2414           if (dest_scan[3] == 0) {
   2415             dest_scan[3] = src_alpha_covered;
   2416             *dest_scan++ = m_Blue;
   2417             *dest_scan++ = m_Green;
   2418             *dest_scan = m_Red;
   2419             dest_scan += 2;
   2420             continue;
   2421           }
   2422           uint8_t cover = cover_scan[col];
   2423           dest_scan[3] = FXDIB_ALPHA_MERGE(dest_scan[3], src_alpha, cover);
   2424           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, cover);
   2425           dest_scan++;
   2426           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, cover);
   2427           dest_scan++;
   2428           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, cover);
   2429           dest_scan += 2;
   2430         }
   2431       }
   2432       return;
   2433     }
   2434     if (Bpp == 3 || Bpp == 4) {
   2435       for (int col = col_start; col < col_end; col++) {
   2436         int src_alpha;
   2437         if (clip_scan) {
   2438           src_alpha = m_Alpha * clip_scan[col] / 255;
   2439         } else {
   2440           src_alpha = m_Alpha;
   2441         }
   2442         if (m_bFullCover) {
   2443           *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha);
   2444           *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha);
   2445           *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha);
   2446           dest_scan += Bpp - 2;
   2447           ori_scan += Bpp - 2;
   2448           continue;
   2449         }
   2450         int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha);
   2451         int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha);
   2452         int r = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha);
   2453         ori_scan += Bpp - 2;
   2454         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]);
   2455         dest_scan++;
   2456         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]);
   2457         dest_scan++;
   2458         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]);
   2459         dest_scan += Bpp - 2;
   2460         continue;
   2461       }
   2462       return;
   2463     }
   2464     if (Bpp == 1) {
   2465       for (int col = col_start; col < col_end; col++) {
   2466         int src_alpha;
   2467         if (clip_scan) {
   2468           src_alpha = m_Alpha * clip_scan[col] / 255;
   2469         } else {
   2470           src_alpha = m_Alpha;
   2471         }
   2472         if (m_bFullCover) {
   2473           *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha);
   2474         } else {
   2475           int gray = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha);
   2476           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, cover_scan[col]);
   2477           dest_scan++;
   2478         }
   2479       }
   2480     } else {
   2481       int index = 0;
   2482       if (m_pDevice->GetPalette()) {
   2483         for (int i = 0; i < 2; i++) {
   2484           if (FXARGB_TODIB(m_pDevice->GetPalette()[i]) == m_Color) {
   2485             index = i;
   2486           }
   2487         }
   2488       } else {
   2489         index = ((uint8_t)m_Color == 0xff) ? 1 : 0;
   2490       }
   2491       uint8_t* dest_scan1 = dest_scan;
   2492       for (int col = col_start; col < col_end; col++) {
   2493         int src_alpha;
   2494         if (clip_scan) {
   2495           src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
   2496         } else {
   2497           src_alpha = m_Alpha * cover_scan[col] / 255;
   2498         }
   2499         if (src_alpha) {
   2500           if (!index) {
   2501             *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8));
   2502           } else {
   2503             *dest_scan1 |= 1 << (7 - (col + span_left) % 8);
   2504           }
   2505         }
   2506         dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8;
   2507       }
   2508     }
   2509   }
   2510 
   2511   void CompositeSpan1bpp(uint8_t* dest_scan,
   2512                          int Bpp,
   2513                          int span_left,
   2514                          int span_len,
   2515                          uint8_t* cover_scan,
   2516                          int clip_left,
   2517                          int clip_right,
   2518                          uint8_t* clip_scan,
   2519                          uint8_t* dest_extra_alpha_scan) {
   2520     ASSERT(!m_bRgbByteOrder);
   2521     ASSERT(!m_pDevice->IsCmykImage());
   2522     int col_start = span_left < clip_left ? clip_left - span_left : 0;
   2523     int col_end = (span_left + span_len) < clip_right
   2524                       ? span_len
   2525                       : (clip_right - span_left);
   2526     dest_scan += col_start / 8;
   2527     int index = 0;
   2528     if (m_pDevice->GetPalette()) {
   2529       for (int i = 0; i < 2; i++) {
   2530         if (FXARGB_TODIB(m_pDevice->GetPalette()[i]) == m_Color) {
   2531           index = i;
   2532         }
   2533       }
   2534     } else {
   2535       index = ((uint8_t)m_Color == 0xff) ? 1 : 0;
   2536     }
   2537     uint8_t* dest_scan1 = dest_scan;
   2538     for (int col = col_start; col < col_end; col++) {
   2539       int src_alpha;
   2540       if (clip_scan) {
   2541         src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
   2542       } else {
   2543         src_alpha = m_Alpha * cover_scan[col] / 255;
   2544       }
   2545       if (src_alpha) {
   2546         if (!index) {
   2547           *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8));
   2548         } else {
   2549           *dest_scan1 |= 1 << (7 - (col + span_left) % 8);
   2550         }
   2551       }
   2552       dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8;
   2553     }
   2554   }
   2555 
   2556   void CompositeSpanGray(uint8_t* dest_scan,
   2557                          int Bpp,
   2558                          int span_left,
   2559                          int span_len,
   2560                          uint8_t* cover_scan,
   2561                          int clip_left,
   2562                          int clip_right,
   2563                          uint8_t* clip_scan,
   2564                          uint8_t* dest_extra_alpha_scan) {
   2565     ASSERT(!m_bRgbByteOrder);
   2566     int col_start = span_left < clip_left ? clip_left - span_left : 0;
   2567     int col_end = (span_left + span_len) < clip_right
   2568                       ? span_len
   2569                       : (clip_right - span_left);
   2570     dest_scan += col_start;
   2571     if (dest_extra_alpha_scan) {
   2572       for (int col = col_start; col < col_end; col++) {
   2573         int src_alpha;
   2574         if (m_bFullCover) {
   2575           if (clip_scan) {
   2576             src_alpha = m_Alpha * clip_scan[col] / 255;
   2577           } else {
   2578             src_alpha = m_Alpha;
   2579           }
   2580         } else {
   2581           if (clip_scan) {
   2582             src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
   2583           } else {
   2584             src_alpha = m_Alpha * cover_scan[col] / 255;
   2585           }
   2586         }
   2587         if (src_alpha) {
   2588           if (src_alpha == 255) {
   2589             *dest_scan = m_Gray;
   2590             *dest_extra_alpha_scan = m_Alpha;
   2591           } else {
   2592             uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha -
   2593                                  (*dest_extra_alpha_scan) * src_alpha / 255;
   2594             *dest_extra_alpha_scan++ = dest_alpha;
   2595             int alpha_ratio = src_alpha * 255 / dest_alpha;
   2596             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio);
   2597             dest_scan++;
   2598             continue;
   2599           }
   2600         }
   2601         dest_extra_alpha_scan++;
   2602         dest_scan++;
   2603       }
   2604     } else {
   2605       for (int col = col_start; col < col_end; col++) {
   2606         int src_alpha;
   2607         if (clip_scan) {
   2608           src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
   2609         } else {
   2610           src_alpha = m_Alpha * cover_scan[col] / 255;
   2611         }
   2612         if (src_alpha) {
   2613           if (src_alpha == 255) {
   2614             *dest_scan = m_Gray;
   2615           } else {
   2616             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha);
   2617           }
   2618         }
   2619         dest_scan++;
   2620       }
   2621     }
   2622   }
   2623 
   2624   void CompositeSpanARGB(uint8_t* dest_scan,
   2625                          int Bpp,
   2626                          int span_left,
   2627                          int span_len,
   2628                          uint8_t* cover_scan,
   2629                          int clip_left,
   2630                          int clip_right,
   2631                          uint8_t* clip_scan,
   2632                          uint8_t* dest_extra_alpha_scan) {
   2633     int col_start = span_left < clip_left ? clip_left - span_left : 0;
   2634     int col_end = (span_left + span_len) < clip_right
   2635                       ? span_len
   2636                       : (clip_right - span_left);
   2637     dest_scan += col_start * Bpp;
   2638     if (m_bRgbByteOrder) {
   2639       for (int col = col_start; col < col_end; col++) {
   2640         int src_alpha;
   2641         if (m_bFullCover) {
   2642           if (clip_scan) {
   2643             src_alpha = m_Alpha * clip_scan[col] / 255;
   2644           } else {
   2645             src_alpha = m_Alpha;
   2646           }
   2647         } else {
   2648           if (clip_scan) {
   2649             src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
   2650           } else {
   2651             src_alpha = m_Alpha * cover_scan[col] / 255;
   2652           }
   2653         }
   2654         if (src_alpha) {
   2655           if (src_alpha == 255) {
   2656             *(uint32_t*)dest_scan = m_Color;
   2657           } else {
   2658             uint8_t dest_alpha =
   2659                 dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255;
   2660             dest_scan[3] = dest_alpha;
   2661             int alpha_ratio = src_alpha * 255 / dest_alpha;
   2662             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
   2663             dest_scan++;
   2664             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
   2665             dest_scan++;
   2666             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
   2667             dest_scan += 2;
   2668             continue;
   2669           }
   2670         }
   2671         dest_scan += 4;
   2672       }
   2673       return;
   2674     }
   2675     for (int col = col_start; col < col_end; col++) {
   2676       int src_alpha;
   2677       if (m_bFullCover) {
   2678         if (clip_scan) {
   2679           src_alpha = m_Alpha * clip_scan[col] / 255;
   2680         } else {
   2681           src_alpha = m_Alpha;
   2682         }
   2683       } else {
   2684         if (clip_scan) {
   2685           src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
   2686         } else {
   2687           src_alpha = m_Alpha * cover_scan[col] / 255;
   2688         }
   2689       }
   2690       if (src_alpha) {
   2691         if (src_alpha == 255) {
   2692           *(uint32_t*)dest_scan = m_Color;
   2693         } else {
   2694           if (dest_scan[3] == 0) {
   2695             dest_scan[3] = src_alpha;
   2696             *dest_scan++ = m_Blue;
   2697             *dest_scan++ = m_Green;
   2698             *dest_scan = m_Red;
   2699             dest_scan += 2;
   2700             continue;
   2701           }
   2702           uint8_t dest_alpha =
   2703               dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255;
   2704           dest_scan[3] = dest_alpha;
   2705           int alpha_ratio = src_alpha * 255 / dest_alpha;
   2706           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
   2707           dest_scan++;
   2708           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
   2709           dest_scan++;
   2710           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
   2711           dest_scan += 2;
   2712           continue;
   2713         }
   2714       }
   2715       dest_scan += Bpp;
   2716     }
   2717   }
   2718 
   2719   void CompositeSpanRGB(uint8_t* dest_scan,
   2720                         int Bpp,
   2721                         int span_left,
   2722                         int span_len,
   2723                         uint8_t* cover_scan,
   2724                         int clip_left,
   2725                         int clip_right,
   2726                         uint8_t* clip_scan,
   2727                         uint8_t* dest_extra_alpha_scan) {
   2728     int col_start = span_left < clip_left ? clip_left - span_left : 0;
   2729     int col_end = (span_left + span_len) < clip_right
   2730                       ? span_len
   2731                       : (clip_right - span_left);
   2732     dest_scan += col_start * Bpp;
   2733     if (m_bRgbByteOrder) {
   2734       for (int col = col_start; col < col_end; col++) {
   2735         int src_alpha;
   2736         if (clip_scan) {
   2737           src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
   2738         } else {
   2739           src_alpha = m_Alpha * cover_scan[col] / 255;
   2740         }
   2741         if (src_alpha) {
   2742           if (src_alpha == 255) {
   2743             if (Bpp == 4) {
   2744               *(uint32_t*)dest_scan = m_Color;
   2745             } else if (Bpp == 3) {
   2746               *dest_scan++ = m_Red;
   2747               *dest_scan++ = m_Green;
   2748               *dest_scan++ = m_Blue;
   2749               continue;
   2750             }
   2751           } else {
   2752             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
   2753             dest_scan++;
   2754             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
   2755             dest_scan++;
   2756             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
   2757             dest_scan += Bpp - 2;
   2758             continue;
   2759           }
   2760         }
   2761         dest_scan += Bpp;
   2762       }
   2763       return;
   2764     }
   2765     if (Bpp == 3 && dest_extra_alpha_scan) {
   2766       for (int col = col_start; col < col_end; col++) {
   2767         int src_alpha;
   2768         if (m_bFullCover) {
   2769           if (clip_scan) {
   2770             src_alpha = m_Alpha * clip_scan[col] / 255;
   2771           } else {
   2772             src_alpha = m_Alpha;
   2773           }
   2774         } else {
   2775           if (clip_scan) {
   2776             src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
   2777           } else {
   2778             src_alpha = m_Alpha * cover_scan[col] / 255;
   2779           }
   2780         }
   2781         if (src_alpha) {
   2782           if (src_alpha == 255) {
   2783             *dest_scan++ = (uint8_t)m_Blue;
   2784             *dest_scan++ = (uint8_t)m_Green;
   2785             *dest_scan++ = (uint8_t)m_Red;
   2786             *dest_extra_alpha_scan++ = (uint8_t)m_Alpha;
   2787             continue;
   2788           } else {
   2789             uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha -
   2790                                  (*dest_extra_alpha_scan) * src_alpha / 255;
   2791             *dest_extra_alpha_scan++ = dest_alpha;
   2792             int alpha_ratio = src_alpha * 255 / dest_alpha;
   2793             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
   2794             dest_scan++;
   2795             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
   2796             dest_scan++;
   2797             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
   2798             dest_scan++;
   2799             continue;
   2800           }
   2801         }
   2802         dest_extra_alpha_scan++;
   2803         dest_scan += Bpp;
   2804       }
   2805     } else {
   2806       for (int col = col_start; col < col_end; col++) {
   2807         int src_alpha;
   2808         if (m_bFullCover) {
   2809           if (clip_scan) {
   2810             src_alpha = m_Alpha * clip_scan[col] / 255;
   2811           } else {
   2812             src_alpha = m_Alpha;
   2813           }
   2814         } else {
   2815           if (clip_scan) {
   2816             src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
   2817           } else {
   2818             src_alpha = m_Alpha * cover_scan[col] / 255;
   2819           }
   2820         }
   2821         if (src_alpha) {
   2822           if (src_alpha == 255) {
   2823             if (Bpp == 4) {
   2824               *(uint32_t*)dest_scan = m_Color;
   2825             } else if (Bpp == 3) {
   2826               *dest_scan++ = m_Blue;
   2827               *dest_scan++ = m_Green;
   2828               *dest_scan++ = m_Red;
   2829               continue;
   2830             }
   2831           } else {
   2832             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
   2833             dest_scan++;
   2834             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
   2835             dest_scan++;
   2836             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
   2837             dest_scan += Bpp - 2;
   2838             continue;
   2839           }
   2840         }
   2841         dest_scan += Bpp;
   2842       }
   2843     }
   2844   }
   2845 
   2846   void CompositeSpanCMYK(uint8_t* dest_scan,
   2847                          int Bpp,
   2848                          int span_left,
   2849                          int span_len,
   2850                          uint8_t* cover_scan,
   2851                          int clip_left,
   2852                          int clip_right,
   2853                          uint8_t* clip_scan,
   2854                          uint8_t* dest_extra_alpha_scan) {
   2855     ASSERT(!m_bRgbByteOrder);
   2856     int col_start = span_left < clip_left ? clip_left - span_left : 0;
   2857     int col_end = (span_left + span_len) < clip_right
   2858                       ? span_len
   2859                       : (clip_right - span_left);
   2860     dest_scan += col_start * 4;
   2861     if (dest_extra_alpha_scan) {
   2862       for (int col = col_start; col < col_end; col++) {
   2863         int src_alpha;
   2864         if (m_bFullCover) {
   2865           if (clip_scan) {
   2866             src_alpha = m_Alpha * clip_scan[col] / 255;
   2867           } else {
   2868             src_alpha = m_Alpha;
   2869           }
   2870         } else {
   2871           if (clip_scan) {
   2872             src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
   2873           } else {
   2874             src_alpha = m_Alpha * cover_scan[col] / 255;
   2875           }
   2876         }
   2877         if (src_alpha) {
   2878           if (src_alpha == 255) {
   2879             *(FX_CMYK*)dest_scan = m_Color;
   2880             *dest_extra_alpha_scan = (uint8_t)m_Alpha;
   2881           } else {
   2882             uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha -
   2883                                  (*dest_extra_alpha_scan) * src_alpha / 255;
   2884             *dest_extra_alpha_scan++ = dest_alpha;
   2885             int alpha_ratio = src_alpha * 255 / dest_alpha;
   2886             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
   2887             dest_scan++;
   2888             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
   2889             dest_scan++;
   2890             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
   2891             dest_scan++;
   2892             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio);
   2893             dest_scan++;
   2894             continue;
   2895           }
   2896         }
   2897         dest_extra_alpha_scan++;
   2898         dest_scan += 4;
   2899       }
   2900     } else {
   2901       for (int col = col_start; col < col_end; col++) {
   2902         int src_alpha;
   2903         if (clip_scan) {
   2904           src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
   2905         } else {
   2906           src_alpha = m_Alpha * cover_scan[col] / 255;
   2907         }
   2908         if (src_alpha) {
   2909           if (src_alpha == 255) {
   2910             *(FX_CMYK*)dest_scan = m_Color;
   2911           } else {
   2912             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
   2913             dest_scan++;
   2914             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
   2915             dest_scan++;
   2916             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
   2917             dest_scan++;
   2918             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha);
   2919             dest_scan++;
   2920             continue;
   2921           }
   2922         }
   2923         dest_scan += 4;
   2924       }
   2925     }
   2926   }
   2927 
   2928   template <class Scanline>
   2929   void render(const Scanline& sl) {
   2930     if (!m_pOriDevice && !composite_span) {
   2931       return;
   2932     }
   2933     int y = sl.y();
   2934     if (y < m_ClipBox.top || y >= m_ClipBox.bottom) {
   2935       return;
   2936     }
   2937     uint8_t* dest_scan = m_pDevice->GetBuffer() + m_pDevice->GetPitch() * y;
   2938     uint8_t* dest_scan_extra_alpha = nullptr;
   2939     CFX_DIBitmap* pAlphaMask = m_pDevice->m_pAlphaMask;
   2940     if (pAlphaMask) {
   2941       dest_scan_extra_alpha =
   2942           pAlphaMask->GetBuffer() + pAlphaMask->GetPitch() * y;
   2943     }
   2944     uint8_t* ori_scan = nullptr;
   2945     if (m_pOriDevice) {
   2946       ori_scan = m_pOriDevice->GetBuffer() + m_pOriDevice->GetPitch() * y;
   2947     }
   2948     int Bpp = m_pDevice->GetBPP() / 8;
   2949     bool bDestAlpha = m_pDevice->HasAlpha() || m_pDevice->IsAlphaMask();
   2950     unsigned num_spans = sl.num_spans();
   2951     typename Scanline::const_iterator span = sl.begin();
   2952     while (1) {
   2953       int x = span->x;
   2954       ASSERT(span->len > 0);
   2955       uint8_t* dest_pos = nullptr;
   2956       uint8_t* dest_extra_alpha_pos = nullptr;
   2957       uint8_t* ori_pos = nullptr;
   2958       if (Bpp) {
   2959         ori_pos = ori_scan ? ori_scan + x * Bpp : nullptr;
   2960         dest_pos = dest_scan + x * Bpp;
   2961         dest_extra_alpha_pos =
   2962             dest_scan_extra_alpha ? dest_scan_extra_alpha + x : nullptr;
   2963       } else {
   2964         dest_pos = dest_scan + x / 8;
   2965         ori_pos = ori_scan ? ori_scan + x / 8 : nullptr;
   2966       }
   2967       uint8_t* clip_pos = nullptr;
   2968       if (m_pClipMask) {
   2969         clip_pos = m_pClipMask->GetBuffer() +
   2970                    (y - m_ClipBox.top) * m_pClipMask->GetPitch() + x -
   2971                    m_ClipBox.left;
   2972       }
   2973       if (ori_pos) {
   2974         CompositeSpan(dest_pos, ori_pos, Bpp, bDestAlpha, x, span->len,
   2975                       span->covers, m_ClipBox.left, m_ClipBox.right, clip_pos);
   2976       } else {
   2977         (this->*composite_span)(dest_pos, Bpp, x, span->len, span->covers,
   2978                                 m_ClipBox.left, m_ClipBox.right, clip_pos,
   2979                                 dest_extra_alpha_pos);
   2980       }
   2981       if (--num_spans == 0) {
   2982         break;
   2983       }
   2984       ++span;
   2985     }
   2986   }
   2987 
   2988   bool Init(CFX_DIBitmap* pDevice,
   2989             CFX_DIBitmap* pOriDevice,
   2990             const CFX_ClipRgn* pClipRgn,
   2991             uint32_t color,
   2992             bool bFullCover,
   2993             bool bRgbByteOrder,
   2994             int alpha_flag = 0,
   2995             void* pIccTransform = nullptr) {
   2996     m_pDevice = pDevice;
   2997     m_pClipRgn = pClipRgn;
   2998     composite_span = nullptr;
   2999     m_bRgbByteOrder = bRgbByteOrder;
   3000     m_pOriDevice = pOriDevice;
   3001     if (m_pClipRgn) {
   3002       m_ClipBox = m_pClipRgn->GetBox();
   3003     } else {
   3004       m_ClipBox.left = m_ClipBox.top = 0;
   3005       m_ClipBox.right = m_pDevice->GetWidth();
   3006       m_ClipBox.bottom = m_pDevice->GetHeight();
   3007     }
   3008     m_pClipMask = nullptr;
   3009     if (m_pClipRgn && m_pClipRgn->GetType() == CFX_ClipRgn::MaskF) {
   3010       m_pClipMask = m_pClipRgn->GetMask().GetObject();
   3011     }
   3012     m_bFullCover = bFullCover;
   3013     bool bObjectCMYK = !!FXGETFLAG_COLORTYPE(alpha_flag);
   3014     bool bDeviceCMYK = pDevice->IsCmykImage();
   3015     m_Alpha = bObjectCMYK ? FXGETFLAG_ALPHA_FILL(alpha_flag) : FXARGB_A(color);
   3016     CCodec_IccModule* pIccModule = nullptr;
   3017     if (!CFX_GEModule::Get()->GetCodecModule() ||
   3018         !CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) {
   3019       pIccTransform = nullptr;
   3020     } else {
   3021       pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
   3022     }
   3023     if (m_pDevice->GetBPP() == 8) {
   3024       ASSERT(!m_bRgbByteOrder);
   3025       composite_span = &CFX_Renderer::CompositeSpanGray;
   3026       if (m_pDevice->IsAlphaMask()) {
   3027         m_Gray = 255;
   3028       } else {
   3029         if (pIccTransform) {
   3030           uint8_t gray;
   3031           color = bObjectCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color);
   3032           pIccModule->TranslateScanline(pIccTransform, &gray,
   3033                                         (const uint8_t*)&color, 1);
   3034           m_Gray = gray;
   3035         } else {
   3036           if (bObjectCMYK) {
   3037             uint8_t r, g, b;
   3038             AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color),
   3039                                FXSYS_GetYValue(color), FXSYS_GetKValue(color),
   3040                                r, g, b);
   3041             m_Gray = FXRGB2GRAY(r, g, b);
   3042           } else {
   3043             m_Gray =
   3044                 FXRGB2GRAY(FXARGB_R(color), FXARGB_G(color), FXARGB_B(color));
   3045           }
   3046         }
   3047       }
   3048       return true;
   3049     }
   3050     if (bDeviceCMYK) {
   3051       ASSERT(!m_bRgbByteOrder);
   3052       composite_span = &CFX_Renderer::CompositeSpanCMYK;
   3053       if (bObjectCMYK) {
   3054         m_Color = FXCMYK_TODIB(color);
   3055         if (pIccTransform) {
   3056           pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color,
   3057                                         (const uint8_t*)&m_Color, 1);
   3058         }
   3059       } else {
   3060         if (!pIccTransform) {
   3061           return false;
   3062         }
   3063         color = FXARGB_TODIB(color);
   3064         pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color,
   3065                                       (const uint8_t*)&color, 1);
   3066       }
   3067       m_Red = ((uint8_t*)&m_Color)[0];
   3068       m_Green = ((uint8_t*)&m_Color)[1];
   3069       m_Blue = ((uint8_t*)&m_Color)[2];
   3070       m_Gray = ((uint8_t*)&m_Color)[3];
   3071     } else {
   3072       composite_span = (pDevice->GetFormat() == FXDIB_Argb)
   3073                            ? &CFX_Renderer::CompositeSpanARGB
   3074                            : &CFX_Renderer::CompositeSpanRGB;
   3075       if (pIccTransform) {
   3076         color = bObjectCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color);
   3077         pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color,
   3078                                       (const uint8_t*)&color, 1);
   3079         ((uint8_t*)&m_Color)[3] = m_Alpha;
   3080         m_Red = ((uint8_t*)&m_Color)[2];
   3081         m_Green = ((uint8_t*)&m_Color)[1];
   3082         m_Blue = ((uint8_t*)&m_Color)[0];
   3083         if (m_bRgbByteOrder) {
   3084           m_Color = FXARGB_TODIB(m_Color);
   3085           m_Color = FXARGB_TOBGRORDERDIB(m_Color);
   3086         }
   3087       } else {
   3088         if (bObjectCMYK) {
   3089           uint8_t r, g, b;
   3090           AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color),
   3091                              FXSYS_GetYValue(color), FXSYS_GetKValue(color), r,
   3092                              g, b);
   3093           m_Color = FXARGB_MAKE(m_Alpha, r, g, b);
   3094           if (m_bRgbByteOrder) {
   3095             m_Color = FXARGB_TOBGRORDERDIB(m_Color);
   3096           } else {
   3097             m_Color = FXARGB_TODIB(m_Color);
   3098           }
   3099           m_Red = r;
   3100           m_Green = g;
   3101           m_Blue = b;
   3102         } else {
   3103           if (m_bRgbByteOrder) {
   3104             m_Color = FXARGB_TOBGRORDERDIB(color);
   3105           } else {
   3106             m_Color = FXARGB_TODIB(color);
   3107           }
   3108           ArgbDecode(color, m_Alpha, m_Red, m_Green, m_Blue);
   3109         }
   3110       }
   3111     }
   3112     if (m_pDevice->GetBPP() == 1) {
   3113       composite_span = &CFX_Renderer::CompositeSpan1bpp;
   3114     }
   3115     return true;
   3116   }
   3117 };
   3118 
   3119 #endif  // _SKIA_SUPPORT_PATHS_
   3120