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 if (pSource->GetPalette()) {
597 *ctPtr =
598 new SkColorTable(pSource->GetPalette(), pSource->GetPaletteSize());
599 colorType = SkColorType::kIndex_8_SkColorType;
600 }
601 break;
602 case 24: {
603 dst32Storage.reset(FX_Alloc2D(uint32_t, width, height));
604 uint32_t* dst32Pixels = dst32Storage.get();
605 for (int y = 0; y < height; ++y) {
606 const uint8_t* srcRow =
607 static_cast<const uint8_t*>(buffer) + y * rowBytes;
608 uint32_t* dstRow = dst32Pixels + y * width;
609 for (int x = 0; x < width; ++x) {
610 dstRow[x] = SkPackARGB32(0xFF, srcRow[x * 3 + 2], srcRow[x * 3 + 1],
611 srcRow[x * 3 + 0]);
612 }
613 }
614 buffer = dst32Storage.get();
615 rowBytes = width * sizeof(uint32_t);
616 colorType = SkColorType::kN32_SkColorType;
617 alphaType = kOpaque_SkAlphaType;
618 break;
619 }
620 case 32:
621 colorType = SkColorType::kN32_SkColorType;
622 alphaType = kPremul_SkAlphaType;
623 pSource->DebugVerifyBitmapIsPreMultiplied(buffer);
624 break;
625 default:
626 SkASSERT(0); // TODO(caryclark) ensure that all cases are covered
627 colorType = SkColorType::kUnknown_SkColorType;
628 }
629 SkImageInfo imageInfo =
630 SkImageInfo::Make(width, height, colorType, alphaType);
631 skBitmap->installPixels(imageInfo, buffer, rowBytes, *ctPtr, nullptr,
632 nullptr);
633 *widthPtr = width;
634 *heightPtr = height;
635 return true;
636 }
637 #endif // _SKIA_SUPPORT_
638
639 } // namespace
640
641 // Encapsulate the state used for successive text and path draws so that
642 // they can be combined.
643 class SkiaState {
644 public:
645 enum class Clip {
646 kSave,
647 kPath,
648 };
649
650 enum class Accumulator {
651 kNone,
652 kPath,
653 kText,
654 kOther,
655 };
656
657 // mark all cached state as uninitialized
SkiaState(CFX_SkiaDeviceDriver * pDriver)658 explicit SkiaState(CFX_SkiaDeviceDriver* pDriver)
659 : m_pDriver(pDriver),
660 m_pFont(nullptr),
661 m_fontSize(0),
662 m_fillColor(0),
663 m_strokeColor(0),
664 m_blendType(0),
665 m_commandIndex(0),
666 m_drawIndex(INT_MAX),
667 m_clipIndex(0),
668 m_type(Accumulator::kNone),
669 m_fillFullCover(false),
670 m_fillPath(false),
671 m_groupKnockout(false),
672 m_debugDisable(false)
673 #if SHOW_SKIA_PATH
674 ,
675 m_debugSaveCounter(0)
676 #endif
677 {
678 }
679
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)680 bool DrawPath(const CFX_PathData* pPathData,
681 const CFX_Matrix* pMatrix,
682 const CFX_GraphStateData* pDrawState,
683 uint32_t fill_color,
684 uint32_t stroke_color,
685 int fill_mode,
686 int blend_type) {
687 if (m_debugDisable)
688 return false;
689 Dump(__func__);
690 int drawIndex = SkTMin(m_drawIndex, m_commands.count());
691 if (Accumulator::kText == m_type || drawIndex != m_commandIndex ||
692 (Accumulator::kPath == m_type &&
693 DrawChanged(pMatrix, pDrawState, fill_color, stroke_color, fill_mode,
694 blend_type, m_pDriver->m_bGroupKnockout))) {
695 Flush();
696 }
697 if (Accumulator::kPath != m_type) {
698 m_skPath.reset();
699 m_fillFullCover = !!(fill_mode & FXFILL_FULLCOVER);
700 m_fillPath = (fill_mode & 3) && fill_color;
701 m_skPath.setFillType((fill_mode & 3) == FXFILL_ALTERNATE
702 ? SkPath::kEvenOdd_FillType
703 : SkPath::kWinding_FillType);
704 if (pDrawState)
705 m_drawState.Copy(*pDrawState);
706 m_fillColor = fill_color;
707 m_strokeColor = stroke_color;
708 m_blendType = blend_type;
709 m_groupKnockout = m_pDriver->m_bGroupKnockout;
710 if (pMatrix)
711 m_drawMatrix = *pMatrix;
712 m_drawIndex = m_commandIndex;
713 m_type = Accumulator::kPath;
714 }
715 SkPath skPath = BuildPath(pPathData);
716 SkPoint delta;
717 if (MatrixOffset(pMatrix, &delta))
718 skPath.offset(delta.fX, delta.fY);
719 m_skPath.addPath(skPath);
720 return true;
721 }
722
FlushPath()723 void FlushPath() {
724 Dump(__func__);
725 SkMatrix skMatrix = ToSkMatrix(m_drawMatrix);
726 SkPaint skPaint;
727 skPaint.setAntiAlias(true);
728 if (m_fillFullCover)
729 skPaint.setBlendMode(SkBlendMode::kPlus);
730 int stroke_alpha = FXARGB_A(m_strokeColor);
731 if (stroke_alpha)
732 m_pDriver->PaintStroke(&skPaint, &m_drawState, skMatrix);
733 SkCanvas* skCanvas = m_pDriver->SkiaCanvas();
734 skCanvas->save();
735 skCanvas->concat(skMatrix);
736 if (m_fillPath) {
737 SkPath strokePath;
738 const SkPath* fillPath = &m_skPath;
739 if (stroke_alpha) {
740 if (m_groupKnockout) {
741 skPaint.getFillPath(m_skPath, &strokePath);
742 if (Op(m_skPath, strokePath, SkPathOp::kDifference_SkPathOp,
743 &strokePath)) {
744 fillPath = &strokePath;
745 }
746 }
747 }
748 skPaint.setStyle(SkPaint::kFill_Style);
749 skPaint.setColor(m_fillColor);
750 #ifdef _SKIA_SUPPORT_PATHS_
751 m_pDriver->PreMultiply();
752 #endif // _SKIA_SUPPORT_PATHS_
753 DebugShowSkiaDrawPath(skCanvas, skPaint, *fillPath);
754 skCanvas->drawPath(*fillPath, skPaint);
755 }
756 if (stroke_alpha) {
757 skPaint.setStyle(SkPaint::kStroke_Style);
758 skPaint.setColor(m_strokeColor);
759 #ifdef _SKIA_SUPPORT_PATHS_
760 m_pDriver->PreMultiply();
761 #endif // _SKIA_SUPPORT_PATHS_
762 DebugShowSkiaDrawPath(skCanvas, skPaint, m_skPath);
763 skCanvas->drawPath(m_skPath, skPaint);
764 }
765 skCanvas->restore();
766 m_drawIndex = INT_MAX;
767 m_type = Accumulator::kNone;
768 }
769
DrawText(int nChars,const FXTEXT_CHARPOS * pCharPos,CFX_Font * pFont,const CFX_Matrix * pMatrix,FX_FLOAT font_size,uint32_t color)770 bool DrawText(int nChars,
771 const FXTEXT_CHARPOS* pCharPos,
772 CFX_Font* pFont,
773 const CFX_Matrix* pMatrix,
774 FX_FLOAT font_size,
775 uint32_t color) {
776 if (m_debugDisable)
777 return false;
778 Dump(__func__);
779 int drawIndex = SkTMin(m_drawIndex, m_commands.count());
780 if (Accumulator::kPath == m_type || drawIndex != m_commandIndex ||
781 (Accumulator::kText == m_type &&
782 FontChanged(pFont, pMatrix, font_size, color))) {
783 Flush();
784 }
785 if (Accumulator::kText != m_type) {
786 m_positions.setCount(0);
787 m_glyphs.setCount(0);
788 m_pFont = pFont;
789 m_fontSize = font_size;
790 m_fillColor = color;
791 m_drawMatrix = *pMatrix;
792 m_drawIndex = m_commandIndex;
793 m_type = Accumulator::kText;
794 }
795 int count = m_positions.count();
796 m_positions.setCount(nChars + count);
797 m_glyphs.setCount(nChars + count);
798 SkScalar flip = m_fontSize < 0 ? -1 : 1;
799 SkScalar vFlip = flip;
800 if (pFont->IsVertical())
801 vFlip *= -1;
802 for (int index = 0; index < nChars; ++index) {
803 const FXTEXT_CHARPOS& cp = pCharPos[index];
804 m_positions[index + count] = {cp.m_Origin.x * flip,
805 cp.m_Origin.y * vFlip};
806 m_glyphs[index + count] = static_cast<uint16_t>(cp.m_GlyphIndex);
807 }
808 SkPoint delta;
809 if (MatrixOffset(pMatrix, &delta)) {
810 for (int index = 0; index < nChars; ++index)
811 m_positions[index + count].offset(delta.fX * flip, -delta.fY * flip);
812 }
813 return true;
814 }
815
FlushText()816 void FlushText() {
817 Dump(__func__);
818 SkPaint skPaint;
819 skPaint.setAntiAlias(true);
820 skPaint.setColor(m_fillColor);
821 if (m_pFont->GetFace()) { // exclude placeholder test fonts
822 sk_sp<SkTypeface> typeface(SkSafeRef(m_pFont->GetDeviceCache()));
823 skPaint.setTypeface(typeface);
824 }
825 skPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
826 skPaint.setHinting(SkPaint::kNo_Hinting);
827 skPaint.setTextSize(SkTAbs(m_fontSize));
828 skPaint.setSubpixelText(true);
829 SkCanvas* skCanvas = m_pDriver->SkiaCanvas();
830 skCanvas->save();
831 SkScalar flip = m_fontSize < 0 ? -1 : 1;
832 SkMatrix skMatrix = ToFlippedSkMatrix(m_drawMatrix, flip);
833 skCanvas->concat(skMatrix);
834 #ifdef _SKIA_SUPPORT_PATHS_
835 m_pDriver->PreMultiply();
836 #endif // _SKIA_SUPPORT_PATHS_
837 skCanvas->drawPosText(m_glyphs.begin(), m_glyphs.count() * 2,
838 m_positions.begin(), skPaint);
839 skCanvas->restore();
840 m_drawIndex = INT_MAX;
841 m_type = Accumulator::kNone;
842 }
843
SetClipFill(const CFX_PathData * pPathData,const CFX_Matrix * pMatrix,int fill_mode)844 bool SetClipFill(const CFX_PathData* pPathData,
845 const CFX_Matrix* pMatrix,
846 int fill_mode) {
847 if (m_debugDisable)
848 return false;
849 Dump(__func__);
850 SkPath skClipPath = BuildPath(pPathData);
851 skClipPath.setFillType((fill_mode & 3) == FXFILL_ALTERNATE
852 ? SkPath::kEvenOdd_FillType
853 : SkPath::kWinding_FillType);
854 SkMatrix skMatrix = ToSkMatrix(*pMatrix);
855 skClipPath.transform(skMatrix);
856 return SetClip(skClipPath);
857 }
858
SetClip(const SkPath & skClipPath)859 bool SetClip(const SkPath& skClipPath) {
860 // if a pending draw depends on clip state that is cached, flush it and draw
861 if (m_commandIndex < m_commands.count()) {
862 if (m_commands[m_commandIndex] == Clip::kPath &&
863 m_clips[m_commandIndex] == skClipPath) {
864 ++m_commandIndex;
865 return true;
866 }
867 Flush();
868 }
869 while (m_clipIndex > m_commandIndex) {
870 do {
871 --m_clipIndex;
872 SkASSERT(m_clipIndex >= 0);
873 } while (m_commands[m_clipIndex] != Clip::kSave);
874 m_pDriver->SkiaCanvas()->restore();
875 }
876 if (m_commandIndex < m_commands.count()) {
877 m_commands[m_commandIndex] = Clip::kPath;
878 m_clips[m_commandIndex] = skClipPath;
879 } else {
880 m_commands.push(Clip::kPath);
881 m_clips.push_back(skClipPath);
882 }
883 ++m_commandIndex;
884 return true;
885 }
886
SetClipStroke(const CFX_PathData * pPathData,const CFX_Matrix * pMatrix,const CFX_GraphStateData * pGraphState)887 bool SetClipStroke(const CFX_PathData* pPathData,
888 const CFX_Matrix* pMatrix,
889 const CFX_GraphStateData* pGraphState) {
890 if (m_debugDisable)
891 return false;
892 Dump(__func__);
893 SkPath skPath = BuildPath(pPathData);
894 SkMatrix skMatrix = ToSkMatrix(*pMatrix);
895 SkPaint skPaint;
896 m_pDriver->PaintStroke(&skPaint, pGraphState, skMatrix);
897 SkPath dst_path;
898 skPaint.getFillPath(skPath, &dst_path);
899 dst_path.transform(skMatrix);
900 return SetClip(dst_path);
901 }
902
MatrixOffset(const CFX_Matrix * pMatrix,SkPoint * delta)903 bool MatrixOffset(const CFX_Matrix* pMatrix, SkPoint* delta) {
904 CFX_Matrix identityMatrix;
905 if (!pMatrix)
906 pMatrix = &identityMatrix;
907 delta->set(pMatrix->e - m_drawMatrix.e, pMatrix->f - m_drawMatrix.f);
908 if (!delta->fX && !delta->fY)
909 return true;
910 SkMatrix drawMatrix = ToSkMatrix(m_drawMatrix);
911 if (!(drawMatrix.getType() & ~SkMatrix::kTranslate_Mask))
912 return true;
913 SkMatrix invDrawMatrix;
914 if (!drawMatrix.invert(&invDrawMatrix))
915 return false;
916 SkMatrix invNewMatrix;
917 SkMatrix newMatrix = ToSkMatrix(*pMatrix);
918 if (!newMatrix.invert(&invNewMatrix))
919 return false;
920 delta->set(invDrawMatrix.getTranslateX() - invNewMatrix.getTranslateX(),
921 invDrawMatrix.getTranslateY() - invNewMatrix.getTranslateY());
922 return true;
923 }
924
925 // returns true if caller should apply command to skia canvas
ClipSave()926 bool ClipSave() {
927 if (m_debugDisable)
928 return false;
929 Dump(__func__);
930 int count = m_commands.count();
931 if (m_commandIndex < count - 1) {
932 if (Clip::kSave == m_commands[m_commandIndex + 1]) {
933 ++m_commandIndex;
934 return true;
935 }
936 Flush();
937 AdjustClip(m_commandIndex);
938 m_commands[++m_commandIndex] = Clip::kSave;
939 m_clips[m_commandIndex] = m_skEmptyPath;
940 } else {
941 AdjustClip(m_commandIndex);
942 m_commands.push(Clip::kSave);
943 m_clips.push_back(m_skEmptyPath);
944 ++m_commandIndex;
945 }
946 return true;
947 }
948
ClipRestore()949 bool ClipRestore() {
950 if (m_debugDisable)
951 return false;
952 Dump(__func__);
953 while (Clip::kSave != m_commands[--m_commandIndex]) {
954 SkASSERT(m_commandIndex > 0);
955 }
956 return true;
957 }
958
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) const959 bool DrawChanged(const CFX_Matrix* pMatrix,
960 const CFX_GraphStateData* pState,
961 uint32_t fill_color,
962 uint32_t stroke_color,
963 int fill_mode,
964 int blend_type,
965 bool group_knockout) const {
966 return MatrixChanged(pMatrix, m_drawMatrix) ||
967 StateChanged(pState, m_drawState) || fill_color != m_fillColor ||
968 stroke_color != m_strokeColor ||
969 ((fill_mode & 3) == FXFILL_ALTERNATE) !=
970 (m_skPath.getFillType() == SkPath::kEvenOdd_FillType) ||
971 blend_type != m_blendType || group_knockout != m_groupKnockout;
972 }
973
FontChanged(CFX_Font * pFont,const CFX_Matrix * pMatrix,FX_FLOAT font_size,uint32_t color) const974 bool FontChanged(CFX_Font* pFont,
975 const CFX_Matrix* pMatrix,
976 FX_FLOAT font_size,
977 uint32_t color) const {
978 return pFont != m_pFont || MatrixChanged(pMatrix, m_drawMatrix) ||
979 font_size != m_fontSize || color != m_fillColor;
980 }
981
MatrixChanged(const CFX_Matrix * pMatrix,const CFX_Matrix & refMatrix) const982 bool MatrixChanged(const CFX_Matrix* pMatrix,
983 const CFX_Matrix& refMatrix) const {
984 CFX_Matrix identityMatrix;
985 if (!pMatrix)
986 pMatrix = &identityMatrix;
987 return pMatrix->a != refMatrix.a || pMatrix->b != refMatrix.b ||
988 pMatrix->c != refMatrix.c || pMatrix->d != refMatrix.d;
989 }
990
StateChanged(const CFX_GraphStateData * pState,const CFX_GraphStateData & refState) const991 bool StateChanged(const CFX_GraphStateData* pState,
992 const CFX_GraphStateData& refState) const {
993 CFX_GraphStateData identityState;
994 if (!pState)
995 pState = &identityState;
996 return pState->m_LineWidth != refState.m_LineWidth ||
997 pState->m_LineCap != refState.m_LineCap ||
998 pState->m_LineJoin != refState.m_LineJoin ||
999 pState->m_MiterLimit != refState.m_MiterLimit ||
1000 DashChanged(pState, refState);
1001 }
1002
DashChanged(const CFX_GraphStateData * pState,const CFX_GraphStateData & refState) const1003 bool DashChanged(const CFX_GraphStateData* pState,
1004 const CFX_GraphStateData& refState) const {
1005 bool dashArray = pState && pState->m_DashArray;
1006 if (!dashArray && !refState.m_DashArray)
1007 return false;
1008 if (!dashArray || !refState.m_DashArray)
1009 return true;
1010 if (pState->m_DashPhase != refState.m_DashPhase ||
1011 pState->m_DashCount != refState.m_DashCount) {
1012 return true;
1013 }
1014 for (int index = 0; index < pState->m_DashCount; ++index) {
1015 if (pState->m_DashArray[index] != refState.m_DashArray[index])
1016 return true;
1017 }
1018 return true;
1019 }
1020
AdjustClip(int limit)1021 void AdjustClip(int limit) {
1022 while (m_clipIndex > limit) {
1023 do {
1024 --m_clipIndex;
1025 SkASSERT(m_clipIndex >= 0);
1026 } while (m_commands[m_clipIndex] != Clip::kSave);
1027 m_pDriver->SkiaCanvas()->restore();
1028 }
1029 while (m_clipIndex < limit) {
1030 if (Clip::kSave == m_commands[m_clipIndex]) {
1031 m_pDriver->SkiaCanvas()->save();
1032 } else {
1033 SkASSERT(Clip::kPath == m_commands[m_clipIndex]);
1034 m_pDriver->SkiaCanvas()->clipPath(m_clips[m_clipIndex],
1035 SkClipOp::kIntersect, true);
1036 }
1037 ++m_clipIndex;
1038 }
1039 }
1040
Flush()1041 void Flush() {
1042 if (m_debugDisable)
1043 return;
1044 Dump(__func__);
1045 if (Accumulator::kPath == m_type || Accumulator::kText == m_type) {
1046 AdjustClip(SkTMin(m_drawIndex, m_commands.count()));
1047 Accumulator::kPath == m_type ? FlushPath() : FlushText();
1048 }
1049 }
1050
FlushForDraw()1051 void FlushForDraw() {
1052 if (m_debugDisable)
1053 return;
1054 Flush(); // draw any pending text or path
1055 AdjustClip(m_commandIndex); // set up clip stack with any pending state
1056 }
1057
1058 #if SHOW_SKIA_PATH
DumpPrefix(int index) const1059 void DumpPrefix(int index) const {
1060 if (index != m_commandIndex && index != m_drawIndex &&
1061 index != m_clipIndex) {
1062 printf(" ");
1063 return;
1064 }
1065 printf("%c%c%c> ", index == m_commandIndex ? 'x' : '-',
1066 index == m_drawIndex ? 'd' : '-', index == m_clipIndex ? 'c' : '-');
1067 }
1068
DumpEndPrefix() const1069 void DumpEndPrefix() const {
1070 int index = m_commands.count();
1071 if (index != m_commandIndex && index > m_drawIndex && index != m_clipIndex)
1072 return;
1073 printf("%c%c%c>\n", index == m_commandIndex ? 'x' : '-',
1074 index <= m_drawIndex ? 'd' : '-', index == m_clipIndex ? 'c' : '-');
1075 }
1076 #endif // SHOW_SKIA_PATH
1077
Dump(const char * where) const1078 void Dump(const char* where) const {
1079 #if SHOW_SKIA_PATH
1080 printf("\n%s\nSkia Save Count %d:\n", where,
1081 m_pDriver->m_pCanvas->getSaveCount());
1082 printf("Cache:\n");
1083 for (int index = 0; index < m_commands.count(); ++index) {
1084 DumpPrefix(index);
1085 switch (m_commands[index]) {
1086 case Clip::kSave:
1087 printf("Save %d\n", ++m_debugSaveCounter);
1088 break;
1089 case Clip::kPath:
1090 m_clips[index].dump();
1091 break;
1092 default:
1093 printf("unknown\n");
1094 }
1095 }
1096 DumpEndPrefix();
1097 #endif // SHOW_SKIA_PATH
1098 #ifdef SK_DEBUG
1099 int skCanvasSaveCount = m_pDriver->m_pCanvas->getSaveCount();
1100 int cacheSaveCount = 1;
1101 SkASSERT(m_clipIndex <= m_commands.count());
1102 for (int index = 0; index < m_clipIndex; ++index)
1103 cacheSaveCount += Clip::kSave == m_commands[index];
1104 SkASSERT(skCanvasSaveCount == cacheSaveCount);
1105 #endif
1106 }
1107
1108 private:
1109 SkTArray<SkPath> m_clips; // stack of clips that may be reused
1110 SkTDArray<Clip> m_commands; // stack of clip-related commands
1111 SkTDArray<SkPoint> m_positions; // accumulator for text positions
1112 SkTDArray<uint16_t> m_glyphs; // accumulator for text glyphs
1113 SkPath m_skPath; // accumulator for path contours
1114 SkPath m_skEmptyPath; // used as placehold in the clips array
1115 CFX_Matrix m_drawMatrix;
1116 CFX_GraphStateData m_clipState;
1117 CFX_GraphStateData m_drawState;
1118 CFX_Matrix m_clipMatrix;
1119 CFX_SkiaDeviceDriver* m_pDriver;
1120 CFX_Font* m_pFont;
1121 FX_FLOAT m_fontSize;
1122 uint32_t m_fillColor;
1123 uint32_t m_strokeColor;
1124 int m_blendType;
1125 int m_commandIndex; // active position in clip command stack
1126 int m_drawIndex; // position of the pending path or text draw
1127 int m_clipIndex; // position reflecting depth of canvas clip stacck
1128 Accumulator m_type; // type of pending draw
1129 bool m_fillFullCover;
1130 bool m_fillPath;
1131 bool m_groupKnockout;
1132 bool m_debugDisable; // turn off cache for debugging
1133 #if SHOW_SKIA_PATH
1134 mutable int m_debugSaveCounter;
1135 #endif
1136 };
1137
1138 // convert a stroking path to scanlines
PaintStroke(SkPaint * spaint,const CFX_GraphStateData * pGraphState,const SkMatrix & matrix)1139 void CFX_SkiaDeviceDriver::PaintStroke(SkPaint* spaint,
1140 const CFX_GraphStateData* pGraphState,
1141 const SkMatrix& matrix) {
1142 SkPaint::Cap cap;
1143 switch (pGraphState->m_LineCap) {
1144 case CFX_GraphStateData::LineCapRound:
1145 cap = SkPaint::kRound_Cap;
1146 break;
1147 case CFX_GraphStateData::LineCapSquare:
1148 cap = SkPaint::kSquare_Cap;
1149 break;
1150 default:
1151 cap = SkPaint::kButt_Cap;
1152 break;
1153 }
1154 SkPaint::Join join;
1155 switch (pGraphState->m_LineJoin) {
1156 case CFX_GraphStateData::LineJoinRound:
1157 join = SkPaint::kRound_Join;
1158 break;
1159 case CFX_GraphStateData::LineJoinBevel:
1160 join = SkPaint::kBevel_Join;
1161 break;
1162 default:
1163 join = SkPaint::kMiter_Join;
1164 break;
1165 }
1166 SkMatrix inverse;
1167 if (!matrix.invert(&inverse))
1168 return; // give up if the matrix is degenerate, and not invertable
1169 inverse.set(SkMatrix::kMTransX, 0);
1170 inverse.set(SkMatrix::kMTransY, 0);
1171 SkVector deviceUnits[2] = {{0, 1}, {1, 0}};
1172 inverse.mapPoints(deviceUnits, SK_ARRAY_COUNT(deviceUnits));
1173 FX_FLOAT width =
1174 SkTMax(pGraphState->m_LineWidth,
1175 SkTMin(deviceUnits[0].length(), deviceUnits[1].length()));
1176 if (pGraphState->m_DashArray) {
1177 int count = (pGraphState->m_DashCount + 1) / 2;
1178 SkScalar* intervals = FX_Alloc2D(SkScalar, count, sizeof(SkScalar));
1179 // Set dash pattern
1180 for (int i = 0; i < count; i++) {
1181 FX_FLOAT on = pGraphState->m_DashArray[i * 2];
1182 if (on <= 0.000001f)
1183 on = 1.f / 10;
1184 FX_FLOAT off = i * 2 + 1 == pGraphState->m_DashCount
1185 ? on
1186 : pGraphState->m_DashArray[i * 2 + 1];
1187 if (off < 0)
1188 off = 0;
1189 intervals[i * 2] = on;
1190 intervals[i * 2 + 1] = off;
1191 }
1192 spaint->setPathEffect(
1193 SkDashPathEffect::Make(intervals, count * 2, pGraphState->m_DashPhase));
1194 }
1195 spaint->setStyle(SkPaint::kStroke_Style);
1196 spaint->setAntiAlias(true);
1197 spaint->setStrokeWidth(width);
1198 spaint->setStrokeMiter(pGraphState->m_MiterLimit);
1199 spaint->setStrokeCap(cap);
1200 spaint->setStrokeJoin(join);
1201 }
1202
CFX_SkiaDeviceDriver(CFX_DIBitmap * pBitmap,bool bRgbByteOrder,CFX_DIBitmap * pOriDevice,bool bGroupKnockout)1203 CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(CFX_DIBitmap* pBitmap,
1204 bool bRgbByteOrder,
1205 CFX_DIBitmap* pOriDevice,
1206 bool bGroupKnockout)
1207 : m_pBitmap(pBitmap),
1208 m_pOriDevice(pOriDevice),
1209 m_pRecorder(nullptr),
1210 m_pCache(new SkiaState(this)),
1211 #ifdef _SKIA_SUPPORT_PATHS_
1212 m_pClipRgn(nullptr),
1213 m_FillFlags(0),
1214 m_bRgbByteOrder(bRgbByteOrder),
1215 #endif // _SKIA_SUPPORT_PATHS_
1216 m_bGroupKnockout(bGroupKnockout) {
1217 SkBitmap skBitmap;
1218 SkASSERT(pBitmap->GetBPP() == 8 || pBitmap->GetBPP() == 32);
1219 SkImageInfo imageInfo = SkImageInfo::Make(
1220 pBitmap->GetWidth(), pBitmap->GetHeight(),
1221 pBitmap->GetBPP() == 8 ? kAlpha_8_SkColorType : kN32_SkColorType,
1222 kOpaque_SkAlphaType);
1223 skBitmap.installPixels(imageInfo, pBitmap->GetBuffer(), pBitmap->GetPitch(),
1224 nullptr, // FIXME(caryclark) set color table
1225 nullptr, nullptr);
1226 m_pCanvas = new SkCanvas(skBitmap);
1227 }
1228
1229 #ifdef _SKIA_SUPPORT_
CFX_SkiaDeviceDriver(int size_x,int size_y)1230 CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(int size_x, int size_y)
1231 : m_pBitmap(nullptr),
1232 m_pOriDevice(nullptr),
1233 m_pRecorder(new SkPictureRecorder),
1234 m_pCache(new SkiaState(this)),
1235 m_bGroupKnockout(false) {
1236 m_pRecorder->beginRecording(SkIntToScalar(size_x), SkIntToScalar(size_y));
1237 m_pCanvas = m_pRecorder->getRecordingCanvas();
1238 }
1239
CFX_SkiaDeviceDriver(SkPictureRecorder * recorder)1240 CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(SkPictureRecorder* recorder)
1241 : m_pBitmap(nullptr),
1242 m_pOriDevice(nullptr),
1243 m_pRecorder(recorder),
1244 m_pCache(new SkiaState(this)),
1245 m_bGroupKnockout(false) {
1246 m_pCanvas = m_pRecorder->getRecordingCanvas();
1247 }
1248 #endif // _SKIA_SUPPORT_
1249
~CFX_SkiaDeviceDriver()1250 CFX_SkiaDeviceDriver::~CFX_SkiaDeviceDriver() {
1251 Flush();
1252 if (!m_pRecorder)
1253 delete m_pCanvas;
1254 }
1255
Flush()1256 void CFX_SkiaDeviceDriver::Flush() {
1257 m_pCache->Flush();
1258 }
1259
DrawDeviceText(int nChars,const FXTEXT_CHARPOS * pCharPos,CFX_Font * pFont,const CFX_Matrix * pObject2Device,FX_FLOAT font_size,uint32_t color)1260 bool CFX_SkiaDeviceDriver::DrawDeviceText(int nChars,
1261 const FXTEXT_CHARPOS* pCharPos,
1262 CFX_Font* pFont,
1263 const CFX_Matrix* pObject2Device,
1264 FX_FLOAT font_size,
1265 uint32_t color) {
1266 if (m_pCache->DrawText(nChars, pCharPos, pFont, pObject2Device, font_size,
1267 color)) {
1268 return true;
1269 }
1270 sk_sp<SkTypeface> typeface(SkSafeRef(pFont->GetDeviceCache()));
1271 SkPaint paint;
1272 paint.setAntiAlias(true);
1273 paint.setColor(color);
1274 paint.setTypeface(typeface);
1275 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
1276 paint.setHinting(SkPaint::kNo_Hinting);
1277 paint.setTextSize(SkTAbs(font_size));
1278 paint.setSubpixelText(true);
1279 m_pCanvas->save();
1280 SkScalar flip = font_size < 0 ? -1 : 1;
1281 SkScalar vFlip = flip;
1282 if (pFont->IsVertical())
1283 vFlip *= -1;
1284 SkMatrix skMatrix = ToFlippedSkMatrix(*pObject2Device, flip);
1285 m_pCanvas->concat(skMatrix);
1286 SkTDArray<SkPoint> positions;
1287 positions.setCount(nChars);
1288 SkTDArray<uint16_t> glyphs;
1289 glyphs.setCount(nChars);
1290 for (int index = 0; index < nChars; ++index) {
1291 const FXTEXT_CHARPOS& cp = pCharPos[index];
1292 positions[index] = {cp.m_Origin.x * flip, cp.m_Origin.y * vFlip};
1293 glyphs[index] = static_cast<uint16_t>(cp.m_GlyphIndex);
1294 }
1295 #ifdef _SKIA_SUPPORT_PATHS_
1296 m_pBitmap->PreMultiply();
1297 #endif // _SKIA_SUPPORT_PATHS_
1298 m_pCanvas->drawPosText(glyphs.begin(), nChars * 2, positions.begin(), paint);
1299 m_pCanvas->restore();
1300
1301 return true;
1302 }
1303
GetDeviceCaps(int caps_id) const1304 int CFX_SkiaDeviceDriver::GetDeviceCaps(int caps_id) const {
1305 switch (caps_id) {
1306 case FXDC_DEVICE_CLASS:
1307 return FXDC_DISPLAY;
1308 #ifdef _SKIA_SUPPORT_
1309 case FXDC_PIXEL_WIDTH:
1310 return m_pCanvas->imageInfo().width();
1311 case FXDC_PIXEL_HEIGHT:
1312 return m_pCanvas->imageInfo().height();
1313 case FXDC_BITS_PIXEL:
1314 return 32;
1315 case FXDC_HORZ_SIZE:
1316 case FXDC_VERT_SIZE:
1317 return 0;
1318 case FXDC_RENDER_CAPS:
1319 return FXRC_GET_BITS | FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE |
1320 FXRC_BLEND_MODE | FXRC_SOFT_CLIP | FXRC_ALPHA_OUTPUT |
1321 FXRC_FILLSTROKE_PATH | FXRC_SHADING;
1322 #endif // _SKIA_SUPPORT_
1323
1324 #ifdef _SKIA_SUPPORT_PATHS_
1325 case FXDC_PIXEL_WIDTH:
1326 return m_pBitmap->GetWidth();
1327 case FXDC_PIXEL_HEIGHT:
1328 return m_pBitmap->GetHeight();
1329 case FXDC_BITS_PIXEL:
1330 return m_pBitmap->GetBPP();
1331 case FXDC_HORZ_SIZE:
1332 case FXDC_VERT_SIZE:
1333 return 0;
1334 case FXDC_RENDER_CAPS: {
1335 int flags = FXRC_GET_BITS | FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE |
1336 FXRC_BLEND_MODE | FXRC_SOFT_CLIP | FXRC_SHADING;
1337 if (m_pBitmap->HasAlpha()) {
1338 flags |= FXRC_ALPHA_OUTPUT;
1339 } else if (m_pBitmap->IsAlphaMask()) {
1340 if (m_pBitmap->GetBPP() == 1) {
1341 flags |= FXRC_BITMASK_OUTPUT;
1342 } else {
1343 flags |= FXRC_BYTEMASK_OUTPUT;
1344 }
1345 }
1346 if (m_pBitmap->IsCmykImage()) {
1347 flags |= FXRC_CMYK_OUTPUT;
1348 }
1349 return flags;
1350 }
1351 #endif // _SKIA_SUPPORT_PATHS_
1352 }
1353 return 0;
1354 }
1355
SaveState()1356 void CFX_SkiaDeviceDriver::SaveState() {
1357 if (!m_pCache->ClipSave())
1358 m_pCanvas->save();
1359
1360 #ifdef _SKIA_SUPPORT_PATHS_
1361 std::unique_ptr<CFX_ClipRgn> pClip;
1362 if (m_pClipRgn)
1363 pClip = pdfium::MakeUnique<CFX_ClipRgn>(*m_pClipRgn);
1364 m_StateStack.push_back(std::move(pClip));
1365 #endif // _SKIA_SUPPORT_PATHS_
1366 }
1367
RestoreState(bool bKeepSaved)1368 void CFX_SkiaDeviceDriver::RestoreState(bool bKeepSaved) {
1369 if (!m_pCache->ClipRestore())
1370 m_pCanvas->restore();
1371 if (bKeepSaved && !m_pCache->ClipSave())
1372 m_pCanvas->save();
1373 #ifdef _SKIA_SUPPORT_PATHS_
1374 m_pClipRgn.reset();
1375
1376 if (m_StateStack.empty())
1377 return;
1378
1379 if (bKeepSaved) {
1380 if (m_StateStack.back())
1381 m_pClipRgn = pdfium::MakeUnique<CFX_ClipRgn>(*m_StateStack.back());
1382 } else {
1383 m_pClipRgn = std::move(m_StateStack.back());
1384 m_StateStack.pop_back();
1385 }
1386 #endif // _SKIA_SUPPORT_PATHS_
1387 }
1388
1389 #ifdef _SKIA_SUPPORT_PATHS_
SetClipMask(const FX_RECT & clipBox,const SkPath & path)1390 void CFX_SkiaDeviceDriver::SetClipMask(const FX_RECT& clipBox,
1391 const SkPath& path) {
1392 FX_RECT path_rect(clipBox.left, clipBox.top, clipBox.right + 1,
1393 clipBox.bottom + 1);
1394 path_rect.Intersect(m_pClipRgn->GetBox());
1395 CFX_DIBitmapRef mask;
1396 CFX_DIBitmap* pThisLayer = mask.Emplace();
1397 pThisLayer->Create(path_rect.Width(), path_rect.Height(), FXDIB_8bppMask);
1398 pThisLayer->Clear(0);
1399
1400 SkImageInfo imageInfo =
1401 SkImageInfo::Make(pThisLayer->GetWidth(), pThisLayer->GetHeight(),
1402 SkColorType::kAlpha_8_SkColorType, kOpaque_SkAlphaType);
1403 SkBitmap bitmap;
1404 bitmap.installPixels(imageInfo, pThisLayer->GetBuffer(),
1405 pThisLayer->GetPitch(), nullptr, nullptr, nullptr);
1406 SkCanvas* canvas = new SkCanvas(bitmap);
1407 canvas->translate(
1408 -path_rect.left,
1409 -path_rect.top); // FIXME(caryclark) wrong sign(s)? upside down?
1410 SkPaint paint;
1411 paint.setAntiAlias((m_FillFlags & FXFILL_NOPATHSMOOTH) == 0);
1412 canvas->drawPath(path, paint);
1413 m_pClipRgn->IntersectMaskF(path_rect.left, path_rect.top, mask);
1414 delete canvas;
1415 }
1416 #endif // _SKIA_SUPPORT_PATHS_
1417
SetClip_PathFill(const CFX_PathData * pPathData,const CFX_Matrix * pObject2Device,int fill_mode)1418 bool CFX_SkiaDeviceDriver::SetClip_PathFill(
1419 const CFX_PathData* pPathData, // path info
1420 const CFX_Matrix* pObject2Device, // flips object's y-axis
1421 int fill_mode // fill mode, WINDING or ALTERNATE
1422 ) {
1423 CFX_Matrix identity;
1424 const CFX_Matrix* deviceMatrix = pObject2Device ? pObject2Device : &identity;
1425 bool cached = m_pCache->SetClipFill(pPathData, deviceMatrix, fill_mode);
1426
1427 #ifdef _SKIA_SUPPORT_PATHS_
1428 m_FillFlags = fill_mode;
1429 if (!m_pClipRgn) {
1430 m_pClipRgn = pdfium::MakeUnique<CFX_ClipRgn>(
1431 GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT));
1432 }
1433 #endif // _SKIA_SUPPORT_PATHS_
1434 if (pPathData->GetPoints().size() == 5 ||
1435 pPathData->GetPoints().size() == 4) {
1436 CFX_FloatRect rectf;
1437 if (pPathData->IsRect(deviceMatrix, &rectf)) {
1438 rectf.Intersect(
1439 CFX_FloatRect(0, 0, (FX_FLOAT)GetDeviceCaps(FXDC_PIXEL_WIDTH),
1440 (FX_FLOAT)GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
1441 // note that PDF's y-axis goes up; Skia's y-axis goes down
1442 if (!cached) {
1443 SkRect skClipRect =
1444 SkRect::MakeLTRB(rectf.left, rectf.bottom, rectf.right, rectf.top);
1445 DebugDrawSkiaClipRect(m_pCanvas, skClipRect);
1446 m_pCanvas->clipRect(skClipRect, SkClipOp::kIntersect, true);
1447 }
1448
1449 #ifdef _SKIA_SUPPORT_PATHS_
1450 FX_RECT rect = rectf.GetOuterRect();
1451 m_pClipRgn->IntersectRect(rect);
1452 #endif // _SKIA_SUPPORT_PATHS_
1453 DebugShowCanvasClip(m_pCanvas);
1454 return true;
1455 }
1456 }
1457 SkPath skClipPath = BuildPath(pPathData);
1458 skClipPath.setFillType((fill_mode & 3) == FXFILL_ALTERNATE
1459 ? SkPath::kEvenOdd_FillType
1460 : SkPath::kWinding_FillType);
1461 SkMatrix skMatrix = ToSkMatrix(*deviceMatrix);
1462 skClipPath.transform(skMatrix);
1463 DebugShowSkiaPath(skClipPath);
1464 if (!cached) {
1465 DebugDrawSkiaClipPath(m_pCanvas, skClipPath);
1466 m_pCanvas->clipPath(skClipPath, SkClipOp::kIntersect, true);
1467 }
1468 #ifdef _SKIA_SUPPORT_PATHS_
1469 FX_RECT clipBox(0, 0, GetDeviceCaps(FXDC_PIXEL_WIDTH),
1470 GetDeviceCaps(FXDC_PIXEL_HEIGHT));
1471 SetClipMask(clipBox, skClipPath);
1472 #endif // _SKIA_SUPPORT_PATHS_
1473 DebugShowCanvasClip(m_pCanvas);
1474 return true;
1475 }
1476
SetClip_PathStroke(const CFX_PathData * pPathData,const CFX_Matrix * pObject2Device,const CFX_GraphStateData * pGraphState)1477 bool CFX_SkiaDeviceDriver::SetClip_PathStroke(
1478 const CFX_PathData* pPathData, // path info
1479 const CFX_Matrix* pObject2Device, // optional transformation
1480 const CFX_GraphStateData* pGraphState // graphic state, for pen attributes
1481 ) {
1482 bool cached = m_pCache->SetClipStroke(pPathData, pObject2Device, pGraphState);
1483
1484 #ifdef _SKIA_SUPPORT_PATHS_
1485 if (!m_pClipRgn) {
1486 m_pClipRgn = pdfium::MakeUnique<CFX_ClipRgn>(
1487 GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT));
1488 }
1489 #endif // _SKIA_SUPPORT_PATHS_
1490 // build path data
1491 SkPath skPath = BuildPath(pPathData);
1492 SkMatrix skMatrix = ToSkMatrix(*pObject2Device);
1493 SkPaint skPaint;
1494 PaintStroke(&skPaint, pGraphState, skMatrix);
1495 SkPath dst_path;
1496 skPaint.getFillPath(skPath, &dst_path);
1497 dst_path.transform(skMatrix);
1498 if (!cached) {
1499 DebugDrawSkiaClipPath(m_pCanvas, dst_path);
1500 m_pCanvas->clipPath(dst_path, SkClipOp::kIntersect, true);
1501 }
1502 #ifdef _SKIA_SUPPORT_PATHS_
1503 FX_RECT clipBox(0, 0, GetDeviceCaps(FXDC_PIXEL_WIDTH),
1504 GetDeviceCaps(FXDC_PIXEL_HEIGHT));
1505 SetClipMask(clipBox, dst_path);
1506 #endif // _SKIA_SUPPORT_PATHS_
1507 DebugShowCanvasClip(m_pCanvas);
1508 return true;
1509 }
1510
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)1511 bool CFX_SkiaDeviceDriver::DrawPath(
1512 const CFX_PathData* pPathData, // path info
1513 const CFX_Matrix* pObject2Device, // optional transformation
1514 const CFX_GraphStateData* pGraphState, // graphic state, for pen attributes
1515 uint32_t fill_color, // fill color
1516 uint32_t stroke_color, // stroke color
1517 int fill_mode, // fill mode, WINDING or ALTERNATE. 0 for not filled
1518 int blend_type) {
1519 if (fill_mode & FX_ZEROAREA_FILL)
1520 return true;
1521 if (m_pCache->DrawPath(pPathData, pObject2Device, pGraphState, fill_color,
1522 stroke_color, fill_mode, blend_type)) {
1523 return true;
1524 }
1525 SkMatrix skMatrix;
1526 if (pObject2Device)
1527 skMatrix = ToSkMatrix(*pObject2Device);
1528 else
1529 skMatrix.setIdentity();
1530 SkPaint skPaint;
1531 skPaint.setAntiAlias(true);
1532 if (fill_mode & FXFILL_FULLCOVER)
1533 skPaint.setBlendMode(SkBlendMode::kPlus);
1534 int stroke_alpha = FXARGB_A(stroke_color);
1535 if (pGraphState && stroke_alpha)
1536 PaintStroke(&skPaint, pGraphState, skMatrix);
1537 SkPath skPath = BuildPath(pPathData);
1538 m_pCanvas->save();
1539 m_pCanvas->concat(skMatrix);
1540 if ((fill_mode & 3) && fill_color) {
1541 skPath.setFillType((fill_mode & 3) == FXFILL_ALTERNATE
1542 ? SkPath::kEvenOdd_FillType
1543 : SkPath::kWinding_FillType);
1544 SkPath strokePath;
1545 const SkPath* fillPath = &skPath;
1546 if (pGraphState && stroke_alpha) {
1547 if (m_bGroupKnockout) {
1548 skPaint.getFillPath(skPath, &strokePath);
1549 if (Op(skPath, strokePath, SkPathOp::kDifference_SkPathOp,
1550 &strokePath)) {
1551 fillPath = &strokePath;
1552 }
1553 }
1554 }
1555 skPaint.setStyle(SkPaint::kFill_Style);
1556 skPaint.setColor(fill_color);
1557 #ifdef _SKIA_SUPPORT_PATHS_
1558 m_pBitmap->PreMultiply();
1559 #endif // _SKIA_SUPPORT_PATHS_
1560 DebugShowSkiaDrawPath(m_pCanvas, skPaint, *fillPath);
1561 m_pCanvas->drawPath(*fillPath, skPaint);
1562 }
1563 if (pGraphState && stroke_alpha) {
1564 skPaint.setStyle(SkPaint::kStroke_Style);
1565 skPaint.setColor(stroke_color);
1566 #ifdef _SKIA_SUPPORT_PATHS_
1567 m_pBitmap->PreMultiply();
1568 #endif // _SKIA_SUPPORT_PATHS_
1569 DebugShowSkiaDrawPath(m_pCanvas, skPaint, skPath);
1570 m_pCanvas->drawPath(skPath, skPaint);
1571 }
1572 m_pCanvas->restore();
1573 return true;
1574 }
1575
DrawCosmeticLine(FX_FLOAT x1,FX_FLOAT y1,FX_FLOAT x2,FX_FLOAT y2,uint32_t color,int blend_type)1576 bool CFX_SkiaDeviceDriver::DrawCosmeticLine(FX_FLOAT x1,
1577 FX_FLOAT y1,
1578 FX_FLOAT x2,
1579 FX_FLOAT y2,
1580 uint32_t color,
1581 int blend_type) {
1582 return false;
1583 }
1584
FillRectWithBlend(const FX_RECT * pRect,uint32_t fill_color,int blend_type)1585 bool CFX_SkiaDeviceDriver::FillRectWithBlend(const FX_RECT* pRect,
1586 uint32_t fill_color,
1587 int blend_type) {
1588 m_pCache->FlushForDraw();
1589 SkPaint spaint;
1590 spaint.setAntiAlias(true);
1591 spaint.setColor(fill_color);
1592 spaint.setBlendMode(GetSkiaBlendMode(blend_type));
1593 SkRect rect =
1594 SkRect::MakeLTRB(pRect->left, SkTMin(pRect->top, pRect->bottom),
1595 pRect->right, SkTMax(pRect->bottom, pRect->top));
1596 DebugShowSkiaDrawRect(m_pCanvas, spaint, rect);
1597 m_pCanvas->drawRect(rect, spaint);
1598 return true;
1599 }
1600
DrawShading(const CPDF_ShadingPattern * pPattern,const CFX_Matrix * pMatrix,const FX_RECT & clip_rect,int alpha,bool bAlphaMode)1601 bool CFX_SkiaDeviceDriver::DrawShading(const CPDF_ShadingPattern* pPattern,
1602 const CFX_Matrix* pMatrix,
1603 const FX_RECT& clip_rect,
1604 int alpha,
1605 bool bAlphaMode) {
1606 m_pCache->FlushForDraw();
1607 ShadingType shadingType = pPattern->GetShadingType();
1608 if (kAxialShading != shadingType && kRadialShading != shadingType &&
1609 kCoonsPatchMeshShading != shadingType) {
1610 // TODO(caryclark) more types
1611 return false;
1612 }
1613 int csFamily = pPattern->GetCS()->GetFamily();
1614 if (PDFCS_DEVICERGB != csFamily && PDFCS_DEVICEGRAY != csFamily)
1615 return false;
1616 const std::vector<std::unique_ptr<CPDF_Function>>& pFuncs =
1617 pPattern->GetFuncs();
1618 int nFuncs = pFuncs.size();
1619 if (nFuncs > 1) // TODO(caryclark) remove this restriction
1620 return false;
1621 CPDF_Dictionary* pDict = pPattern->GetShadingObject()->GetDict();
1622 CPDF_Array* pCoords = pDict->GetArrayFor("Coords");
1623 if (!pCoords && kCoonsPatchMeshShading != shadingType)
1624 return false;
1625 // TODO(caryclark) Respect Domain[0], Domain[1]. (Don't know what they do
1626 // yet.)
1627 SkTDArray<SkColor> skColors;
1628 SkTDArray<SkScalar> skPos;
1629 for (int j = 0; j < nFuncs; j++) {
1630 if (!pFuncs[j])
1631 continue;
1632
1633 if (const CPDF_SampledFunc* pSampledFunc = pFuncs[j]->ToSampledFunc()) {
1634 /* TODO(caryclark)
1635 Type 0 Sampled Functions in PostScript can also have an Order integer
1636 in the dictionary. PDFium doesn't appear to check for this anywhere.
1637 */
1638 if (!AddSamples(pSampledFunc, &skColors, &skPos))
1639 return false;
1640 } else if (const CPDF_ExpIntFunc* pExpIntFuc = pFuncs[j]->ToExpIntFunc()) {
1641 if (!AddColors(pExpIntFuc, &skColors))
1642 return false;
1643 skPos.push(0);
1644 skPos.push(1);
1645 } else if (const CPDF_StitchFunc* pStitchFunc = pFuncs[j]->ToStitchFunc()) {
1646 if (!AddStitching(pStitchFunc, &skColors, &skPos))
1647 return false;
1648 } else {
1649 return false;
1650 }
1651 }
1652 CPDF_Array* pArray = pDict->GetArrayFor("Extend");
1653 bool clipStart = !pArray || !pArray->GetIntegerAt(0);
1654 bool clipEnd = !pArray || !pArray->GetIntegerAt(1);
1655 SkPaint paint;
1656 paint.setAntiAlias(true);
1657 paint.setAlpha(alpha);
1658 SkMatrix skMatrix = ToSkMatrix(*pMatrix);
1659 SkRect skRect = SkRect::MakeLTRB(clip_rect.left, clip_rect.top,
1660 clip_rect.right, clip_rect.bottom);
1661 SkPath skClip;
1662 SkPath skPath;
1663 if (kAxialShading == shadingType) {
1664 FX_FLOAT start_x = pCoords->GetNumberAt(0);
1665 FX_FLOAT start_y = pCoords->GetNumberAt(1);
1666 FX_FLOAT end_x = pCoords->GetNumberAt(2);
1667 FX_FLOAT end_y = pCoords->GetNumberAt(3);
1668 SkPoint pts[] = {{start_x, start_y}, {end_x, end_y}};
1669 skMatrix.mapPoints(pts, SK_ARRAY_COUNT(pts));
1670 paint.setShader(SkGradientShader::MakeLinear(
1671 pts, skColors.begin(), skPos.begin(), skColors.count(),
1672 SkShader::kClamp_TileMode));
1673 if (clipStart || clipEnd) {
1674 // if the gradient is horizontal or vertical, modify the draw rectangle
1675 if (pts[0].fX == pts[1].fX) { // vertical
1676 if (pts[0].fY > pts[1].fY) {
1677 SkTSwap(pts[0].fY, pts[1].fY);
1678 SkTSwap(clipStart, clipEnd);
1679 }
1680 if (clipStart)
1681 skRect.fTop = SkTMax(skRect.fTop, pts[0].fY);
1682 if (clipEnd)
1683 skRect.fBottom = SkTMin(skRect.fBottom, pts[1].fY);
1684 } else if (pts[0].fY == pts[1].fY) { // horizontal
1685 if (pts[0].fX > pts[1].fX) {
1686 SkTSwap(pts[0].fX, pts[1].fX);
1687 SkTSwap(clipStart, clipEnd);
1688 }
1689 if (clipStart)
1690 skRect.fLeft = SkTMax(skRect.fLeft, pts[0].fX);
1691 if (clipEnd)
1692 skRect.fRight = SkTMin(skRect.fRight, pts[1].fX);
1693 } else { // if the gradient is angled and contained by the rect, clip
1694 SkPoint rectPts[4] = {{skRect.fLeft, skRect.fTop},
1695 {skRect.fRight, skRect.fTop},
1696 {skRect.fRight, skRect.fBottom},
1697 {skRect.fLeft, skRect.fBottom}};
1698 ClipAngledGradient(pts, rectPts, clipStart, clipEnd, &skClip);
1699 }
1700 }
1701 skPath.addRect(skRect);
1702 skMatrix.setIdentity();
1703 } else if (kRadialShading == shadingType) {
1704 FX_FLOAT start_x = pCoords->GetNumberAt(0);
1705 FX_FLOAT start_y = pCoords->GetNumberAt(1);
1706 FX_FLOAT start_r = pCoords->GetNumberAt(2);
1707 FX_FLOAT end_x = pCoords->GetNumberAt(3);
1708 FX_FLOAT end_y = pCoords->GetNumberAt(4);
1709 FX_FLOAT end_r = pCoords->GetNumberAt(5);
1710 SkPoint pts[] = {{start_x, start_y}, {end_x, end_y}};
1711
1712 paint.setShader(SkGradientShader::MakeTwoPointConical(
1713 pts[0], start_r, pts[1], end_r, skColors.begin(), skPos.begin(),
1714 skColors.count(), SkShader::kClamp_TileMode));
1715 if (clipStart || clipEnd) {
1716 if (clipStart && start_r)
1717 skClip.addCircle(pts[0].fX, pts[0].fY, start_r);
1718 if (clipEnd)
1719 skClip.addCircle(pts[1].fX, pts[1].fY, end_r, SkPath::kCCW_Direction);
1720 else
1721 skClip.setFillType(SkPath::kInverseWinding_FillType);
1722 skClip.transform(skMatrix);
1723 }
1724 SkMatrix inverse;
1725 if (!skMatrix.invert(&inverse))
1726 return false;
1727 skPath.addRect(skRect);
1728 skPath.transform(inverse);
1729 } else {
1730 ASSERT(kCoonsPatchMeshShading == shadingType);
1731 CPDF_Stream* pStream = ToStream(pPattern->GetShadingObject());
1732 if (!pStream)
1733 return false;
1734 CPDF_MeshStream stream(shadingType, pPattern->GetFuncs(), pStream,
1735 pPattern->GetCS());
1736 if (!stream.Load())
1737 return false;
1738 SkPoint cubics[12];
1739 SkColor colors[4];
1740 m_pCanvas->save();
1741 if (!skClip.isEmpty())
1742 m_pCanvas->clipPath(skClip, SkClipOp::kIntersect, true);
1743 m_pCanvas->concat(skMatrix);
1744 while (!stream.BitStream()->IsEOF()) {
1745 uint32_t flag = stream.ReadFlag();
1746 int iStartPoint = flag ? 4 : 0;
1747 int iStartColor = flag ? 2 : 0;
1748 if (flag) {
1749 SkPoint tempCubics[4];
1750 for (int i = 0; i < (int)SK_ARRAY_COUNT(tempCubics); i++)
1751 tempCubics[i] = cubics[(flag * 3 + i) % 12];
1752 FXSYS_memcpy(cubics, tempCubics, sizeof(tempCubics));
1753 SkColor tempColors[2];
1754 tempColors[0] = colors[flag];
1755 tempColors[1] = colors[(flag + 1) % 4];
1756 FXSYS_memcpy(colors, tempColors, sizeof(tempColors));
1757 }
1758 for (int i = iStartPoint; i < (int)SK_ARRAY_COUNT(cubics); i++) {
1759 CFX_PointF point = stream.ReadCoords();
1760 cubics[i].fX = point.x;
1761 cubics[i].fY = point.y;
1762 }
1763 for (int i = iStartColor; i < (int)SK_ARRAY_COUNT(colors); i++) {
1764 FX_FLOAT r;
1765 FX_FLOAT g;
1766 FX_FLOAT b;
1767 std::tie(r, g, b) = stream.ReadColor();
1768 colors[i] = SkColorSetARGBInline(0xFF, (U8CPU)(r * 255),
1769 (U8CPU)(g * 255), (U8CPU)(b * 255));
1770 }
1771 m_pCanvas->drawPatch(cubics, colors, nullptr, paint);
1772 }
1773 m_pCanvas->restore();
1774 return true;
1775 }
1776 m_pCanvas->save();
1777 if (!skClip.isEmpty())
1778 m_pCanvas->clipPath(skClip, SkClipOp::kIntersect, true);
1779 m_pCanvas->concat(skMatrix);
1780 m_pCanvas->drawPath(skPath, paint);
1781 m_pCanvas->restore();
1782 return true;
1783 }
1784
GetBuffer() const1785 uint8_t* CFX_SkiaDeviceDriver::GetBuffer() const {
1786 return m_pBitmap->GetBuffer();
1787 }
1788
GetClipBox(FX_RECT * pRect)1789 bool CFX_SkiaDeviceDriver::GetClipBox(FX_RECT* pRect) {
1790 // TODO(caryclark) call m_canvas->getClipDeviceBounds() instead
1791 pRect->left = 0;
1792 pRect->top = 0;
1793 const SkImageInfo& canvasSize = m_pCanvas->imageInfo();
1794 pRect->right = canvasSize.width();
1795 pRect->bottom = canvasSize.height();
1796 return true;
1797 }
1798
GetDIBits(CFX_DIBitmap * pBitmap,int left,int top)1799 bool CFX_SkiaDeviceDriver::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) {
1800 if (!m_pBitmap)
1801 return true;
1802 uint8_t* srcBuffer = m_pBitmap->GetBuffer();
1803 if (!srcBuffer)
1804 return true;
1805 #ifdef _SKIA_SUPPORT_
1806 m_pCache->FlushForDraw();
1807 int srcWidth = m_pBitmap->GetWidth();
1808 int srcHeight = m_pBitmap->GetHeight();
1809 int srcRowBytes = srcWidth * sizeof(uint32_t);
1810 SkImageInfo srcImageInfo = SkImageInfo::Make(
1811 srcWidth, srcHeight, SkColorType::kN32_SkColorType, kPremul_SkAlphaType);
1812 SkBitmap skSrcBitmap;
1813 skSrcBitmap.installPixels(srcImageInfo, srcBuffer, srcRowBytes, nullptr,
1814 nullptr, nullptr);
1815 SkASSERT(pBitmap);
1816 uint8_t* dstBuffer = pBitmap->GetBuffer();
1817 SkASSERT(dstBuffer);
1818 int dstWidth = pBitmap->GetWidth();
1819 int dstHeight = pBitmap->GetHeight();
1820 int dstRowBytes = dstWidth * sizeof(uint32_t);
1821 SkImageInfo dstImageInfo = SkImageInfo::Make(
1822 dstWidth, dstHeight, SkColorType::kN32_SkColorType, kPremul_SkAlphaType);
1823 SkBitmap skDstBitmap;
1824 skDstBitmap.installPixels(dstImageInfo, dstBuffer, dstRowBytes, nullptr,
1825 nullptr, nullptr);
1826 SkCanvas canvas(skDstBitmap);
1827 canvas.drawBitmap(skSrcBitmap, left, top, nullptr);
1828 return true;
1829 #endif // _SKIA_SUPPORT_
1830
1831 #ifdef _SKIA_SUPPORT_PATHS_
1832 Flush();
1833 m_pBitmap->UnPreMultiply();
1834 FX_RECT rect(left, top, left + pBitmap->GetWidth(),
1835 top + pBitmap->GetHeight());
1836 std::unique_ptr<CFX_DIBitmap> pBack;
1837 if (m_pOriDevice) {
1838 pBack = m_pOriDevice->Clone(&rect);
1839 if (!pBack)
1840 return true;
1841
1842 pBack->CompositeBitmap(0, 0, pBack->GetWidth(), pBack->GetHeight(),
1843 m_pBitmap, 0, 0);
1844 } else {
1845 pBack = m_pBitmap->Clone(&rect);
1846 if (!pBack)
1847 return true;
1848 }
1849
1850 bool bRet = true;
1851 left = std::min(left, 0);
1852 top = std::min(top, 0);
1853 if (m_bRgbByteOrder) {
1854 RgbByteOrderTransferBitmap(pBitmap, 0, 0, rect.Width(), rect.Height(),
1855 pBack.get(), left, top);
1856 } else {
1857 bRet = pBitmap->TransferBitmap(0, 0, rect.Width(), rect.Height(),
1858 pBack.get(), left, top);
1859 }
1860 return bRet;
1861 #endif // _SKIA_SUPPORT_PATHS_
1862 }
1863
GetBackDrop()1864 CFX_DIBitmap* CFX_SkiaDeviceDriver::GetBackDrop() {
1865 return m_pOriDevice;
1866 }
1867
SetDIBits(const CFX_DIBSource * pBitmap,uint32_t argb,const FX_RECT * pSrcRect,int left,int top,int blend_type)1868 bool CFX_SkiaDeviceDriver::SetDIBits(const CFX_DIBSource* pBitmap,
1869 uint32_t argb,
1870 const FX_RECT* pSrcRect,
1871 int left,
1872 int top,
1873 int blend_type) {
1874 if (!m_pBitmap || !m_pBitmap->GetBuffer())
1875 return true;
1876
1877 #ifdef _SKIA_SUPPORT_
1878 CFX_Matrix m(pBitmap->GetWidth(), 0, 0, -pBitmap->GetHeight(), left,
1879 top + pBitmap->GetHeight());
1880 void* dummy;
1881 return StartDIBits(pBitmap, 0xFF, argb, &m, 0, dummy, blend_type);
1882 #endif // _SKIA_SUPPORT_
1883
1884 #ifdef _SKIA_SUPPORT_PATHS_
1885 Flush();
1886 if (pBitmap->IsAlphaMask()) {
1887 return m_pBitmap->CompositeMask(
1888 left, top, pSrcRect->Width(), pSrcRect->Height(), pBitmap, argb,
1889 pSrcRect->left, pSrcRect->top, blend_type, m_pClipRgn.get(),
1890 m_bRgbByteOrder, 0, nullptr);
1891 }
1892 return m_pBitmap->CompositeBitmap(
1893 left, top, pSrcRect->Width(), pSrcRect->Height(), pBitmap, pSrcRect->left,
1894 pSrcRect->top, blend_type, m_pClipRgn.get(), m_bRgbByteOrder, nullptr);
1895 #endif // _SKIA_SUPPORT_PATHS_
1896 }
1897
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)1898 bool CFX_SkiaDeviceDriver::StretchDIBits(const CFX_DIBSource* pSource,
1899 uint32_t argb,
1900 int dest_left,
1901 int dest_top,
1902 int dest_width,
1903 int dest_height,
1904 const FX_RECT* pClipRect,
1905 uint32_t flags,
1906 int blend_type) {
1907 #ifdef _SKIA_SUPPORT_
1908 m_pCache->FlushForDraw();
1909 if (!m_pBitmap->GetBuffer())
1910 return true;
1911 CFX_Matrix m(dest_width, 0, 0, -dest_height, dest_left,
1912 dest_top + dest_height);
1913
1914 m_pCanvas->save();
1915 SkRect skClipRect = SkRect::MakeLTRB(pClipRect->left, pClipRect->bottom,
1916 pClipRect->right, pClipRect->top);
1917 m_pCanvas->clipRect(skClipRect, SkClipOp::kIntersect, true);
1918 void* dummy;
1919 bool result = StartDIBits(pSource, 0xFF, argb, &m, 0, dummy, blend_type);
1920 m_pCanvas->restore();
1921
1922 return result;
1923 #endif // _SKIA_SUPPORT_
1924
1925 #ifdef _SKIA_SUPPORT_PATHS_
1926 if (dest_width == pSource->GetWidth() &&
1927 dest_height == pSource->GetHeight()) {
1928 FX_RECT rect(0, 0, dest_width, dest_height);
1929 return SetDIBits(pSource, argb, &rect, dest_left, dest_top, blend_type);
1930 }
1931 Flush();
1932 FX_RECT dest_rect(dest_left, dest_top, dest_left + dest_width,
1933 dest_top + dest_height);
1934 dest_rect.Normalize();
1935 FX_RECT dest_clip = dest_rect;
1936 dest_clip.Intersect(*pClipRect);
1937 CFX_BitmapComposer composer;
1938 composer.Compose(m_pBitmap, m_pClipRgn.get(), 255, argb, dest_clip, false,
1939 false, false, m_bRgbByteOrder, 0, nullptr, blend_type);
1940 dest_clip.Offset(-dest_rect.left, -dest_rect.top);
1941 CFX_ImageStretcher stretcher(&composer, pSource, dest_width, dest_height,
1942 dest_clip, flags);
1943 if (stretcher.Start())
1944 stretcher.Continue(nullptr);
1945 return true;
1946 #endif // _SKIA_SUPPORT_PATHS_
1947 }
1948
StartDIBits(const CFX_DIBSource * pSource,int bitmap_alpha,uint32_t argb,const CFX_Matrix * pMatrix,uint32_t render_flags,void * & handle,int blend_type)1949 bool CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource,
1950 int bitmap_alpha,
1951 uint32_t argb,
1952 const CFX_Matrix* pMatrix,
1953 uint32_t render_flags,
1954 void*& handle,
1955 int blend_type) {
1956 #ifdef _SKIA_SUPPORT_
1957 m_pCache->FlushForDraw();
1958 DebugValidate(m_pBitmap, m_pOriDevice);
1959 SkColorTable* ct = nullptr;
1960 std::unique_ptr<uint8_t, FxFreeDeleter> dst8Storage;
1961 std::unique_ptr<uint32_t, FxFreeDeleter> dst32Storage;
1962 SkBitmap skBitmap;
1963 int width, height;
1964 if (!Upsample(pSource, dst8Storage, dst32Storage, &ct, &skBitmap, &width,
1965 &height, false)) {
1966 return false;
1967 }
1968 m_pCanvas->save();
1969 SkMatrix skMatrix;
1970 SetBitmapMatrix(pMatrix, width, height, &skMatrix);
1971 m_pCanvas->concat(skMatrix);
1972 SkPaint paint;
1973 SetBitmapPaint(pSource->IsAlphaMask(), argb, bitmap_alpha, blend_type,
1974 &paint);
1975 // TODO(caryclark) Once Skia supports 8 bit src to 8 bit dst remove this
1976 if (m_pBitmap && m_pBitmap->GetBPP() == 8 && pSource->GetBPP() == 8) {
1977 SkMatrix inv;
1978 SkAssertResult(skMatrix.invert(&inv));
1979 for (int y = 0; y < m_pBitmap->GetHeight(); ++y) {
1980 for (int x = 0; x < m_pBitmap->GetWidth(); ++x) {
1981 SkPoint src = {x + 0.5f, y + 0.5f};
1982 inv.mapPoints(&src, 1);
1983 // TODO(caryclark) Why does the matrix map require clamping?
1984 src.fX = SkTMax(0.5f, SkTMin(src.fX, width - 0.5f));
1985 src.fY = SkTMax(0.5f, SkTMin(src.fY, height - 0.5f));
1986 m_pBitmap->SetPixel(x, y, skBitmap.getColor(src.fX, src.fY));
1987 }
1988 }
1989 } else {
1990 m_pCanvas->drawBitmap(skBitmap, 0, 0, &paint);
1991 }
1992 m_pCanvas->restore();
1993 if (ct)
1994 ct->unref();
1995 DebugValidate(m_pBitmap, m_pOriDevice);
1996 #endif // _SKIA_SUPPORT_
1997
1998 #ifdef _SKIA_SUPPORT_PATHS_
1999 Flush();
2000 if (!m_pBitmap->GetBuffer())
2001 return true;
2002 m_pBitmap->UnPreMultiply();
2003 CFX_ImageRenderer* pRenderer = new CFX_ImageRenderer;
2004 pRenderer->Start(m_pBitmap, m_pClipRgn.get(), pSource, bitmap_alpha, argb,
2005 pMatrix, render_flags, m_bRgbByteOrder, 0, nullptr);
2006 handle = pRenderer;
2007 #endif // _SKIA_SUPPORT_PATHS_
2008 return true;
2009 }
2010
ContinueDIBits(void * handle,IFX_Pause * pPause)2011 bool CFX_SkiaDeviceDriver::ContinueDIBits(void* handle, IFX_Pause* pPause) {
2012 #ifdef _SKIA_SUPPORT_
2013 m_pCache->FlushForDraw();
2014 return false;
2015 #endif // _SKIA_SUPPORT_
2016
2017 #ifdef _SKIA_SUPPORT_PATHS_
2018 Flush();
2019 if (!m_pBitmap->GetBuffer()) {
2020 return true;
2021 }
2022 return static_cast<CFX_ImageRenderer*>(handle)->Continue(pPause);
2023 #endif // _SKIA_SUPPORT_PATHS_
2024 }
2025
2026 #if defined _SKIA_SUPPORT_
PreMultiply(CFX_DIBitmap * pDIBitmap)2027 void CFX_SkiaDeviceDriver::PreMultiply(CFX_DIBitmap* pDIBitmap) {
2028 pDIBitmap->PreMultiply();
2029 }
2030 #endif // _SKIA_SUPPORT_
2031
PreMultiply()2032 void CFX_DIBitmap::PreMultiply() {
2033 if (this->GetBPP() != 32)
2034 return;
2035 void* buffer = this->GetBuffer();
2036 if (!buffer)
2037 return;
2038 #if defined _SKIA_SUPPORT_PATHS_
2039 Format priorFormat = m_nFormat;
2040 m_nFormat = Format::kPreMultiplied;
2041 if (priorFormat != Format::kUnPreMultiplied)
2042 return;
2043 #endif
2044 int height = this->GetHeight();
2045 int width = this->GetWidth();
2046 int rowBytes = this->GetPitch();
2047 SkImageInfo unpremultipliedInfo =
2048 SkImageInfo::Make(width, height, kN32_SkColorType, kUnpremul_SkAlphaType);
2049 SkPixmap unpremultiplied(unpremultipliedInfo, buffer, rowBytes);
2050 SkImageInfo premultipliedInfo =
2051 SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType);
2052 SkPixmap premultiplied(premultipliedInfo, buffer, rowBytes);
2053 unpremultiplied.readPixels(premultiplied);
2054 this->DebugVerifyBitmapIsPreMultiplied();
2055 }
2056
2057 #ifdef _SKIA_SUPPORT_PATHS_
UnPreMultiply()2058 void CFX_DIBitmap::UnPreMultiply() {
2059 if (this->GetBPP() != 32)
2060 return;
2061 void* buffer = this->GetBuffer();
2062 if (!buffer)
2063 return;
2064 Format priorFormat = m_nFormat;
2065 m_nFormat = Format::kUnPreMultiplied;
2066 if (priorFormat != Format::kPreMultiplied)
2067 return;
2068 this->DebugVerifyBitmapIsPreMultiplied();
2069 int height = this->GetHeight();
2070 int width = this->GetWidth();
2071 int rowBytes = this->GetPitch();
2072 SkImageInfo premultipliedInfo =
2073 SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType);
2074 SkPixmap premultiplied(premultipliedInfo, buffer, rowBytes);
2075 SkImageInfo unpremultipliedInfo =
2076 SkImageInfo::Make(width, height, kN32_SkColorType, kUnpremul_SkAlphaType);
2077 SkPixmap unpremultiplied(unpremultipliedInfo, buffer, rowBytes);
2078 premultiplied.readPixels(unpremultiplied);
2079 }
2080 #endif // _SKIA_SUPPORT_PATHS_
2081
2082 #ifdef _SKIA_SUPPORT_
DrawBitsWithMask(const CFX_DIBSource * pSource,const CFX_DIBSource * pMask,int bitmap_alpha,const CFX_Matrix * pMatrix,int blend_type)2083 bool CFX_SkiaDeviceDriver::DrawBitsWithMask(const CFX_DIBSource* pSource,
2084 const CFX_DIBSource* pMask,
2085 int bitmap_alpha,
2086 const CFX_Matrix* pMatrix,
2087 int blend_type) {
2088 DebugValidate(m_pBitmap, m_pOriDevice);
2089 SkColorTable* srcCt = nullptr;
2090 SkColorTable* maskCt = nullptr;
2091 std::unique_ptr<uint8_t, FxFreeDeleter> src8Storage, mask8Storage;
2092 std::unique_ptr<uint32_t, FxFreeDeleter> src32Storage, mask32Storage;
2093 SkBitmap skBitmap, skMask;
2094 int srcWidth, srcHeight, maskWidth, maskHeight;
2095 if (!Upsample(pSource, src8Storage, src32Storage, &srcCt, &skBitmap,
2096 &srcWidth, &srcHeight, false)) {
2097 return false;
2098 }
2099 if (!Upsample(pMask, mask8Storage, mask32Storage, &maskCt, &skMask,
2100 &maskWidth, &maskHeight, true)) {
2101 return false;
2102 }
2103 m_pCanvas->save();
2104 SkMatrix skMatrix;
2105 SetBitmapMatrix(pMatrix, srcWidth, srcHeight, &skMatrix);
2106 m_pCanvas->concat(skMatrix);
2107 SkPaint paint;
2108 SetBitmapPaint(pSource->IsAlphaMask(), 0xFFFFFFFF, bitmap_alpha, blend_type,
2109 &paint);
2110 sk_sp<SkImage> skSrc = SkImage::MakeFromBitmap(skBitmap);
2111 sk_sp<SkShader> skSrcShader =
2112 skSrc->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
2113 sk_sp<SkImage> skMaskImage = SkImage::MakeFromBitmap(skMask);
2114 sk_sp<SkShader> skMaskShader = skMaskImage->makeShader(
2115 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
2116 paint.setShader(SkShader::MakeComposeShader(skMaskShader, skSrcShader,
2117 SkBlendMode::kSrcIn));
2118 SkRect r = {0, 0, SkIntToScalar(srcWidth), SkIntToScalar(srcHeight)};
2119 m_pCanvas->drawRect(r, paint);
2120 m_pCanvas->restore();
2121 if (srcCt)
2122 srcCt->unref();
2123 DebugValidate(m_pBitmap, m_pOriDevice);
2124 return true;
2125 }
2126
SetBitsWithMask(const CFX_DIBSource * pBitmap,const CFX_DIBSource * pMask,int dest_left,int dest_top,int bitmap_alpha,int blend_type)2127 bool CFX_SkiaDeviceDriver::SetBitsWithMask(const CFX_DIBSource* pBitmap,
2128 const CFX_DIBSource* pMask,
2129 int dest_left,
2130 int dest_top,
2131 int bitmap_alpha,
2132 int blend_type) {
2133 if (!m_pBitmap || !m_pBitmap->GetBuffer())
2134 return true;
2135 CFX_Matrix m(pBitmap->GetWidth(), 0, 0, -pBitmap->GetHeight(), dest_left,
2136 dest_top + pBitmap->GetHeight());
2137 return DrawBitsWithMask(pBitmap, pMask, bitmap_alpha, &m, blend_type);
2138 }
2139
Clear(uint32_t color)2140 void CFX_SkiaDeviceDriver::Clear(uint32_t color) {
2141 m_pCanvas->clear(color);
2142 }
2143 #endif // _SKIA_SUPPORT_
2144
Dump() const2145 void CFX_SkiaDeviceDriver::Dump() const {
2146 #if SHOW_SKIA_PATH && defined _SKIA_SUPPORT_
2147 if (m_pCache)
2148 m_pCache->Dump(this);
2149 #endif // SHOW_SKIA_PATH && defined _SKIA_SUPPORT_
2150 }
2151
2152 #ifdef _SKIA_SUPPORT_
DebugVerifyBitmapIsPreMultiplied() const2153 void CFX_SkiaDeviceDriver::DebugVerifyBitmapIsPreMultiplied() const {
2154 if (m_pOriDevice)
2155 m_pOriDevice->DebugVerifyBitmapIsPreMultiplied();
2156 }
2157 #endif // _SKIA_SUPPORT_
2158
CFX_FxgeDevice()2159 CFX_FxgeDevice::CFX_FxgeDevice() {
2160 #ifdef _SKIA_SUPPORT_
2161 m_bOwnedBitmap = false;
2162 #endif // _SKIA_SUPPORT_
2163 }
2164
2165 #ifdef _SKIA_SUPPORT_
Clear(uint32_t color)2166 void CFX_FxgeDevice::Clear(uint32_t color) {
2167 CFX_SkiaDeviceDriver* skDriver =
2168 static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver());
2169 skDriver->Clear(color);
2170 }
2171
CreateRecorder(int size_x,int size_y)2172 SkPictureRecorder* CFX_FxgeDevice::CreateRecorder(int size_x, int size_y) {
2173 CFX_SkiaDeviceDriver* skDriver = new CFX_SkiaDeviceDriver(size_x, size_y);
2174 SetDeviceDriver(pdfium::WrapUnique(skDriver));
2175 return skDriver->GetRecorder();
2176 }
2177 #endif // _SKIA_SUPPORT_
2178
Attach(CFX_DIBitmap * pBitmap,bool bRgbByteOrder,CFX_DIBitmap * pOriDevice,bool bGroupKnockout)2179 bool CFX_FxgeDevice::Attach(CFX_DIBitmap* pBitmap,
2180 bool bRgbByteOrder,
2181 CFX_DIBitmap* pOriDevice,
2182 bool bGroupKnockout) {
2183 if (!pBitmap)
2184 return false;
2185 SetBitmap(pBitmap);
2186 SetDeviceDriver(pdfium::MakeUnique<CFX_SkiaDeviceDriver>(
2187 pBitmap, bRgbByteOrder, pOriDevice, bGroupKnockout));
2188 return true;
2189 }
2190
2191 #ifdef _SKIA_SUPPORT_
AttachRecorder(SkPictureRecorder * recorder)2192 bool CFX_FxgeDevice::AttachRecorder(SkPictureRecorder* recorder) {
2193 if (!recorder)
2194 return false;
2195 SetDeviceDriver(pdfium::MakeUnique<CFX_SkiaDeviceDriver>(recorder));
2196 return true;
2197 }
2198 #endif // _SKIA_SUPPORT_
2199
Create(int width,int height,FXDIB_Format format,CFX_DIBitmap * pOriDevice)2200 bool CFX_FxgeDevice::Create(int width,
2201 int height,
2202 FXDIB_Format format,
2203 CFX_DIBitmap* pOriDevice) {
2204 m_bOwnedBitmap = true;
2205 CFX_DIBitmap* pBitmap = new CFX_DIBitmap;
2206 if (!pBitmap->Create(width, height, format)) {
2207 delete pBitmap;
2208 return false;
2209 }
2210 SetBitmap(pBitmap);
2211 SetDeviceDriver(pdfium::MakeUnique<CFX_SkiaDeviceDriver>(pBitmap, false,
2212 pOriDevice, false));
2213 return true;
2214 }
2215
~CFX_FxgeDevice()2216 CFX_FxgeDevice::~CFX_FxgeDevice() {
2217 #ifdef _SKIA_SUPPORT_
2218 Flush();
2219 // call destructor of CFX_RenderDevice / CFX_SkiaDeviceDriver immediately
2220 if (m_bOwnedBitmap && GetBitmap())
2221 delete GetBitmap();
2222 #endif // _SKIA_SUPPORT_
2223 }
2224
2225 #ifdef _SKIA_SUPPORT_
DebugVerifyBitmapIsPreMultiplied() const2226 void CFX_FxgeDevice::DebugVerifyBitmapIsPreMultiplied() const {
2227 #ifdef SK_DEBUG
2228 CFX_SkiaDeviceDriver* skDriver =
2229 static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver());
2230 if (skDriver)
2231 skDriver->DebugVerifyBitmapIsPreMultiplied();
2232 #endif // SK_DEBUG
2233 }
2234
SetBitsWithMask(const CFX_DIBSource * pBitmap,const CFX_DIBSource * pMask,int left,int top,int bitmap_alpha,int blend_type)2235 bool CFX_FxgeDevice::SetBitsWithMask(const CFX_DIBSource* pBitmap,
2236 const CFX_DIBSource* pMask,
2237 int left,
2238 int top,
2239 int bitmap_alpha,
2240 int blend_type) {
2241 CFX_SkiaDeviceDriver* skDriver =
2242 static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver());
2243 if (skDriver)
2244 return skDriver->SetBitsWithMask(pBitmap, pMask, left, top, bitmap_alpha,
2245 blend_type);
2246 return false;
2247 }
2248 #endif // _SKIA_SUPPORT_
2249
DebugVerifyBitmapIsPreMultiplied(void * opt) const2250 void CFX_DIBSource::DebugVerifyBitmapIsPreMultiplied(void* opt) const {
2251 #ifdef SK_DEBUG
2252 SkASSERT(32 == GetBPP());
2253 const uint32_t* buffer = (const uint32_t*)(opt ? opt : GetBuffer());
2254 int width = GetWidth();
2255 int height = GetHeight();
2256 // verify that input is really premultiplied
2257 for (int y = 0; y < height; ++y) {
2258 const uint32_t* srcRow = buffer + y * width;
2259 for (int x = 0; x < width; ++x) {
2260 uint8_t a = SkGetPackedA32(srcRow[x]);
2261 uint8_t r = SkGetPackedR32(srcRow[x]);
2262 uint8_t g = SkGetPackedG32(srcRow[x]);
2263 uint8_t b = SkGetPackedB32(srcRow[x]);
2264 SkA32Assert(a);
2265 SkASSERT(r <= a);
2266 SkASSERT(g <= a);
2267 SkASSERT(b <= a);
2268 }
2269 }
2270 #endif // SK_DEBUG
2271 }
2272
2273 #ifdef _SKIA_SUPPORT_PATHS_
2274 class CFX_Renderer {
2275 private:
2276 int m_Alpha, m_Red, m_Green, m_Blue, m_Gray;
2277 uint32_t m_Color;
2278 bool m_bFullCover;
2279 bool m_bRgbByteOrder;
2280 CFX_DIBitmap* m_pOriDevice;
2281 FX_RECT m_ClipBox;
2282 const CFX_DIBitmap* m_pClipMask;
2283 CFX_DIBitmap* m_pDevice;
2284 const CFX_ClipRgn* m_pClipRgn;
2285 void (CFX_Renderer::*composite_span)(uint8_t*,
2286 int,
2287 int,
2288 int,
2289 uint8_t*,
2290 int,
2291 int,
2292 uint8_t*,
2293 uint8_t*);
2294
2295 public:
prepare(unsigned)2296 void prepare(unsigned) {}
2297
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)2298 void CompositeSpan(uint8_t* dest_scan,
2299 uint8_t* ori_scan,
2300 int Bpp,
2301 bool bDestAlpha,
2302 int span_left,
2303 int span_len,
2304 uint8_t* cover_scan,
2305 int clip_left,
2306 int clip_right,
2307 uint8_t* clip_scan) {
2308 ASSERT(!m_pDevice->IsCmykImage());
2309 int col_start = span_left < clip_left ? clip_left - span_left : 0;
2310 int col_end = (span_left + span_len) < clip_right
2311 ? span_len
2312 : (clip_right - span_left);
2313 if (Bpp) {
2314 dest_scan += col_start * Bpp;
2315 ori_scan += col_start * Bpp;
2316 } else {
2317 dest_scan += col_start / 8;
2318 ori_scan += col_start / 8;
2319 }
2320 if (m_bRgbByteOrder) {
2321 if (Bpp == 4 && bDestAlpha) {
2322 for (int col = col_start; col < col_end; col++) {
2323 int src_alpha;
2324 if (clip_scan) {
2325 src_alpha = m_Alpha * clip_scan[col] / 255;
2326 } else {
2327 src_alpha = m_Alpha;
2328 }
2329 uint8_t dest_alpha =
2330 ori_scan[3] + src_alpha - ori_scan[3] * src_alpha / 255;
2331 dest_scan[3] = dest_alpha;
2332 int alpha_ratio = src_alpha * 255 / dest_alpha;
2333 if (m_bFullCover) {
2334 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio);
2335 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio);
2336 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio);
2337 dest_scan++;
2338 ori_scan++;
2339 } else {
2340 int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio);
2341 int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio);
2342 int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio);
2343 ori_scan++;
2344 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]);
2345 dest_scan++;
2346 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]);
2347 dest_scan++;
2348 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]);
2349 dest_scan += 2;
2350 }
2351 }
2352 return;
2353 }
2354 if (Bpp == 3 || Bpp == 4) {
2355 for (int col = col_start; col < col_end; col++) {
2356 int src_alpha;
2357 if (clip_scan) {
2358 src_alpha = m_Alpha * clip_scan[col] / 255;
2359 } else {
2360 src_alpha = m_Alpha;
2361 }
2362 int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, src_alpha);
2363 int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha);
2364 int b = FXDIB_ALPHA_MERGE(*ori_scan, m_Blue, src_alpha);
2365 ori_scan += Bpp - 2;
2366 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]);
2367 dest_scan++;
2368 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]);
2369 dest_scan++;
2370 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]);
2371 dest_scan += Bpp - 2;
2372 }
2373 }
2374 return;
2375 }
2376 if (Bpp == 4 && bDestAlpha) {
2377 for (int col = col_start; col < col_end; col++) {
2378 int src_alpha;
2379 if (clip_scan) {
2380 src_alpha = m_Alpha * clip_scan[col] / 255;
2381 } else {
2382 src_alpha = m_Alpha;
2383 }
2384 int src_alpha_covered = src_alpha * cover_scan[col] / 255;
2385 if (src_alpha_covered == 0) {
2386 dest_scan += 4;
2387 continue;
2388 }
2389 if (cover_scan[col] == 255) {
2390 dest_scan[3] = src_alpha_covered;
2391 *dest_scan++ = m_Blue;
2392 *dest_scan++ = m_Green;
2393 *dest_scan = m_Red;
2394 dest_scan += 2;
2395 continue;
2396 } else {
2397 if (dest_scan[3] == 0) {
2398 dest_scan[3] = src_alpha_covered;
2399 *dest_scan++ = m_Blue;
2400 *dest_scan++ = m_Green;
2401 *dest_scan = m_Red;
2402 dest_scan += 2;
2403 continue;
2404 }
2405 uint8_t cover = cover_scan[col];
2406 dest_scan[3] = FXDIB_ALPHA_MERGE(dest_scan[3], src_alpha, cover);
2407 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, cover);
2408 dest_scan++;
2409 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, cover);
2410 dest_scan++;
2411 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, cover);
2412 dest_scan += 2;
2413 }
2414 }
2415 return;
2416 }
2417 if (Bpp == 3 || Bpp == 4) {
2418 for (int col = col_start; col < col_end; col++) {
2419 int src_alpha;
2420 if (clip_scan) {
2421 src_alpha = m_Alpha * clip_scan[col] / 255;
2422 } else {
2423 src_alpha = m_Alpha;
2424 }
2425 if (m_bFullCover) {
2426 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha);
2427 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha);
2428 *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha);
2429 dest_scan += Bpp - 2;
2430 ori_scan += Bpp - 2;
2431 continue;
2432 }
2433 int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha);
2434 int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha);
2435 int r = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha);
2436 ori_scan += Bpp - 2;
2437 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]);
2438 dest_scan++;
2439 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]);
2440 dest_scan++;
2441 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]);
2442 dest_scan += Bpp - 2;
2443 continue;
2444 }
2445 return;
2446 }
2447 if (Bpp == 1) {
2448 for (int col = col_start; col < col_end; col++) {
2449 int src_alpha;
2450 if (clip_scan) {
2451 src_alpha = m_Alpha * clip_scan[col] / 255;
2452 } else {
2453 src_alpha = m_Alpha;
2454 }
2455 if (m_bFullCover) {
2456 *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha);
2457 } else {
2458 int gray = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha);
2459 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, cover_scan[col]);
2460 dest_scan++;
2461 }
2462 }
2463 } else {
2464 int index = 0;
2465 if (m_pDevice->GetPalette()) {
2466 for (int i = 0; i < 2; i++) {
2467 if (FXARGB_TODIB(m_pDevice->GetPalette()[i]) == m_Color) {
2468 index = i;
2469 }
2470 }
2471 } else {
2472 index = ((uint8_t)m_Color == 0xff) ? 1 : 0;
2473 }
2474 uint8_t* dest_scan1 = dest_scan;
2475 for (int col = col_start; col < col_end; col++) {
2476 int src_alpha;
2477 if (clip_scan) {
2478 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
2479 } else {
2480 src_alpha = m_Alpha * cover_scan[col] / 255;
2481 }
2482 if (src_alpha) {
2483 if (!index) {
2484 *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8));
2485 } else {
2486 *dest_scan1 |= 1 << (7 - (col + span_left) % 8);
2487 }
2488 }
2489 dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8;
2490 }
2491 }
2492 }
2493
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)2494 void CompositeSpan1bpp(uint8_t* dest_scan,
2495 int Bpp,
2496 int span_left,
2497 int span_len,
2498 uint8_t* cover_scan,
2499 int clip_left,
2500 int clip_right,
2501 uint8_t* clip_scan,
2502 uint8_t* dest_extra_alpha_scan) {
2503 ASSERT(!m_bRgbByteOrder);
2504 ASSERT(!m_pDevice->IsCmykImage());
2505 int col_start = span_left < clip_left ? clip_left - span_left : 0;
2506 int col_end = (span_left + span_len) < clip_right
2507 ? span_len
2508 : (clip_right - span_left);
2509 dest_scan += col_start / 8;
2510 int index = 0;
2511 if (m_pDevice->GetPalette()) {
2512 for (int i = 0; i < 2; i++) {
2513 if (FXARGB_TODIB(m_pDevice->GetPalette()[i]) == m_Color) {
2514 index = i;
2515 }
2516 }
2517 } else {
2518 index = ((uint8_t)m_Color == 0xff) ? 1 : 0;
2519 }
2520 uint8_t* dest_scan1 = dest_scan;
2521 for (int col = col_start; col < col_end; col++) {
2522 int src_alpha;
2523 if (clip_scan) {
2524 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
2525 } else {
2526 src_alpha = m_Alpha * cover_scan[col] / 255;
2527 }
2528 if (src_alpha) {
2529 if (!index) {
2530 *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8));
2531 } else {
2532 *dest_scan1 |= 1 << (7 - (col + span_left) % 8);
2533 }
2534 }
2535 dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8;
2536 }
2537 }
2538
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)2539 void CompositeSpanGray(uint8_t* dest_scan,
2540 int Bpp,
2541 int span_left,
2542 int span_len,
2543 uint8_t* cover_scan,
2544 int clip_left,
2545 int clip_right,
2546 uint8_t* clip_scan,
2547 uint8_t* dest_extra_alpha_scan) {
2548 ASSERT(!m_bRgbByteOrder);
2549 int col_start = span_left < clip_left ? clip_left - span_left : 0;
2550 int col_end = (span_left + span_len) < clip_right
2551 ? span_len
2552 : (clip_right - span_left);
2553 dest_scan += col_start;
2554 if (dest_extra_alpha_scan) {
2555 for (int col = col_start; col < col_end; col++) {
2556 int src_alpha;
2557 if (m_bFullCover) {
2558 if (clip_scan) {
2559 src_alpha = m_Alpha * clip_scan[col] / 255;
2560 } else {
2561 src_alpha = m_Alpha;
2562 }
2563 } else {
2564 if (clip_scan) {
2565 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
2566 } else {
2567 src_alpha = m_Alpha * cover_scan[col] / 255;
2568 }
2569 }
2570 if (src_alpha) {
2571 if (src_alpha == 255) {
2572 *dest_scan = m_Gray;
2573 *dest_extra_alpha_scan = m_Alpha;
2574 } else {
2575 uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha -
2576 (*dest_extra_alpha_scan) * src_alpha / 255;
2577 *dest_extra_alpha_scan++ = dest_alpha;
2578 int alpha_ratio = src_alpha * 255 / dest_alpha;
2579 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio);
2580 dest_scan++;
2581 continue;
2582 }
2583 }
2584 dest_extra_alpha_scan++;
2585 dest_scan++;
2586 }
2587 } else {
2588 for (int col = col_start; col < col_end; col++) {
2589 int src_alpha;
2590 if (clip_scan) {
2591 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
2592 } else {
2593 src_alpha = m_Alpha * cover_scan[col] / 255;
2594 }
2595 if (src_alpha) {
2596 if (src_alpha == 255) {
2597 *dest_scan = m_Gray;
2598 } else {
2599 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha);
2600 }
2601 }
2602 dest_scan++;
2603 }
2604 }
2605 }
2606
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)2607 void CompositeSpanARGB(uint8_t* dest_scan,
2608 int Bpp,
2609 int span_left,
2610 int span_len,
2611 uint8_t* cover_scan,
2612 int clip_left,
2613 int clip_right,
2614 uint8_t* clip_scan,
2615 uint8_t* dest_extra_alpha_scan) {
2616 int col_start = span_left < clip_left ? clip_left - span_left : 0;
2617 int col_end = (span_left + span_len) < clip_right
2618 ? span_len
2619 : (clip_right - span_left);
2620 dest_scan += col_start * Bpp;
2621 if (m_bRgbByteOrder) {
2622 for (int col = col_start; col < col_end; col++) {
2623 int src_alpha;
2624 if (m_bFullCover) {
2625 if (clip_scan) {
2626 src_alpha = m_Alpha * clip_scan[col] / 255;
2627 } else {
2628 src_alpha = m_Alpha;
2629 }
2630 } else {
2631 if (clip_scan) {
2632 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
2633 } else {
2634 src_alpha = m_Alpha * cover_scan[col] / 255;
2635 }
2636 }
2637 if (src_alpha) {
2638 if (src_alpha == 255) {
2639 *(uint32_t*)dest_scan = m_Color;
2640 } else {
2641 uint8_t dest_alpha =
2642 dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255;
2643 dest_scan[3] = dest_alpha;
2644 int alpha_ratio = src_alpha * 255 / dest_alpha;
2645 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
2646 dest_scan++;
2647 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
2648 dest_scan++;
2649 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
2650 dest_scan += 2;
2651 continue;
2652 }
2653 }
2654 dest_scan += 4;
2655 }
2656 return;
2657 }
2658 for (int col = col_start; col < col_end; col++) {
2659 int src_alpha;
2660 if (m_bFullCover) {
2661 if (clip_scan) {
2662 src_alpha = m_Alpha * clip_scan[col] / 255;
2663 } else {
2664 src_alpha = m_Alpha;
2665 }
2666 } else {
2667 if (clip_scan) {
2668 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
2669 } else {
2670 src_alpha = m_Alpha * cover_scan[col] / 255;
2671 }
2672 }
2673 if (src_alpha) {
2674 if (src_alpha == 255) {
2675 *(uint32_t*)dest_scan = m_Color;
2676 } else {
2677 if (dest_scan[3] == 0) {
2678 dest_scan[3] = src_alpha;
2679 *dest_scan++ = m_Blue;
2680 *dest_scan++ = m_Green;
2681 *dest_scan = m_Red;
2682 dest_scan += 2;
2683 continue;
2684 }
2685 uint8_t dest_alpha =
2686 dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255;
2687 dest_scan[3] = dest_alpha;
2688 int alpha_ratio = src_alpha * 255 / dest_alpha;
2689 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
2690 dest_scan++;
2691 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
2692 dest_scan++;
2693 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
2694 dest_scan += 2;
2695 continue;
2696 }
2697 }
2698 dest_scan += Bpp;
2699 }
2700 }
2701
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)2702 void CompositeSpanRGB(uint8_t* dest_scan,
2703 int Bpp,
2704 int span_left,
2705 int span_len,
2706 uint8_t* cover_scan,
2707 int clip_left,
2708 int clip_right,
2709 uint8_t* clip_scan,
2710 uint8_t* dest_extra_alpha_scan) {
2711 int col_start = span_left < clip_left ? clip_left - span_left : 0;
2712 int col_end = (span_left + span_len) < clip_right
2713 ? span_len
2714 : (clip_right - span_left);
2715 dest_scan += col_start * Bpp;
2716 if (m_bRgbByteOrder) {
2717 for (int col = col_start; col < col_end; col++) {
2718 int src_alpha;
2719 if (clip_scan) {
2720 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
2721 } else {
2722 src_alpha = m_Alpha * cover_scan[col] / 255;
2723 }
2724 if (src_alpha) {
2725 if (src_alpha == 255) {
2726 if (Bpp == 4) {
2727 *(uint32_t*)dest_scan = m_Color;
2728 } else if (Bpp == 3) {
2729 *dest_scan++ = m_Red;
2730 *dest_scan++ = m_Green;
2731 *dest_scan++ = m_Blue;
2732 continue;
2733 }
2734 } else {
2735 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
2736 dest_scan++;
2737 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
2738 dest_scan++;
2739 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
2740 dest_scan += Bpp - 2;
2741 continue;
2742 }
2743 }
2744 dest_scan += Bpp;
2745 }
2746 return;
2747 }
2748 if (Bpp == 3 && dest_extra_alpha_scan) {
2749 for (int col = col_start; col < col_end; col++) {
2750 int src_alpha;
2751 if (m_bFullCover) {
2752 if (clip_scan) {
2753 src_alpha = m_Alpha * clip_scan[col] / 255;
2754 } else {
2755 src_alpha = m_Alpha;
2756 }
2757 } else {
2758 if (clip_scan) {
2759 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
2760 } else {
2761 src_alpha = m_Alpha * cover_scan[col] / 255;
2762 }
2763 }
2764 if (src_alpha) {
2765 if (src_alpha == 255) {
2766 *dest_scan++ = (uint8_t)m_Blue;
2767 *dest_scan++ = (uint8_t)m_Green;
2768 *dest_scan++ = (uint8_t)m_Red;
2769 *dest_extra_alpha_scan++ = (uint8_t)m_Alpha;
2770 continue;
2771 } else {
2772 uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha -
2773 (*dest_extra_alpha_scan) * src_alpha / 255;
2774 *dest_extra_alpha_scan++ = dest_alpha;
2775 int alpha_ratio = src_alpha * 255 / dest_alpha;
2776 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
2777 dest_scan++;
2778 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
2779 dest_scan++;
2780 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
2781 dest_scan++;
2782 continue;
2783 }
2784 }
2785 dest_extra_alpha_scan++;
2786 dest_scan += Bpp;
2787 }
2788 } else {
2789 for (int col = col_start; col < col_end; col++) {
2790 int src_alpha;
2791 if (m_bFullCover) {
2792 if (clip_scan) {
2793 src_alpha = m_Alpha * clip_scan[col] / 255;
2794 } else {
2795 src_alpha = m_Alpha;
2796 }
2797 } else {
2798 if (clip_scan) {
2799 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
2800 } else {
2801 src_alpha = m_Alpha * cover_scan[col] / 255;
2802 }
2803 }
2804 if (src_alpha) {
2805 if (src_alpha == 255) {
2806 if (Bpp == 4) {
2807 *(uint32_t*)dest_scan = m_Color;
2808 } else if (Bpp == 3) {
2809 *dest_scan++ = m_Blue;
2810 *dest_scan++ = m_Green;
2811 *dest_scan++ = m_Red;
2812 continue;
2813 }
2814 } else {
2815 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
2816 dest_scan++;
2817 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
2818 dest_scan++;
2819 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
2820 dest_scan += Bpp - 2;
2821 continue;
2822 }
2823 }
2824 dest_scan += Bpp;
2825 }
2826 }
2827 }
2828
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)2829 void CompositeSpanCMYK(uint8_t* dest_scan,
2830 int Bpp,
2831 int span_left,
2832 int span_len,
2833 uint8_t* cover_scan,
2834 int clip_left,
2835 int clip_right,
2836 uint8_t* clip_scan,
2837 uint8_t* dest_extra_alpha_scan) {
2838 ASSERT(!m_bRgbByteOrder);
2839 int col_start = span_left < clip_left ? clip_left - span_left : 0;
2840 int col_end = (span_left + span_len) < clip_right
2841 ? span_len
2842 : (clip_right - span_left);
2843 dest_scan += col_start * 4;
2844 if (dest_extra_alpha_scan) {
2845 for (int col = col_start; col < col_end; col++) {
2846 int src_alpha;
2847 if (m_bFullCover) {
2848 if (clip_scan) {
2849 src_alpha = m_Alpha * clip_scan[col] / 255;
2850 } else {
2851 src_alpha = m_Alpha;
2852 }
2853 } else {
2854 if (clip_scan) {
2855 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
2856 } else {
2857 src_alpha = m_Alpha * cover_scan[col] / 255;
2858 }
2859 }
2860 if (src_alpha) {
2861 if (src_alpha == 255) {
2862 *(FX_CMYK*)dest_scan = m_Color;
2863 *dest_extra_alpha_scan = (uint8_t)m_Alpha;
2864 } else {
2865 uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha -
2866 (*dest_extra_alpha_scan) * src_alpha / 255;
2867 *dest_extra_alpha_scan++ = dest_alpha;
2868 int alpha_ratio = src_alpha * 255 / dest_alpha;
2869 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
2870 dest_scan++;
2871 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
2872 dest_scan++;
2873 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
2874 dest_scan++;
2875 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio);
2876 dest_scan++;
2877 continue;
2878 }
2879 }
2880 dest_extra_alpha_scan++;
2881 dest_scan += 4;
2882 }
2883 } else {
2884 for (int col = col_start; col < col_end; col++) {
2885 int src_alpha;
2886 if (clip_scan) {
2887 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
2888 } else {
2889 src_alpha = m_Alpha * cover_scan[col] / 255;
2890 }
2891 if (src_alpha) {
2892 if (src_alpha == 255) {
2893 *(FX_CMYK*)dest_scan = m_Color;
2894 } else {
2895 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
2896 dest_scan++;
2897 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
2898 dest_scan++;
2899 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
2900 dest_scan++;
2901 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha);
2902 dest_scan++;
2903 continue;
2904 }
2905 }
2906 dest_scan += 4;
2907 }
2908 }
2909 }
2910
2911 template <class Scanline>
render(const Scanline & sl)2912 void render(const Scanline& sl) {
2913 if (!m_pOriDevice && !composite_span) {
2914 return;
2915 }
2916 int y = sl.y();
2917 if (y < m_ClipBox.top || y >= m_ClipBox.bottom) {
2918 return;
2919 }
2920 uint8_t* dest_scan = m_pDevice->GetBuffer() + m_pDevice->GetPitch() * y;
2921 uint8_t* dest_scan_extra_alpha = nullptr;
2922 CFX_DIBitmap* pAlphaMask = m_pDevice->m_pAlphaMask;
2923 if (pAlphaMask) {
2924 dest_scan_extra_alpha =
2925 pAlphaMask->GetBuffer() + pAlphaMask->GetPitch() * y;
2926 }
2927 uint8_t* ori_scan = nullptr;
2928 if (m_pOriDevice) {
2929 ori_scan = m_pOriDevice->GetBuffer() + m_pOriDevice->GetPitch() * y;
2930 }
2931 int Bpp = m_pDevice->GetBPP() / 8;
2932 bool bDestAlpha = m_pDevice->HasAlpha() || m_pDevice->IsAlphaMask();
2933 unsigned num_spans = sl.num_spans();
2934 typename Scanline::const_iterator span = sl.begin();
2935 while (1) {
2936 int x = span->x;
2937 ASSERT(span->len > 0);
2938 uint8_t* dest_pos = nullptr;
2939 uint8_t* dest_extra_alpha_pos = nullptr;
2940 uint8_t* ori_pos = nullptr;
2941 if (Bpp) {
2942 ori_pos = ori_scan ? ori_scan + x * Bpp : nullptr;
2943 dest_pos = dest_scan + x * Bpp;
2944 dest_extra_alpha_pos =
2945 dest_scan_extra_alpha ? dest_scan_extra_alpha + x : nullptr;
2946 } else {
2947 dest_pos = dest_scan + x / 8;
2948 ori_pos = ori_scan ? ori_scan + x / 8 : nullptr;
2949 }
2950 uint8_t* clip_pos = nullptr;
2951 if (m_pClipMask) {
2952 clip_pos = m_pClipMask->GetBuffer() +
2953 (y - m_ClipBox.top) * m_pClipMask->GetPitch() + x -
2954 m_ClipBox.left;
2955 }
2956 if (ori_pos) {
2957 CompositeSpan(dest_pos, ori_pos, Bpp, bDestAlpha, x, span->len,
2958 span->covers, m_ClipBox.left, m_ClipBox.right, clip_pos);
2959 } else {
2960 (this->*composite_span)(dest_pos, Bpp, x, span->len, span->covers,
2961 m_ClipBox.left, m_ClipBox.right, clip_pos,
2962 dest_extra_alpha_pos);
2963 }
2964 if (--num_spans == 0) {
2965 break;
2966 }
2967 ++span;
2968 }
2969 }
2970
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)2971 bool Init(CFX_DIBitmap* pDevice,
2972 CFX_DIBitmap* pOriDevice,
2973 const CFX_ClipRgn* pClipRgn,
2974 uint32_t color,
2975 bool bFullCover,
2976 bool bRgbByteOrder,
2977 int alpha_flag = 0,
2978 void* pIccTransform = nullptr) {
2979 m_pDevice = pDevice;
2980 m_pClipRgn = pClipRgn;
2981 composite_span = nullptr;
2982 m_bRgbByteOrder = bRgbByteOrder;
2983 m_pOriDevice = pOriDevice;
2984 if (m_pClipRgn) {
2985 m_ClipBox = m_pClipRgn->GetBox();
2986 } else {
2987 m_ClipBox.left = m_ClipBox.top = 0;
2988 m_ClipBox.right = m_pDevice->GetWidth();
2989 m_ClipBox.bottom = m_pDevice->GetHeight();
2990 }
2991 m_pClipMask = nullptr;
2992 if (m_pClipRgn && m_pClipRgn->GetType() == CFX_ClipRgn::MaskF) {
2993 m_pClipMask = m_pClipRgn->GetMask().GetObject();
2994 }
2995 m_bFullCover = bFullCover;
2996 bool bObjectCMYK = !!FXGETFLAG_COLORTYPE(alpha_flag);
2997 bool bDeviceCMYK = pDevice->IsCmykImage();
2998 m_Alpha = bObjectCMYK ? FXGETFLAG_ALPHA_FILL(alpha_flag) : FXARGB_A(color);
2999 CCodec_IccModule* pIccModule = nullptr;
3000 if (!CFX_GEModule::Get()->GetCodecModule() ||
3001 !CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) {
3002 pIccTransform = nullptr;
3003 } else {
3004 pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
3005 }
3006 if (m_pDevice->GetBPP() == 8) {
3007 ASSERT(!m_bRgbByteOrder);
3008 composite_span = &CFX_Renderer::CompositeSpanGray;
3009 if (m_pDevice->IsAlphaMask()) {
3010 m_Gray = 255;
3011 } else {
3012 if (pIccTransform) {
3013 uint8_t gray;
3014 color = bObjectCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color);
3015 pIccModule->TranslateScanline(pIccTransform, &gray,
3016 (const uint8_t*)&color, 1);
3017 m_Gray = gray;
3018 } else {
3019 if (bObjectCMYK) {
3020 uint8_t r, g, b;
3021 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color),
3022 FXSYS_GetYValue(color), FXSYS_GetKValue(color),
3023 r, g, b);
3024 m_Gray = FXRGB2GRAY(r, g, b);
3025 } else {
3026 m_Gray =
3027 FXRGB2GRAY(FXARGB_R(color), FXARGB_G(color), FXARGB_B(color));
3028 }
3029 }
3030 }
3031 return true;
3032 }
3033 if (bDeviceCMYK) {
3034 ASSERT(!m_bRgbByteOrder);
3035 composite_span = &CFX_Renderer::CompositeSpanCMYK;
3036 if (bObjectCMYK) {
3037 m_Color = FXCMYK_TODIB(color);
3038 if (pIccTransform) {
3039 pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color,
3040 (const uint8_t*)&m_Color, 1);
3041 }
3042 } else {
3043 if (!pIccTransform) {
3044 return false;
3045 }
3046 color = FXARGB_TODIB(color);
3047 pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color,
3048 (const uint8_t*)&color, 1);
3049 }
3050 m_Red = ((uint8_t*)&m_Color)[0];
3051 m_Green = ((uint8_t*)&m_Color)[1];
3052 m_Blue = ((uint8_t*)&m_Color)[2];
3053 m_Gray = ((uint8_t*)&m_Color)[3];
3054 } else {
3055 composite_span = (pDevice->GetFormat() == FXDIB_Argb)
3056 ? &CFX_Renderer::CompositeSpanARGB
3057 : &CFX_Renderer::CompositeSpanRGB;
3058 if (pIccTransform) {
3059 color = bObjectCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color);
3060 pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color,
3061 (const uint8_t*)&color, 1);
3062 ((uint8_t*)&m_Color)[3] = m_Alpha;
3063 m_Red = ((uint8_t*)&m_Color)[2];
3064 m_Green = ((uint8_t*)&m_Color)[1];
3065 m_Blue = ((uint8_t*)&m_Color)[0];
3066 if (m_bRgbByteOrder) {
3067 m_Color = FXARGB_TODIB(m_Color);
3068 m_Color = FXARGB_TOBGRORDERDIB(m_Color);
3069 }
3070 } else {
3071 if (bObjectCMYK) {
3072 uint8_t r, g, b;
3073 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color),
3074 FXSYS_GetYValue(color), FXSYS_GetKValue(color), r,
3075 g, b);
3076 m_Color = FXARGB_MAKE(m_Alpha, r, g, b);
3077 if (m_bRgbByteOrder) {
3078 m_Color = FXARGB_TOBGRORDERDIB(m_Color);
3079 } else {
3080 m_Color = FXARGB_TODIB(m_Color);
3081 }
3082 m_Red = r;
3083 m_Green = g;
3084 m_Blue = b;
3085 } else {
3086 if (m_bRgbByteOrder) {
3087 m_Color = FXARGB_TOBGRORDERDIB(color);
3088 } else {
3089 m_Color = FXARGB_TODIB(color);
3090 }
3091 ArgbDecode(color, m_Alpha, m_Red, m_Green, m_Blue);
3092 }
3093 }
3094 }
3095 if (m_pDevice->GetBPP() == 1) {
3096 composite_span = &CFX_Renderer::CompositeSpan1bpp;
3097 }
3098 return true;
3099 }
3100 };
3101
3102 #endif // _SKIA_SUPPORT_PATHS_
3103