Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Macros | Functions
SkPDFDevice.cpp File Reference
#include "src/pdf/SkPDFDevice.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorFilter.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathEffect.h"
#include "include/core/SkPathUtils.h"
#include "include/core/SkRRect.h"
#include "include/core/SkString.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTextBlob.h"
#include "include/docs/SkPDFDocument.h"
#include "include/encode/SkJpegEncoder.h"
#include "include/pathops/SkPathOps.h"
#include "include/private/base/SkTemplates.h"
#include "include/private/base/SkTo.h"
#include "src/base/SkScopeExit.h"
#include "src/base/SkUTF.h"
#include "src/core/SkAdvancedTypefaceMetrics.h"
#include "src/core/SkAnnotationKeys.h"
#include "src/core/SkBitmapDevice.h"
#include "src/core/SkBlendModePriv.h"
#include "src/core/SkColorSpacePriv.h"
#include "src/core/SkDraw.h"
#include "src/core/SkFontPriv.h"
#include "src/core/SkImageFilterCache.h"
#include "src/core/SkImageFilter_Base.h"
#include "src/core/SkMaskFilterBase.h"
#include "src/core/SkRasterClip.h"
#include "src/core/SkStrike.h"
#include "src/core/SkStrikeSpec.h"
#include "src/core/SkTextFormatParams.h"
#include "src/pdf/SkBitmapKey.h"
#include "src/pdf/SkClusterator.h"
#include "src/pdf/SkPDFBitmap.h"
#include "src/pdf/SkPDFDocumentPriv.h"
#include "src/pdf/SkPDFFont.h"
#include "src/pdf/SkPDFFormXObject.h"
#include "src/pdf/SkPDFGraphicState.h"
#include "src/pdf/SkPDFResourceDict.h"
#include "src/pdf/SkPDFShader.h"
#include "src/pdf/SkPDFTypes.h"
#include "src/pdf/SkPDFUtils.h"
#include "src/shaders/SkColorShader.h"
#include "src/text/GlyphRun.h"
#include "src/utils/SkClipStackUtils.h"
#include <vector>

Go to the source code of this file.

Classes

class  ScopedContentEntry
 

Macros

#define SK_PDF_MASK_QUALITY   50
 

Functions

sk_sp< SkImagemask_to_greyscale_image (SkMaskBuilder *mask)
 
sk_sp< SkImagealpha_image_to_greyscale_image (const SkImage *mask)
 
static int add_resource (THashSet< SkPDFIndirectReference > &resources, SkPDFIndirectReference ref)
 
static void draw_points (SkCanvas::PointMode mode, size_t count, const SkPoint *points, const SkPaint &paint, const SkIRect &bounds, SkDevice *device)
 
static void transform_shader (SkPaint *paint, const SkMatrix &ctm)
 
static SkTCopyOnFirstWrite< SkPaintclean_paint (const SkPaint &srcPaint)
 
static void set_style (SkTCopyOnFirstWrite< SkPaint > *paint, SkPaint::Style style)
 
static bool calculate_inverse_path (const SkRect &bounds, const SkPath &invPath, SkPath *outPath)
 
static SkUnichar map_glyph (const std::vector< SkUnichar > &glyphToUnicode, SkGlyphID glyph)
 
static SkRect get_glyph_bounds_device_space (const SkGlyph *glyph, SkScalar xScale, SkScalar yScale, SkPoint xy, const SkMatrix &ctm)
 
static bool contains (const SkRect &r, SkPoint p)
 
static bool needs_new_font (SkPDFFont *font, const SkGlyph *glyph, SkAdvancedTypefaceMetrics::FontType fontType)
 
static std::vector< SkPDFIndirectReferencesort (const THashSet< SkPDFIndirectReference > &src)
 
static bool treat_as_regular_pdf_blend_mode (SkBlendMode blendMode)
 
