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