From 31dcee7b84ac8a50fe8269a39ac0431b01da48d1 Mon Sep 17 00:00:00 2001 From: "vandebo@chromium.org" Date: Sat, 23 Jul 2011 21:13:30 +0000 Subject: Revert "[PDF] Refactor SkPDFFont to enable font/cmap subsetting." The PDF xref table is corrupt with this change. Revert until we figure it out. Review URL: http://codereview.appspot.com/4803049 git-svn-id: http://skia.googlecode.com/svn/trunk@1944 2bbb7eff-a529-9590-31e7-b0007b416f81 --- gyp/pdf.gyp | 3 +- include/pdf/SkBitSet.h | 6 +- include/pdf/SkPDFDevice.h | 19 +- include/pdf/SkPDFDocument.h | 1 - include/pdf/SkPDFFont.h | 172 ++++------ include/pdf/SkPDFPage.h | 5 - src/pdf/SkBitSet.cpp | 4 +- src/pdf/SkPDFDevice.cpp | 31 +- src/pdf/SkPDFDocument.cpp | 28 -- src/pdf/SkPDFFont.cpp | 776 ++++++++++++++++---------------------------- src/pdf/SkPDFFontImpl.h | 90 ----- src/pdf/SkPDFPage.cpp | 4 - 12 files changed, 355 insertions(+), 784 deletions(-) mode change 100644 => 100755 src/pdf/SkPDFFont.cpp delete mode 100755 src/pdf/SkPDFFontImpl.h diff --git a/gyp/pdf.gyp b/gyp/pdf.gyp index f0c6b47e1f..f0c39372ab 100644 --- a/gyp/pdf.gyp +++ b/gyp/pdf.gyp @@ -27,12 +27,11 @@ '../include/pdf/SkPDFTypes.h', '../include/pdf/SkPDFUtils.h', - '../src/pdf/SkBitSet.cpp', + '../src/pdf/SkBitSet.cpp', '../src/pdf/SkPDFCatalog.cpp', '../src/pdf/SkPDFDevice.cpp', '../src/pdf/SkPDFDocument.cpp', '../src/pdf/SkPDFFont.cpp', - '../src/pdf/SkPDFFontImpl.h', '../src/pdf/SkPDFFormXObject.cpp', '../src/pdf/SkPDFGraphicState.cpp', '../src/pdf/SkPDFImage.cpp', diff --git a/include/pdf/SkBitSet.h b/include/pdf/SkBitSet.h index 01d9c6cf3a..84d52e547c 100755 --- a/include/pdf/SkBitSet.h +++ b/include/pdf/SkBitSet.h @@ -40,12 +40,12 @@ public: /** Test if bit index is set. */ - bool isBitSet(int index) const; + bool isBitSet(int index); /** Or bits from source. false is returned if this doesn't have the same * bit count as source. */ - bool orBits(const SkBitSet& source); + bool orBits(SkBitSet& source); private: SkAutoFree fBitData; @@ -53,7 +53,7 @@ private: size_t fDwordCount; size_t fBitCount; - uint32_t* internalGet(int index) const { + uint32_t* internalGet(int index) { SkASSERT((size_t)index < fBitCount); size_t internalIndex = index / 32; SkASSERT(internalIndex < fDwordCount); diff --git a/include/pdf/SkPDFDevice.h b/include/pdf/SkPDFDevice.h index 1a0807aa67..7a3e7bb7f1 100644 --- a/include/pdf/SkPDFDevice.h +++ b/include/pdf/SkPDFDevice.h @@ -30,7 +30,6 @@ class SkPDFDevice; class SkPDFDict; class SkPDFFont; class SkPDFFormXObject; -class SkPDFGlyphSetMap; class SkPDFGraphicState; class SkPDFObject; class SkPDFShader; @@ -151,18 +150,11 @@ public: * for calling data->unref() when it is finished. */ SK_API SkData* copyContentToData() const; - + SK_API const SkMatrix& initialTransform() const { return fInitialTransform; } - /** Returns a SkPDFGlyphSetMap which represents glyph usage of every font - * that shows on this device. - */ - const SkPDFGlyphSetMap& getFontGlyphUsage() const { - return *(fFontGlyphUsage.get()); - } - private: // TODO(vandebo) push most of SkPDFDevice's state into a core object in // order to get the right access levels without using friend. @@ -191,20 +183,17 @@ private: ContentEntry* getLastContentEntry(); void setLastContentEntry(ContentEntry* contentEntry); - // Glyph ids used for each font on this device. - SkTScopedPtr fFontGlyphUsage; - SkPDFDevice(const SkISize& layerSize, const SkClipStack& existingClipStack, const SkRegion& existingClipRegion); // override from SkDevice - virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config, - int width, int height, + virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config, + int width, int height, bool isOpaque, Usage usage); void init(); - void cleanUp(bool clearFontUsage); + void cleanUp(); void createFormXObjectFromDevice(SkRefPtr* xobject); // Clear the passed clip from all existing content entries. diff --git a/include/pdf/SkPDFDocument.h b/include/pdf/SkPDFDocument.h index 8b472e1bd0..3f171f5f27 100644 --- a/include/pdf/SkPDFDocument.h +++ b/include/pdf/SkPDFDocument.h @@ -81,7 +81,6 @@ private: SkTDArray fPageTree; SkRefPtr fDocCatalog; SkTDArray fPageResources; - SkTDArray fSubstitutes; int fSecondPageFirstResourceIndex; SkRefPtr fTrailerDict; diff --git a/include/pdf/SkPDFFont.h b/include/pdf/SkPDFFont.h index 00dcb95a6a..182f27d062 100644 --- a/include/pdf/SkPDFFont.h +++ b/include/pdf/SkPDFFont.h @@ -18,63 +18,11 @@ #define SkPDFFont_DEFINED #include "SkAdvancedTypefaceMetrics.h" -#include "SkBitSet.h" #include "SkPDFTypes.h" #include "SkTDArray.h" #include "SkThread.h" -#include "SkTypeface.h" class SkPaint; -class SkPDFCatalog; -class SkPDFFont; - -class SkPDFGlyphSet : public SkNoncopyable { -public: - SkPDFGlyphSet(); - - void set(const uint16_t* glyphIDs, int numGlyphs); - bool has(uint16_t glyphID) const; - void merge(const SkPDFGlyphSet& usage); - -private: - SkBitSet fBitSet; -}; - -class SkPDFGlyphSetMap : public SkNoncopyable { -public: - struct FontGlyphSetPair { - FontGlyphSetPair(SkPDFFont* font, SkPDFGlyphSet* glyphSet); - - SkPDFFont* fFont; - SkPDFGlyphSet* fGlyphSet; - }; - - SkPDFGlyphSetMap(); - ~SkPDFGlyphSetMap(); - - class F2BIter { - public: - F2BIter(const SkPDFGlyphSetMap& map); - FontGlyphSetPair* next() const; - void reset(const SkPDFGlyphSetMap& map); - - private: - const SkTDArray* fMap; - mutable int fIndex; - }; - - void merge(const SkPDFGlyphSetMap& usage); - void reset(); - - void noteGlyphUsage(SkPDFFont* font, const uint16_t* glyphIDs, - int numGlyphs); - -private: - SkPDFGlyphSet* getGlyphSetForFont(SkPDFFont* font); - - SkTDArray fMap; -}; - /** \class SkPDFFont A PDF Object class representing a font. The font may have resources @@ -97,16 +45,16 @@ public: /** Returns the font type represented in this font. For Type0 fonts, * returns the type of the decendant font. */ - SK_API virtual SkAdvancedTypefaceMetrics::FontType getType(); - - /** Returns true if this font encoding supports glyph IDs above 255. - */ - SK_API virtual bool multiByteGlyphs() const = 0; + SK_API SkAdvancedTypefaceMetrics::FontType getType(); /** Return true if this font has an encoding for the passed glyph id. */ SK_API bool hasGlyph(uint16_t glyphID); + /** Returns true if this font encoding supports glyph IDs above 255. + */ + SK_API bool multiByteGlyphs(); + /** Convert (in place) the input glyph IDs into the font encoding. If the * font has more glyphs than can be encoded (like a type 1 font with more * than 255 glyphs) this method only converts up to the first out of range @@ -128,64 +76,13 @@ public: SK_API static SkPDFFont* GetFontResource(SkTypeface* typeface, uint16_t glyphID); - /** Subset the font based on usage set. Returns a SkPDFFont instance with - * subset. - * @param usage Glyph subset requested. - * @return NULL if font does not support subsetting, a new instance - * of SkPDFFont otherwise. - */ - SK_API virtual SkPDFFont* getFontSubset(const SkPDFGlyphSet* usage); - -protected: - // Common constructor to handle common members. - SkPDFFont(SkAdvancedTypefaceMetrics* fontInfo, SkTypeface* typeface, - uint16_t glyphID, bool descendantFont); - - // Accessors for subclass. - SkAdvancedTypefaceMetrics* fontInfo(); - uint16_t firstGlyphID() const; - uint16_t lastGlyphID() const; - void setLastGlyphID(uint16_t glyphID); - - // Add object to resource list. - void addResource(SkPDFObject* object); - - // Accessors for FontDescriptor associated with this object. - SkPDFDict* getFontDescriptor(); - void setFontDescriptor(SkPDFDict* descriptor); - - // Add common entries to FontDescriptor. - bool addCommonFontDescriptorEntries(int16_t defaultWidth); - - /** Set fFirstGlyphID and fLastGlyphID to span at most 255 glyphs, - * including the passed glyphID. - */ - void adjustGlyphRangeForSingleByteEncoding(int16_t glyphID); - - // Generate ToUnicode table according to glyph usage subset. - // If subset is NULL, all available glyph ids will be used. - void populateToUnicodeTable(const SkPDFGlyphSet* subset); - - // Create instances of derived types based on fontInfo. - static SkPDFFont* Create(SkAdvancedTypefaceMetrics* fontInfo, - SkTypeface* typeface, uint16_t glyphID, - SkPDFDict* fontDescriptor); - - static bool Find(uint32_t fontID, uint16_t glyphID, int* index); - private: - class FontRec { - public: - SkPDFFont* fFont; - uint32_t fFontID; - uint16_t fGlyphID; - - // A fGlyphID of 0 with no fFont always matches. - bool operator==(const FontRec& b) const; - FontRec(SkPDFFont* font, uint32_t fontID, uint16_t fGlyphID); - }; - SkRefPtr fTypeface; + SkAdvancedTypefaceMetrics::FontType fType; +#ifdef SK_DEBUG + bool fDescendant; +#endif + bool fMultiByteGlyphs; // The glyph IDs accessible with this font. For Type1 (non CID) fonts, // this will be a subset if the font has more than 255 glyphs. @@ -197,11 +94,58 @@ private: SkTDArray fResources; SkRefPtr fDescriptor; - SkAdvancedTypefaceMetrics::FontType fFontType; + class FontRec { + public: + SkPDFFont* fFont; + uint32_t fFontID; + uint16_t fGlyphID; + + // A fGlyphID of 0 with no fFont always matches. + bool operator==(const FontRec& b) const; + FontRec(SkPDFFont* font, uint32_t fontID, uint16_t fGlyphID); + }; // This should be made a hash table if performance is a problem. static SkTDArray& CanonicalFonts(); static SkMutex& CanonicalFontsMutex(); + + /** Construct a new font dictionary and support objects. + * @param fontInfo Information about the to create. + * @param typeface The typeface for the font. + * @param glyphID The glyph ID the caller is interested in. This + * is important only for Type1 fonts, which have + * more than 255 glyphs. + * @param descendantFont If this is the descendant (true) or root + * (Type 0 font - false) font dictionary. Only True + * Type and CID encoded fonts will use a true value. + * @param fontDescriptor If the font descriptor has already have generated + * for this font, pass it in here, otherwise pass + * NULL. + */ + SkPDFFont(class SkAdvancedTypefaceMetrics* fontInfo, SkTypeface* typeface, + uint16_t glyphID, bool descendantFont, SkPDFDict* fontDescriptor); + + void populateType0Font(); + void populateCIDFont(); + bool populateType1Font(int16_t glyphID); + + /** Populate the PDF font dictionary as Type3 font which includes glyph + * descriptions with instructions for painting the glyphs. This function + * doesn't use any fields from SkAdvancedTypefaceMetrics (fFontInfo). Font + * information including glyph paths are queried from the platform + * dependent SkGlyphCache. + */ + void populateType3Font(int16_t glyphID); + bool addFontDescriptor(int16_t defaultWidth); + void populateToUnicodeTable(); + void addWidthInfoFromRange(int16_t defaultWidth, + const SkAdvancedTypefaceMetrics::WidthRange* widthRangeEntry); + /** Set fFirstGlyphID and fLastGlyphID to span at most 255 glyphs, + * including the passed glyphID. + */ + void adjustGlyphRangeForSingleByteEncoding(int16_t glyphID); + + static bool Find(uint32_t fontID, uint16_t glyphID, int* index); }; #endif diff --git a/include/pdf/SkPDFPage.h b/include/pdf/SkPDFPage.h index 7a9505bbed..a3978744e7 100644 --- a/include/pdf/SkPDFPage.h +++ b/include/pdf/SkPDFPage.h @@ -90,11 +90,6 @@ public: */ SK_API const SkTDArray& getFontResources() const; - /** Returns a SkPDFGlyphSetMap which represents glyph usage of every font - * that shows on this page. - */ - const SkPDFGlyphSetMap& getFontGlyphUsage() const; - private: // Multiple pages may reference the content. SkRefPtr fDevice; diff --git a/src/pdf/SkBitSet.cpp b/src/pdf/SkBitSet.cpp index c7af832b43..f19dd69a51 100755 --- a/src/pdf/SkBitSet.cpp +++ b/src/pdf/SkBitSet.cpp @@ -73,12 +73,12 @@ void SkBitSet::setBit(int index, bool value) { } } -bool SkBitSet::isBitSet(int index) const { +bool SkBitSet::isBitSet(int index) { uint32_t mask = 1 << (index % 32); return (*internalGet(index) & mask); } -bool SkBitSet::orBits(const SkBitSet& source) { +bool SkBitSet::orBits(SkBitSet& source) { if (fBitCount != source.fBitCount) { return false; } diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index e2dfba6941..619d55d4c1 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -424,8 +424,8 @@ void GraphicStackState::updateDrawingState(const GraphicStateEntry& state) { } } -SkDevice* SkPDFDevice::onCreateCompatibleDevice(SkBitmap::Config config, - int width, int height, +SkDevice* SkPDFDevice::onCreateCompatibleDevice(SkBitmap::Config config, + int width, int height, bool isOpaque, Usage usage) { SkMatrix initialTransform; @@ -544,7 +544,7 @@ SkPDFDevice::SkPDFDevice(const SkISize& layerSize, } SkPDFDevice::~SkPDFDevice() { - this->cleanUp(true); + this->cleanUp(); } void SkPDFDevice::init() { @@ -553,24 +553,18 @@ void SkPDFDevice::init() { fLastContentEntry = NULL; fMarginContentEntries.reset(); fLastMarginContentEntry = NULL; - fDrawingArea = kContent_DrawingArea; - if (fFontGlyphUsage == NULL) { - fFontGlyphUsage.reset(new SkPDFGlyphSetMap()); - } + fDrawingArea = kContent_DrawingArea; } -void SkPDFDevice::cleanUp(bool clearFontUsage) { +void SkPDFDevice::cleanUp() { fGraphicStateResources.unrefAll(); fXObjectResources.unrefAll(); fFontResources.unrefAll(); fShaderResources.unrefAll(); - if (clearFontUsage) { - fFontGlyphUsage->reset(); - } } void SkPDFDevice::clear(SkColor color) { - this->cleanUp(true); + this->cleanUp(); this->init(); SkPaint paint; @@ -831,8 +825,6 @@ void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len, size_t availableGlyphs = font->glyphsToPDFFontEncoding(glyphIDs + consumedGlyphCount, numGlyphs - consumedGlyphCount); - fFontGlyphUsage->noteGlyphUsage(font, glyphIDs + consumedGlyphCount, - availableGlyphs); SkString encodedString = SkPDFString::FormatString(glyphIDs + consumedGlyphCount, availableGlyphs, font->multiByteGlyphs()); @@ -901,7 +893,6 @@ void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len, i--; continue; } - fFontGlyphUsage->noteGlyphUsage(font, &encodedValue, 1); SkScalar x = pos[i * scalarsPerPos]; SkScalar y = scalarsPerPos == 1 ? constY : pos[i * scalarsPerPos + 1]; align_text(glyphCacheProc, textPaint, glyphIDs + i, 1, &x, &y, NULL); @@ -961,9 +952,6 @@ void SkPDFDevice::drawDevice(const SkDraw& d, SkDevice* device, int x, int y, fXObjectResources.push(xobject); // Transfer reference. SkPDFUtils::DrawFormXObject(fXObjectResources.count() - 1, &content.entry()->fContent); - - // Merge glyph sets from the drawn device. - fFontGlyphUsage->merge(pdfDevice->getFontGlyphUsage()); } ContentEntry* SkPDFDevice::getLastContentEntry() { @@ -1154,7 +1142,7 @@ SkData* SkPDFDevice::copyContentToData() const { SkRect r = SkRect::MakeWH(this->width(), this->height()); emit_clip(NULL, &r, &data); } - + SkPDFDevice::copyContentEntriesToData(fContentEntries.get(), &data); // potentially we could cache this SkData, and only rebuild it if we @@ -1166,10 +1154,7 @@ void SkPDFDevice::createFormXObjectFromDevice( SkRefPtr* xobject) { *xobject = new SkPDFFormXObject(this); (*xobject)->unref(); // SkRefPtr and new both took a reference. - // We always draw the form xobjects that we create back into the device, so - // we simply preserve the font usage instead of pulling it out and merging - // it back in later. - cleanUp(false); // Reset this device to have no content. + cleanUp(); // Reset this device to have no content. init(); } diff --git a/src/pdf/SkPDFDocument.cpp b/src/pdf/SkPDFDocument.cpp index 38f4f32977..71c3784c02 100644 --- a/src/pdf/SkPDFDocument.cpp +++ b/src/pdf/SkPDFDocument.cpp @@ -18,7 +18,6 @@ #include "SkPDFDevice.h" #include "SkPDFDocument.h" #include "SkPDFPage.h" -#include "SkPDFFont.h" #include "SkStream.h" // Add the resources, starting at firstIndex to the catalog, removing any dupes. @@ -38,29 +37,6 @@ void addResourcesToCatalog(int firstIndex, bool firstPage, } } -static void perform_font_subsetting(SkPDFCatalog* catalog, - const SkTDArray& pages, - SkTDArray* substitutes) { - SkASSERT(catalog); - SkASSERT(substitutes); - - SkPDFGlyphSetMap usage; - for (int i = 0; i < pages.count(); ++i) { - usage.merge(pages[i]->getFontGlyphUsage()); - } - SkPDFGlyphSetMap::F2BIter iterator(usage); - SkPDFGlyphSetMap::FontGlyphSetPair* entry = iterator.next(); - while (entry) { - SkPDFFont* subsetFont = - entry->fFont->getFontSubset(entry->fGlyphSet); - if (subsetFont) { - catalog->setSubstitute(entry->fFont, subsetFont); - substitutes->push(subsetFont); // Transfer ownership to substitutes - } - entry = iterator.next(); - } -} - SkPDFDocument::SkPDFDocument(Flags flags) : fXRefFileOffset(0), fSecondPageFirstResourceIndex(0) { @@ -79,7 +55,6 @@ SkPDFDocument::~SkPDFDocument() { fPageTree[i]->clear(); fPageTree.safeUnrefAll(); fPageResources.safeUnrefAll(); - fSubstitutes.safeUnrefAll(); } bool SkPDFDocument::emitPDF(SkWStream* stream) { @@ -123,9 +98,6 @@ bool SkPDFDocument::emitPDF(SkWStream* stream) { } } - // Build font subsetting info before proceeding. - perform_font_subsetting(fCatalog.get(), fPages, &fSubstitutes); - // Figure out the size of things and inform the catalog of file offsets. off_t fileOffset = headerSize(); fileOffset += fCatalog->setFileOffset(fDocCatalog.get(), fileOffset); diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp old mode 100644 new mode 100755 index f50580a4c4..be16c76936 --- a/src/pdf/SkPDFFont.cpp +++ b/src/pdf/SkPDFFont.cpp @@ -20,10 +20,8 @@ #include "SkFontHost.h" #include "SkGlyphCache.h" #include "SkPaint.h" -#include "SkPDFCatalog.h" #include "SkPDFDevice.h" #include "SkPDFFont.h" -#include "SkPDFFontImpl.h" #include "SkPDFStream.h" #include "SkPDFTypes.h" #include "SkPDFUtils.h" @@ -36,10 +34,6 @@ namespace { -/////////////////////////////////////////////////////////////////////////////// -// File-Local Functions -/////////////////////////////////////////////////////////////////////////////// - bool parsePFBSection(const uint8_t** src, size_t* len, int sectionType, size_t* size) { // PFB sections have a two or six bytes header. 0x80 and a one byte @@ -140,7 +134,7 @@ int8_t hexToBin(uint8_t c) { SkStream* handleType1Stream(SkStream* srcStream, size_t* headerLen, size_t* dataLen, size_t* trailerLen) { - // srcStream may be backed by a file or a unseekable fd, so we may not be + // srcStream may be backed by a file or a unseekable fd, so we may not be // able to use skip(), rewind(), or getMemoryBase(). read()ing through // the input only once is doable, but very ugly. Furthermore, it'd be nice // if the data was NUL terminated so that we can use strstr() to search it. @@ -391,14 +385,14 @@ static void append_cmap_footer(SkDynamicMemoryWStream* cmap) { // Generate table according to PDF spec 1.4 and Adobe Technote 5014. static void append_cmap_bfchar_sections( const SkTDArray& glyphUnicode, - const SkPDFGlyphSet* subset, SkDynamicMemoryWStream* cmap) { + SkDynamicMemoryWStream* cmap) { // PDF spec defines that every bf* list can have at most 100 entries. const size_t kMaxEntries = 100; uint16_t glyphId[kMaxEntries]; SkUnichar unicode[kMaxEntries]; size_t index = 0; for (int i = 0; i < glyphUnicode.count(); i++) { - if (glyphUnicode[i] && (subset == NULL || subset->has(i))) { + if (glyphUnicode[i]) { glyphId[index] = i; unicode[index] = glyphUnicode[i]; ++index; @@ -414,112 +408,6 @@ static void append_cmap_bfchar_sections( } } -static SkPDFStream* generate_tounicode_cmap( - const SkTDArray& glyphUnicode, - const SkPDFGlyphSet* subset) { - SkDynamicMemoryWStream cmap; - append_tounicode_header(&cmap); - append_cmap_bfchar_sections(glyphUnicode, subset, &cmap); - append_cmap_footer(&cmap); - SkRefPtr cmapStream = new SkMemoryStream(); - cmapStream->unref(); // SkRefPtr and new took a reference. - cmapStream->setData(cmap.copyToData()); - return new SkPDFStream(cmapStream.get()); -} - -/////////////////////////////////////////////////////////////////////////////// -// class SkPDFGlyphSet -/////////////////////////////////////////////////////////////////////////////// - -SkPDFGlyphSet::SkPDFGlyphSet() : fBitSet(SK_MaxU16 + 1) { -} - -void SkPDFGlyphSet::set(const uint16_t* glyphIDs, int numGlyphs) { - for (int i = 0; i < numGlyphs; ++i) { - fBitSet.setBit(glyphIDs[i], true); - } -} - -bool SkPDFGlyphSet::has(uint16_t glyphID) const { - return fBitSet.isBitSet(glyphID); -} - -void SkPDFGlyphSet::merge(const SkPDFGlyphSet& usage) { - fBitSet.orBits(usage.fBitSet); -} - -/////////////////////////////////////////////////////////////////////////////// -// class SkPDFGlyphSetMap -/////////////////////////////////////////////////////////////////////////////// -SkPDFGlyphSetMap::FontGlyphSetPair::FontGlyphSetPair(SkPDFFont* font, - SkPDFGlyphSet* glyphSet) - : fFont(font), - fGlyphSet(glyphSet) { -} - -SkPDFGlyphSetMap::F2BIter::F2BIter(const SkPDFGlyphSetMap& map) { - reset(map); -} - -SkPDFGlyphSetMap::FontGlyphSetPair* SkPDFGlyphSetMap::F2BIter::next() const { - if (fIndex >= fMap->count()) { - return NULL; - } - return &((*fMap)[fIndex++]); -} - -void SkPDFGlyphSetMap::F2BIter::reset(const SkPDFGlyphSetMap& map) { - fMap = &(map.fMap); - fIndex = 0; -} - -SkPDFGlyphSetMap::SkPDFGlyphSetMap() { -} - -SkPDFGlyphSetMap::~SkPDFGlyphSetMap() { - reset(); -} - -void SkPDFGlyphSetMap::merge(const SkPDFGlyphSetMap& usage) { - for (int i = 0; i < usage.fMap.count(); ++i) { - SkPDFGlyphSet* myUsage = getGlyphSetForFont(usage.fMap[i].fFont); - myUsage->merge(*(usage.fMap[i].fGlyphSet)); - } -} - -void SkPDFGlyphSetMap::reset() { - for (int i = 0; i < fMap.count(); ++i) { - delete fMap[i].fGlyphSet; // Should not be NULL. - } - fMap.reset(); -} - -void SkPDFGlyphSetMap::noteGlyphUsage(SkPDFFont* font, const uint16_t* glyphIDs, - int numGlyphs) { - SkPDFGlyphSet* subset = getGlyphSetForFont(font); - if (subset) { - subset->set(glyphIDs, numGlyphs); - } -} - -SkPDFGlyphSet* SkPDFGlyphSetMap::getGlyphSetForFont(SkPDFFont* font) { - int index = fMap.count(); - for (int i = 0; i < index; ++i) { - if (fMap[i].fFont == font) { - return fMap[i].fGlyphSet; - } - } - fMap.append(); - index = fMap.count() - 1; - fMap[index].fFont = font; - fMap[index].fGlyphSet = new SkPDFGlyphSet(); - return fMap[index].fGlyphSet; -} - -/////////////////////////////////////////////////////////////////////////////// -// class SkPDFFont -/////////////////////////////////////////////////////////////////////////////// - /* Font subset design: It would be nice to be able to subset fonts * (particularly type 3 fonts), but it's a lot of work and not a priority. * @@ -537,6 +425,11 @@ SkPDFFont::~SkPDFFont() { int index; if (Find(SkTypeface::UniqueID(fTypeface.get()), fFirstGlyphID, &index)) { CanonicalFonts().removeShuffle(index); +#ifdef SK_DEBUG + SkASSERT(!fDescendant); + } else { + SkASSERT(fDescendant); +#endif } fResources.unrefAll(); } @@ -550,17 +443,21 @@ SkTypeface* SkPDFFont::typeface() { } SkAdvancedTypefaceMetrics::FontType SkPDFFont::getType() { - return fFontType; + return fType; } bool SkPDFFont::hasGlyph(uint16_t id) { return (id >= fFirstGlyphID && id <= fLastGlyphID) || id == 0; } +bool SkPDFFont::multiByteGlyphs() { + return fMultiByteGlyphs; +} + size_t SkPDFFont::glyphsToPDFFontEncoding(uint16_t* glyphIDs, size_t numGlyphs) { // A font with multibyte glyphs will support all glyph IDs in a single font. - if (this->multiByteGlyphs()) { + if (fMultiByteGlyphs) { return numGlyphs; } @@ -581,19 +478,19 @@ size_t SkPDFFont::glyphsToPDFFontEncoding(uint16_t* glyphIDs, SkPDFFont* SkPDFFont::GetFontResource(SkTypeface* typeface, uint16_t glyphID) { SkAutoMutexAcquire lock(CanonicalFontsMutex()); const uint32_t fontID = SkTypeface::UniqueID(typeface); - int relatedFontIndex; - if (Find(fontID, glyphID, &relatedFontIndex)) { - CanonicalFonts()[relatedFontIndex].fFont->ref(); - return CanonicalFonts()[relatedFontIndex].fFont; + int index; + if (Find(fontID, glyphID, &index)) { + CanonicalFonts()[index].fFont->ref(); + return CanonicalFonts()[index].fFont; } - SkRefPtr fontMetrics; - SkPDFDict* relatedFontDescriptor = NULL; - if (relatedFontIndex >= 0) { - SkPDFFont* relatedFont = CanonicalFonts()[relatedFontIndex].fFont; + SkRefPtr fontInfo; + SkPDFDict* fontDescriptor = NULL; + if (index >= 0) { + SkPDFFont* relatedFont = CanonicalFonts()[index].fFont; SkASSERT(relatedFont->fFontInfo.get()); - fontMetrics = relatedFont->fontInfo(); - relatedFontDescriptor = relatedFont->getFontDescriptor(); + fontInfo = relatedFont->fFontInfo; + fontDescriptor = relatedFont->fDescriptor.get(); } else { SkAdvancedTypefaceMetrics::PerGlyphInfo info; info = SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo; @@ -601,21 +498,18 @@ SkPDFFont* SkPDFFont::GetFontResource(SkTypeface* typeface, uint16_t glyphID) { info, SkAdvancedTypefaceMetrics::kGlyphNames_PerGlyphInfo); info = SkTBitOr( info, SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo); - fontMetrics = SkFontHost::GetAdvancedTypefaceMetrics(fontID, info); - SkSafeUnref(fontMetrics.get()); // SkRefPtr and Get both took a ref. + fontInfo = SkFontHost::GetAdvancedTypefaceMetrics(fontID, info); + SkSafeUnref(fontInfo.get()); // SkRefPtr and Get both took a reference. } - SkPDFFont* font = Create(fontMetrics.get(), typeface, glyphID, - relatedFontDescriptor); + SkPDFFont* font = new SkPDFFont(fontInfo.get(), typeface, glyphID, false, + fontDescriptor); FontRec newEntry(font, fontID, font->fFirstGlyphID); + index = CanonicalFonts().count(); CanonicalFonts().push(newEntry); return font; // Return the reference new SkPDFFont() created. } -SkPDFFont* SkPDFFont::getFontSubset(const SkPDFGlyphSet* usage) { - return NULL; // Default: no support. -} - // static SkTDArray& SkPDFFont::CanonicalFonts() { // This initialization is only thread safe with gcc. @@ -642,270 +536,96 @@ bool SkPDFFont::Find(uint32_t fontID, uint16_t glyphID, int* index) { return false; } -SkPDFFont::SkPDFFont(SkAdvancedTypefaceMetrics* info, SkTypeface* typeface, - uint16_t glyphID, bool descendantFont) +SkPDFFont::SkPDFFont(class SkAdvancedTypefaceMetrics* fontInfo, + SkTypeface* typeface, + uint16_t glyphID, + bool descendantFont, + SkPDFDict* fontDescriptor) : SkPDFDict("Font"), fTypeface(typeface), + fType(fontInfo ? fontInfo->fType : + SkAdvancedTypefaceMetrics::kNotEmbeddable_Font), +#ifdef SK_DEBUG + fDescendant(descendantFont), +#endif + fMultiByteGlyphs(false), fFirstGlyphID(1), - fLastGlyphID(info ? info->fLastGlyphID : 0), - fFontInfo(info) { - if (info == NULL) { - fFontType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font; - } else if (info->fMultiMaster) { - fFontType = SkAdvancedTypefaceMetrics::kOther_Font; - } else { - fFontType = info->fType; - } -} - -// static -SkPDFFont* SkPDFFont::Create(SkAdvancedTypefaceMetrics* info, - SkTypeface* typeface, uint16_t glyphID, - SkPDFDict* relatedFontDescriptor) { - SkAdvancedTypefaceMetrics::FontType type = - info ? info->fType : SkAdvancedTypefaceMetrics::kNotEmbeddable_Font; - - if (info && info->fMultiMaster) { + fLastGlyphID(fontInfo ? fontInfo->fLastGlyphID : 0), + fFontInfo(fontInfo), + fDescriptor(fontDescriptor) { + if (fontInfo && fontInfo->fMultiMaster) { NOT_IMPLEMENTED(true, true); - return new SkPDFType3Font(info, - typeface, - glyphID, - relatedFontDescriptor); - } - if (type == SkAdvancedTypefaceMetrics::kType1CID_Font || - type == SkAdvancedTypefaceMetrics::kTrueType_Font) { - SkASSERT(relatedFontDescriptor == NULL); - return new SkPDFType0Font(info, typeface); - } - if (type == SkAdvancedTypefaceMetrics::kType1_Font) { - return new SkPDFType1Font(info, - typeface, - glyphID, - relatedFontDescriptor); - } - - SkASSERT(type == SkAdvancedTypefaceMetrics::kCFF_Font || - type == SkAdvancedTypefaceMetrics::kOther_Font || - type == SkAdvancedTypefaceMetrics::kNotEmbeddable_Font); - - return new SkPDFType3Font(info, typeface, glyphID, relatedFontDescriptor); -} - -SkAdvancedTypefaceMetrics* SkPDFFont::fontInfo() { - return fFontInfo.get(); -} - -uint16_t SkPDFFont::firstGlyphID() const { - return fFirstGlyphID; -} - -uint16_t SkPDFFont::lastGlyphID() const { - return fLastGlyphID; -} - -void SkPDFFont::setLastGlyphID(uint16_t glyphID) { - fLastGlyphID = glyphID; -} - -void SkPDFFont::addResource(SkPDFObject* object) { - SkASSERT(object != NULL); - fResources.push(object); -} - -SkPDFDict* SkPDFFont::getFontDescriptor() { - return fDescriptor.get(); -} - -void SkPDFFont::setFontDescriptor(SkPDFDict* descriptor) { - fDescriptor = descriptor; -} - -bool SkPDFFont::addCommonFontDescriptorEntries(int16_t defaultWidth) { - if (fDescriptor.get() == NULL) { - return false; - } - - const uint16_t emSize = fFontInfo->fEmSize; - - fDescriptor->insertName("FontName", fFontInfo->fFontName); - fDescriptor->insertInt("Flags", fFontInfo->fStyle); - fDescriptor->insertScalar("Ascent", - scaleFromFontUnits(fFontInfo->fAscent, emSize)); - fDescriptor->insertScalar("Descent", - scaleFromFontUnits(fFontInfo->fDescent, emSize)); - fDescriptor->insertScalar("StemV", - scaleFromFontUnits(fFontInfo->fStemV, emSize)); - fDescriptor->insertScalar("CapHeight", - scaleFromFontUnits(fFontInfo->fCapHeight, emSize)); - fDescriptor->insertInt("ItalicAngle", fFontInfo->fItalicAngle); - fDescriptor->insert("FontBBox", makeFontBBox(fFontInfo->fBBox, - fFontInfo->fEmSize))->unref(); - - if (defaultWidth > 0) { - fDescriptor->insertScalar("MissingWidth", - scaleFromFontUnits(defaultWidth, emSize)); - } - return true; -} - -void SkPDFFont::adjustGlyphRangeForSingleByteEncoding(int16_t glyphID) { - // Single byte glyph encoding supports a max of 255 glyphs. - fFirstGlyphID = glyphID - (glyphID - 1) % 255; - if (fLastGlyphID > fFirstGlyphID + 255 - 1) { - fLastGlyphID = fFirstGlyphID + 255 - 1; + fType = SkAdvancedTypefaceMetrics::kOther_Font; } -} - -bool SkPDFFont::FontRec::operator==(const SkPDFFont::FontRec& b) const { - if (fFontID != b.fFontID) - return false; - if (fFont != NULL && b.fFont != NULL) { - return fFont->fFirstGlyphID == b.fFont->fFirstGlyphID && - fFont->fLastGlyphID == b.fFont->fLastGlyphID; - } - if (fGlyphID == 0 || b.fGlyphID == 0) - return true; - - if (fFont != NULL) { - return fFont->fFirstGlyphID <= b.fGlyphID && - b.fGlyphID <= fFont->fLastGlyphID; - } else if (b.fFont != NULL) { - return b.fFont->fFirstGlyphID <= fGlyphID && - fGlyphID <= b.fFont->fLastGlyphID; + if (fType == SkAdvancedTypefaceMetrics::kType1CID_Font || + fType == SkAdvancedTypefaceMetrics::kTrueType_Font) { + if (descendantFont) { + populateCIDFont(); + } else { + populateType0Font(); + } + // No need to hold onto the font info for fonts types that + // support multibyte glyphs. + fFontInfo = NULL; + return; } - return fGlyphID == b.fGlyphID; -} -SkPDFFont::FontRec::FontRec(SkPDFFont* font, uint32_t fontID, uint16_t glyphID) - : fFont(font), - fFontID(fontID), - fGlyphID(glyphID) { -} - -void SkPDFFont::populateToUnicodeTable(const SkPDFGlyphSet* subset) { - if (fFontInfo == NULL || fFontInfo->fGlyphToUnicode.begin() == NULL) { + if (fType == SkAdvancedTypefaceMetrics::kType1_Font && + populateType1Font(glyphID)) { return; } - SkRefPtr pdfCmap = - generate_tounicode_cmap(fFontInfo->fGlyphToUnicode, subset); - addResource(pdfCmap.get()); // Pass reference from new. - insert("ToUnicode", new SkPDFObjRef(pdfCmap.get()))->unref(); -} - -/////////////////////////////////////////////////////////////////////////////// -// class SkPDFType0Font -/////////////////////////////////////////////////////////////////////////////// -SkPDFType0Font::SkPDFType0Font(SkAdvancedTypefaceMetrics* info, - SkTypeface* typeface) - : SkPDFFont(info, typeface, 0, false) { - SkDEBUGCODE(fPopulated = false); + SkASSERT(fType == SkAdvancedTypefaceMetrics::kType1_Font || + fType == SkAdvancedTypefaceMetrics::kCFF_Font || + fType == SkAdvancedTypefaceMetrics::kOther_Font || + fType == SkAdvancedTypefaceMetrics::kNotEmbeddable_Font); + populateType3Font(glyphID); } -SkPDFType0Font::~SkPDFType0Font() {} +void SkPDFFont::populateType0Font() { + fMultiByteGlyphs = true; -SkPDFFont* SkPDFType0Font::getFontSubset(const SkPDFGlyphSet* subset) { - SkPDFType0Font* newSubset = new SkPDFType0Font(fontInfo(), typeface()); - newSubset->populate(subset); - return newSubset; -} - -#ifdef SK_DEBUG -void SkPDFType0Font::emitObject(SkWStream* stream, SkPDFCatalog* catalog, - bool indirect) { - SkASSERT(fPopulated); - return INHERITED::emitObject(stream, catalog, indirect); -} -#endif - -bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset) { insertName("Subtype", "Type0"); - insertName("BaseFont", fontInfo()->fFontName); + insertName("BaseFont", fFontInfo->fFontName); insertName("Encoding", "Identity-H"); - // Pass ref new created to fResources. - SkPDFCIDFont* newCIDFont = - new SkPDFCIDFont(fontInfo(), typeface(), subset); - addResource(newCIDFont); SkRefPtr descendantFonts = new SkPDFArray(); descendantFonts->unref(); // SkRefPtr and new took a reference. - descendantFonts->append(new SkPDFObjRef(newCIDFont))->unref(); - insert("DescendantFonts", descendantFonts.get()); - - populateToUnicodeTable(subset); - SkDEBUGCODE(fPopulated = true); - return true; -} - -/////////////////////////////////////////////////////////////////////////////// -// class SkPDFCIDFont -/////////////////////////////////////////////////////////////////////////////// + // Pass ref new created to fResources. + fResources.push( + new SkPDFFont(fFontInfo.get(), fTypeface.get(), 1, true, NULL)); + descendantFonts->append(new SkPDFObjRef(fResources.top()))->unref(); + insert("DescendantFonts", descendantFonts.get()); -SkPDFCIDFont::SkPDFCIDFont(SkAdvancedTypefaceMetrics* info, - SkTypeface* typeface, const SkPDFGlyphSet* subset) - : SkPDFFont(info, typeface, 0, true) { - populate(subset); + populateToUnicodeTable(); } -SkPDFCIDFont::~SkPDFCIDFont() {} - -bool SkPDFCIDFont::addFontDescriptor(int16_t defaultWidth, - const SkPDFGlyphSet* subset) { - SkRefPtr descriptor = new SkPDFDict("FontDescriptor"); - descriptor->unref(); // SkRefPtr and new both took a ref. - setFontDescriptor(descriptor.get()); - - switch (getType()) { - case SkAdvancedTypefaceMetrics::kTrueType_Font: { - // TODO(arthurhsu): sfntly font subsetting - SkRefPtr fontData = - SkFontHost::OpenStream(SkTypeface::UniqueID(typeface())); - fontData->unref(); // SkRefPtr and OpenStream both took a ref. - SkRefPtr fontStream = new SkPDFStream(fontData.get()); - // SkRefPtr and new both ref()'d fontStream, pass one. - addResource(fontStream.get()); - - fontStream->insertInt("Length1", fontData->getLength()); - descriptor->insert("FontFile2", - new SkPDFObjRef(fontStream.get()))->unref(); - break; - } - case SkAdvancedTypefaceMetrics::kCFF_Font: - case SkAdvancedTypefaceMetrics::kType1CID_Font: { - SkRefPtr fontData = - SkFontHost::OpenStream(SkTypeface::UniqueID(typeface())); - fontData->unref(); // SkRefPtr and OpenStream both took a ref. - SkRefPtr fontStream = new SkPDFStream(fontData.get()); - // SkRefPtr and new both ref()'d fontStream, pass one. - addResource(fontStream.get()); - - if (getType() == SkAdvancedTypefaceMetrics::kCFF_Font) { - fontStream->insertName("Subtype", "Type1C"); - } else { - fontStream->insertName("Subtype", "CIDFontType0c"); - } - descriptor->insert("FontFile3", - new SkPDFObjRef(fontStream.get()))->unref(); - break; - } - default: - SkASSERT(false); +void SkPDFFont::populateToUnicodeTable() { + if (fFontInfo.get() == NULL || + fFontInfo->fGlyphToUnicode.begin() == NULL) { + return; } - addResource(descriptor.get()); - descriptor->ref(); - - insert("FontDescriptor", new SkPDFObjRef(descriptor.get()))->unref(); - return addCommonFontDescriptorEntries(defaultWidth); + SkDynamicMemoryWStream cmap; + append_tounicode_header(&cmap); + append_cmap_bfchar_sections(fFontInfo->fGlyphToUnicode, &cmap); + append_cmap_footer(&cmap); + SkRefPtr cmapStream = new SkMemoryStream(); + cmapStream->unref(); // SkRefPtr and new took a reference. + cmapStream->setData(cmap.copyToData())->unref(); + SkRefPtr pdfCmap = new SkPDFStream(cmapStream.get()); + fResources.push(pdfCmap.get()); // Pass reference from new. + insert("ToUnicode", new SkPDFObjRef(pdfCmap.get()))->unref(); } -bool SkPDFCIDFont::populate(const SkPDFGlyphSet* subset) { - insertName("BaseFont", fontInfo()->fFontName); +void SkPDFFont::populateCIDFont() { + fMultiByteGlyphs = true; + insertName("BaseFont", fFontInfo->fFontName); - if (getType() == SkAdvancedTypefaceMetrics::kType1CID_Font) { + if (fFontInfo->fType == SkAdvancedTypefaceMetrics::kType1CID_Font) { insertName("Subtype", "CIDFontType0"); - } else if (getType() == SkAdvancedTypefaceMetrics::kTrueType_Font) { + } else if (fFontInfo->fType == SkAdvancedTypefaceMetrics::kTrueType_Font) { insertName("Subtype", "CIDFontType2"); insertName("CIDToGIDMap", "Identity"); } else { @@ -919,30 +639,29 @@ bool SkPDFCIDFont::populate(const SkPDFGlyphSet* subset) { sysInfo->insertInt("Supplement", 0); insert("CIDSystemInfo", sysInfo.get()); - addFontDescriptor(0, subset); + addFontDescriptor(0); - if (fontInfo()->fGlyphWidths.get()) { + if (fFontInfo->fGlyphWidths.get()) { int16_t defaultWidth = 0; SkRefPtr widths = - composeAdvanceData(fontInfo()->fGlyphWidths.get(), - fontInfo()->fEmSize, &appendWidth, - &defaultWidth); + composeAdvanceData(fFontInfo->fGlyphWidths.get(), + fFontInfo->fEmSize, &appendWidth, &defaultWidth); widths->unref(); // SkRefPtr and compose both took a reference. if (widths->size()) insert("W", widths.get()); if (defaultWidth != 0) { insertScalar("DW", scaleFromFontUnits(defaultWidth, - fontInfo()->fEmSize)); + fFontInfo->fEmSize)); } } - if (fontInfo()->fVerticalMetrics.get()) { + if (fFontInfo->fVerticalMetrics.get()) { struct SkAdvancedTypefaceMetrics::VerticalMetric defaultAdvance; defaultAdvance.fVerticalAdvance = 0; defaultAdvance.fOriginXDisp = 0; defaultAdvance.fOriginYDisp = 0; SkRefPtr advances = - composeAdvanceData(fontInfo()->fVerticalMetrics.get(), - fontInfo()->fEmSize, &appendVerticalAdvance, + composeAdvanceData(fFontInfo->fVerticalMetrics.get(), + fFontInfo->fEmSize, &appendVerticalAdvance, &defaultAdvance); advances->unref(); // SkRefPtr and compose both took a ref. if (advances->size()) @@ -951,77 +670,22 @@ bool SkPDFCIDFont::populate(const SkPDFGlyphSet* subset) { defaultAdvance.fOriginXDisp || defaultAdvance.fOriginYDisp) { insert("DW2", appendVerticalAdvance(defaultAdvance, - fontInfo()->fEmSize, + fFontInfo->fEmSize, new SkPDFArray))->unref(); } } - - return true; } -/////////////////////////////////////////////////////////////////////////////// -// class SkPDFType1Font -/////////////////////////////////////////////////////////////////////////////// - -SkPDFType1Font::SkPDFType1Font(SkAdvancedTypefaceMetrics* info, - SkTypeface* typeface, - uint16_t glyphID, - SkPDFDict* relatedFontDescriptor) - : SkPDFFont(info, typeface, glyphID, false) { - populate(glyphID); -} - -SkPDFType1Font::~SkPDFType1Font() {} - -bool SkPDFType1Font::addFontDescriptor(int16_t defaultWidth) { - SkRefPtr descriptor = getFontDescriptor(); - if (descriptor.get() != NULL) { - addResource(descriptor.get()); - descriptor->ref(); - insert("FontDescriptor", new SkPDFObjRef(descriptor.get()))->unref(); - return true; - } - - descriptor = new SkPDFDict("FontDescriptor"); - descriptor->unref(); // SkRefPtr and new both took a ref. - setFontDescriptor(descriptor.get()); - - size_t header SK_INIT_TO_AVOID_WARNING; - size_t data SK_INIT_TO_AVOID_WARNING; - size_t trailer SK_INIT_TO_AVOID_WARNING; - SkRefPtr rawFontData = - SkFontHost::OpenStream(SkTypeface::UniqueID(typeface())); - rawFontData->unref(); // SkRefPtr and OpenStream both took a ref. - SkStream* fontData = handleType1Stream(rawFontData.get(), &header, &data, - &trailer); - if (fontData == NULL) { - return false; - } - SkRefPtr fontStream = new SkPDFStream(fontData); - // SkRefPtr and new both ref()'d fontStream, pass one. - addResource(fontStream.get()); - fontStream->insertInt("Length1", header); - fontStream->insertInt("Length2", data); - fontStream->insertInt("Length3", trailer); - descriptor->insert("FontFile", new SkPDFObjRef(fontStream.get()))->unref(); - - addResource(descriptor.get()); - descriptor->ref(); - insert("FontDescriptor", new SkPDFObjRef(descriptor.get()))->unref(); - - return addCommonFontDescriptorEntries(defaultWidth); -} - -bool SkPDFType1Font::populate(int16_t glyphID) { - SkASSERT(!fontInfo()->fVerticalMetrics.get()); - SkASSERT(fontInfo()->fGlyphWidths.get()); +bool SkPDFFont::populateType1Font(int16_t glyphID) { + SkASSERT(!fFontInfo->fVerticalMetrics.get()); + SkASSERT(fFontInfo->fGlyphWidths.get()); adjustGlyphRangeForSingleByteEncoding(glyphID); int16_t defaultWidth = 0; const SkAdvancedTypefaceMetrics::WidthRange* widthRangeEntry = NULL; const SkAdvancedTypefaceMetrics::WidthRange* widthEntry; - for (widthEntry = fontInfo()->fGlyphWidths.get(); + for (widthEntry = fFontInfo.get()->fGlyphWidths.get(); widthEntry != NULL; widthEntry = widthEntry->fNext.get()) { switch (widthEntry->fType) { @@ -1042,7 +706,7 @@ bool SkPDFType1Font::populate(int16_t glyphID) { return false; insertName("Subtype", "Type1"); - insertName("BaseFont", fontInfo()->fFontName); + insertName("BaseFont", fFontInfo->fFontName); addWidthInfoFromRange(defaultWidth, widthRangeEntry); @@ -1054,67 +718,26 @@ bool SkPDFType1Font::populate(int16_t glyphID) { encDiffs->unref(); // SkRefPtr and new both took a reference. encoding->insert("Differences", encDiffs.get()); - encDiffs->reserve(lastGlyphID() - firstGlyphID() + 2); + encDiffs->reserve(fLastGlyphID - fFirstGlyphID + 2); encDiffs->appendInt(1); - for (int gID = firstGlyphID(); gID <= lastGlyphID(); gID++) { - encDiffs->appendName(fontInfo()->fGlyphNames->get()[gID].c_str()); + for (int gID = fFirstGlyphID; gID <= fLastGlyphID; gID++) { + encDiffs->appendName(fFontInfo->fGlyphNames->get()[gID].c_str()); } + if (fFontInfo->fLastGlyphID <= 255) + fFontInfo = NULL; return true; } -void SkPDFType1Font::addWidthInfoFromRange( - int16_t defaultWidth, - const SkAdvancedTypefaceMetrics::WidthRange* widthRangeEntry) { - SkRefPtr widthArray = new SkPDFArray(); - widthArray->unref(); // SkRefPtr and new both took a ref. - int firstChar = 0; - if (widthRangeEntry) { - const uint16_t emSize = fontInfo()->fEmSize; - int startIndex = firstGlyphID() - widthRangeEntry->fStartId; - int endIndex = startIndex + lastGlyphID() - firstGlyphID() + 1; - if (startIndex < 0) - startIndex = 0; - if (endIndex > widthRangeEntry->fAdvance.count()) - endIndex = widthRangeEntry->fAdvance.count(); - if (widthRangeEntry->fStartId == 0) { - appendWidth(widthRangeEntry->fAdvance[0], emSize, widthArray.get()); - } else { - firstChar = startIndex + widthRangeEntry->fStartId; - } - for (int i = startIndex; i < endIndex; i++) - appendWidth(widthRangeEntry->fAdvance[i], emSize, widthArray.get()); - } else { - appendWidth(defaultWidth, 1000, widthArray.get()); - } - insertInt("FirstChar", firstChar); - insertInt("LastChar", firstChar + widthArray->size() - 1); - insert("Widths", widthArray.get()); -} - -/////////////////////////////////////////////////////////////////////////////// -// class SkPDFType3Font -/////////////////////////////////////////////////////////////////////////////// - -SkPDFType3Font::SkPDFType3Font(SkAdvancedTypefaceMetrics* info, - SkTypeface* typeface, - uint16_t glyphID, - SkPDFDict* relatedFontDescriptor) - : SkPDFFont(info, typeface, glyphID, false) { - populate(glyphID); -} - -SkPDFType3Font::~SkPDFType3Font() {} - -bool SkPDFType3Font::populate(int16_t glyphID) { +void SkPDFFont::populateType3Font(int16_t glyphID) { SkPaint paint; - paint.setTypeface(typeface()); + paint.setTypeface(fTypeface.get()); paint.setTextSize(1000); SkAutoGlyphCache autoCache(paint, NULL); SkGlyphCache* cache = autoCache.getCache(); // If fLastGlyphID isn't set (because there is not fFontInfo), look it up. - if (lastGlyphID() == 0) { - setLastGlyphID(cache->getGlyphCount() - 1); + if (fLastGlyphID == 0) { + fLastGlyphID = cache->getGlyphCount() - 1; } adjustGlyphRangeForSingleByteEncoding(glyphID); @@ -1136,14 +759,14 @@ bool SkPDFType3Font::populate(int16_t glyphID) { SkRefPtr encDiffs = new SkPDFArray; encDiffs->unref(); // SkRefPtr and new both took a reference. encoding->insert("Differences", encDiffs.get()); - encDiffs->reserve(lastGlyphID() - firstGlyphID() + 2); + encDiffs->reserve(fLastGlyphID - fFirstGlyphID + 2); encDiffs->appendInt(1); SkRefPtr widthArray = new SkPDFArray(); widthArray->unref(); // SkRefPtr and new both took a ref. SkIRect bbox = SkIRect::MakeEmpty(); - for (int gID = firstGlyphID(); gID <= lastGlyphID(); gID++) { + for (int gID = fFirstGlyphID; gID <= fLastGlyphID; gID++) { SkString characterName; characterName.printf("gid%d", gID); encDiffs->appendName(characterName.c_str()); @@ -1170,17 +793,176 @@ bool SkPDFType3Font::populate(int16_t glyphID) { SkRefPtr glyphDescription = new SkPDFStream(glyphStream.get()); // SkRefPtr and new both ref()'d charProcs, pass one. - addResource(glyphDescription.get()); + fResources.push(glyphDescription.get()); charProcs->insert(characterName.c_str(), new SkPDFObjRef(glyphDescription.get()))->unref(); } insert("FontBBox", makeFontBBox(bbox, 1000))->unref(); - insertInt("FirstChar", firstGlyphID()); - insertInt("LastChar", lastGlyphID()); + insertInt("FirstChar", fFirstGlyphID); + insertInt("LastChar", fLastGlyphID); insert("Widths", widthArray.get()); insertName("CIDToGIDMap", "Identity"); - populateToUnicodeTable(NULL); + if (fFontInfo && fFontInfo->fLastGlyphID <= 255) { + fFontInfo = NULL; + } + populateToUnicodeTable(); +} + +bool SkPDFFont::addFontDescriptor(int16_t defaultWidth) { + if (fDescriptor.get() != NULL) { + fResources.push(fDescriptor.get()); + fDescriptor->ref(); + insert("FontDescriptor", new SkPDFObjRef(fDescriptor.get()))->unref(); + return true; + } + + fDescriptor = new SkPDFDict("FontDescriptor"); + fDescriptor->unref(); // SkRefPtr and new both took a ref. + + switch (fFontInfo->fType) { + case SkAdvancedTypefaceMetrics::kType1_Font: { + size_t header SK_INIT_TO_AVOID_WARNING; + size_t data SK_INIT_TO_AVOID_WARNING; + size_t trailer SK_INIT_TO_AVOID_WARNING; + SkRefPtr rawFontData = + SkFontHost::OpenStream(SkTypeface::UniqueID(fTypeface.get())); + rawFontData->unref(); // SkRefPtr and OpenStream both took a ref. + SkStream* fontData = handleType1Stream(rawFontData.get(), &header, + &data, &trailer); + if (fontData == NULL) + return false; + SkRefPtr fontStream = new SkPDFStream(fontData); + // SkRefPtr and new both ref()'d fontStream, pass one. + fResources.push(fontStream.get()); + fontStream->insertInt("Length1", header); + fontStream->insertInt("Length2", data); + fontStream->insertInt("Length3", trailer); + fDescriptor->insert("FontFile", + new SkPDFObjRef(fontStream.get()))->unref(); + break; + } + case SkAdvancedTypefaceMetrics::kTrueType_Font: { + SkRefPtr fontData = + SkFontHost::OpenStream(SkTypeface::UniqueID(fTypeface.get())); + fontData->unref(); // SkRefPtr and OpenStream both took a ref. + SkRefPtr fontStream = new SkPDFStream(fontData.get()); + // SkRefPtr and new both ref()'d fontStream, pass one. + fResources.push(fontStream.get()); + + fontStream->insertInt("Length1", fontData->getLength()); + fDescriptor->insert("FontFile2", + new SkPDFObjRef(fontStream.get()))->unref(); + break; + } + case SkAdvancedTypefaceMetrics::kCFF_Font: + case SkAdvancedTypefaceMetrics::kType1CID_Font: { + SkRefPtr fontData = + SkFontHost::OpenStream(SkTypeface::UniqueID(fTypeface.get())); + fontData->unref(); // SkRefPtr and OpenStream both took a ref. + SkRefPtr fontStream = new SkPDFStream(fontData.get()); + // SkRefPtr and new both ref()'d fontStream, pass one. + fResources.push(fontStream.get()); + + if (fFontInfo->fType == SkAdvancedTypefaceMetrics::kCFF_Font) { + fontStream->insertName("Subtype", "Type1C"); + } else { + fontStream->insertName("Subtype", "CIDFontType0c"); + } + fDescriptor->insert("FontFile3", + new SkPDFObjRef(fontStream.get()))->unref(); + break; + } + default: + SkASSERT(false); + } + + const uint16_t emSize = fFontInfo->fEmSize; + fResources.push(fDescriptor.get()); + fDescriptor->ref(); + insert("FontDescriptor", new SkPDFObjRef(fDescriptor.get()))->unref(); + + fDescriptor->insertName("FontName", fFontInfo->fFontName); + fDescriptor->insertInt("Flags", fFontInfo->fStyle); + fDescriptor->insertScalar("Ascent", + scaleFromFontUnits(fFontInfo->fAscent, emSize)); + fDescriptor->insertScalar("Descent", + scaleFromFontUnits(fFontInfo->fDescent, emSize)); + fDescriptor->insertScalar("StemV", + scaleFromFontUnits(fFontInfo->fStemV, emSize)); + fDescriptor->insertScalar("CapHeight", + scaleFromFontUnits(fFontInfo->fCapHeight, emSize)); + fDescriptor->insertInt("ItalicAngle", fFontInfo->fItalicAngle); + fDescriptor->insert("FontBBox", makeFontBBox(fFontInfo->fBBox, + fFontInfo->fEmSize))->unref(); + + if (defaultWidth > 0) { + fDescriptor->insertScalar("MissingWidth", + scaleFromFontUnits(defaultWidth, emSize)); + } return true; } +void SkPDFFont::addWidthInfoFromRange( + int16_t defaultWidth, + const SkAdvancedTypefaceMetrics::WidthRange* widthRangeEntry) { + SkRefPtr widthArray = new SkPDFArray(); + widthArray->unref(); // SkRefPtr and new both took a ref. + int firstChar = 0; + if (widthRangeEntry) { + const uint16_t emSize = fFontInfo->fEmSize; + int startIndex = fFirstGlyphID - widthRangeEntry->fStartId; + int endIndex = startIndex + fLastGlyphID - fFirstGlyphID + 1; + if (startIndex < 0) + startIndex = 0; + if (endIndex > widthRangeEntry->fAdvance.count()) + endIndex = widthRangeEntry->fAdvance.count(); + if (widthRangeEntry->fStartId == 0) { + appendWidth(widthRangeEntry->fAdvance[0], emSize, widthArray.get()); + } else { + firstChar = startIndex + widthRangeEntry->fStartId; + } + for (int i = startIndex; i < endIndex; i++) + appendWidth(widthRangeEntry->fAdvance[i], emSize, widthArray.get()); + } else { + appendWidth(defaultWidth, 1000, widthArray.get()); + } + insertInt("FirstChar", firstChar); + insertInt("LastChar", firstChar + widthArray->size() - 1); + insert("Widths", widthArray.get()); +} + +void SkPDFFont::adjustGlyphRangeForSingleByteEncoding(int16_t glyphID) { + // Single byte glyph encoding supports a max of 255 glyphs. + fFirstGlyphID = glyphID - (glyphID - 1) % 255; + if (fLastGlyphID > fFirstGlyphID + 255 - 1) { + fLastGlyphID = fFirstGlyphID + 255 - 1; + } +} + + +bool SkPDFFont::FontRec::operator==(const SkPDFFont::FontRec& b) const { + if (fFontID != b.fFontID) + return false; + if (fFont != NULL && b.fFont != NULL) { + return fFont->fFirstGlyphID == b.fFont->fFirstGlyphID && + fFont->fLastGlyphID == b.fFont->fLastGlyphID; + } + if (fGlyphID == 0 || b.fGlyphID == 0) + return true; + + if (fFont != NULL) { + return fFont->fFirstGlyphID <= b.fGlyphID && + b.fGlyphID <= fFont->fLastGlyphID; + } else if (b.fFont != NULL) { + return b.fFont->fFirstGlyphID <= fGlyphID && + fGlyphID <= b.fFont->fLastGlyphID; + } + return fGlyphID == b.fGlyphID; +} + +SkPDFFont::FontRec::FontRec(SkPDFFont* font, uint32_t fontID, uint16_t glyphID) + : fFont(font), + fFontID(fontID), + fGlyphID(glyphID) { +} diff --git a/src/pdf/SkPDFFontImpl.h b/src/pdf/SkPDFFontImpl.h deleted file mode 100755 index 22206255c4..0000000000 --- a/src/pdf/SkPDFFontImpl.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SkPDFFontImpl_DEFINED -#define SkPDFFontImpl_DEFINED - -#include "SkPDFFont.h" - -class SkPDFType0Font : public SkPDFFont { -public: - virtual ~SkPDFType0Font(); - virtual bool multiByteGlyphs() const { return true; } - SK_API virtual SkPDFFont* getFontSubset(const SkPDFGlyphSet* usage); -#ifdef SK_DEBUG - virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, - bool indirect); -#endif - -private: - friend class SkPDFFont; // to access the constructor -#ifdef SK_DEBUG - bool fPopulated; - typedef SkPDFDict INHERITED; -#endif - - SkPDFType0Font(SkAdvancedTypefaceMetrics* info, SkTypeface* typeface); - - bool populate(const SkPDFGlyphSet* subset); -}; - -class SkPDFCIDFont : public SkPDFFont { -public: - virtual ~SkPDFCIDFont(); - virtual bool multiByteGlyphs() const { return true; } - -private: - friend class SkPDFType0Font; // to access the constructor - - SkPDFCIDFont(SkAdvancedTypefaceMetrics* info, SkTypeface* typeface, - const SkPDFGlyphSet* subset); - - bool populate(const SkPDFGlyphSet* subset); - bool addFontDescriptor(int16_t defaultWidth, const SkPDFGlyphSet* subset); -}; - -class SkPDFType1Font : public SkPDFFont { -public: - virtual ~SkPDFType1Font(); - virtual bool multiByteGlyphs() const { return false; } - -private: - friend class SkPDFFont; // to access the constructor - - SkPDFType1Font(SkAdvancedTypefaceMetrics* info, SkTypeface* typeface, - uint16_t glyphID, SkPDFDict* relatedFontDescriptor); - - bool populate(int16_t glyphID); - bool addFontDescriptor(int16_t defaultWidth); - void addWidthInfoFromRange(int16_t defaultWidth, - const SkAdvancedTypefaceMetrics::WidthRange* widthRangeEntry); -}; - -class SkPDFType3Font : public SkPDFFont { -public: - virtual ~SkPDFType3Font(); - virtual bool multiByteGlyphs() const { return false; } - -private: - friend class SkPDFFont; // to access the constructor - - SkPDFType3Font(SkAdvancedTypefaceMetrics* info, SkTypeface* typeface, - uint16_t glyphID, SkPDFDict* relatedFontDescriptor); - - bool populate(int16_t glyphID); -}; - -#endif diff --git a/src/pdf/SkPDFPage.cpp b/src/pdf/SkPDFPage.cpp index 846df64a23..09849b0ac8 100644 --- a/src/pdf/SkPDFPage.cpp +++ b/src/pdf/SkPDFPage.cpp @@ -141,7 +141,3 @@ void SkPDFPage::GeneratePageTree(const SkTDArray& pages, const SkTDArray& SkPDFPage::getFontResources() const { return fDevice->getFontResources(); } - -const SkPDFGlyphSetMap& SkPDFPage::getFontGlyphUsage() const { - return fDevice->getFontGlyphUsage(); -} -- cgit v1.2.3