5#include "core/fxge/skia/fx_skia_device.h"
18#include "build/build_config.h"
19#include "core/fpdfapi/page/cpdf_expintfunc.h"
20#include "core/fpdfapi/page/cpdf_function.h"
21#include "core/fpdfapi/page/cpdf_meshstream.h"
22#include "core/fpdfapi/page/cpdf_sampledfunc.h"
23#include "core/fpdfapi/page/cpdf_shadingpattern.h"
24#include "core/fpdfapi/page/cpdf_stitchfunc.h"
25#include "core/fpdfapi/parser/cpdf_array.h"
26#include "core/fpdfapi/parser/cpdf_dictionary.h"
27#include "core/fpdfapi/parser/cpdf_stream.h"
28#include "core/fpdfapi/parser/cpdf_stream_acc.h"
29#include "core/fxcrt/cfx_bitstream.h"
30#include "core/fxcrt/check.h"
31#include "core/fxcrt/check_op.h"
32#include "core/fxcrt/data_vector.h"
33#include "core/fxcrt/fx_2d_size.h"
34#include "core/fxcrt/fx_coordinates.h"
35#include "core/fxcrt/fx_memory.h"
36#include "core/fxcrt/fx_system.h"
37#include "core/fxcrt/notreached.h"
38#include "core/fxcrt/numerics/safe_conversions.h"
39#include "core/fxcrt/ptr_util.h"
40#include "core/fxcrt/span.h"
41#include "core/fxcrt/stl_util.h"
42#include "core/fxge/agg/cfx_agg_imagerenderer.h"
43#include "core/fxge/cfx_defaultrenderdevice.h"
44#include "core/fxge/cfx_fillrenderoptions.h"
45#include "core/fxge/cfx_font.h"
46#include "core/fxge/cfx_graphstatedata.h"
47#include "core/fxge/cfx_path.h"
48#include "core/fxge/cfx_renderdevice.h"
49#include "core/fxge/cfx_substfont.h"
50#include "core/fxge/cfx_textrenderoptions.h"
51#include "core/fxge/dib/cfx_dibitmap.h"
52#include "core/fxge/dib/cstretchengine.h"
53#include "core/fxge/dib/fx_dib.h"
54#include "core/fxge/text_char_pos.h"
55#include "third_party/skia/include/core/SkBlendMode.h"
56#include "third_party/skia/include/core/SkCanvas.h"
57#include "third_party/skia/include/core/SkClipOp.h"
58#include "third_party/skia/include/core/SkColorFilter.h"
59#include "third_party/skia/include/core/SkColorPriv.h"
60#include "third_party/skia/include/core/SkColorType.h"
61#include "third_party/skia/include/core/SkImage.h"
62#include "third_party/skia/include/core/SkImageInfo.h"
63#include "third_party/skia/include/core/SkMaskFilter.h"
64#include "third_party/skia/include/core/SkPaint.h"
65#include "third_party/skia/include/core/SkPath.h"
66#include "third_party/skia/include/core/SkPathEffect.h"
67#include "third_party/skia/include/core/SkPathUtils.h"
68#include "third_party/skia/include/core/SkPixmap.h"
69#include "third_party/skia/include/core/SkRSXform.h"
70#include "third_party/skia/include/core/SkRect.h"
71#include "third_party/skia/include/core/SkRefCnt.h"
72#include "third_party/skia/include/core/SkSamplingOptions.h"
73#include "third_party/skia/include/core/SkShader.h"
74#include "third_party/skia/include/core/SkStream.h"
75#include "third_party/skia/include/core/SkSurface.h"
76#include "third_party/skia/include/core/SkTextBlob.h"
77#include "third_party/skia/include/core/SkTileMode.h"
78#include "third_party/skia/include/core/SkTypeface.h"
79#include "third_party/skia/include/effects/SkDashPathEffect.h"
80#include "third_party/skia/include/effects/SkGradientShader.h"
81#include "third_party/skia/include/pathops/SkPathOps.h"
85#define SHOW_SKIA_PATH 0
87#define SHOW_SKIA_PATH_SHORTHAND 0
91void DebugShowSkiaPaint(
const SkPaint& paint) {
92 if (SkPaint::kFill_Style == paint.getStyle()) {
93 printf(
"fill 0x%08x\n", paint.getColor());
95 printf(
"stroke 0x%08x width %g\n", paint.getColor(),
96 paint.getStrokeWidth());
101void DebugShowSkiaPath(
const SkPath& path) {
103#if SHOW_SKIA_PATH_SHORTHAND
106 SkDynamicMemoryWStream stream;
107 path.dump(&stream,
false);
108 DataVector<
char> storage(stream.bytesWritten());
109 stream.copyTo(storage.data());
110 printf(
"%.*s",
static_cast<
int>(storage.size()), storage.data());
115void DebugShowCanvasClip(CFX_SkiaDeviceDriver* driver,
const SkCanvas* canvas) {
117 SkMatrix matrix = canvas->getTotalMatrix();
120 printf(
"matrix (%g,%g,%g) (%g,%g,%g) (%g,%g,%g)\n", m[0], m[1], m[2], m[3],
121 m[4], m[5], m[6], m[7], m[8]);
122 SkRect local = canvas->getLocalClipBounds();
123 SkIRect device = canvas->getDeviceClipBounds();
125 printf(
"local bounds %g %g %g %g\n", local.fLeft, local.fTop, local.fRight,
127 printf(
"device bounds %d %d %d %d\n", device.fLeft, device.fTop,
128 device.fRight, device.fBottom);
129 FX_RECT clip_box = driver->GetClipBox();
130 printf(
"reported bounds %d %d %d %d\n", clip_box.left, clip_box.top,
131 clip_box.right, clip_box.bottom);
135void DebugShowSkiaDrawPath(CFX_SkiaDeviceDriver* driver,
136 const SkCanvas* canvas,
137 const SkPaint& paint,
138 const SkPath& path) {
140 DebugShowSkiaPaint(paint);
141 DebugShowCanvasClip(driver, canvas);
142 DebugShowSkiaPath(path);
147void DebugShowSkiaDrawRect(CFX_SkiaDeviceDriver* driver,
148 const SkCanvas* canvas,
149 const SkPaint& paint,
150 const SkRect& rect) {
152 DebugShowSkiaPaint(paint);
153 DebugShowCanvasClip(driver, canvas);
154 printf(
"rect %g %g %g %g\n", rect.fLeft, rect.fTop, rect.fRight,
159void DebugValidate(
const RetainPtr<CFX_DIBitmap>& bitmap) {
162 DCHECK(bitmap->GetBPP() == 8 || bitmap->GetBPP() == 32);
166SkColorType Get32BitSkColorType(
bool is_rgb_byte_order) {
167 return is_rgb_byte_order ? kRGBA_8888_SkColorType : kBGRA_8888_SkColorType;
170SkPathFillType GetAlternateOrWindingFillType(
174 return fill_options.fill_type == CFX_FillRenderOptions::FillType::kEvenOdd
175 ? SkPathFillType::kEvenOdd
176 : SkPathFillType::kWinding;
180 if (text_options.aliasing_type == CFX_TextRenderOptions::kAliasing)
181 return SkFont::Edging::kAlias;
183 if (text_options.aliasing_type == CFX_TextRenderOptions::kAntiAliasing)
184 return SkFont::Edging::kAntiAlias;
187 return SkFont::Edging::kSubpixelAntiAlias;
190bool IsPathAPoint(
const SkPath& path) {
194 if (path.countPoints() == 1)
197 for (
int i = 0; i < path.countPoints() - 1; ++i) {
198 if (path.getPoint(i) != path.getPoint(i + 1))
204SkPath BuildPath(
const CFX_Path& path) {
206 pdfium::span<
const CFX_Path::Point> points = path.GetPoints();
207 for (size_t i = 0; i < points.size(); ++i) {
211 sk_path.moveTo(point.x, point.y);
213 sk_path.lineTo(point.x, point.y);
215 const CFX_PointF& point2 = points[i + 1].m_Point;
216 const CFX_PointF& point3 = points[i + 2].m_Point;
217 sk_path.cubicTo(point.x, point.y, point2.x, point2.y, point3.x, point3.y);
220 if (points[i].m_CloseFigure)
233SkMatrix ToFlippedSkMatrix(
const CFX_Matrix& m, SkScalar flip) {
235 skMatrix.setAll(m
.a * flip, -m
.c * flip, m
.e, m
.b * flip, -m
.d * flip, m
.f, 0,
240SkBlendMode GetSkiaBlendMode(
BlendMode blend_type) {
241 switch (blend_type) {
242 case BlendMode::kMultiply:
243 return SkBlendMode::kMultiply;
244 case BlendMode::kScreen:
245 return SkBlendMode::kScreen;
246 case BlendMode::kOverlay:
247 return SkBlendMode::kOverlay;
248 case BlendMode::kDarken:
249 return SkBlendMode::kDarken;
250 case BlendMode::kLighten:
251 return SkBlendMode::kLighten;
252 case BlendMode::kColorDodge:
253 return SkBlendMode::kColorDodge;
254 case BlendMode::kColorBurn:
255 return SkBlendMode::kColorBurn;
256 case BlendMode::kHardLight:
257 return SkBlendMode::kHardLight;
258 case BlendMode::kSoftLight:
259 return SkBlendMode::kSoftLight;
260 case BlendMode::kDifference:
261 return SkBlendMode::kDifference;
262 case BlendMode::kExclusion:
263 return SkBlendMode::kExclusion;
264 case BlendMode::kHue:
265 return SkBlendMode::kHue;
266 case BlendMode::kSaturation:
267 return SkBlendMode::kSaturation;
268 case BlendMode::kColor:
269 return SkBlendMode::kColor;
270 case BlendMode::kLuminosity:
271 return SkBlendMode::kLuminosity;
272 case BlendMode::kNormal:
273 return SkBlendMode::kSrcOver;
282bool AddColors(
const CPDF_ExpIntFunc* func,
283 DataVector<SkColor>& colors,
284 bool is_encode_reversed) {
295 pdfium::span<
const float> begin_values = func->GetBeginValues();
296 pdfium::span<
const float> end_values = func->GetEndValues();
297 if (is_encode_reversed)
298 std::swap(begin_values, end_values);
300 colors.push_back(SkColorSetARGB(0xFF,
301 SkUnitScalarClampToByte(begin_values[0]),
302 SkUnitScalarClampToByte(begin_values[1]),
303 SkUnitScalarClampToByte(begin_values[2])));
304 colors.push_back(SkColorSetARGB(0xFF, SkUnitScalarClampToByte(end_values[0]),
305 SkUnitScalarClampToByte(end_values[1]),
306 SkUnitScalarClampToByte(end_values[2])));
310uint8_t FloatToByte(
float f) {
313 return (uint8_t)(f * 255.99f);
316bool AddSamples(
const CPDF_SampledFunc* func,
317 DataVector<SkColor>& colors,
318 DataVector<SkScalar>& pos) {
325 if (func->GetEncodeInfo().empty()) {
329 func->GetEncodeInfo()[0];
337 uint32_t sample_count = encode_info
.sizes;
338 if (sample_count != 1U << sample_size) {
341 if (func->GetSampleStream()->GetSize() < sample_count * 3 * sample_size / 8) {
345 std::array<
float, 3> colors_min;
346 std::array<
float, 3> colors_max;
347 for (
int i = 0; i < 3; ++i) {
351 pdfium::span<
const uint8_t> sample_data =
352 func->GetSampleStream()->GetSpan();
354 for (uint32_t i = 0; i < sample_count; ++i) {
355 std::array<
float, 3> float_colors;
356 for (uint32_t j = 0; j < 3; ++j) {
357 float sample =
static_cast<
float>(bitstream
.GetBits(sample_size
));
358 float interp = sample / (sample_count - 1);
360 colors_min[j] + (colors_max[j] - colors_min[j]) * interp;
362 colors.push_back(SkPackARGB32(0xFF, FloatToByte(float_colors[0]),
363 FloatToByte(float_colors[1]),
364 FloatToByte(float_colors[2])));
365 pos.push_back(
static_cast<
float>(i) / (sample_count - 1));
370bool AddStitching(
const CPDF_StitchFunc* func,
371 DataVector<SkColor>& colors,
372 DataVector<SkScalar>& pos) {
375 const auto& sub_functions = func->GetSubFunctions();
376 const size_t sub_function_count = sub_functions.size();
377 for (size_t i = 0; i < sub_function_count; ++i) {
378 const CPDF_ExpIntFunc* sub_func = sub_functions[i]->ToExpIntFunc();
382 bool is_encode_reversed =
383 func->GetEncode(2 * i) > func->GetEncode(2 * i + 1);
384 if (!AddColors(sub_func, colors, is_encode_reversed)) {
388 i < sub_function_count - 1 ? func->GetBound(i + 1) : func
->GetDomain(1);
389 pos.push_back(bounds_start);
390 pos.push_back(bounds_end);
391 bounds_start = bounds_end;
397SkScalar LineSide(
const SkPoint& line_start,
398 const SkPoint& line_end,
400 return (line_end.fY - line_start.fY) * pt.fX -
401 (line_end.fX - line_start.fX) * pt.fY + line_end.fX * line_start.fY -
402 line_end.fY * line_start.fX;
405SkPoint IntersectSides(
const SkPoint& parallelPt,
406 const SkVector& paraRay,
407 const SkPoint& perpendicularPt) {
408 SkVector perpRay = {paraRay.fY, -paraRay.fX};
409 SkScalar denom = perpRay.fY * paraRay.fX - paraRay.fY * perpRay.fX;
411 SkPoint zeroPt = {0, 0};
414 SkVector ab0 = parallelPt - perpendicularPt;
415 SkScalar numerA = ab0.fY * perpRay.fX - perpRay.fY * ab0.fX;
417 SkPoint result = {parallelPt.fX + paraRay.fX * numerA,
418 parallelPt.fY + paraRay.fY * numerA};
422void ClipAngledGradient(pdfium::span<
const SkPoint, 2> pts,
423 pdfium::span<
const SkPoint, 4> rect_pts,
428 SkScalar minPerpDist = SK_ScalarMax;
429 SkScalar maxPerpDist = SK_ScalarMin;
430 int minPerpPtIndex = -1;
431 int maxPerpPtIndex = -1;
432 SkVector slope = pts[1] - pts[0];
433 const SkPoint start_perp[2] = {pts[0],
434 {pts[0].fX + slope.fY, pts[0].fY - slope.fX}};
435 const SkPoint end_perp[2] = {pts[1],
436 {pts[1].fX + slope.fY, pts[1].fY - slope.fX}};
437 for (
int i = 0; i < 4; ++i) {
438 SkScalar sDist = LineSide(start_perp[0], start_perp[1], rect_pts[i]);
439 SkScalar eDist = LineSide(end_perp[0], end_perp[1], rect_pts[i]);
440 if (sDist * eDist <= 0) {
444 SkScalar smaller =
std::min(sDist, eDist);
445 if (minPerpDist > smaller) {
446 minPerpDist = smaller;
450 SkScalar larger =
std::max(sDist, eDist);
451 if (maxPerpDist < larger) {
452 maxPerpDist = larger;
457 if (minPerpPtIndex < 0 && maxPerpPtIndex < 0) {
462 const SkPoint before_start = {pts[0].fX * 2 - pts[1].fX,
463 pts[0].fY * 2 - pts[1].fY};
464 bool before_neg = LineSide(start_perp[0], start_perp[1], before_start) < 0;
466 int noClipStartIndex = maxPerpPtIndex;
467 int noClipEndIndex = minPerpPtIndex;
469 std::swap(noClipStartIndex, noClipEndIndex);
471 if ((!clip_start && noClipStartIndex < 0) ||
472 (!clip_end && noClipEndIndex < 0)) {
476 const SkPoint& startEdgePt = clip_start ? pts[0] : rect_pts[noClipStartIndex];
477 const SkPoint& endEdgePt = clip_end ? pts[1] : rect_pts[noClipEndIndex];
480 SkScalar minDist = SK_ScalarMax;
481 SkScalar maxDist = SK_ScalarMin;
484 for (
int i = 0; i < 4; ++i) {
485 SkScalar dist = LineSide(pts[0], pts[1], rect_pts[i]);
486 if (minDist > dist) {
490 if (maxDist < dist) {
495 if (minBounds < 0 || maxBounds < 0) {
498 if (minBounds == maxBounds) {
504 clip->moveTo(IntersectSides(rect_pts[minBounds], slope, startEdgePt));
505 clip->lineTo(IntersectSides(rect_pts[minBounds], slope, endEdgePt));
506 clip->lineTo(IntersectSides(rect_pts[maxBounds], slope, endEdgePt));
507 clip->lineTo(IntersectSides(rect_pts[maxBounds], slope, startEdgePt));
511void PaintStroke(SkPaint* spaint,
513 const SkMatrix& matrix,
517 case CFX_GraphStateData::LineCap::kRound:
518 cap = SkPaint::kRound_Cap;
520 case CFX_GraphStateData::LineCap::kSquare:
521 cap = SkPaint::kSquare_Cap;
524 cap = SkPaint::kButt_Cap;
529 case CFX_GraphStateData::LineJoin::kRound:
530 join = SkPaint::kRound_Join;
532 case CFX_GraphStateData::LineJoin::kBevel:
533 join = SkPaint::kBevel_Join;
536 join = SkPaint::kMiter_Join;
540 if (!matrix.invert(&inverse)) {
543 inverse.set(SkMatrix::kMTransX, 0);
544 inverse.set(SkMatrix::kMTransY, 0);
545 SkVector deviceUnits[2] = {{0, 1}, {1, 0}};
546 inverse.mapPoints(deviceUnits,
std::size(deviceUnits));
551 std::min(deviceUnits[0].length(),
552 deviceUnits[1].length()));
553 if (!graph_state->m_DashArray.empty()) {
554 size_t count = (graph_state->m_DashArray.size() + 1) / 2;
555 DataVector<SkScalar> intervals(count * 2);
557 for (size_t i = 0; i < count; i++) {
558 float on = graph_state->m_DashArray[i * 2];
559 if (on <= 0.000001f) {
562 float off = i * 2 + 1 == graph_state->m_DashArray.size()
564 : graph_state->m_DashArray[i * 2 + 1];
565 off =
std::max(off, 0.0f);
566 intervals[i * 2] = on;
567 intervals[i * 2 + 1] = off;
569 spaint->setPathEffect(SkDashPathEffect::Make(
570 intervals.data(), pdfium::checked_cast<
int>(intervals.size()),
571 graph_state->m_DashPhase));
573 spaint->setStyle(SkPaint::kStroke_Style);
575 spaint->setStrokeWidth(width);
577 spaint->setStrokeCap(cap);
578 spaint->setStrokeJoin(join);
584 SkMatrix* skMatrix) {
585 skMatrix->setAll(m
.a / width, -m
.c / height, m
.c + m
.e, m
.b / width,
586 -m
.d / height, m
.d + m
.f, 0, 0, 1);
589void SetBitmapPaint(
bool is_mask,
599 paint->setColor(argb);
600 }
else if (alpha != 1.0f) {
601 paint->setAlphaf(alpha);
604 paint->setAntiAlias(anti_alias);
605 paint->setBlendMode(GetSkiaBlendMode(blend_type));
608void SetBitmapPaintForMerge(
bool is_mask,
614 paint->setColorFilter(SkColorFilters::Blend(0xFFFFFFFF, SkBlendMode::kSrc));
617 paint->setAlphaf(alpha);
618 paint->setAntiAlias(anti_alias);
619 paint->setBlendMode(GetSkiaBlendMode(blend_type));
623RetainPtr<CFX_DIBitmap> MakeDebugBitmap(
int width,
int height, uint32_t color) {
624 auto bitmap =
pdfium::MakeRetain<CFX_DIBitmap>();
631 bitmap->Clear(color);
635bool HasRSX(pdfium::span<
const TextCharPos> char_pos,
637 bool* oneAtATimePtr) {
638 bool useRSXform =
false;
639 bool oneAtATime =
false;
641 for (
const TextCharPos& cp : char_pos) {
642 if (!cp.m_bGlyphAdjust) {
645 bool upright = 0 == cp.m_AdjustMatrix[1] && 0 == cp.m_AdjustMatrix[2];
646 if (cp.m_AdjustMatrix[0] != cp.m_AdjustMatrix[3]) {
647 if (upright && 1 == cp.m_AdjustMatrix[3]) {
649 scaleX = cp.m_AdjustMatrix[0];
650 }
else if (scaleX != cp.m_AdjustMatrix[0]) {
656 }
else if (cp.m_AdjustMatrix[1] != -cp.m_AdjustMatrix[2]) {
662 *oneAtATimePtr = oneAtATime;
663 *scaleXPtr = oneAtATime ? 1 : scaleX;
664 return oneAtATime ?
false : useRSXform;
670std::unique_ptr<CFX_SkiaDeviceDriver> CFX_SkiaDeviceDriver::Create(
674 bool bGroupKnockout) {
675 auto driver =
pdfium::WrapUnique(
676 new CFX_SkiaDeviceDriver(
std::move(pBitmap), bRgbByteOrder,
677 std::move(pBackdropBitmap), bGroupKnockout));
678 if (!driver->m_pCanvas) {
686std::unique_ptr<CFX_SkiaDeviceDriver> CFX_SkiaDeviceDriver::Create(
688 auto driver =
pdfium::WrapUnique(
new CFX_SkiaDeviceDriver(canvas));
689 if (!driver->m_pBitmap || !driver->m_pBackdropBitmap) {
696CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(
701 : m_pBitmap(std::move(pBitmap)),
702 m_pBackdropBitmap(pBackdropBitmap),
703 m_bRgbByteOrder(bRgbByteOrder),
704 m_bGroupKnockout(bGroupKnockout) {
705 SkColorType color_type;
706 const int bpp = m_pBitmap->GetBPP();
707 SkAlphaType alpha_type = kPremul_SkAlphaType;
709 color_type = m_pBitmap->IsAlphaFormat() || m_pBitmap->IsMaskFormat()
710 ? kAlpha_8_SkColorType
711 : kGray_8_SkColorType;
712 }
else if (bpp == 24) {
713 DCHECK_EQ(m_pBitmap->GetFormat(), FXDIB_Format::kBgr);
717 m_pOriginalBitmap = std::move(m_pBitmap);
718 const int width = m_pOriginalBitmap->GetWidth();
719 const int height = m_pOriginalBitmap->GetHeight();
721 m_pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
722 if (!m_pBitmap->Create(width, height, FXDIB_Format::kBgraPremul) ||
723 !m_pBitmap->TransferBitmap(width, height, m_pOriginalBitmap,
730 m_pOriginalBitmap.Reset();
734 color_type = Get32BitSkColorType(bRgbByteOrder);
737 color_type = Get32BitSkColorType(bRgbByteOrder);
740 alpha_type = kOpaque_SkAlphaType;
742 alpha_type = kUnpremul_SkAlphaType;
746 SkImageInfo imageInfo = SkImageInfo::Make(
747 m_pBitmap->GetWidth(), m_pBitmap->GetHeight(), color_type, alpha_type);
748 surface_ = SkSurfaces::WrapPixels(
749 imageInfo, m_pBitmap->GetWritableBuffer().data(), m_pBitmap->GetPitch());
750 m_pCanvas = surface_->getCanvas();
753CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(SkCanvas& canvas)
754 : m_pCanvas(&canvas), m_bGroupKnockout(
false) {
755 int width = m_pCanvas->imageInfo().width();
756 int height = m_pCanvas->imageInfo().height();
757 DCHECK_EQ(kUnknown_SkColorType, m_pCanvas->imageInfo().colorType());
759 constexpr uint32_t kMagenta = 0xffff00ff;
760 constexpr uint32_t kGreen = 0xff00ff00;
761 m_pBitmap = MakeDebugBitmap(width, height, kMagenta);
762 m_pBackdropBitmap = MakeDebugBitmap(width, height, kGreen);
772 pdfium::span<
const TextCharPos> pCharPos,
782 if (pFont->GetFontSpan().empty())
785 if (TryDrawText(pCharPos, pFont, mtObject2Device, font_size, color,
789 sk_sp<SkTypeface> typeface(SkSafeRef(pFont->GetDeviceCache()));
791 paint.setAntiAlias(
true);
792 paint.setColor(color);
795 font.setTypeface(typeface);
796 font.setEmbolden(pFont->IsSubstFontBold());
797 font.setHinting(SkFontHinting::kNone);
798 font.setSize(SkTAbs(font_size));
799 font.setSubpixel(
true);
801 font.setEdging(GetFontEdgingType(options));
803 SkAutoCanvasRestore scoped_save_restore(m_pCanvas,
true);
804 const SkScalar horizontal_flip = font_size < 0 ? -1 : 1;
806 SkMatrix skMatrix = ToFlippedSkMatrix(mtObject2Device, horizontal_flip);
807 m_pCanvas->concat(skMatrix);
808 DataVector<SkPoint> positions(pCharPos.size());
809 DataVector<uint16_t> glyphs(pCharPos.size());
811 for (size_t index = 0; index < pCharPos.size(); ++index) {
813 positions[index] = {cp.m_Origin.x * horizontal_flip,
814 cp.m_Origin.y * vertical_flip};
815 glyphs[index] =
static_cast<uint16_t>(cp.m_GlyphIndex);
816#if BUILDFLAG(IS_APPLE)
818 glyphs[index] =
static_cast<uint16_t>(cp.m_ExtGID);
822 for (size_t index = 0; index < pCharPos.size(); ++index) {
825 if (0 == cp.m_AdjustMatrix[1] && 0 == cp.m_AdjustMatrix[2] &&
826 1 == cp.m_AdjustMatrix[3]) {
827 font.setScaleX(cp.m_AdjustMatrix[0]);
829 SkTextBlob::MakeFromText(&glyphs[index],
sizeof(glyphs[index]),
830 font, SkTextEncoding::kGlyphID);
831 m_pCanvas->drawTextBlob(blob, positions[index].fX, positions[index].fY,
833 font.setScaleX(SkIntToScalar(1));
835 SkAutoCanvasRestore scoped_save_restore2(m_pCanvas,
true);
837 adjust.preTranslate(positions[index].fX, -positions[index].fY);
838 adjust.setScaleX(cp.m_AdjustMatrix[0]);
839 adjust.setSkewX(cp.m_AdjustMatrix[1]);
840 adjust.setSkewY(cp.m_AdjustMatrix[2]);
841 adjust.setScaleY(cp.m_AdjustMatrix[3]);
842 m_pCanvas->concat(adjust);
844 SkTextBlob::MakeFromText(&glyphs[index],
sizeof(glyphs[index]),
845 font, SkTextEncoding::kGlyphID);
846 m_pCanvas->drawTextBlob(blob, 0, 0, paint);
850 SkTextBlob::MakeFromText(&glyphs[index],
sizeof(glyphs[index]), font,
851 SkTextEncoding::kGlyphID);
852 m_pCanvas->drawTextBlob(blob, positions[index].fX, positions[index].fY,
863bool CFX_SkiaDeviceDriver::TryDrawText(pdfium::span<
const TextCharPos> char_pos,
870 bool oneAtATime =
false;
871 bool hasRSX = HasRSX(char_pos, &scaleX, &oneAtATime);
876 m_charDetails.SetCount(char_pos.size());
878 m_rsxform.resize(char_pos.size());
883 const SkScalar horizontal_flip = font_size < 0 ? -1 : 1;
885 for (size_t index = 0; index < char_pos.size(); ++index) {
887 m_charDetails.SetPositionAt(index, {cp.m_Origin.x * horizontal_flip,
888 cp.m_Origin.y * vertical_flip});
889 m_charDetails.SetGlyphAt(index,
static_cast<uint16_t>(cp.m_GlyphIndex));
890 m_charDetails.SetFontCharWidthAt(index, cp.m_FontCharWidth);
891#if BUILDFLAG(IS_APPLE)
893 m_charDetails.SetGlyphAt(index,
static_cast<uint16_t>(cp.m_ExtGID));
898 const DataVector<SkPoint>& positions = m_charDetails.GetPositions();
899 for (size_t index = 0; index < char_pos.size(); ++index) {
901 SkRSXform& rsxform = m_rsxform[index];
903 rsxform.fSCos = cp.m_AdjustMatrix[0];
904 rsxform.fSSin = cp.m_AdjustMatrix[1];
905 rsxform.fTx = cp.m_AdjustMatrix[0] * positions[index].fX;
906 rsxform.fTy = -cp.m_AdjustMatrix[3] * positions[index].fY;
910 rsxform.fTx = positions[index].fX;
911 rsxform.fTy = positions[index].fY;
917 skPaint.setAntiAlias(
true);
918 skPaint.setColor(color);
922 font.setTypeface(sk_ref_sp(pFont->GetDeviceCache()));
924 font.setEmbolden(pFont->IsSubstFontBold());
925 font.setHinting(SkFontHinting::kNone);
926 font.setScaleX(scaleX);
928 font.setSize(SkTAbs(font_size));
929 font.setSubpixel(
true);
930 font.setEdging(GetFontEdgingType(options));
932 SkAutoCanvasRestore scoped_save_restore(m_pCanvas,
true);
933 m_pCanvas->concat(ToFlippedSkMatrix(matrix, horizontal_flip));
935 const DataVector<uint16_t>& glyphs = m_charDetails.GetGlyphs();
936 if (!m_rsxform.empty()) {
937 sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromRSXform(
938 glyphs.data(), glyphs.size() *
sizeof(uint16_t), m_rsxform.data(), font,
939 SkTextEncoding::kGlyphID);
940 m_pCanvas->drawTextBlob(blob, 0, 0, skPaint);
943 const DataVector<SkPoint>& positions = m_charDetails.GetPositions();
944 const DataVector<uint32_t>& widths = m_charDetails.GetFontCharWidths();
945 for (size_t i = 0; i < m_charDetails.Count(); ++i) {
946 const uint32_t font_glyph_width = pFont->GetGlyphWidth(glyphs[i]);
947 const uint32_t pdf_glyph_width = widths[i];
948 if (pdf_glyph_width > 0 && font_glyph_width > 0) {
951 font.setScaleX(scaleX * SkIntToScalar(pdf_glyph_width) /
954 font.setScaleX(scaleX);
957 SkTextBlob::MakeFromPosText(&glyphs[i],
sizeof(uint16_t), &positions[i],
958 font, SkTextEncoding::kGlyphID);
959 m_pCanvas->drawTextBlob(blob, 0, 0, skPaint);
974 paint.setAlphaf(alpha);
975 paint.setBlendMode(SkBlendMode::kDstIn);
976 m_pCanvas->drawPaint(paint);
985 sk_sp<SkImage> skia_mask = mask->RealizeSkImage();
989 DCHECK_EQ(skia_mask->colorType(), kAlpha_8_SkColorType);
992 paint.setBlendMode(SkBlendMode::kDstIn);
993 m_pCanvas->drawImageRect(skia_mask,
994 SkRect::Make(m_pCanvas->imageInfo().bounds()),
995 SkSamplingOptions(), &paint);
1006 return m_pCanvas->imageInfo().width();
1008 return m_pCanvas->imageInfo().height();
1017 FXRC_FILLSTROKE_PATH | FXRC_SHADING | FXRC_PREMULTIPLIED_ALPHA;
1028 m_pCanvas->restore();
1038 m_FillOptions = fill_options;
1043 if (path.GetPoints().size() == 5 || path.GetPoints().size() == 4) {
1045 if (maybe_rectf.has_value()) {
1052 skClipPath.addRect({(
float)outer
.left, (
float)outer
.bottom,
1056 if (skClipPath.isEmpty()) {
1057 skClipPath = BuildPath(path);
1058 skClipPath.setFillType(GetAlternateOrWindingFillType(fill_options));
1059 skClipPath.transform(ToSkMatrix(deviceMatrix));
1060 DebugShowSkiaPath(skClipPath);
1062 m_pCanvas->clipPath(skClipPath, SkClipOp::kIntersect,
true);
1063 DebugShowCanvasClip(
this, m_pCanvas);
1072 SkPath skPath = BuildPath(path);
1073 SkMatrix skMatrix = ToSkMatrix(*pObject2Device);
1077 skpathutils::FillPathWithPaint(skPath, skPaint, &dst_path);
1078 dst_path.transform(skMatrix);
1079 m_pCanvas->clipPath(dst_path, SkClipOp::kIntersect,
true);
1080 DebugShowCanvasClip(
this, m_pCanvas);
1087 uint32_t fill_color,
1088 uint32_t stroke_color,
1090 m_FillOptions = fill_options;
1092 SkPath skia_path = BuildPath(path);
1093 skia_path.setFillType(GetAlternateOrWindingFillType(fill_options));
1095 SkMatrix skMatrix = pObject2Device ? ToSkMatrix(*pObject2Device) : SkMatrix();
1099 skPaint.setBlendMode(SkBlendMode::kPlus);
1101 int stroke_alpha =
FXARGB_A(stroke_color);
1105 PaintStroke(&skPaint, &graph_state, skMatrix, fill_options);
1108 SkAutoCanvasRestore scoped_save_restore(m_pCanvas,
true);
1109 m_pCanvas->concat(skMatrix);
1110 bool do_stroke =
true;
1114 const SkPath* fillPath = &skia_path;
1116 if (m_bGroupKnockout) {
1117 skpathutils::FillPathWithPaint(skia_path, skPaint, &strokePath);
1118 if (stroke_color == fill_color &&
1119 Op(skia_path, strokePath, SkPathOp::kUnion_SkPathOp, &strokePath)) {
1120 fillPath = &strokePath;
1122 }
else if (Op(skia_path, strokePath, SkPathOp::kDifference_SkPathOp,
1124 fillPath = &strokePath;
1128 skPaint.setStyle(SkPaint::kFill_Style);
1129 skPaint.setColor(fill_color);
1130 DrawPathImpl(*fillPath, skPaint);
1132 if (stroke_alpha && do_stroke) {
1133 skPaint.setStyle(SkPaint::kStroke_Style);
1134 skPaint.setColor(stroke_color);
1135 if (!skia_path.isLastContourClosed() && IsPathAPoint(skia_path)) {
1137 m_pCanvas->drawPoint(skia_path.getPoint(0), skPaint);
1138 }
else if (IsPathAPoint(skia_path) &&
1139 skPaint.getStrokeCap() != SkPaint::kRound_Cap) {
1143 DrawPathImpl(skia_path, skPaint);
1151 spaint.setAntiAlias(
true);
1152 spaint.setColor(fill_color);
1153 SkRect srect = SkRect::MakeLTRB(rect.left, std::min(rect.top, rect.bottom),
1154 rect.right, std::max(rect.bottom, rect.top));
1155 DebugShowSkiaDrawRect(
this, m_pCanvas, spaint, srect);
1156 m_pCanvas->drawRect(srect, spaint);
1160bool CFX_SkiaDeviceDriver::
DrawShading(
const CPDF_ShadingPattern& pattern,
1175 const std::vector<std::unique_ptr<CPDF_Function>>& pFuncs =
1177 size_t nFuncs = pFuncs.size();
1181 pattern.GetShadingObject()->GetDict();
1188 DataVector<SkColor> sk_colors;
1189 DataVector<SkScalar> sk_pos;
1190 for (size_t j = 0; j < nFuncs; j++) {
1194 if (
const CPDF_SampledFunc* pSampledFunc = pFuncs[j]->ToSampledFunc()) {
1196
1197
1198
1199 if (!AddSamples(pSampledFunc, sk_colors, sk_pos)) {
1202 }
else if (
const CPDF_ExpIntFunc* pExpIntFuc = pFuncs[j]->ToExpIntFunc()) {
1203 if (!AddColors(pExpIntFuc, sk_colors,
false)) {
1206 sk_pos.push_back(0);
1207 sk_pos.push_back(1);
1208 }
else if (
const CPDF_StitchFunc* pStitchFunc = pFuncs[j]->ToStitchFunc()) {
1209 if (!AddStitching(pStitchFunc, sk_colors, sk_pos)) {
1217 bool clipStart = !pArray || !pArray->GetIntegerAt(0);
1218 bool clipEnd = !pArray || !pArray->GetIntegerAt(1);
1220 paint.setAntiAlias(
true);
1221 paint.setAlpha(alpha);
1222 SkMatrix skMatrix = ToSkMatrix(matrix);
1223 SkRect skRect = SkRect::MakeLTRB(clip_rect.left, clip_rect.top,
1224 clip_rect.right, clip_rect.bottom);
1228 float start_x = pCoords->GetFloatAt(0);
1229 float start_y = pCoords->GetFloatAt(1);
1230 float end_x = pCoords->GetFloatAt(2);
1231 float end_y = pCoords->GetFloatAt(3);
1232 SkPoint pts[] = {{start_x, start_y}, {end_x, end_y}};
1233 skMatrix.mapPoints(pts,
std::size(pts));
1234 paint.setShader(SkGradientShader::MakeLinear(
1235 pts, sk_colors.data(), sk_pos.data(),
1236 fxcrt::CollectionSize<
int>(sk_colors), SkTileMode::kClamp));
1237 if (clipStart || clipEnd) {
1239 if (pts[0].fX == pts[1].fX) {
1240 if (pts[0].fY > pts[1].fY) {
1241 std::swap(pts[0].fY, pts[1].fY);
1242 std::swap(clipStart, clipEnd);
1245 skRect.fTop =
std::max(skRect.fTop, pts[0].fY);
1247 skRect.fBottom =
std::min(skRect.fBottom, pts[1].fY);
1248 }
else if (pts[0].fY == pts[1].fY) {
1249 if (pts[0].fX > pts[1].fX) {
1250 std::swap(pts[0].fX, pts[1].fX);
1251 std::swap(clipStart, clipEnd);
1254 skRect.fLeft =
std::max(skRect.fLeft, pts[0].fX);
1256 skRect.fRight =
std::min(skRect.fRight, pts[1].fX);
1258 SkPoint rectPts[4] = {{skRect.fLeft, skRect.fTop},
1259 {skRect.fRight, skRect.fTop},
1260 {skRect.fRight, skRect.fBottom},
1261 {skRect.fLeft, skRect.fBottom}};
1262 ClipAngledGradient(pts, rectPts, clipStart, clipEnd, &skClip);
1265 skPath.addRect(skRect);
1266 skMatrix.setIdentity();
1268 float start_x = pCoords->GetFloatAt(0);
1269 float start_y = pCoords->GetFloatAt(1);
1270 float start_r = pCoords->GetFloatAt(2);
1271 float end_x = pCoords->GetFloatAt(3);
1272 float end_y = pCoords->GetFloatAt(4);
1273 float end_r = pCoords->GetFloatAt(5);
1274 SkPoint pts[] = {{start_x, start_y}, {end_x, end_y}};
1276 paint.setShader(SkGradientShader::MakeTwoPointConical(
1277 pts[0], start_r, pts[1], end_r, sk_colors.data(), sk_pos.data(),
1278 fxcrt::CollectionSize<
int>(sk_colors), SkTileMode::kClamp));
1279 if (clipStart || clipEnd) {
1280 if (clipStart && start_r)
1281 skClip.addCircle(pts[0].fX, pts[0].fY, start_r);
1283 skClip.addCircle(pts[1].fX, pts[1].fY, end_r, SkPathDirection::kCCW);
1285 skClip.setFillType(SkPathFillType::kInverseWinding);
1286 skClip.transform(skMatrix);
1289 if (!skMatrix.invert(&inverse))
1291 skPath.addRect(skRect);
1292 skPath.transform(inverse);
1295 RetainPtr<
const CPDF_Stream> pStream = ToStream(pattern.GetShadingObject());
1302 std::array<SkPoint, 12> cubics;
1303 std::array<SkColor, 4> colors;
1304 SkAutoCanvasRestore scoped_save_restore(m_pCanvas,
true);
1305 if (!skClip.isEmpty())
1306 m_pCanvas->clipPath(skClip, SkClipOp::kIntersect,
true);
1307 m_pCanvas->concat(skMatrix);
1311 std::array<SkPoint, 4> temp_cubics;
1312 for (size_t i = 0; i < temp_cubics.size(); ++i) {
1313 temp_cubics[i] = cubics[(flag * 3 + i) % cubics.size()];
1315 fxcrt::Copy(temp_cubics, cubics);
1316 SkColor temp_colors[2] = {colors[flag % 4],
1317 colors[(flag + 1) % colors.size()]};
1318 fxcrt::Copy(temp_colors, colors);
1320 const size_t start_point = flag ? 4 : 0;
1321 for (size_t i = start_point; i < cubics.size(); ++i) {
1323 cubics[i].fX = point.x;
1324 cubics[i].fY = point.y;
1326 const size_t start_color = flag ? 2 : 0;
1327 for (size_t i = start_color; i < colors.size(); ++i) {
1330 SkColorSetARGB(0xFF, (U8CPU)(rgb.red * 255),
1331 (U8CPU)(rgb.green * 255), (U8CPU)(rgb.blue * 255));
1333 m_pCanvas->drawPatch(cubics.data(), colors.data(),
nullptr,
1334 SkBlendMode::kDst, paint);
1338 SkAutoCanvasRestore scoped_save_restore(m_pCanvas,
true);
1339 if (!skClip.isEmpty())
1340 m_pCanvas->clipPath(skClip, SkClipOp::kIntersect,
true);
1341 m_pCanvas->concat(skMatrix);
1342 DrawPathImpl(skPath, paint);
1347 SkIRect clip = m_pCanvas->getDeviceClipBounds();
1348 return FX_RECT(clip.fLeft, clip.fTop, clip.fRight, clip.fBottom);
1354 const uint8_t* input_buffer = m_pBitmap->GetBuffer().data();
1355 if (!input_buffer) {
1359 uint8_t* output_buffer = bitmap->GetWritableBuffer().data();
1362 SkImageInfo input_info = m_pCanvas->imageInfo();
1363 sk_sp<SkImage> input = SkImages::RasterFromPixmap(
1364 SkPixmap(input_info, input_buffer, m_pBitmap->GetPitch()),
1368 SkImageInfo output_info = SkImageInfo::Make(
1369 bitmap->GetWidth(), bitmap->GetHeight(),
1370 Get32BitSkColorType(m_bRgbByteOrder),
1371 bitmap->IsPremultiplied() ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
1372 sk_sp<SkSurface> output =
1373 SkSurfaces::WrapPixels(output_info, output_buffer, bitmap->GetPitch());
1375 output->getCanvas()->drawImage(input, left, top, SkSamplingOptions());
1380 return m_pBackdropBitmap;
1389 if (m_pBitmap->GetBuffer().empty()) {
1394 bitmap->GetWidth()
, bitmap->GetHeight()
, left
, top
);
1400 return StartDIBitsSkia(
std::move(bitmap), src_rect, 1.0f, color,
1401 matrix, sampling_options, blend_type);
1413 if (m_pBitmap->GetBuffer().empty())
1417 dest_left
, dest_top
);
1418 SkAutoCanvasRestore scoped_save_restore(m_pCanvas,
true);
1419 SkRect skClipRect = SkRect::MakeLTRB(pClipRect->left, pClipRect->bottom,
1420 pClipRect->right, pClipRect->top);
1421 m_pCanvas->clipRect(skClipRect, SkClipOp::kIntersect,
true);
1427 FX_RECT rect(0, 0, bitmap->GetWidth(), bitmap->GetHeight());
1428 return StartDIBitsSkia(
std::move(bitmap), rect, 1.0f, color, matrix,
1429 sampling_options, blend_type);
1439 FX_RECT rect(0, 0, bitmap->GetWidth(), bitmap->GetHeight());
1440 bool success = StartDIBitsSkia(
std::move(bitmap), rect, alpha, color, matrix,
1441 options, blend_type);
1445void CFX_DIBitmap::PreMultiply() {
1451 void* buffer = GetWritableBuffer().data();
1456 SetFormat(FXDIB_Format::kBgraPremul);
1460 SkImageInfo premultiplied_info =
1461 SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType);
1462 SkPixmap premultiplied(premultiplied_info, buffer, row_bytes);
1463 SkImageInfo unpremultiplied_info =
1464 SkImageInfo::Make(width, height, kN32_SkColorType, kUnpremul_SkAlphaType);
1465 SkPixmap unpremultiplied(unpremultiplied_info, buffer, row_bytes);
1466 unpremultiplied.readPixels(premultiplied);
1469void CFX_DIBitmap::UnPreMultiply() {
1471 if (GetFormat() != FXDIB_Format::kBgraPremul) {
1475 void* buffer = GetWritableBuffer().data();
1484 SkImageInfo premultiplied_info =
1485 SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType);
1486 SkPixmap premultiplied(premultiplied_info, buffer, row_bytes);
1487 SkImageInfo unpremultiplied_info =
1488 SkImageInfo::Make(width, height, kN32_SkColorType, kUnpremul_SkAlphaType);
1489 SkPixmap unpremultiplied(unpremultiplied_info, buffer, row_bytes);
1490 premultiplied.readPixels(unpremultiplied);
1498 DebugValidate(m_pBitmap);
1500 sk_sp<SkImage> skia_source = bitmap->RealizeSkImage();
1505 DCHECK(mask->IsMaskFormat());
1506 sk_sp<SkImage> skia_mask = mask->RealizeSkImage();
1510 DCHECK_EQ(skia_mask->colorType(), kAlpha_8_SkColorType);
1513 SkAutoCanvasRestore scoped_save_restore(m_pCanvas,
true);
1515 const int src_width = bitmap->GetWidth();
1516 const int src_height = bitmap->GetHeight();
1518 SetBitmapMatrix(matrix, src_width, src_height, &skMatrix);
1519 m_pCanvas->concat(skMatrix);
1521 SetBitmapPaintForMerge(bitmap->IsMaskFormat(), !m_FillOptions
.aliased_path,
1522 alpha, blend_type, &paint);
1523 sk_sp<SkShader> source_shader = skia_source->makeShader(
1524 SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions());
1525 sk_sp<SkShader> mask_shader = skia_mask->makeShader(
1526 SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions());
1527 paint.setShader(SkShaders::Blend(
1528 SkBlendMode::kSrcIn, std::move(mask_shader), std::move(source_shader)));
1529 m_pCanvas->drawRect(
1530 SkRect::MakeWH(SkIntToScalar(src_width), SkIntToScalar(src_height)),
1534 DebugValidate(m_pBitmap);
1544 if (m_pBitmap->GetBuffer().empty()) {
1549 bitmap->GetWidth()
, bitmap->GetHeight()
, dest_left
, dest_top
);
1555 m_bGroupKnockout = group_knockout;
1559 if (!m_pOriginalBitmap) {
1563 int width = m_pOriginalBitmap->GetWidth();
1564 int height = m_pOriginalBitmap->GetHeight();
1565 DCHECK_EQ(width, m_pBitmap->GetWidth());
1566 DCHECK_EQ(height, m_pBitmap->GetHeight());
1567 DCHECK_EQ(FXDIB_Format::kBgr, m_pOriginalBitmap->GetFormat());
1568 m_pOriginalBitmap->TransferBitmap(width, height, m_pBitmap, 0,
1572void CFX_SkiaDeviceDriver::
Clear(uint32_t color) {
1573 m_pCanvas->clear(color);
1583 DebugValidate(m_pBitmap);
1585 sk_sp<SkImage> skia_source = bitmap->RealizeSkImage();
1591 SkAutoCanvasRestore scoped_save_restore(m_pCanvas,
true);
1593 const int width = bitmap->GetWidth();
1594 const int height = bitmap->GetHeight();
1596 SetBitmapMatrix(matrix, width, height, &skMatrix);
1597 m_pCanvas->concat(skMatrix);
1599 SetBitmapPaint(bitmap->IsMaskFormat(), !m_FillOptions
.aliased_path, alpha,
1600 color, blend_type, &paint);
1603 if (!use_interpolate_bilinear) {
1606 if (
pdfium::IsValueInRangeForNumericType<
int>(dest_width) &&
1607 pdfium::IsValueInRangeForNumericType<
int>(dest_height)) {
1609 options
, static_cast<
int>(dest_width)
,
1610 static_cast<
int>(dest_height)
, width
, height
);
1613 SkSamplingOptions sampling_options;
1614 if (use_interpolate_bilinear) {
1616 SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear);
1619 m_pCanvas->drawImageRect(
1621 SkRect::MakeLTRB(src_rect.left, src_rect.top, src_rect.right,
1623 SkRect::MakeWH(src_rect.Width(), src_rect.Height()), sampling_options,
1624 &paint, SkCanvas::kFast_SrcRectConstraint);
1627 DebugValidate(m_pBitmap);
1631void CFX_SkiaDeviceDriver::DrawPathImpl(
const SkPath& path,
1632 const SkPaint& paint) {
1633 DebugShowSkiaDrawPath(
this, m_pCanvas, paint, path);
1634 m_pCanvas->drawPath(path, paint);
1637CFX_SkiaDeviceDriver::CharDetail::CharDetail() =
default;
1638CFX_SkiaDeviceDriver::CharDetail::~CharDetail() =
default;
1640bool CFX_DefaultRenderDevice::AttachSkiaImpl(
1643 RetainPtr<CFX_DIBitmap> pBackdropBitmap,
1644 bool bGroupKnockout) {
1651 CFX_SkiaDeviceDriver::Create(std::move(pBitmap), bRgbByteOrder,
1652 std::move(pBackdropBitmap), bGroupKnockout);
1656 SetDeviceDriver(std::move(driver));
1660bool CFX_DefaultRenderDevice::AttachCanvas(SkCanvas& canvas) {
1661 auto driver = CFX_SkiaDeviceDriver::Create(canvas);
1665 SetDeviceDriver(std::move(driver));
1669bool CFX_DefaultRenderDevice::CreateSkia(
1673 RetainPtr<CFX_DIBitmap> pBackdropBitmap) {
1674 auto pBitmap =
pdfium::MakeRetain<CFX_DIBitmap>();
1675 if (!pBitmap->Create(width, height, format))
1679 auto driver = CFX_SkiaDeviceDriver::Create(std::move(pBitmap),
false,
1680 std::move(pBackdropBitmap),
false);
1684 SetDeviceDriver(std::move(driver));
uint32_t GetBits(uint32_t nBits)
FXDIB_Format GetFormat() const
void SetFormat(FXDIB_Format format)
uint32_t GetPitch() const
static bool UseSkiaRenderer()
constexpr CFX_FloatRect(float l, float b, float r, float t)
void Intersect(const CFX_FloatRect &other_rect)
FX_RECT GetOuterRect() const
int GetSubstFontItalicAngle() const
FXFT_FaceRec * GetFaceRec() const
constexpr CFX_Matrix()=default
static CFX_Matrix GetFlipMatrix(float width, float height, float left, float top)
void SetBitmap(RetainPtr< CFX_DIBitmap > bitmap)
~CFX_SkiaDeviceDriver() override
bool DrawBitsWithMask(RetainPtr< const CFX_DIBBase > bitmap, RetainPtr< const CFX_DIBBase > mask, float alpha, const CFX_Matrix &matrix, BlendMode blend_type)
void SyncInternalBitmaps() override
bool DrawDeviceText(pdfium::span< const TextCharPos > pCharPos, CFX_Font *pFont, const CFX_Matrix &mtObject2Device, float font_size, uint32_t color, const CFX_TextRenderOptions &options) override
bool MultiplyAlpha(float alpha) override
StartResult StartDIBits(RetainPtr< const CFX_DIBBase > bitmap, float alpha, uint32_t color, const CFX_Matrix &matrix, const FXDIB_ResampleOptions &options, BlendMode blend_type) override
bool FillRect(const FX_RECT &rect, uint32_t fill_color) override
bool DrawShading(const CPDF_ShadingPattern &pattern, const CFX_Matrix &matrix, const FX_RECT &clip_rect, int alpha) override
void SetGroupKnockout(bool group_knockout) override
DeviceType GetDeviceType() const override
void SaveState() override
bool MultiplyAlphaMask(RetainPtr< const CFX_DIBitmap > mask) override
bool SetClip_PathFill(const CFX_Path &path, const CFX_Matrix *pObject2Device, const CFX_FillRenderOptions &fill_options) override
RetainPtr< const CFX_DIBitmap > GetBackDrop() const override
bool DrawPath(const CFX_Path &path, const CFX_Matrix *pObject2Device, const CFX_GraphStateData *pGraphState, uint32_t fill_color, uint32_t stroke_color, const CFX_FillRenderOptions &fill_options) override
int GetDriverType() const override
int GetDeviceCaps(int caps_id) const override
bool SetDIBits(RetainPtr< const CFX_DIBBase > bitmap, uint32_t color, const FX_RECT &src_rect, int dest_left, int dest_top, BlendMode blend_type) override
FX_RECT GetClipBox() const override
bool StretchDIBits(RetainPtr< const CFX_DIBBase > bitmap, uint32_t color, int dest_left, int dest_top, int dest_width, int dest_height, const FX_RECT *pClipRect, const FXDIB_ResampleOptions &options, BlendMode blend_type) override
void RestoreState(bool bKeepSaved) override
bool GetDIBits(RetainPtr< CFX_DIBitmap > bitmap, int left, int top) const override
bool SetClip_PathStroke(const CFX_Path &path, const CFX_Matrix *pObject2Device, const CFX_GraphStateData *pGraphState) override
bool SetBitsWithMask(RetainPtr< const CFX_DIBBase > bitmap, RetainPtr< const CFX_DIBBase > mask, int dest_left, int dest_top, float alpha, BlendMode blend_type) override
void Clear(uint32_t color)
std::vector< RetainPtr< CPDF_Object > >::const_iterator const_iterator
std::map< ByteString, RetainPtr< CPDF_Object >, std::less<> > DictMap
float GetExponent() const
uint32_t GetOrigOutputs() const
uint32_t InputCount() const
float GetRange(int i) const
float GetDomain(int i) const
uint32_t OutputCount() const
uint32_t ReadFlag() const
uint32_t GetBitsPerSample() const
ShadingType GetShadingType() const
static bool UseInterpolateBilinear(const FXDIB_ResampleOptions &options, int dest_width, int dest_height, int src_width, int src_height)
CFX_PTemplate< float > CFX_PointF
#define NOTREACHED_NORETURN()
#define FXRC_ALPHA_OUTPUT
#define FXDC_PIXEL_HEIGHT
constexpr CFX_FillRenderOptions()
AliasingType aliasing_type
bool bInterpolateBilinear