Flutter Engine
The Flutter Engine
SkPDFGraphicState.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9
12#include "include/core/SkData.h"
17#include "src/core/SkTHash.h"
19#include "src/pdf/SkPDFUtils.h"
20
21#include <memory>
22#include <utility>
23
25 const char* name = SkPDFUtils::BlendModeName(mode);
27 return name;
28}
29
30static int to_stroke_cap(uint8_t cap) {
31 // PDF32000.book section 8.4.3.3 "Line Cap Style"
32 switch ((SkPaint::Cap)cap) {
33 case SkPaint::kButt_Cap: return 0;
34 case SkPaint::kRound_Cap: return 1;
35 case SkPaint::kSquare_Cap: return 2;
36 default: SkASSERT(false); return 0;
37 }
38}
39
40static int to_stroke_join(uint8_t join) {
41 // PDF32000.book section 8.4.3.4 "Line Join Style"
42 switch ((SkPaint::Join)join) {
43 case SkPaint::kMiter_Join: return 0;
44 case SkPaint::kRound_Join: return 1;
45 case SkPaint::kBevel_Join: return 2;
46 default: SkASSERT(false); return 0;
47 }
48}
49
50// If a SkBlendMode is unsupported in PDF, this function returns
51// SrcOver, otherwise, it returns the blend mode.
56 {
58 }
59 return SkToU8((unsigned)mode);
60}
61
63 const SkPaint& p) {
64 SkASSERT(doc);
65 const SkBlendMode mode = p.getBlendMode_or(SkBlendMode::kSrcOver);
66
67 if (SkPaint::kFill_Style == p.getStyle()) {
68 SkPDFFillGraphicState fillKey = {p.getColor4f().fA, pdf_blend_mode(mode)};
69 auto& fillMap = doc->fFillGSMap;
70 if (SkPDFIndirectReference* statePtr = fillMap.find(fillKey)) {
71 return *statePtr;
72 }
74 state.reserve(2);
75 state.insertColorComponentF("ca", fillKey.fAlpha);
76 state.insertName("BM", as_pdf_blend_mode_name((SkBlendMode)fillKey.fBlendMode));
78 fillMap.set(fillKey, ref);
79 return ref;
80 } else {
81 SkPDFStrokeGraphicState strokeKey = {
82 p.getStrokeWidth(),
83 p.getStrokeMiter(),
84 p.getColor4f().fA,
85 SkToU8(p.getStrokeCap()),
86 SkToU8(p.getStrokeJoin()),
88 };
89 auto& sMap = doc->fStrokeGSMap;
90 if (SkPDFIndirectReference* statePtr = sMap.find(strokeKey)) {
91 return *statePtr;
92 }
94 state.reserve(8);
95 state.insertColorComponentF("CA", strokeKey.fAlpha);
96 state.insertColorComponentF("ca", strokeKey.fAlpha);
97 state.insertInt("LC", to_stroke_cap(strokeKey.fStrokeCap));
98 state.insertInt("LJ", to_stroke_join(strokeKey.fStrokeJoin));
99 state.insertScalar("LW", strokeKey.fStrokeWidth);
100 state.insertScalar("ML", strokeKey.fStrokeMiter);
101 state.insertBool("SA", true); // SA = Auto stroke adjustment.
102 state.insertName("BM", as_pdf_blend_mode_name((SkBlendMode)strokeKey.fBlendMode));
104 sMap.set(strokeKey, ref);
105 return ref;
106 }
107}
108
109////////////////////////////////////////////////////////////////////////////////
110
112 // Acrobat crashes if we use a type 0 function, kpdf crashes if we use
113 // a type 2 function, so we use a type 4 function.
114 static const char psInvert[] = "{1 exch sub}";
115 // Do not copy the trailing '\0' into the SkData.
116 auto invertFunction = SkData::MakeWithoutCopy(psInvert, strlen(psInvert));
117
118 std::unique_ptr<SkPDFDict> dict = SkPDFMakeDict();
119 dict->insertInt("FunctionType", 4);
120 dict->insertObject("Domain", SkPDFMakeArray(0, 1));
121 dict->insertObject("Range", SkPDFMakeArray(0, 1));
122 return SkPDFStreamOut(std::move(dict), SkMemoryStream::Make(std::move(invertFunction)), doc);
123}
124
126 bool invert,
127 SkPDFSMaskMode sMaskMode,
128 SkPDFDocument* doc) {
129 // The practical chances of using the same mask more than once are unlikely
130 // enough that it's not worth canonicalizing.
131 auto sMaskDict = SkPDFMakeDict("Mask");
132 if (sMaskMode == kAlpha_SMaskMode) {
133 sMaskDict->insertName("S", "Alpha");
134 } else if (sMaskMode == kLuminosity_SMaskMode) {
135 sMaskDict->insertName("S", "Luminosity");
136 }
137 sMaskDict->insertRef("G", sMask);
138 if (invert) {
139 // let the doc deduplicate this object.
142 }
143 sMaskDict->insertRef("TR", doc->fInvertFunction);
144 }
145 SkPDFDict result("ExtGState");
146 result.insertObject("SMask", std::move(sMaskDict));
147 return doc->emit(result);
148}
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkBlendMode
Definition: SkBlendMode.h:38
@ kPlus
r = min(s + d, 1)
@ kSrcOver
r = s + (1-sa)*d
@ kXor
r = s*(1-da) + d*(1-sa)
static int to_stroke_cap(uint8_t cap)
static SkPDFIndirectReference make_invert_function(SkPDFDocument *doc)
static uint8_t pdf_blend_mode(SkBlendMode mode)
static int to_stroke_join(uint8_t join)
static const char * as_pdf_blend_mode_name(SkBlendMode mode)
SkPDFIndirectReference SkPDFStreamOut(std::unique_ptr< SkPDFDict > dict, std::unique_ptr< SkStreamAsset > content, SkPDFDocument *doc, SkPDFSteamCompressionEnabled compress)
Definition: SkPDFTypes.cpp:591
static std::unique_ptr< SkPDFDict > SkPDFMakeDict(const char *type=nullptr)
Definition: SkPDFTypes.h:185
static std::unique_ptr< SkPDFArray > SkPDFMakeArray(Args... args)
Definition: SkPDFTypes.h:125
constexpr uint8_t SkToU8(S x)
Definition: SkTo.h:22
static sk_sp< SkData > MakeWithoutCopy(const void *data, size_t length)
Definition: SkData.h:116
static std::unique_ptr< SkMemoryStream > Make(sk_sp< SkData > data)
Definition: SkStream.cpp:314
skia_private::THashMap< SkPDFStrokeGraphicState, SkPDFIndirectReference, SkPDFStrokeGraphicState::Hash > fStrokeGSMap
SkPDFIndirectReference emit(const SkPDFObject &, SkPDFIndirectReference)
skia_private::THashMap< SkPDFFillGraphicState, SkPDFIndirectReference, SkPDFFillGraphicState::Hash > fFillGSMap
SkPDFIndirectReference fInvertFunction
@ kRound_Cap
adds circle
Definition: SkPaint.h:335
@ kButt_Cap
no stroke extension
Definition: SkPaint.h:334
@ kSquare_Cap
adds square
Definition: SkPaint.h:336
@ kFill_Style
set to fill geometry
Definition: SkPaint.h:193
@ kRound_Join
adds circle
Definition: SkPaint.h:360
@ kMiter_Join
extends to miter limit
Definition: SkPaint.h:359
@ kBevel_Join
connects outside edges
Definition: SkPaint.h:361
AtkStateType state
gboolean invert
GAsyncResult * result
SkPDFIndirectReference GetGraphicStateForPaint(SkPDFDocument *, const SkPaint &)
SkPDFIndirectReference GetSMaskGraphicState(SkPDFIndirectReference sMask, bool invert, SkPDFSMaskMode sMaskMode, SkPDFDocument *doc)
const char * BlendModeName(SkBlendMode)
Definition: SkPDFUtils.cpp:37
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
Definition: switches.h:228
static SkString join(const CommandLineFlags::StringArray &)
Definition: skpbench.cpp:741