• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #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_
RgbByteOrderTransferBitmap(CFX_DIBitmap * pBitmap,int dest_left,int dest_top,int width,int height,const CFX_DIBSource * pSrcBitmap,int src_left,int src_top)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
DebugShowSkiaPaint(const SkPaint & paint)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 
DebugShowCanvasMatrix(const SkCanvas * canvas)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 
DebugShowSkiaPath(const SkPath & path)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 
DebugShowCanvasClip(const SkCanvas * canvas)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
DebugShowSkiaPaint(const SkPaint & paint)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 
DebugShowSkiaDrawPath(const SkCanvas * canvas,const SkPaint & paint,const SkPath & path)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 
DebugShowSkiaDrawRect(const SkCanvas * canvas,const SkPaint & paint,const SkRect & rect)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 
DebugClipPaint()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 
DebugDrawSkiaClipRect(SkCanvas * canvas,const SkRect & rect)242 void DebugDrawSkiaClipRect(SkCanvas* canvas, const SkRect& rect) {
243   SkPaint paint = DebugClipPaint();
244   canvas->drawRect(rect, paint);
245 }
246 
DebugDrawSkiaClipPath(SkCanvas * canvas,const SkPath & path)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 
DebugDrawSkiaClipRect(SkCanvas * canvas,const SkRect & rect)254 void DebugDrawSkiaClipRect(SkCanvas* canvas, const SkRect& rect) {}
255 
DebugDrawSkiaClipPath(SkCanvas * canvas,const SkPath & path)256 void DebugDrawSkiaClipPath(SkCanvas* canvas, const SkPath& path) {}
257 
258 #endif  // DRAW_SKIA_CLIP
259 
260 #ifdef _SKIA_SUPPORT_
DebugValidate(const CFX_DIBitmap * bitmap,const CFX_DIBitmap * device)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 
BuildPath(const CFX_PathData * pPathData)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 
ToSkMatrix(const CFX_Matrix & m)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
ToFlippedSkMatrix(const CFX_Matrix & m,SkScalar flip)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 
GetSkiaBlendMode(int blend_type)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 
AddColors(const CPDF_ExpIntFunc * pFunc,SkTDArray<SkColor> * skColors)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 
FloatToByte(FX_FLOAT f)371 uint8_t FloatToByte(FX_FLOAT f) {
372   ASSERT(0 <= f && f <= 1);
373   return (uint8_t)(f * 255.99f);
374 }
375 
AddSamples(const CPDF_SampledFunc * pFunc,SkTDArray<SkColor> * skColors,SkTDArray<SkScalar> * skPos)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 
AddStitching(const CPDF_StitchFunc * pFunc,SkTDArray<SkColor> * skColors,SkTDArray<SkScalar> * skPos)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
LineSide(const SkPoint line[2],const SkPoint & pt)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 
IntersectSides(const SkPoint & parallelPt,const SkVector & paraRay,const SkPoint & perpendicularPt)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 
ClipAngledGradient(const SkPoint pts[2],SkPoint rectPts[4],bool clipStart,bool clipEnd,SkPath * clip)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_
SetBitmapMatrix(const CFX_Matrix * pMatrix,int width,int height,SkMatrix * skMatrix)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 
SetBitmapPaint(bool isAlphaMask,uint32_t argb,int bitmap_alpha,int blend_type,SkPaint * paint)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 
Upsample(const CFX_DIBSource * pSource,std::unique_ptr<uint8_t,FxFreeDeleter> & dst8Storage,std::unique_ptr<uint32_t,FxFreeDeleter> & dst32Storage,SkColorTable ** ctPtr,SkBitmap * skBitmap,int * widthPtr,int * heightPtr,bool forceAlpha)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
SkiaState(CFX_SkiaDeviceDriver * pDriver)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 
DrawPath(const CFX_PathData * pPathData,const CFX_Matrix * pMatrix,const CFX_GraphStateData * pDrawState,uint32_t fill_color,uint32_t stroke_color,int fill_mode,int blend_type)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 
FlushPath()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 
DrawText(int nChars,const FXTEXT_CHARPOS * pCharPos,CFX_Font * pFont,const CFX_Matrix * pMatrix,FX_FLOAT font_size,uint32_t color)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 
FlushText()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 
SetClipFill(const CFX_PathData * pPathData,const CFX_Matrix * pMatrix,int fill_mode)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 
SetClip(const SkPath & skClipPath)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 
SetClipStroke(const CFX_PathData * pPathData,const CFX_Matrix * pMatrix,const CFX_GraphStateData * pGraphState)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 
MatrixOffset(const CFX_Matrix * pMatrix,SkPoint * delta)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
ClipSave()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 
ClipRestore()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 
DrawChanged(const CFX_Matrix * pMatrix,const CFX_GraphStateData * pState,uint32_t fill_color,uint32_t stroke_color,int fill_mode,int blend_type,bool group_knockout) const976   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 
FontChanged(CFX_Font * pFont,const CFX_Matrix * pMatrix,FX_FLOAT font_size,uint32_t color) const991   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 
MatrixChanged(const CFX_Matrix * pMatrix,const CFX_Matrix & refMatrix) const999   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 
StateChanged(const CFX_GraphStateData * pState,const CFX_GraphStateData & refState) const1008   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 
DashChanged(const CFX_GraphStateData * pState,const CFX_GraphStateData & refState) const1020   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 
AdjustClip(int limit)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 
Flush()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 
FlushForDraw()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
DumpPrefix(int index) const1076   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 
DumpEndPrefix() const1086   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 
Dump(const char * where) const1095   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
PaintStroke(SkPaint * spaint,const CFX_GraphStateData * pGraphState,const SkMatrix & matrix)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 
CFX_SkiaDeviceDriver(CFX_DIBitmap * pBitmap,bool bRgbByteOrder,CFX_DIBitmap * pOriDevice,bool bGroupKnockout)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_
CFX_SkiaDeviceDriver(int size_x,int size_y)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 
CFX_SkiaDeviceDriver(SkPictureRecorder * recorder)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 
~CFX_SkiaDeviceDriver()1267 CFX_SkiaDeviceDriver::~CFX_SkiaDeviceDriver() {
1268   Flush();
1269   if (!m_pRecorder)
1270     delete m_pCanvas;
1271 }
1272 
Flush()1273 void CFX_SkiaDeviceDriver::Flush() {
1274   m_pCache->Flush();
1275 }
1276 
DrawDeviceText(int nChars,const FXTEXT_CHARPOS * pCharPos,CFX_Font * pFont,const CFX_Matrix * pObject2Device,FX_FLOAT font_size,uint32_t color)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 
GetDeviceCaps(int caps_id) const1321 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 
SaveState()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 
RestoreState(bool bKeepSaved)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_
SetClipMask(const FX_RECT & clipBox,const SkPath & path)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 
SetClip_PathFill(const CFX_PathData * pPathData,const CFX_Matrix * pObject2Device,int fill_mode)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 
SetClip_PathStroke(const CFX_PathData * pPathData,const CFX_Matrix * pObject2Device,const CFX_GraphStateData * pGraphState)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 
DrawPath(const CFX_PathData * pPathData,const CFX_Matrix * pObject2Device,const CFX_GraphStateData * pGraphState,uint32_t fill_color,uint32_t stroke_color,int fill_mode,int blend_type)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 
DrawCosmeticLine(FX_FLOAT x1,FX_FLOAT y1,FX_FLOAT x2,FX_FLOAT y2,uint32_t color,int blend_type)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 
FillRectWithBlend(const FX_RECT * pRect,uint32_t fill_color,int blend_type)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 
DrawShading(const CPDF_ShadingPattern * pPattern,const CFX_Matrix * pMatrix,const FX_RECT & clip_rect,int alpha,bool bAlphaMode)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 
GetBuffer() const1802 uint8_t* CFX_SkiaDeviceDriver::GetBuffer() const {
1803   return m_pBitmap->GetBuffer();
1804 }
1805 
GetClipBox(FX_RECT * pRect)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 
GetDIBits(CFX_DIBitmap * pBitmap,int left,int top)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 
GetBackDrop()1881 CFX_DIBitmap* CFX_SkiaDeviceDriver::GetBackDrop() {
1882   return m_pOriDevice;
1883 }
1884 
SetDIBits(const CFX_DIBSource * pBitmap,uint32_t argb,const FX_RECT * pSrcRect,int left,int top,int blend_type)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 
StretchDIBits(const CFX_DIBSource * pSource,uint32_t argb,int dest_left,int dest_top,int dest_width,int dest_height,const FX_RECT * pClipRect,uint32_t flags,int blend_type)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 
StartDIBits(const CFX_DIBSource * pSource,int bitmap_alpha,uint32_t argb,const CFX_Matrix * pMatrix,uint32_t render_flags,void * & handle,int blend_type)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 
ContinueDIBits(void * handle,IFX_Pause * pPause)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_
PreMultiply(CFX_DIBitmap * pDIBitmap)2044 void CFX_SkiaDeviceDriver::PreMultiply(CFX_DIBitmap* pDIBitmap) {
2045   pDIBitmap->PreMultiply();
2046 }
2047 #endif  // _SKIA_SUPPORT_
2048 
PreMultiply()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_
UnPreMultiply()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_
DrawBitsWithMask(const CFX_DIBSource * pSource,const CFX_DIBSource * pMask,int bitmap_alpha,const CFX_Matrix * pMatrix,int blend_type)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 
SetBitsWithMask(const CFX_DIBSource * pBitmap,const CFX_DIBSource * pMask,int dest_left,int dest_top,int bitmap_alpha,int blend_type)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 
Clear(uint32_t color)2157 void CFX_SkiaDeviceDriver::Clear(uint32_t color) {
2158   m_pCanvas->clear(color);
2159 }
2160 #endif  // _SKIA_SUPPORT_
2161 
Dump() const2162 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_
DebugVerifyBitmapIsPreMultiplied() const2170 void CFX_SkiaDeviceDriver::DebugVerifyBitmapIsPreMultiplied() const {
2171   if (m_pOriDevice)
2172     m_pOriDevice->DebugVerifyBitmapIsPreMultiplied();
2173 }
2174 #endif  // _SKIA_SUPPORT_
2175 
CFX_FxgeDevice()2176 CFX_FxgeDevice::CFX_FxgeDevice() {
2177 #ifdef _SKIA_SUPPORT_
2178   m_bOwnedBitmap = false;
2179 #endif  // _SKIA_SUPPORT_
2180 }
2181 
2182 #ifdef _SKIA_SUPPORT_
Clear(uint32_t color)2183 void CFX_FxgeDevice::Clear(uint32_t color) {
2184   CFX_SkiaDeviceDriver* skDriver =
2185       static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver());
2186   skDriver->Clear(color);
2187 }
2188 
CreateRecorder(int size_x,int size_y)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 
Attach(CFX_DIBitmap * pBitmap,bool bRgbByteOrder,CFX_DIBitmap * pOriDevice,bool bGroupKnockout)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_
AttachRecorder(SkPictureRecorder * recorder)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 
Create(int width,int height,FXDIB_Format format,CFX_DIBitmap * pOriDevice)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 
~CFX_FxgeDevice()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_
DebugVerifyBitmapIsPreMultiplied() const2243 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 
SetBitsWithMask(const CFX_DIBSource * pBitmap,const CFX_DIBSource * pMask,int left,int top,int bitmap_alpha,int blend_type)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 
DebugVerifyBitmapIsPreMultiplied(void * opt) const2267 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:
prepare(unsigned)2313   void prepare(unsigned) {}
2314 
CompositeSpan(uint8_t * dest_scan,uint8_t * ori_scan,int Bpp,bool bDestAlpha,int span_left,int span_len,uint8_t * cover_scan,int clip_left,int clip_right,uint8_t * clip_scan)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 
CompositeSpan1bpp(uint8_t * dest_scan,int Bpp,int span_left,int span_len,uint8_t * cover_scan,int clip_left,int clip_right,uint8_t * clip_scan,uint8_t * dest_extra_alpha_scan)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 
CompositeSpanGray(uint8_t * dest_scan,int Bpp,int span_left,int span_len,uint8_t * cover_scan,int clip_left,int clip_right,uint8_t * clip_scan,uint8_t * dest_extra_alpha_scan)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 
CompositeSpanARGB(uint8_t * dest_scan,int Bpp,int span_left,int span_len,uint8_t * cover_scan,int clip_left,int clip_right,uint8_t * clip_scan,uint8_t * dest_extra_alpha_scan)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 
CompositeSpanRGB(uint8_t * dest_scan,int Bpp,int span_left,int span_len,uint8_t * cover_scan,int clip_left,int clip_right,uint8_t * clip_scan,uint8_t * dest_extra_alpha_scan)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 
CompositeSpanCMYK(uint8_t * dest_scan,int Bpp,int span_left,int span_len,uint8_t * cover_scan,int clip_left,int clip_right,uint8_t * clip_scan,uint8_t * dest_extra_alpha_scan)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>
render(const Scanline & sl)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 
Init(CFX_DIBitmap * pDevice,CFX_DIBitmap * pOriDevice,const CFX_ClipRgn * pClipRgn,uint32_t color,bool bFullCover,bool bRgbByteOrder,int alpha_flag=0,void * pIccTransform=nullptr)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