static void populate_graphic_state_entry_from_paint (SkPDFDocument *doc, const SkMatrix &matrix, const SkClipStack *clipStack, SkIRect deviceBounds, const SkPaint &paint, const SkMatrix &initialTransform, SkScalar textScale, SkPDFGraphicStackState::Entry *entry, THashSet< SkPDFIndirectReference > *shaderResources, THashSet< SkPDFIndirectReference > *graphicStateResources)
 
static SkSize rect_to_size (const SkRect &r)
 
static sk_sp< SkImagecolor_filter (const SkImage *image, SkColorFilter *colorFilter)
 
static bool is_integer (SkScalar x)
 
static bool is_integral (const SkRect &r)
 

Macro Definition Documentation

◆ SK_PDF_MASK_QUALITY

#define SK_PDF_MASK_QUALITY   50

Definition at line 63 of file SkPDFDevice.cpp.

Function Documentation

◆ add_resource()

static int add_resource ( THashSet< SkPDFIndirectReference > &  resources,
SkPDFIndirectReference  ref 
)
static

Definition at line 149 of file SkPDFDevice.cpp.

149 {
150 resources.add(ref);
151 return ref.fValue;
152}
void add(T item)
Definition SkTHash.h:573

◆ alpha_image_to_greyscale_image()

sk_sp< SkImage > alpha_image_to_greyscale_image ( const SkImage mask)

Definition at line 136 of file SkPDFDevice.cpp.

136 {
137 int w = mask->width(), h = mask->height();
138 SkBitmap greyBitmap;
140 // TODO: support gpu images in pdf
141 if (!mask->readPixels(nullptr, SkImageInfo::MakeA8(w, h),
142 greyBitmap.getPixels(), greyBitmap.rowBytes(), 0, 0)) {
143 return nullptr;
144 }
145 greyBitmap.setImmutable();
146 return greyBitmap.asImage();
147}
@ kOpaque_SkAlphaType
pixel is opaque
Definition SkAlphaType.h:28
@ kGray_8_SkColorType
pixel with grayscale level in 8-bit byte
Definition SkColorType.h:35
void allocPixels(const SkImageInfo &info, size_t rowBytes)
Definition SkBitmap.cpp:258
sk_sp< SkImage > asImage() const
Definition SkBitmap.cpp:645
void setImmutable()
Definition SkBitmap.cpp:400
size_t rowBytes() const
Definition SkBitmap.h:238
void * getPixels() const
Definition SkBitmap.h:283
bool readPixels(GrDirectContext *context, const SkImageInfo &dstInfo, void *dstPixels, size_t dstRowBytes, int srcX, int srcY, CachingHint cachingHint=kAllow_CachingHint) const
Definition SkImage.cpp:42
int width() const
Definition SkImage.h:285
int height() const
Definition SkImage.h:291
SkScalar w
SkScalar h
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
static SkImageInfo MakeA8(int width, int height)

◆ calculate_inverse_path()

static bool calculate_inverse_path ( const SkRect bounds,
const SkPath invPath,
SkPath outPath 
)
static

Definition at line 218 of file SkPDFDevice.cpp.

219 {
220 SkASSERT(invPath.isInverseFillType());
221 return Op(SkPath::Rect(bounds), invPath, kIntersect_SkPathOp, outPath);
222}
#define SkASSERT(cond)
Definition SkAssert.h:116
@ kIntersect_SkPathOp
intersect the two paths
Definition SkPathOps.h:24
bool isInverseFillType() const
Definition SkPath.h:244
static SkPath Rect(const SkRect &, SkPathDirection=SkPathDirection::kCW, unsigned startIndex=0)
Definition SkPath.cpp:3518

◆ clean_paint()

static SkTCopyOnFirstWrite< SkPaint > clean_paint ( const SkPaint srcPaint)
static

Definition at line 191 of file SkPDFDevice.cpp.

