diff --git a/include/core/SkFontHost.h b/include/core/SkFontHost.h index 3c2ed0924..07957da31 100644 --- a/include/core/SkFontHost.h +++ b/include/core/SkFontHost.h @@ -49,6 +49,92 @@ class SkWStream; */ class SK_API SkFontHost { public: + /** LCDs either have their color elements arranged horizontally or + vertically. When rendering subpixel glyphs we need to know which way + round they are. + + Note, if you change this after startup, you'll need to flush the glyph + cache because it'll have the wrong type of masks cached. + + @deprecated use SkPixelGeometry instead. + */ + enum LCDOrientation { + kHorizontal_LCDOrientation = 0, //!< this is the default + kVertical_LCDOrientation = 1 + }; + + /** @deprecated set on Device creation. */ + static void SetSubpixelOrientation(LCDOrientation orientation); + /** @deprecated get from Device. */ + static LCDOrientation GetSubpixelOrientation(); + + /** LCD color elements can vary in order. For subpixel text we need to know + the order which the LCDs uses so that the color fringes are in the + correct place. + + Note, if you change this after startup, you'll need to flush the glyph + cache because it'll have the wrong type of masks cached. + + kNONE_LCDOrder means that the subpixel elements are not spatially + separated in any usable fashion. + + @deprecated use SkPixelGeometry instead. + */ + enum LCDOrder { + kRGB_LCDOrder = 0, //!< this is the default + kBGR_LCDOrder = 1, + kNONE_LCDOrder = 2 + }; + + /** @deprecated set on Device creation. */ + static void SetSubpixelOrder(LCDOrder order); + /** @deprecated get from Device. */ + static LCDOrder GetSubpixelOrder(); + +#ifdef SK_BUILD_FOR_ANDROID + /** + * Return the number of font units per em. + * + * @param fontID the font to query. + * @return the number of font units per em or 0 on error. + */ + static uint32_t GetUnitsPerEm(SkFontID fontID); +#endif + + /** If Skia is running in a constrained environment and the typeface + implementation is handle based, the typeface data may become + unavailable asynchronously. If a font host or scaler context method is + unable to access font data, it may call this function as a request to + make the handle contained in the typeface useable. + */ + static void EnsureTypefaceAccessible(const SkTypeface& typeface); + + /** + * Return a subclass of SkScalarContext + * DEPRECATED -- will be moved to SkTypeface + */ + static SkScalerContext* CreateScalerContext(const SkDescriptor* desc); + + /** + * DEPRECATED -- will be DESTROYED + * + * Given a "current" fontID, return the next logical fontID to use + * when searching fonts for a given unicode value. Typically the caller + * will query a given font, and if a unicode value is not supported, they + * will call this, and if 0 is not returned, will search that font, and so + * on. This process must be finite, and when the fonthost sees a + * font with no logical successor, it must return 0. + * + * The original fontID is also provided. This is the initial font that was + * stored in the typeface of the caller. It is provided as an aid to choose + * the best next logical font. e.g. If the original font was bold or serif, + * but the 2nd in the logical chain was plain, then a subsequent call to + * get the 3rd can still inspect the original, and try to match its + * stylistic attributes. + */ + static SkFontID NextLogicalFont(SkFontID currFontID, SkFontID origFontID); + +private: /** Return a new, closest matching typeface given either an existing family (specified by a typeface in that family) or by a familyName and a requested style. @@ -135,29 +221,6 @@ public: /////////////////////////////////////////////////////////////////////////// - /** Return a subclass of SkScalarContext - */ - static SkScalerContext* CreateScalerContext(const SkDescriptor* desc); - - /** - * Given a "current" fontID, return the next logical fontID to use - * when searching fonts for a given unicode value. Typically the caller - * will query a given font, and if a unicode value is not supported, they - * will call this, and if 0 is not returned, will search that font, and so - * on. This process must be finite, and when the fonthost sees a - * font with no logical successor, it must return 0. - * - * The original fontID is also provided. This is the initial font that was - * stored in the typeface of the caller. It is provided as an aid to choose - * the best next logical font. e.g. If the original font was bold or serif, - * but the 2nd in the logical chain was plain, then a subsequent call to - * get the 3rd can still inspect the original, and try to match its - * stylistic attributes. - */ - static SkFontID NextLogicalFont(SkFontID currFontID, SkFontID origFontID); - - /////////////////////////////////////////////////////////////////////////// - /** Given a filled-out rec, the fonthost may decide to modify it to reflect what the host is actually capable of fulfilling. For example, if the rec is requesting a level of hinting that, for this host, maps some @@ -230,67 +293,7 @@ public: /////////////////////////////////////////////////////////////////////////// - /** LCDs either have their color elements arranged horizontally or - vertically. When rendering subpixel glyphs we need to know which way - round they are. - - Note, if you change this after startup, you'll need to flush the glyph - cache because it'll have the wrong type of masks cached. - - @deprecated use SkPixelGeometry instead. - */ - enum LCDOrientation { - kHorizontal_LCDOrientation = 0, //!< this is the default - kVertical_LCDOrientation = 1 - }; - - /** @deprecated set on Device creation. */ - static void SetSubpixelOrientation(LCDOrientation orientation); - /** @deprecated get from Device. */ - static LCDOrientation GetSubpixelOrientation(); - - /** LCD color elements can vary in order. For subpixel text we need to know - the order which the LCDs uses so that the color fringes are in the - correct place. - - Note, if you change this after startup, you'll need to flush the glyph - cache because it'll have the wrong type of masks cached. - - kNONE_LCDOrder means that the subpixel elements are not spatially - separated in any usable fashion. - - @deprecated use SkPixelGeometry instead. - */ - enum LCDOrder { - kRGB_LCDOrder = 0, //!< this is the default - kBGR_LCDOrder = 1, - kNONE_LCDOrder = 2 - }; - - /** @deprecated set on Device creation. */ - static void SetSubpixelOrder(LCDOrder order); - /** @deprecated get from Device. */ - static LCDOrder GetSubpixelOrder(); - -#ifdef SK_BUILD_FOR_ANDROID - /////////////////////////////////////////////////////////////////////////// - - /** - * Return the number of font units per em. - * - * @param fontID the font to query. - * @return the number of font units per em or 0 on error. - */ - static uint32_t GetUnitsPerEm(SkFontID fontID); -#endif - - /** If Skia is running in a constrained environment and the typeface - implementation is handle based, the typeface data may become - unavailable asynchronously. If a font host or scaler context method is - unable to access font data, it may call this function as a request to - make the handle contained in the typeface useable. - */ - static void EnsureTypefaceAccessible(const SkTypeface& typeface); + friend class SkTypeface; }; #endif diff --git a/include/core/SkTypeface.h b/include/core/SkTypeface.h index 79b821f99..a531cf2c8 100644 --- a/include/core/SkTypeface.h +++ b/include/core/SkTypeface.h @@ -80,6 +80,12 @@ public: */ static bool Equal(const SkTypeface* facea, const SkTypeface* faceb); + /** + * Returns a ref() to the default typeface. The caller must call unref() + * when they are done referencing the object. Never returns NULL. + */ + static SkTypeface* RefDefault(); + /** Return a new reference to the typeface that most closely matches the requested familyName and style. Pass null as the familyName to return the default font for the requested style. Will never return null @@ -187,6 +193,8 @@ public: */ int getUnitsPerEm() const; + SkStream* openStream(int* ttcIndex) const; + protected: /** uniqueID must be unique and non-zero */ @@ -209,6 +217,7 @@ private: Style fStyle; bool fIsFixedWidth; + friend class SkPaint; // just so deprecated fonthost can call protected methods friend class SkFontHost; diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp index 37edfbb6f..b9dc5e5d0 100644 --- a/src/core/SkPaint.cpp +++ b/src/core/SkPaint.cpp @@ -1655,7 +1655,7 @@ void SkScalerContext::MakeRec(const SkPaint& paint, they can modify our rec up front, so we don't create duplicate cache entries. */ - SkFontHost::FilterRec(rec, typeface); + typeface->onFilterRec(rec); // be sure to call PostMakeRec(rec) before you actually use it! } diff --git a/src/core/SkTypeface.cpp b/src/core/SkTypeface.cpp index 769947072..80fa43825 100644 --- a/src/core/SkTypeface.cpp +++ b/src/core/SkTypeface.cpp @@ -49,6 +49,10 @@ SkTypeface* SkTypeface::GetDefaultTypeface() { return gDefaultTypeface; } +SkTypeface* SkTypeface::RefDefault() { + return SkRef(GetDefaultTypeface()); +} + uint32_t SkTypeface::UniqueID(const SkTypeface* face) { if (NULL == face) { face = GetDefaultTypeface(); @@ -121,6 +125,15 @@ size_t SkTypeface::getTableData(SkFontTableTag tag, size_t offset, size_t length return SkFontHost::GetTableData(fUniqueID, tag, offset, length, data); } +SkStream* SkTypeface::openStream(int* ttcIndex) const { + if (ttcIndex) { + int32_t ndx = 0; + (void)SkFontHost::GetFileName(fUniqueID, NULL, 0, &ndx); + *ttcIndex = (int)ndx; + } + return SkFontHost::OpenStream(fUniqueID); +} + int SkTypeface::getUnitsPerEm() const { int upem = 0; @@ -139,6 +152,16 @@ int SkTypeface::getUnitsPerEm() const { return upem; } +// TODO: move this impl into the subclass +SkScalerContext* SkTypeface::onCreateScalerContext(const SkDescriptor* desc) const { + return SkFontHost::CreateScalerContext(desc); +} + +// TODO: move this impl into the subclass +void SkTypeface::onFilterRec(SkScalerContextRec* rec) const { + SkFontHost::FilterRec(rec, const_cast(this)); +} + /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// @@ -148,10 +171,6 @@ int SkTypeface::onGetUPEM() const { return 0; } int SkTypeface::onGetTableTags(SkFontTableTag tags[]) const { return 0; } size_t SkTypeface::onGetTableData(SkFontTableTag, size_t offset, size_t length, void* data) const { return 0; } -SkScalerContext* SkTypeface::onCreateScalerContext(const SkDescriptor*) const { - return NULL; -} -void SkTypeface::onFilterRec(SkScalerContextRec*) const {} void SkTypeface::onGetFontDescriptor(SkFontDescriptor* desc) const { desc->setStyle(this->style()); } diff --git a/src/core/SkTypefacePriv.h b/src/core/SkTypefacePriv.h new file mode 100644 index 000000000..2f48372b0 --- /dev/null +++ b/src/core/SkTypefacePriv.h @@ -0,0 +1,38 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkTypefacePriv_DEFINED +#define SkTypefacePriv_DEFINED + +#include "SkTypeface.h" + +/** + * Return a ref'd typeface, which must later be unref'd + * + * If the parameter is non-null, it will be ref'd and returned, otherwise + * it will be the default typeface. + */ +static inline SkTypeface* ref_or_default(SkTypeface* face) { + return face ? SkRef(face) : SkTypeface::RefDefault(); +} + +/** + * Always resolves to a non-null typeface, either the value passed to its + * constructor, or the default typeface if null was passed. + */ +class SkAutoResolveDefaultTypeface : public SkAutoTUnref { +public: + SkAutoResolveDefaultTypeface() : INHERITED(SkTypeface::RefDefault()) {} + + SkAutoResolveDefaultTypeface(SkTypeface* face) + : INHERITED(ref_or_default(face)) {} + +private: + typedef SkAutoTUnref INHERITED; +}; + +#endif diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index be1bca591..8f0f3d255 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * @@ -6,7 +5,6 @@ * found in the LICENSE file. */ - #include "SkPDFDevice.h" #include "SkAnnotation.h" @@ -30,8 +28,7 @@ #include "SkString.h" #include "SkTextFormatParams.h" #include "SkTemplates.h" -#include "SkTypeface.h" -#include "SkTypes.h" +#include "SkTypefacePriv.h" // Utility functions @@ -104,10 +101,12 @@ static void align_text(SkDrawCacheProc glyphCacheProc, const SkPaint& paint, *y = *y - yAdj; } -static size_t max_glyphid_for_typeface(const SkTypeface* typeface) { +static size_t max_glyphid_for_typeface(SkTypeface* typeface) { + SkAutoResolveDefaultTypeface autoResolve(typeface); + typeface = autoResolve.get(); + SkAdvancedTypefaceMetrics* metrics; - metrics = SkFontHost::GetAdvancedTypefaceMetrics( - SkTypeface::UniqueID(typeface), + metrics = typeface->getAdvancedTypefaceMetrics( SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo, NULL, 0); diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp index 10252ad52..34f2feeeb 100644 --- a/src/pdf/SkPDFFont.cpp +++ b/src/pdf/SkPDFFont.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * @@ -6,7 +5,6 @@ * found in the LICENSE file. */ - #include #include "SkData.h" @@ -23,7 +21,7 @@ #include "SkRefCnt.h" #include "SkScalar.h" #include "SkStream.h" -#include "SkTypeface.h" +#include "SkTypefacePriv.h" #include "SkTypes.h" #include "SkUtils.h" @@ -549,8 +547,8 @@ static int get_subset_font_stream(const char* fontName, const SkTypeface* typeface, const SkTDArray& subset, SkPDFStream** fontStream) { - SkAutoTUnref fontData( - SkFontHost::OpenStream(SkTypeface::UniqueID(typeface))); + int ttcIndex; + SkAutoTUnref fontData(typeface->openStream(&ttcIndex)); int fontSize = fontData->getLength(); @@ -714,7 +712,7 @@ SkPDFFont::~SkPDFFont() { SkDEBUGCODE(int indexFound;) SkASSERT(index == -1 || - (Find(SkTypeface::UniqueID(fTypeface.get()), + (Find(fTypeface->uniqueID(), fFirstGlyphID, &indexFound) && index == indexFound)); @@ -763,7 +761,11 @@ size_t SkPDFFont::glyphsToPDFFontEncoding(uint16_t* glyphIDs, // static SkPDFFont* SkPDFFont::GetFontResource(SkTypeface* typeface, uint16_t glyphID) { SkAutoMutexAcquire lock(CanonicalFontsMutex()); - const uint32_t fontID = SkTypeface::UniqueID(typeface); + + SkAutoResolveDefaultTypeface autoResolve(typeface); + typeface = autoResolve.get(); + + const uint32_t fontID = typeface->uniqueID(); int relatedFontIndex; if (Find(fontID, glyphID, &relatedFontIndex)) { CanonicalFonts()[relatedFontIndex].fFont->ref(); @@ -800,7 +802,7 @@ SkPDFFont* SkPDFFont::GetFontResource(SkTypeface* typeface, uint16_t glyphID) { info, SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo); #endif fontMetrics.reset( - SkFontHost::GetAdvancedTypefaceMetrics(fontID, info, NULL, 0)); + typeface->getAdvancedTypefaceMetrics(info, NULL, 0)); #if defined (SK_SFNTLY_SUBSETTER) if (fontMetrics.get() && fontMetrics->fType != SkAdvancedTypefaceMetrics::kTrueType_Font) { @@ -808,7 +810,7 @@ SkPDFFont* SkPDFFont::GetFontResource(SkTypeface* typeface, uint16_t glyphID) { info = SkTBitOr( info, SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo); fontMetrics.reset( - SkFontHost::GetAdvancedTypefaceMetrics(fontID, info, NULL, 0)); + typeface->getAdvancedTypefaceMetrics(info, NULL, 0)); } #endif } @@ -855,7 +857,7 @@ bool SkPDFFont::Find(uint32_t fontID, uint16_t glyphID, int* index) { SkPDFFont::SkPDFFont(SkAdvancedTypefaceMetrics* info, SkTypeface* typeface, SkPDFDict* relatedFontDescriptor) : SkPDFDict("Font"), - fTypeface(typeface), + fTypeface(ref_or_default(typeface)), fFirstGlyphID(1), fLastGlyphID(info ? info->fLastGlyphID : 0), fFontInfo(info), @@ -1099,8 +1101,8 @@ bool SkPDFCIDFont::addFontDescriptor(int16_t defaultWidth, } case SkAdvancedTypefaceMetrics::kCFF_Font: case SkAdvancedTypefaceMetrics::kType1CID_Font: { - SkAutoTUnref fontData( - SkFontHost::OpenStream(SkTypeface::UniqueID(typeface()))); + int ttcIndex; + SkAutoTUnref fontData(typeface()->openStream(&ttcIndex)); SkAutoTUnref fontStream( new SkPDFStream(fontData.get())); addResource(fontStream.get()); @@ -1139,11 +1141,7 @@ bool SkPDFCIDFont::populate(const SkPDFGlyphSet* subset) { uint32_t* glyphs = (glyphIDs.count() == 1) ? NULL : glyphIDs.begin(); uint32_t glyphsCount = glyphs ? glyphIDs.count() : 0; SkAutoTUnref fontMetrics( - SkFontHost::GetAdvancedTypefaceMetrics( - SkTypeface::UniqueID(typeface()), - info, - glyphs, - glyphsCount)); + typeface()->getAdvancedTypefaceMetrics(info, glyphs, glyphsCount)); setFontInfo(fontMetrics.get()); addFontDescriptor(0, &glyphIDs); } else { @@ -1229,11 +1227,11 @@ bool SkPDFType1Font::addFontDescriptor(int16_t defaultWidth) { SkAutoTUnref descriptor(new SkPDFDict("FontDescriptor")); setFontDescriptor(descriptor.get()); + int ttcIndex; size_t header SK_INIT_TO_AVOID_WARNING; size_t data SK_INIT_TO_AVOID_WARNING; size_t trailer SK_INIT_TO_AVOID_WARNING; - SkAutoTUnref rawFontData( - SkFontHost::OpenStream(SkTypeface::UniqueID(typeface()))); + SkAutoTUnref rawFontData(typeface()->openStream(&ttcIndex)); SkStream* fontData = handleType1Stream(rawFontData.get(), &header, &data, &trailer); if (fontData == NULL) { diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp index 4a6b8d8b6..ae1e75e4d 100755 --- a/src/ports/SkFontHost_mac.cpp +++ b/src/ports/SkFontHost_mac.cpp @@ -1681,7 +1681,6 @@ SkStream* SkFontHost::OpenStream(SkFontID uniqueID) { } size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length, int32_t* index) { - SkDEBUGFAIL("SkFontHost::GetFileName unimplemented"); return 0; } diff --git a/tests/FontHostStreamTest.cpp b/tests/FontHostStreamTest.cpp index bbf1a03ef..4fd88cc4d 100644 --- a/tests/FontHostStreamTest.cpp +++ b/tests/FontHostStreamTest.cpp @@ -91,8 +91,13 @@ static void test_fontHostStream(skiatest::Reporter* reporter) { origCanvas.drawText("A", 1, point.fX, point.fY, paint); SkTypeface* origTypeface = paint.getTypeface(); - const SkFontID typefaceID = SkTypeface::UniqueID(origTypeface); - SkStream* fontData = SkFontHost::OpenStream(typefaceID); + SkAutoTUnref aur; + if (NULL == origTypeface) { + origTypeface = aur.reset(SkTypeface::RefDefault()); + } + + int ttcIndex; + SkStream* fontData = origTypeface->openStream(&ttcIndex); SkTypeface* streamTypeface = SkTypeface::CreateFromStream(fontData); SkSafeUnref(paint.setTypeface(streamTypeface)); drawBG(&streamCanvas);