aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/pdf/SkPDFFont.cpp
diff options
context:
space:
mode:
authorGravatar halcanary <halcanary@google.com>2016-08-26 13:17:44 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-08-26 13:17:44 -0700
commit4871f2277738fa7e9232d25424c008b36dae4711 (patch)
tree050146b76e6a7f80cc50c856081ac92110dc1956 /src/pdf/SkPDFFont.cpp
parentab83da71426195dad58a85e2caff213358c8461d (diff)
SkPDF: Glyph validation change
Instead of mapping invaid glyphIDs to zero or maxGlyphID, don't draw them at all. Validate glyphs when glyph is written, not ahead of time. Don't allocate array to copy user-provided glyphs. Easy early exit from SkPDFDevice::internalDrawText() GlyphPositioner::flush() called ~GlyphPositioner() SkScopeExit class now exists. Assume SkTypeface* pointers are now never null in more places. precalculate alignmentFactor to clean up code. SkPDFDevice::updateFont must be called with validated glyphID. Skip bad glyphs to make this true. SkPDFDevice::updateFont always succeeds. SkPDFFont::GetFontResource always succeeds (preconditions are asserted). If GetMetrics fails, don't call GetFontResource. SkPDFFont::glyphsToPDFFontEncodingCount() becomes SkPDFFont::countStretch() and is inlined. SkPDFFont::glyphsToPDFFontEncoding now works one Glyph at a time and is inlined. SkPDFFont::noteGlyphUsage() operates one glyph at a time. Add SkScopeExit.h; also a unit test for it. SkPostConfig: Fix SK_UNUSED for Win32. No public API changes. TBR=reed@google.com BUG=625995 GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2278703002 Review-Url: https://codereview.chromium.org/2278703002
Diffstat (limited to 'src/pdf/SkPDFFont.cpp')
-rw-r--r--src/pdf/SkPDFFont.cpp97
1 files changed, 29 insertions, 68 deletions
diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp
index 389df62fd5..d7ef8123a2 100644
--- a/src/pdf/SkPDFFont.cpp
+++ b/src/pdf/SkPDFFont.cpp
@@ -18,7 +18,6 @@
#include "SkRefCnt.h"
#include "SkScalar.h"
#include "SkStream.h"
-#include "SkTypefacePriv.h"
#include "SkTypes.h"
#include "SkUtils.h"
@@ -148,63 +147,28 @@ static bool can_subset(const SkAdvancedTypefaceMetrics& metrics) {
}
#endif
-int SkPDFFont::glyphsToPDFFontEncoding(SkGlyphID* glyphIDs, int numGlyphs) const {
- // A font with multibyte glyphs will support all glyph IDs in a single font.
- if (this->multiByteGlyphs()) {
- return numGlyphs;
- }
-
- for (int i = 0; i < numGlyphs; i++) {
- if (glyphIDs[i] == 0) {
- continue;
- }
- if (glyphIDs[i] < fFirstGlyphID || glyphIDs[i] > fLastGlyphID) {
- return i;
- }
- glyphIDs[i] -= (fFirstGlyphID - 1);
- }
-
- return numGlyphs;
-}
-
-int SkPDFFont::glyphsToPDFFontEncodingCount(const SkGlyphID* glyphIDs,
- int numGlyphs) const {
- if (this->multiByteGlyphs()) { // A font with multibyte glyphs will
- return numGlyphs; // support all glyph IDs in a single font.
- }
- for (int i = 0; i < numGlyphs; i++) {
- if (glyphIDs[i] != 0 &&
- (glyphIDs[i] < fFirstGlyphID || glyphIDs[i] > fLastGlyphID)) {
- return i;
- }
- }
- return numGlyphs;
-}
-
-
const SkAdvancedTypefaceMetrics* SkPDFFont::GetMetrics(SkTypeface* typeface,
SkPDFCanon* canon) {
- SkFontID id = SkTypeface::UniqueID(typeface);
+ SkASSERT(typeface);
+ SkFontID id = typeface->uniqueID();
if (SkAdvancedTypefaceMetrics** ptr = canon->fTypefaceMetrics.find(id)) {
return *ptr;
}
- sk_sp<SkTypeface> defaultFace;
- if (!typeface) {
- defaultFace = SkTypeface::MakeDefault();
- typeface = defaultFace.get();
+ int count = typeface->countGlyphs();
+ if (count <= 0 || count > 1 + SK_MaxU16) {
+ // Cache nullptr to skip this check. Use SkSafeUnref().
+ canon->fTypefaceMetrics.set(id, nullptr);
+ return nullptr;
}
sk_sp<SkAdvancedTypefaceMetrics> metrics(
typeface->getAdvancedTypefaceMetrics(
SkTypeface::kGlyphNames_PerGlyphInfo | SkTypeface::kToUnicode_PerGlyphInfo,
nullptr, 0));
if (!metrics) {
- if (typeface->countGlyphs() > 0) {
- metrics = sk_make_sp<SkAdvancedTypefaceMetrics>();
- } else {
- SkDEBUGF(("SkPDF: SkTypeface:getAdvancedTypefaceMetrics() returned null.\n"));
- }
- }
- // May cache null to skip this check. use SkSafeUnref.
+ metrics = sk_make_sp<SkAdvancedTypefaceMetrics>();
+ metrics->fLastGlyphID = SkToU16(count - 1);
+ }
+ SkASSERT(metrics->fLastGlyphID == SkToU16(count - 1));
return *canon->fTypefaceMetrics.set(id, metrics.release());
}
@@ -216,7 +180,7 @@ SkAdvancedTypefaceMetrics::FontType font_type(const SkAdvancedTypefaceMetrics& m
return metrics.fType;
}
-static SkGlyphID first_glyph_for_single_byte_encoding(SkGlyphID gid) {
+static SkGlyphID first_nonzero_glyph_for_single_byte_encoding(SkGlyphID gid) {
return gid != 0 ? gid - (gid - 1) % 255 : 1;
}
@@ -224,40 +188,37 @@ SkPDFFont* SkPDFFont::GetFontResource(SkPDFCanon* canon,
SkTypeface* face,
SkGlyphID glyphID) {
SkASSERT(canon);
+ SkASSERT(face); // All SkPDFDevice::internalDrawText ensures this.
const SkAdvancedTypefaceMetrics* fontMetrics = SkPDFFont::GetMetrics(face, canon);
- if (!fontMetrics) {
- return nullptr; // bad font, return early.
- }
+ SkASSERT(fontMetrics); // SkPDFDevice::internalDrawText ensures the typeface is good.
+ // GetMetrics only returns null to signify a bad typeface.
const SkAdvancedTypefaceMetrics& metrics = *fontMetrics;
SkAdvancedTypefaceMetrics::FontType type = font_type(metrics);
bool multibyte = SkPDFFont::IsMultiByte(type);
- SkGlyphID firstGlyph = multibyte ? 0 : first_glyph_for_single_byte_encoding(glyphID);
- uint64_t fontID = (SkTypeface::UniqueID(face) << 16) | firstGlyph;
+ SkGlyphID subsetCode = multibyte ? 0 : first_nonzero_glyph_for_single_byte_encoding(glyphID);
+ uint64_t fontID = (SkTypeface::UniqueID(face) << 16) | subsetCode;
if (SkPDFFont** found = canon->fFontMap.find(fontID)) {
- SkASSERT(multibyte == (*found)->multiByteGlyphs());
- return SkRef(*found);
+ SkPDFFont* foundFont = *found;
+ SkASSERT(foundFont && multibyte == foundFont->multiByteGlyphs());
+ return SkRef(foundFont);
}
- sk_sp<SkTypeface> typeface(face ? sk_ref_sp(face) : SkTypeface::MakeDefault());
+ sk_sp<SkTypeface> typeface(sk_ref_sp(face));
SkASSERT(typeface);
- int glyphCount = typeface->countGlyphs();
- // Validate typeface + glyph;
- if (glyphCount < 1 || // typeface lacks even a NOTDEF glyph.
- glyphCount > 1 + SK_MaxU16 || // invalid glyphCount
- glyphID >= glyphCount) { // invalid glyph
- return nullptr;
- }
+
+ SkGlyphID lastGlyph = metrics.fLastGlyphID;
+ SkASSERT(typeface->countGlyphs() == SkToInt(1 + metrics.fLastGlyphID));
+
+ // should be caught by SkPDFDevice::internalDrawText
+ SkASSERT(glyphID <= lastGlyph);
SkGlyphID firstNonZeroGlyph;
- SkGlyphID lastGlyph;
if (multibyte) {
firstNonZeroGlyph = 1;
- lastGlyph = SkToU16(glyphCount - 1);
} else {
- firstNonZeroGlyph = firstGlyph;
- lastGlyph = SkToU16(SkTMin<int>(glyphCount - 1,
- 254 + (int)firstGlyph));
+ firstNonZeroGlyph = subsetCode;
+ lastGlyph = SkToU16(SkTMin<int>((int)lastGlyph, 254 + (int)subsetCode));
}
SkPDFFont::Info info = {std::move(typeface), firstNonZeroGlyph, lastGlyph, type};
sk_sp<SkPDFFont> font;