191 {
193 // If the paint will definitely draw opaquely, replace kSrc with
194 // kSrcOver. http://crbug.com/473572
195 if (!paint->isSrcOver() &&
197 {
198 paint.writable()->setBlendMode(SkBlendMode::kSrcOver);
199 }
200 if (paint->getColorFilter()) {
201 // We assume here that PDFs all draw in sRGB.
203 }
204 SkASSERT(!paint->getColorFilter());
205 return paint;
206}
SkBlendFastPath CheckFastPath(const SkPaint &paint, bool dstIsOpaque)
@ kSrcOver
r = s + (1-sa)*d
SkColorSpace * sk_srgb_singleton()
static void RemoveColorFilter(SkPaint *, SkColorSpace *dstCS)
const Paint & paint

◆ color_filter()

static sk_sp< SkImage > color_filter ( const SkImage image,
SkColorFilter colorFilter 
)
static

Definition at line 1460 of file SkPDFDevice.cpp.

1461 {
1464 SkCanvas* canvas = surface->getCanvas();
1465 canvas->clear(SK_ColorTRANSPARENT);
1466 SkPaint paint;
1467 paint.setColorFilter(sk_ref_sp(colorFilter));
1468 canvas->drawImage(image, 0, 0, SkSamplingOptions(), &paint);
1469 return surface->makeImageSnapshot();
1470}
constexpr SkColor SK_ColorTRANSPARENT
Definition SkColor.h:99
sk_sp< T > sk_ref_sp(T *obj)
Definition SkRefCnt.h:381
void clear(SkColor color)
Definition SkCanvas.h:1199
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition SkCanvas.h:1528
SkISize dimensions() const
Definition SkImage.h:297
VkSurfaceKHR surface
Definition main.cc:49
sk_sp< SkImage > image
Definition examples.cpp:29
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
static SkImageInfo MakeN32Premul(int width, int height)

◆ contains()

static bool contains ( const SkRect r,
SkPoint  p 
)
static

Definition at line 763 of file SkPDFDevice.cpp.

763 {
764 return r.left() <= p.x() && p.x() <= r.right() &&
765 r.top() <= p.y() && p.y() <= r.bottom();
766}
constexpr float left() const
Definition SkRect.h:734
constexpr float top() const
Definition SkRect.h:741
constexpr float right() const
Definition SkRect.h:748
constexpr float bottom() const
Definition SkRect.h:755

◆ draw_points()

static void draw_points ( SkCanvas::PointMode  mode,
size_t  count,
const SkPoint points,
const SkPaint paint,
const SkIRect bounds,
SkDevice device 
)
static

Definition at line 154 of file SkPDFDevice.cpp.

159 {
160 SkRasterClip rc(bounds);
161 SkDraw draw;
162 draw.fDst = SkPixmap(SkImageInfo::MakeUnknown(bounds.right(), bounds.bottom()), nullptr, 0);
163 draw.fCTM = &device->localToDevice();
164 draw.fRC = &rc;
165 draw.drawPoints(mode, count, points, paint, device);
166}
int count
static const int points[]
static void draw(SkCanvas *canvas, SkRect &target, int x, int y)
Definition aaclip.cpp:27
SkPixmap fDst
Definition SkDrawBase.h:151
VkDevice device
Definition main.cc:53
Optional< SkRect > bounds
Definition SkRecords.h:189
static SkImageInfo MakeUnknown()

◆ get_glyph_bounds_device_space()

static SkRect get_glyph_bounds_device_space ( const SkGlyph glyph,
SkScalar  xScale,
SkScalar  yScale,
SkPoint  xy,
const SkMatrix ctm 
)
static

Definition at line 754 of file SkPDFDevice.cpp.

756 {
757 SkRect glyphBounds = SkMatrix::Scale(xScale, yScale).mapRect(glyph->rect());
758 glyphBounds.offset(xy);
759 ctm.mapRect(&glyphBounds); // now in dev space.
760 return glyphBounds;
761}
SkRect rect() const
Definition SkGlyph.h:506
static SkMatrix Scale(SkScalar sx, SkScalar sy)
Definition SkMatrix.h:75
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
void offset(float dx, float dy)
Definition SkRect.h:1016

◆ is_integer()

static bool is_integer ( SkScalar  x)
static

Definition at line 1474 of file SkPDFDevice.cpp.

1474 {
1475 return x == SkScalarTruncToScalar(x);
1476}
#define SkScalarTruncToScalar(x)
Definition SkScalar.h:33
double x

◆ is_integral()

static bool is_integral ( const SkRect r)
static

Definition at line 1478 of file SkPDFDevice.cpp.

1478 {
1479 return is_integer(r.left()) &&
1480 is_integer(r.top()) &&
1481 is_integer(r.right()) &&
1482 is_integer(r.bottom());
1483}
static bool is_integer(SkScalar x)

◆ map_glyph()

static SkUnichar map_glyph ( const std::vector< SkUnichar > &  glyphToUnicode,
SkGlyphID  glyph 
)
static

Definition at line 743 of file SkPDFDevice.cpp.

743 {
744 return glyph < glyphToUnicode.size() ? glyphToUnicode[SkToInt(glyph)] : -1;
745}
constexpr int SkToInt(S x)
Definition SkTo.h:29

◆ mask_to_greyscale_image()

sk_sp< SkImage > mask_to_greyscale_image ( SkMaskBuilder mask)

Definition at line 110 of file SkPDFDevice.cpp.

110 {
111 sk_sp<SkImage> img;
114 mask->fImage, mask->fRowBytes);
115 const int imgQuality = SK_PDF_MASK_QUALITY;
116 if (imgQuality <= 100 && imgQuality >= 0) {
118 SkJpegEncoder::Options jpegOptions;
119 jpegOptions.fQuality = imgQuality;
120 if (SkJpegEncoder::Encode(&buffer, pm, jpegOptions)) {
121 img = SkImages::DeferredFromEncodedData(buffer.detachAsData());
122 SkASSERT(img);
123 if (img) {
125 }
126 }
127 }
128 if (!img) {
130 pm, [](const void* p, void*) { SkMaskBuilder::FreeImage(const_cast<void*>(p)); }, nullptr);
131 }
132 *mask = SkMaskBuilder(); // destructive;
133 return img;
134}
#define SK_PDF_MASK_QUALITY
static const uint8_t buffer[]
SK_API sk_sp< SkImage > DeferredFromEncodedData(sk_sp< SkData > encoded, std::optional< SkAlphaType > alphaType=std::nullopt)
SK_API sk_sp< SkImage > RasterFromPixmap(const SkPixmap &pixmap, RasterReleaseProc rasterReleaseProc, ReleaseContext releaseContext)
SK_API bool Encode(SkWStream *dst, const SkPixmap &src, const Options &options)
constexpr int32_t height() const
Definition SkRect.h:165
constexpr int32_t width() const
Definition SkRect.h:158
static void FreeImage(void *image)
Definition SkMask.cpp:57
uint8_t *& image()
Definition SkMask.h:236
const uint32_t fRowBytes
Definition SkMask.h:43
uint8_t const *const fImage
Definition SkMask.h:41
const SkIRect fBounds
Definition SkMask.h:42

