55#include <initializer_list>
67static const int32_t kPdfSymbolic = 4;
72 return emSize == 1000 ? scaled : scaled * 1000 / emSize;
75inline SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) {
126 if (count <= 0 || count > 1 + SkTo<int>(UINT16_MAX)) {
131 std::unique_ptr<SkAdvancedTypefaceMetrics> metrics =
typeface->getAdvancedMetrics();
133 metrics = std::make_unique<SkAdvancedTypefaceMetrics>();
136 if (0 == metrics->fStemV || 0 == metrics->fCapHeight) {
141 if (0 == metrics->fStemV) {
144 int16_t stemV = SHRT_MAX;
145 for (
char c : {
'i',
'I',
'!',
'1'}) {
146 uint16_t g =
font.unicharToGlyph(c);
151 metrics->fStemV = stemV;
153 if (0 == metrics->fCapHeight) {
156 for (
char c : {
'M',
'X'}) {
157 uint16_t g =
font.unicharToGlyph(c);
160 capHeight +=
bounds.height();
201 return metrics.
fType;
205 return gid != 0 ? gid - (gid - 1) % 255 : 1;
224 uint64_t typefaceID = (
static_cast<uint64_t
>(face->
uniqueID()) << 16) | subsetCode;
227 SkASSERT(multibyte == found->multiByteGlyphs());
241 firstNonZeroGlyph = 1;
243 firstNonZeroGlyph = subsetCode;
244 lastGlyph =
SkToU16(std::min<int>((
int)lastGlyph, 254 + (
int)subsetCode));
256 : fTypeface(
std::move(typeface))
257 , fGlyphUsage(firstGlyphID, lastGlyphID)
258 , fIndirectReference(indirectReference)
259 , fFontType(fontType)
268 int16_t defaultWidth) {
270 descriptor->
insertInt(
"Flags", (
size_t)(metrics.
fStyle | kPdfSymbolic));
272 scaleFromFontUnits(metrics.
fAscent, emSize));
274 scaleFromFontUnits(metrics.
fDescent, emSize));
276 scaleFromFontUnits(metrics.
fStemV, emSize));
278 scaleFromFontUnits(metrics.
fCapHeight, emSize));
282 scaleFromFontUnits(metrics.
fBBox.
bottom(), emSize),
283 scaleFromFontUnits(metrics.
fBBox.
right(), emSize),
284 scaleFromFontUnits(metrics.
fBBox.
top(), emSize)));
285 if (defaultWidth > 0) {
287 scaleFromFontUnits(defaultWidth, emSize));
308 uint16_t emSize =
SkToU16(
font.typeface()->getUnitsPerEm());
312 std::unique_ptr<SkStreamAsset> fontAsset = face->
openStream(&ttcIndex);
313 size_t fontSize = fontAsset ? fontAsset->getLength() : 0;
315 SkDebugf(
"Error: (SkTypeface)(%p)::openStream() returned "
316 "empty stream (%p) when identified as kType1CID_Font "
317 "or kTrueType_Font.\n", face, fontAsset.get());
326 std::unique_ptr<SkStreamAsset> subsetFontAsset;
327 if (subsetFontData) {
331 subsetFontAsset = std::move(fontAsset);
334 streamDict->insertInt(
"Length1", subsetFontAsset->getLength());
335 const char* fontFileKey;
337 fontFileKey =
"FontFile2";
339 streamDict->insertName(
"Subtype",
"OpenType");
340 fontFileKey =
"FontFile3";
342 descriptor->insertRef(fontFileKey,
347 streamDict->insertName(
"Subtype",
"CIDFontType0C");
348 descriptor->insertRef(
"FontFile3",
356 newCIDFont->insertRef(
"FontDescriptor", doc->
emit(*descriptor));
361 newCIDFont->insertName(
"Subtype",
"CIDFontType0");
364 newCIDFont->insertName(
"Subtype",
"CIDFontType0");
365 newCIDFont->insertName(
"CIDToGIDMap",
"Identity");
368 newCIDFont->insertName(
"Subtype",
"CIDFontType2");
369 newCIDFont->insertName(
"CIDToGIDMap",
"Identity");
376 sysInfo->insertByteString(
"Registry",
"Adobe");
377 sysInfo->insertByteString(
"Ordering",
"Identity");
378 sysInfo->insertInt(
"Supplement", 0);
379 newCIDFont->insertObject(
"CIDSystemInfo", std::move(sysInfo));
382 int32_t defaultWidth = 0;
385 *face,
font.glyphUsage(), &defaultWidth);
387 newCIDFont->insertObject(
"W", std::move(
widths));
389 newCIDFont->insertInt(
"DW", defaultWidth);
397 fontDict.
insertName(
"Encoding",
"Identity-H");
399 descendantFonts->appendRef(doc->
emit(*newCIDFont));
400 fontDict.
insertObject(
"DescendantFonts", std::move(descendantFonts));
402 const std::vector<SkUnichar>& glyphToUnicode =
405 std::unique_ptr<SkStreamAsset> toUnicode =
408 font.multiByteGlyphs(),
413 doc->
emit(fontDict,
font.indirectReference());
422struct SingleByteGlyphIdIterator {
424 : fFirst(first), fLast(last) {
430 fCurrent = (0 == fCurrent) ? fFirst : fCurrent + 1;
435 return fCurrent != rhs.fCurrent;
437 Iter(
SkGlyphID f,
int c) : fFirst(
f), fCurrent(c) {}
442 Iter
begin()
const {
return Iter(fFirst, 0); }
443 Iter
end()
const {
return Iter(fFirst, (
int)fLast + 1); }
458 return {
nullptr, {0, 0}};
466 for (
int x8 = 0; x8 < bm.
width(); x8 += 8) {
469 for (
int x = x8;
x <
e; ++
x) {
470 *bm.
getAddr8(
x,
y) = (v >> (
x & 0x7)) & 0x1 ? 0xFF : 0x00;
492 return {
nullptr, {0, 0}};
504 int32_t fontDescriptorFlags = kPdfSymbolic;
514 static constexpr const char* stretchNames[9] = {
525 const char* stretchName = stretchNames[typeface->
fontStyle().
width() - 1];
526 descriptor.
insertName(
"FontStretch", stretchName);
534 descriptor.
insertName(
"FontName", metrics->fPostScriptName);
535 descriptor.
insertInt(
"ItalicAngle", metrics->fItalicAngle);
536 fontDescriptorFlags |= (int32_t)metrics->fStyle;
539 if (metrics->fCapHeight != 0) { descriptor.
insertInt(
"CapHeight", metrics->fCapHeight); }
540 if (metrics->fStemV != 0) { descriptor.
insertInt(
"StemV", metrics->fStemV); }
545 descriptor.
insertInt(
"Flags", fontDescriptorFlags);
551#ifdef SK_PDF_BITMAP_GLYPH_RASTER_SIZE
552static constexpr float kBitmapFontSize = SK_PDF_BITMAP_GLYPH_RASTER_SIZE;
573 SkASSERT(lastGlyphID >= firstGlyphID);
576 while (lastGlyphID > firstGlyphID && !subset.
has(lastGlyphID)) {
584 SkScalar xHeight = strike->getFontMetrics().fXHeight;
595 font.insertName(
"Subtype",
"Type3");
608 SkASSERT(lastGlyphID >= firstGlyphID);
609 int glyphCount = lastGlyphID - firstGlyphID + 2;
611 encDiffs->reserve(glyphCount + 1);
612 encDiffs->appendInt(0);
615 widthArray->reserve(glyphCount);
619 std::vector<std::pair<SkGlyphID, SkPDFIndirectReference>> imageGlyphs;
620 for (
SkGlyphID gID : SingleByteGlyphIdIterator(firstGlyphID, lastGlyphID)) {
621 bool skipGlyph = gID != 0 && !subset.
has(gID);
626 characterName.
set(
"g0");
628 characterName.
printf(
"g%X", gID);
630 const SkGlyph* drawableGlyph = metricsAndDrawables.
glyph(gID);
632 glyphBBox = pathGlyph->
iRect();
633 bbox.
join(glyphBBox);
647 imageGlyphs.emplace_back(gID, xobject);
649 content.writeText(
" 0 d0\n1 0 0 1 0 0 cm\n/X");
652 }
else if (
path && !
path->isEmpty()) {
653 setGlyphWidthAndBoundingBox(pathGlyph->
advanceX(), glyphBBox, &
content);
657 auto pimg =
to_image(gID, &smallGlyphs);
659 setGlyphWidthAndBoundingBox(pathGlyph->
advanceX(), glyphBBox, &
content);
671 AppendScalar((pimg.fImage->height() + pimg.fOffset.y()) * bitmapScale,
679 content.detachAsStream(), doc));
681 encDiffs->appendName(std::move(characterName));
682 widthArray->appendScalar(advance);
685 if (!imageGlyphs.empty()) {
687 for (
const auto& pair : imageGlyphs) {
691 d1->insertObject(
"XObject", std::move(d0));
692 font.insertObject(
"Resources", std::move(d1));
695 encoding->insertObject(
"Differences", std::move(encDiffs));
696 font.insertInt(
"FirstChar", 0);
697 font.insertInt(
"LastChar", lastGlyphID - firstGlyphID + 1);
708 font.insertName(
"CIDToGIDMap",
"Identity");
719 font.insertObject(
"Widths", std::move(widthArray));
720 font.insertObject(
"Encoding", std::move(encoding));
721 font.insertObject(
"CharProcs", std::move(charProcs));
732#ifndef SK_PDF_DO_NOT_SUPPORT_TYPE_1_FONTS
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
@ kNone
glyph outlines unchanged
SkPDFIndirectReference SkPDFSerializeImage(const SkImage *img, SkPDFDocument *doc, int encodingQuality)
SkStrikeSpec make_small_strike(const SkTypeface &typeface)
static SkPDFIndirectReference type3_descriptor(SkPDFDocument *doc, const SkTypeface *typeface, SkScalar xHeight)
static ImageAndOffset to_image(SkGlyphID gid, SkBulkGlyphMetricsAndImages *smallGlyphs)
static bool can_subset(const SkAdvancedTypefaceMetrics &metrics)
static void emit_subset_type3(const SkPDFFont &pdfFont, SkPDFDocument *doc)
static void emit_subset_type0(const SkPDFFont &font, SkPDFDocument *doc)
static constexpr float kBitmapFontSize
static SkGlyphID first_nonzero_glyph_for_single_byte_encoding(SkGlyphID gid)
static bool can_embed(const SkAdvancedTypefaceMetrics &metrics)
std::unique_ptr< SkPDFArray > SkPDFMakeCIDGlyphWidthsArray(const SkTypeface &typeface, const SkPDFGlyphUse &subset, int32_t *defaultAdvance)
std::unique_ptr< SkStreamAsset > SkPDFMakeToUnicodeCmap(const SkUnichar *glyphToUnicode, const SkPDFGlyphUse *subset, bool multiByteGlyphs, SkGlyphID firstGlyphID, SkGlyphID lastGlyphID)
sk_sp< SkData > SkPDFSubsetFont(const SkTypeface &, const SkPDFGlyphUse &)
void SkPDFEmitType1Font(const SkPDFFont &pdfFont, SkPDFDocument *doc)
static SkScalar from_font_units(SkScalar scaled, uint16_t emSize)
SkPDFIndirectReference SkPDFStreamOut(std::unique_ptr< SkPDFDict > dict, std::unique_ptr< SkStreamAsset > content, SkPDFDocument *doc, SkPDFSteamCompressionEnabled compress)
static std::unique_ptr< SkPDFDict > SkPDFMakeDict(const char *type=nullptr)
static std::unique_ptr< SkPDFArray > SkPDFMakeArray(Args... args)
sk_sp< T > sk_ref_sp(T *obj)
#define SkScalarInvert(x)
#define SkScalarRoundToInt(x)
@ kFakeGammaAndBoostContrast
SK_API SkString SkStringPrintf(const char *format,...) SK_PRINTF_LIKE(1
Creates a new string and writes into it using a printf()-style format.
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
constexpr size_t SkToSizeT(S x)
constexpr uint16_t SkToU16(S x)
static constexpr bool SkToBool(const T &x)
constexpr int16_t SkToS16(S x)
static constexpr SkFourByteTag SkSetFourByteTag(char a, char b, char c, char d)
void allocPixels(const SkImageInfo &info, size_t rowBytes)
sk_sp< SkImage > asImage() const
uint8_t * getAddr8(int x, int y) const
const SkGlyph * glyph(SkGlyphID glyphID)
const SkGlyph * glyph(SkPackedGlyphID packedID)
const SkGlyph * glyph(SkGlyphID glyphID)
void translate(SkScalar dx, SkScalar dy)
void drawDrawable(SkDrawable *drawable, const SkMatrix *matrix=nullptr)
static sk_sp< SkData > MakeWithCopy(const void *data, size_t length)
@ kAlias
no transparent pixels on glyph edges
SkGlyphID getGlyphID() const
const SkPath * path() const
SkScalar advanceX() const
SkDrawable * drawable() const
static SkMatrix Translate(SkScalar dx, SkScalar dy)
SkMatrix & setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
static const SkMatrix & I()
static std::unique_ptr< SkMemoryStream > Make(sk_sp< SkData > data)
std::unique_ptr< SkStreamAsset > content()
std::unique_ptr< SkPDFDict > makeResourceDict()
void insertName(const char key[], const char nameValue[])
void insertObject(const char key[], std::unique_ptr< SkPDFObject > &&)
void insertInt(const char key[], int32_t value)
void insertRef(const char key[], SkPDFIndirectReference)
void insertScalar(const char key[], SkScalar value)
void insertByteString(const char key[], const char value[])
SkPDFIndirectReference emit(const SkPDFObject &, SkPDFIndirectReference)
skia_private::THashMap< uint64_t, SkPDFFont > fFontMap
skia_private::THashMap< uint32_t, std::vector< SkUnichar > > fToUnicodeMap
SkString nextFontSubsetTag()
skia_private::THashMap< uint32_t, SkPDFIndirectReference > fType3FontDescriptors
SkPDFIndirectReference reserveRef()
skia_private::THashMap< uint32_t, std::unique_ptr< SkAdvancedTypefaceMetrics > > fTypefaceMetrics
void noteGlyphUsage(SkGlyphID glyph)
static const SkAdvancedTypefaceMetrics * GetMetrics(const SkTypeface *typeface, SkPDFDocument *canon)
static void PopulateCommonFontDescriptor(SkPDFDict *descriptor, const SkAdvancedTypefaceMetrics &, uint16_t emSize, int16_t defaultWidth)
static SkPDFFont * GetFontResource(SkPDFDocument *doc, const SkGlyph *glyphs, SkTypeface *typeface)
SkPDFIndirectReference indirectReference() const
static SkAdvancedTypefaceMetrics::FontType FontType(const SkTypeface &, const SkAdvancedTypefaceMetrics &)
static bool IsMultiByte(SkAdvancedTypefaceMetrics::FontType type)
static const std::vector< SkUnichar > & GetUnicodeMap(const SkTypeface *typeface, SkPDFDocument *canon)
SkPDFFont & operator=(SkPDFFont &&)
SkGlyphID lastGlyphID() const
SkGlyphID firstGlyphID() const
void emitSubset(SkPDFDocument *) const
const SkPDFGlyphUse & glyphUsage() const
static void GetType1GlyphNames(const SkTypeface &, SkString *)
SkTypeface * typeface() const
static bool CanEmbedTypeface(SkTypeface *, SkPDFDocument *)
bool has(SkGlyphID gid) const
@ kFill_Style
set to fill geometry
static SkStrikeSpec MakeMask(const SkFont &font, const SkPaint &paint, const SkSurfaceProps &surfaceProps, SkScalerContextFlags scalerContextFlags, const SkMatrix &deviceMatrix)
sk_sp< SkStrike > findOrCreateStrike() const
static SkStrikeSpec MakePDFVector(const SkTypeface &typeface, int *size)
void printf(const char format[],...) SK_PRINTF_LIKE(2
void set(const SkString &src)
const char * c_str() const
virtual void getPostScriptGlyphNames(SkString *) const =0
SkTypefaceID uniqueID() const
virtual void getGlyphToUnicodeMap(SkUnichar *dstArray) const =0
void getFamilyName(SkString *name) const
SkFontStyle fontStyle() const
size_t getTableSize(SkFontTableTag) const
std::unique_ptr< SkStreamAsset > openStream(int *ttcIndex) const
V * find(const K &key) const
static const char * begin(const StringSlice &s)
static float min(float r, float g, float b)
union flutter::testing::@2836::KeyboardChange::@76 content
SK_API sk_sp< SkImage > RasterFromData(const SkImageInfo &info, sk_sp< SkData > pixels, size_t rowBytes)
std::unique_ptr< SkPDFArray > MatrixToArray(const SkMatrix &matrix)
void EmitPath(const SkPath &path, SkPaint::Style paintStyle, bool doConsumeDegerates, SkWStream *content, SkScalar tolerance=0.25f)
void PaintPath(SkPaint::Style style, SkPathFillType fill, SkWStream *content)
void AppendScalar(SkScalar value, SkWStream *stream)
Optional< SkRect > bounds
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
bool operator!=(C p1, const scoped_nsprotocol< C > &p2)
font
Font Metadata and Metrics.
constexpr Color operator*(T value, const Color &c)
@ kNotEmbeddable_FontFlag
May not be embedded.
@ kAltDataFormat_FontFlag
Data compressed. Table access may still work.
@ kNotSubsettable_FontFlag
May not be subset.
@ kVariable_FontFlag
May be true for Type1, CFF, or TrueType fonts.
int32_t fBottom
larger y-axis bounds
constexpr int32_t top() const
constexpr SkISize size() const
constexpr int32_t bottom() const
constexpr int32_t height() const
constexpr int32_t right() const
int32_t fTop
smaller y-axis bounds
void join(const SkIRect &r)
static constexpr SkIRect MakeEmpty()
constexpr int32_t width() const
int32_t fLeft
smaller x-axis bounds
constexpr int32_t left() const
int32_t fRight
larger x-axis bounds
static SkImageInfo MakeN32Premul(int width, int height)
static SkImageInfo MakeA8(int width, int height)
@ k3D_Format
3 8bit per pixl planes: alpha, mul, add
@ kA8_Format
8bits per pixel mask (e.g. antialiasing)
@ kLCD16_Format
565 alpha for r/g/b
@ kARGB32_Format
SkPMColor.
@ kBW_Format
1bit per pixel mask (e.g. monochrome)
const uint8_t * getAddr1(int x, int y) const
uint8_t const *const fImage
size_t computeTotalImageSize() const