◆ needs_new_font()

static bool needs_new_font ( SkPDFFont font,
const SkGlyph glyph,
SkAdvancedTypefaceMetrics::FontType  fontType 
)
static

Definition at line 807 of file SkPDFDevice.cpp.

808 {
809 if (!font || !font->hasGlyph(glyph->getGlyphID())) {
810 return true;
811 }
813 return false;
814 }
815 if (glyph->isEmpty()) {
816 return false;
817 }
818
819 bool bitmapOnly = nullptr == glyph->path();
820 bool convertedToType3 = (font->getType() == SkAdvancedTypefaceMetrics::kOther_Font);
821 return convertedToType3 != bitmapOnly;
822}
bool isEmpty() const
Definition SkGlyph.h:514
SkGlyphID getGlyphID() const
Definition SkGlyph.h:429
const SkPath * path() const
Definition SkGlyph.cpp:284
font
Font Metadata and Metrics.

◆ populate_graphic_state_entry_from_paint()

static void populate_graphic_state_entry_from_paint ( SkPDFDocument doc,
const SkMatrix matrix,
const SkClipStack clipStack,
SkIRect  deviceBounds,
const SkPaint paint,
const SkMatrix initialTransform,
SkScalar  textScale,
SkPDFGraphicStackState::Entry entry,
THashSet< SkPDFIndirectReference > *  shaderResources,
THashSet< SkPDFIndirectReference > *  graphicStateResources 
)
static

Definition at line 1182 of file SkPDFDevice.cpp.

1192 {
1193 NOT_IMPLEMENTED(paint.getPathEffect() != nullptr, false);
1194 NOT_IMPLEMENTED(paint.getMaskFilter() != nullptr, false);
1195 NOT_IMPLEMENTED(paint.getColorFilter() != nullptr, false);
1196
1197 entry->fMatrix = matrix;
1198 entry->fClipStackGenID = clipStack ? clipStack->getTopmostGenID()
1200 SkColor4f color = paint.getColor4f();
1201 entry->fColor = {color.fR, color.fG, color.fB, 1};
1202 entry->fShaderIndex = -1;
1203
1204 // PDF treats a shader as a color, so we only set one or the other.
1205 SkShader* shader = paint.getShader();
1206 if (shader) {
1207 // note: we always present the alpha as 1 for the shader, knowing that it will be
1208 // accounted for when we create our newGraphicsState (below)
1209 if (as_SB(shader)->type() == SkShaderBase::ShaderType::kColor) {
1210 auto colorShader = static_cast<SkColorShader*>(shader);
1211 // We don't have to set a shader just for a color.
1212 color = SkColor4f::FromColor(colorShader->color());
1213 entry->fColor = {color.fR, color.fG, color.fB, 1};
1214 } else {
1215 // PDF positions patterns relative to the initial transform, so
1216 // we need to apply the current transform to the shader parameters.
1218 transform.postConcat(initialTransform);
1219
1220 // PDF doesn't support kClamp_TileMode, so we simulate it by making
1221 // a pattern the size of the current clip.
1222 SkRect clipStackBounds = clipStack ? clipStack->bounds(deviceBounds)
1223 : SkRect::Make(deviceBounds);
1224
1225 // We need to apply the initial transform to bounds in order to get
1226 // bounds in a consistent coordinate system.
1227 initialTransform.mapRect(&clipStackBounds);
1229 clipStackBounds.roundOut(&bounds);
1230
1231 auto c = paint.getColor4f();
1232 SkPDFIndirectReference pdfShader = SkPDFMakeShader(doc, shader, transform, bounds,
1233 {c.fR, c.fG, c.fB, 1.0f});
1234
1235 if (pdfShader) {
1236 // pdfShader has been canonicalized so we can directly compare pointers.
1237 entry->fShaderIndex = add_resource(*shaderResources, pdfShader);
1238 }
1239 }
1240 }
1241
1242 SkPDFIndirectReference newGraphicState;
1243 if (color == paint.getColor4f()) {
1244 newGraphicState = SkPDFGraphicState::GetGraphicStateForPaint(doc, paint);
1245 } else {
1246 SkPaint newPaint = paint;
1247 newPaint.setColor4f(color, nullptr);
1248 newGraphicState = SkPDFGraphicState::GetGraphicStateForPaint(doc, newPaint);
1249 }
1250 entry->fGraphicStateIndex = add_resource(*graphicStateResources, newGraphicState);
1251 entry->fTextScaleX = textScale;
1252}
SkColor4f color
static int add_resource(THashSet< SkPDFIndirectReference > &resources, SkPDFIndirectReference ref)
SkPDFIndirectReference SkPDFMakeShader(SkPDFDocument *doc, SkShader *shader, const SkMatrix &canvasTransform, const SkIRect &surfaceBBox, SkColor4f paintColor)
#define NOT_IMPLEMENTED(condition, assert)
Definition SkPDFUtils.h:39
SkShaderBase * as_SB(SkShader *shader)
uint32_t getTopmostGenID() const
static const uint32_t kWideOpenGenID
SkRect bounds(const SkIRect &deviceBounds) const
void setColor4f(const SkColor4f &color, SkColorSpace *colorSpace=nullptr)
Definition SkPaint.h:253
SkPDFIndirectReference GetGraphicStateForPaint(SkPDFDocument *, const SkPaint &)
unsigned useCenter Optional< SkMatrix > matrix
Definition SkRecords.h:258
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
Definition p3.cpp:47
static SkRGBA4f FromColor(SkColor color)
static SkRect Make(const SkISize &size)
Definition SkRect.h:669
void roundOut(SkIRect *dst) const
Definition SkRect.h:1241

◆ rect_to_size()

static SkSize rect_to_size ( const SkRect r)
static

Definition at line 1458 of file SkPDFDevice.cpp.

1458{ return {r.width(), r.height()}; }
constexpr float height() const
Definition SkRect.h:769
constexpr float width() const
Definition SkRect.h:762

◆ set_style()

static void set_style ( SkTCopyOnFirstWrite< SkPaint > *  paint,
SkPaint::Style  style 
)
static

Definition at line 208 of file SkPDFDevice.cpp.

208 {
209 if (paint->get()->getStyle() != style) {
210 paint->writable()->setStyle(style);
211 }
212}
const sk_sp< Effect > & get() const

◆ sort()

static std::vector< SkPDFIndirectReference > sort ( const THashSet< SkPDFIndirectReference > &  src)
static

Definition at line 1029 of file SkPDFDevice.cpp.

1029 {
1030 std::vector<SkPDFIndirectReference> dst;
1031 dst.reserve(src.count());
1032 for (SkPDFIndirectReference ref : src) {
1033 dst.push_back(ref);
1034 }
1035 std::sort(dst.begin(), dst.end(),
1036 [](SkPDFIndirectReference a, SkPDFIndirectReference b) { return a.fValue < b.fValue; });
1037 return dst;
1038}
static bool b
struct MyStruct a[10]
dst
Definition cp.py:12

◆ transform_shader()

static void transform_shader ( SkPaint paint,
const SkMatrix ctm 
)
static

Definition at line 168 of file SkPDFDevice.cpp.

168 {
169 SkASSERT(!ctm.isIdentity());
170#if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)
171 // A shader's matrix is: CTM x LocalMatrix x WrappingLocalMatrix. We want to
172 // switch to device space, where CTM = I, while keeping the original behavior.
173 //
174 // I * LocalMatrix * NewWrappingMatrix = CTM * LocalMatrix
175 // LocalMatrix * NewWrappingMatrix = CTM * LocalMatrix
176 // InvLocalMatrix * LocalMatrix * NewWrappingMatrix = InvLocalMatrix * CTM * LocalMatrix
177 // NewWrappingMatrix = InvLocalMatrix * CTM * LocalMatrix
178 //
180 SkMatrix lmInv;
181 if (lm.invert(&lmInv)) {
182 SkMatrix m = SkMatrix::Concat(SkMatrix::Concat(lmInv, ctm), lm);
183 paint->setShader(paint->getShader()->makeWithLocalMatrix(m));
184 }
185 return;
186#endif
187 paint->setShader(paint->getShader()->makeWithLocalMatrix(ctm));
188}
static SkMatrix Concat(const SkMatrix &a, const SkMatrix &b)
Definition SkMatrix.h:1775
bool invert(SkMatrix *inverse) const
Definition SkMatrix.h:1206
bool isIdentity() const
Definition SkMatrix.h:223
SkMatrix GetShaderLocalMatrix(const SkShader *shader)
Definition SkPDFUtils.h:117

◆ treat_as_regular_pdf_blend_mode()

static bool treat_as_regular_pdf_blend_mode ( SkBlendMode  blendMode)
static

Definition at line 1178 of file SkPDFDevice.cpp.

1178 {
1179 return nullptr != SkPDFUtils::BlendModeName(blendMode);
1180}
const char * BlendModeName(SkBlendMode)