diff options
author | bungeman <bungeman@google.com> | 2015-05-13 12:16:41 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-05-13 12:16:41 -0700 |
commit | 5ae1312c9faa25531c07e591b4dff6804020f121 (patch) | |
tree | 5ad34f4f5ddbe8f628d078be9480444d0d883f1d | |
parent | 1573206f202c6d2ffcffab78b17160da95a80466 (diff) |
Revert of Font variations. (patchset #21 id:400001 of https://codereview.chromium.org/1027373002/)
Reason for revert:
Mac failing to build due to CFNumberType in Chromium Canary.
Original issue's description:
> Font variations.
>
> Multiple Master and TrueType fonts support variation axes.
> This implements back-end support for axes on platforms which
> support it.
>
> Committed: https://skia.googlesource.com/skia/+/05773ed30920c0214d1433c07cf6360a05476c97
TBR=reed@google.com,mtklein@google.com,djsollen@google.com,halcanary@google.com
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
Review URL: https://codereview.chromium.org/1128913008
24 files changed, 134 insertions, 889 deletions
diff --git a/gm/fontscalerdistortable.cpp b/gm/fontscalerdistortable.cpp deleted file mode 100644 index 715f32169c..0000000000 --- a/gm/fontscalerdistortable.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2015 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#include "gm.h" -#include "Resources.h" -#include "SkFixed.h" -#include "SkFontDescriptor.h" -#include "SkFontMgr.h" -#include "SkTypeface.h" - -namespace skiagm { - -class FontScalerDistortableGM : public GM { -public: - FontScalerDistortableGM() { - this->setBGColor(0xFFFFFFFF); - } - - virtual ~FontScalerDistortableGM() { } - -protected: - - SkString onShortName() override { - return SkString("fontscalerdistortable"); - } - - SkISize onISize() override { - return SkISize::Make(550, 700); - } - - static void rotate_about(SkCanvas* canvas, SkScalar degrees, SkScalar px, SkScalar py) { - canvas->translate(px, py); - canvas->rotate(degrees); - canvas->translate(-px, -py); - } - - void onDraw(SkCanvas* canvas) override { - SkPaint paint; - paint.setAntiAlias(true); - paint.setLCDRenderText(true); - - SkAutoTDelete<SkStreamAsset> distortable(GetResourceAsStream("/fonts/Distortable.ttf")); - if (!distortable) { - return; - } - const char* text = "abc"; - const size_t textLen = strlen(text); - - for (int j = 0; j < 2; ++j) { - for (int i = 0; i < 5; ++i) { - SkScalar x = SkIntToScalar(10); - SkScalar y = SkIntToScalar(20); - - SkFixed axis = SkDoubleToFixed(0.5 + (5*j + i) * ((2.0 - 0.5) / (2 * 5))); - SkAutoTUnref<SkTypeface> typeface(SkTypeface::CreateFromFontData( - new SkFontData(distortable->duplicate(), 0, &axis, 1))); - paint.setTypeface(typeface); - - SkAutoCanvasRestore acr(canvas, true); - canvas->translate(SkIntToScalar(30 + i * 100), SkIntToScalar(20)); - rotate_about(canvas, SkIntToScalar(i * 5), x, y * 10); - - { - SkPaint p; - p.setAntiAlias(true); - SkRect r; - r.set(x - SkIntToScalar(3), SkIntToScalar(15), - x - SkIntToScalar(1), SkIntToScalar(280)); - canvas->drawRect(r, p); - } - - for (int ps = 6; ps <= 22; ps++) { - paint.setTextSize(SkIntToScalar(ps)); - canvas->drawText(text, textLen, x, y, paint); - y += paint.getFontMetrics(NULL); - } - } - canvas->translate(0, SkIntToScalar(360)); - paint.setSubpixelText(true); - } - } - -private: - typedef GM INHERITED; -}; - -////////////////////////////////////////////////////////////////////////////// - -static GM* MyFactory(void*) { return new FontScalerDistortableGM; } -static GMRegistry reg(MyFactory); - -} diff --git a/gyp/gmslides.gypi b/gyp/gmslides.gypi index cc88e07a52..79333bdc9f 100644 --- a/gyp/gmslides.gypi +++ b/gyp/gmslides.gypi @@ -109,7 +109,6 @@ '../gm/fontcache.cpp', '../gm/fontmgr.cpp', '../gm/fontscaler.cpp', - '../gm/fontscalerdistortable.cpp', '../gm/gammatext.cpp', '../gm/getpostextpath.cpp', '../gm/giantbitmap.cpp', diff --git a/include/core/SkTypeface.h b/include/core/SkTypeface.h index f0059deb25..7d8b892f2c 100644 --- a/include/core/SkTypeface.h +++ b/include/core/SkTypeface.h @@ -17,7 +17,6 @@ #include "SkWeakRefCnt.h" class SkDescriptor; -class SkFontData; class SkFontDescriptor; class SkScalerContext; struct SkScalerContextRec; @@ -135,12 +134,6 @@ public: */ static SkTypeface* CreateFromStream(SkStreamAsset* stream, int index = 0); - /** Return a new typeface given font data and configuration. If the data - is not valid font data, returns null. Ownership of the font data is - transferred, so the caller must not reference it again. - */ - static SkTypeface* CreateFromFontData(SkFontData*); - /** Write a unique signature to a stream, sufficient to reconstruct a typeface referencing the same font when Deserialize is called. */ @@ -291,12 +284,6 @@ public: SkStreamAsset* openStream(int* ttcIndex) const; /** - * Return the font data, or NULL on failure. - * The caller is responsible for deleting the font data. - */ - SkFontData* createFontData() const; - - /** * Return a scalercontext for the given descriptor. If this fails, then * if allowFailure is true, this returns NULL, else it returns a * dummy scalercontext that will not crash, but will draw nothing. @@ -350,9 +337,6 @@ protected: uint32_t glyphIDsCount) const = 0; virtual SkStreamAsset* onOpenStream(int* ttcIndex) const = 0; - // TODO: make pure virtual. - virtual SkFontData* onCreateFontData() const; - virtual void onGetFontDescriptor(SkFontDescriptor*, bool* isLocal) const = 0; virtual int onCharsToGlyphs(const void* chars, Encoding, uint16_t glyphs[], diff --git a/include/ports/SkFontMgr.h b/include/ports/SkFontMgr.h index 48a0494a7a..4dde920085 100644 --- a/include/ports/SkFontMgr.h +++ b/include/ports/SkFontMgr.h @@ -12,7 +12,6 @@ #include "SkFontStyle.h" class SkData; -class SkFontData; class SkStreamAsset; class SkString; class SkTypeface; @@ -96,14 +95,6 @@ public: SkTypeface* createFromStream(SkStreamAsset*, int ttcIndex = 0) const; /** - * Create a typeface from the specified font data. - * Takes ownership of the font data, so the caller should not reference it again. - * Will return NULL if the typeface could not be created. - * The caller must call unref() on the returned object if it is not null. - */ - SkTypeface* createFromFontData(SkFontData*) const; - - /** * Create a typeface for the specified fileName and TTC index * (pass 0 for none) or NULL if the file is not found, or its contents are * not recognized. The caller must call unref() on the returned object @@ -138,8 +129,6 @@ protected: virtual SkTypeface* onCreateFromData(SkData*, int ttcIndex) const = 0; virtual SkTypeface* onCreateFromStream(SkStreamAsset*, int ttcIndex) const = 0; - // TODO: make pure virtual. - virtual SkTypeface* onCreateFromFontData(SkFontData*) const; virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const = 0; virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], diff --git a/resources/android_fonts/v22/fonts.xml b/resources/android_fonts/v22/fonts.xml index f310ac4dfd..b9ea87fc0d 100644 --- a/resources/android_fonts/v22/fonts.xml +++ b/resources/android_fonts/v22/fonts.xml @@ -25,18 +25,6 @@ <alias name="tahoma" to="sans-serif" /> <alias name="verdana" to="sans-serif" /> - <family name="var"> - <font weight="100" style="normal"><axis tag="wght" stylevalue="0.5"/>Distortable.ttf</font> - <font weight="200" style="normal"><axis tag="wght" stylevalue="0.65"/>Distortable.ttf</font> - <font weight="300" style="normal"><axis tag="wght" stylevalue="0.85"/>Distortable.ttf</font> - <font weight="400" style="normal"><axis tag="wght" stylevalue="1.0"/>Distortable.ttf</font> - <font weight="500" style="normal"><axis tag="wght" stylevalue="1.2"/>Distortable.ttf</font> - <font weight="600" style="normal"><axis tag="wght" stylevalue="1.4"/>Distortable.ttf</font> - <font weight="700" style="normal"><axis tag="wght" stylevalue="1.6"/>Distortable.ttf</font> - <font weight="800" style="normal"><axis tag="wght" stylevalue="1.8"/>Distortable.ttf</font> - <font weight="900" style="normal"><axis tag="wght" stylevalue="2.0"/>Distortable.ttf</font> - </family> - <family name="sans-serif-condensed"> <font weight="300" style="normal">RobotoCondensed-Light.ttf</font> <font weight="300" style="italic">RobotoCondensed-LightItalic.ttf</font> diff --git a/src/core/SkAdvancedTypefaceMetrics.h b/src/core/SkAdvancedTypefaceMetrics.h index 877a2d60fb..34c5211ba4 100644 --- a/src/core/SkAdvancedTypefaceMetrics.h +++ b/src/core/SkAdvancedTypefaceMetrics.h @@ -43,7 +43,7 @@ public: enum FontFlags { kEmpty_FontFlag = 0x0, //!<No flags set - kMultiMaster_FontFlag = 0x1, //!<May be true for Type1, CFF, or TrueType fonts. + kMultiMaster_FontFlag = 0x1, //!<May be true for Type1 or CFF fonts. kNotEmbeddable_FontFlag = 0x2, //!<May not be embedded. kNotSubsettable_FontFlag = 0x4, //!<May not be subset. }; diff --git a/src/core/SkFontDescriptor.cpp b/src/core/SkFontDescriptor.cpp index cb149b98a9..4a6b5db837 100644 --- a/src/core/SkFontDescriptor.cpp +++ b/src/core/SkFontDescriptor.cpp @@ -17,13 +17,12 @@ enum { // These count backwards from 0xFF, so as not to collide with the SFNT // defines for names in its 'name' table. - kFontAxes = 0xFC, kFontIndex = 0xFD, kFontFileName = 0xFE, // Remove when MIN_PICTURE_VERSION > 41 kSentinel = 0xFF, }; -SkFontDescriptor::SkFontDescriptor(SkTypeface::Style style) : fStyle(style) { } +SkFontDescriptor::SkFontDescriptor(SkTypeface::Style style) : fFontIndex(0), fStyle(style) { } static void read_string(SkStream* stream, SkString* string) { const uint32_t length = SkToU32(stream->readPackedUInt()); @@ -41,7 +40,8 @@ static void skip_string(SkStream* stream) { } } -static void write_string(SkWStream* stream, const SkString& string, uint32_t id) { +static void write_string(SkWStream* stream, const SkString& string, + uint32_t id) { if (!string.isEmpty()) { stream->writePackedUInt(id); stream->writePackedUInt(string.size()); @@ -58,12 +58,9 @@ static void write_uint(SkWStream* stream, size_t n, uint32_t id) { stream->writePackedUInt(n); } -SkFontDescriptor::SkFontDescriptor(SkStream* stream) { +SkFontDescriptor::SkFontDescriptor(SkStream* stream) : fFontIndex(0) { fStyle = (SkTypeface::Style)stream->readPackedUInt(); - SkAutoSTMalloc<4, SkFixed> axis; - size_t axisCount = 0; - size_t index = 0; for (size_t id; (id = stream->readPackedUInt()) != kSentinel;) { switch (id) { case kFontFamilyName: @@ -75,15 +72,8 @@ SkFontDescriptor::SkFontDescriptor(SkStream* stream) { case kPostscriptName: read_string(stream, &fPostscriptName); break; - case kFontAxes: - axisCount = read_uint(stream); - axis.reset(axisCount); - for (size_t i = 0; i < axisCount; ++i) { - axis[i] = read_uint(stream); - } - break; case kFontIndex: - index = read_uint(stream); + fFontIndex = read_uint(stream); break; case kFontFileName: // Remove when MIN_PICTURE_VERSION > 41 skip_string(stream); @@ -98,8 +88,7 @@ SkFontDescriptor::SkFontDescriptor(SkStream* stream) { if (length > 0) { SkAutoTUnref<SkData> data(SkData::NewUninitialized(length)); if (stream->read(data->writable_data(), length) == length) { - fFontData.reset(new SkFontData(SkNEW_ARGS(SkMemoryStream, (data)), index, - axis, axisCount)); + fFontData.reset(SkNEW_ARGS(SkMemoryStream, (data))); } } } @@ -110,25 +99,16 @@ void SkFontDescriptor::serialize(SkWStream* stream) { write_string(stream, fFamilyName, kFontFamilyName); write_string(stream, fFullName, kFullName); write_string(stream, fPostscriptName, kPostscriptName); - if (fFontData.get()) { - if (fFontData->getIndex()) { - write_uint(stream, fFontData->getIndex(), kFontIndex); - } - if (fFontData->getAxisCount()) { - write_uint(stream, fFontData->getAxisCount(), kFontAxes); - for (int i = 0; i < fFontData->getAxisCount(); ++i) { - stream->writePackedUInt(fFontData->getAxis()[i]); - } - } + if (fFontIndex) { + write_uint(stream, fFontIndex, kFontIndex); } stream->writePackedUInt(kSentinel); - if (fFontData.get() && fFontData->hasStream()) { - SkAutoTDelete<SkStreamAsset> fontData(fFontData->detachStream()); - size_t length = fontData->getLength(); + if (fFontData) { + size_t length = fFontData->getLength(); stream->writePackedUInt(length); - stream->writeStream(fontData, length); + stream->writeStream(fFontData, length); } else { stream->writePackedUInt(0); } diff --git a/src/core/SkFontDescriptor.h b/src/core/SkFontDescriptor.h index 933a36a095..66707ddd3c 100644 --- a/src/core/SkFontDescriptor.h +++ b/src/core/SkFontDescriptor.h @@ -12,42 +12,7 @@ #include "SkString.h" #include "SkTypeface.h" -class SkFontData { -public: - /** This takes ownership of 'stream'. Makes a copy of the data in 'axis'. */ - SkFontData(SkStreamAsset* stream, int index, const SkFixed axis[], int axisCount) - : fStream(stream), fIndex(index), fAxisCount(axisCount), fAxis(axisCount) - { - for (int i = 0; i < axisCount; ++i) { - fAxis[i] = axis[i]; - } - } - SkFontData(const SkFontData& that) - : fStream(that.fStream->duplicate()) - , fIndex(that.fIndex) - , fAxisCount(that.fAxisCount) - , fAxis(fAxisCount) - { - for (int i = 0; i < fAxisCount; ++i) { - fAxis[i] = that.fAxis[i]; - } - } - bool hasStream() const { return fStream.get() != NULL; } - SkStreamAsset* duplicateStream() const { return fStream->duplicate(); } - SkStreamAsset* detachStream() { return fStream.detach(); } - SkStreamAsset* getStream() { return fStream.get(); } - int getIndex() const { return fIndex; } - int getAxisCount() const { return fAxisCount; } - const SkFixed* getAxis() const { return fAxis.get(); } - -private: - SkAutoTDelete<SkStreamAsset> fStream; - int fIndex; - int fAxisCount; - SkAutoSTMalloc<4, SkFixed> fAxis; -}; - -class SkFontDescriptor : SkNoncopyable { +class SkFontDescriptor { public: SkFontDescriptor(SkTypeface::Style = SkTypeface::kNormal); // Does not affect ownership of SkStream. @@ -62,20 +27,25 @@ public: const char* getFullName() const { return fFullName.c_str(); } const char* getPostscriptName() const { return fPostscriptName.c_str(); } bool hasFontData() const { return fFontData.get() != NULL; } - SkFontData* detachFontData() { return fFontData.detach(); } + // Transfers ownership to the caller. + SkStreamAsset* transferFontData() { return fFontData.detach(); } + int getFontIndex() const { return fFontIndex; } void setFamilyName(const char* name) { fFamilyName.set(name); } void setFullName(const char* name) { fFullName.set(name); } void setPostscriptName(const char* name) { fPostscriptName.set(name); } /** Set the font data only if it is necessary for serialization. - * This method takes ownership of the font data. */ - void setFontData(SkFontData* data) { fFontData.reset(data); } + * This method takes ownership of the stream (both reference and cursor). + */ + void setFontData(SkStreamAsset* stream) { fFontData.reset(stream); } + void setFontIndex(int index) { fFontIndex = index; } private: SkString fFamilyName; SkString fFullName; SkString fPostscriptName; - SkAutoTDelete<SkFontData> fFontData; + SkAutoTDelete<SkStreamAsset> fFontData; + int fFontIndex; SkTypeface::Style fStyle; }; diff --git a/src/core/SkFontMgr.cpp b/src/core/SkFontMgr.cpp index 33da1db376..a03e05e0e4 100644 --- a/src/core/SkFontMgr.cpp +++ b/src/core/SkFontMgr.cpp @@ -5,7 +5,6 @@ * found in the LICENSE file. */ -#include "SkFontDescriptor.h" #include "SkFontMgr.h" #include "SkLazyPtr.h" #include "SkStream.h" @@ -134,20 +133,6 @@ SkTypeface* SkFontMgr::createFromStream(SkStreamAsset* stream, int ttcIndex) con return this->onCreateFromStream(stream, ttcIndex); } -SkTypeface* SkFontMgr::createFromFontData(SkFontData* data) const { - if (NULL == data) { - return NULL; - } - return this->onCreateFromFontData(data); -} - -// This implementation is temporary until it can be made pure virtual. -SkTypeface* SkFontMgr::onCreateFromFontData(SkFontData* data) const { - SkTypeface* ret = this->createFromStream(data->detachStream(), data->getIndex()); - delete data; - return ret; -} - SkTypeface* SkFontMgr::createFromFile(const char path[], int ttcIndex) const { if (NULL == path) { return NULL; diff --git a/src/core/SkTypeface.cpp b/src/core/SkTypeface.cpp index 6d9759f42c..0f5d70b1a8 100644 --- a/src/core/SkTypeface.cpp +++ b/src/core/SkTypeface.cpp @@ -143,11 +143,6 @@ SkTypeface* SkTypeface::CreateFromStream(SkStreamAsset* stream, int index) { return fm->createFromStream(stream, index); } -SkTypeface* SkTypeface::CreateFromFontData(SkFontData* data) { - SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault()); - return fm->createFromFontData(data); -} - SkTypeface* SkTypeface::CreateFromFile(const char path[], int index) { SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault()); return fm->createFromFile(path, index); @@ -161,8 +156,10 @@ void SkTypeface::serialize(SkWStream* wstream) const { this->onGetFontDescriptor(&desc, &isLocal); // Embed font data if it's a local font. - if (!desc.hasFontData()) { - desc.setFontData(this->onCreateFontData()); + if (isLocal && !desc.hasFontData()) { + int ttcIndex; + desc.setFontData(this->onOpenStream(&ttcIndex)); + desc.setFontIndex(ttcIndex); } desc.serialize(wstream); } @@ -174,16 +171,18 @@ void SkTypeface::serializeForcingEmbedding(SkWStream* wstream) const { // Always embed font data. if (!desc.hasFontData()) { - desc.setFontData(this->onCreateFontData()); + int ttcIndex; + desc.setFontData(this->onOpenStream(&ttcIndex)); + desc.setFontIndex(ttcIndex); } desc.serialize(wstream); } SkTypeface* SkTypeface::Deserialize(SkStream* stream) { SkFontDescriptor desc(stream); - SkFontData* data = desc.detachFontData(); + SkStreamAsset* data = desc.transferFontData(); if (data) { - SkTypeface* typeface = SkTypeface::CreateFromFontData(data); + SkTypeface* typeface = SkTypeface::CreateFromStream(data, desc.getFontIndex()); if (typeface) { return typeface; } @@ -219,17 +218,6 @@ SkStreamAsset* SkTypeface::openStream(int* ttcIndex) const { return this->onOpenStream(ttcIndex); } -SkFontData* SkTypeface::createFontData() const { - return this->onCreateFontData(); -} - -// This implementation is temporary until this method can be made pure virtual. -SkFontData* SkTypeface::onCreateFontData() const { - int index; - SkAutoTDelete<SkStreamAsset> stream(this->onOpenStream(&index)); - return new SkFontData(stream.detach(), index, NULL, 0); -}; - int SkTypeface::charsToGlyphs(const void* chars, Encoding encoding, uint16_t glyphs[], int glyphCount) const { if (glyphCount <= 0) { diff --git a/src/fonts/SkFontMgr_fontconfig.cpp b/src/fonts/SkFontMgr_fontconfig.cpp index 9294990c98..9bdc9272f3 100644 --- a/src/fonts/SkFontMgr_fontconfig.cpp +++ b/src/fonts/SkFontMgr_fontconfig.cpp @@ -308,7 +308,7 @@ protected: // TODO should the caller give us the style or should we get it from freetype? SkFontStyle style; bool isFixedWidth = false; - if (!fScanner.scanFont(stream, 0, NULL, &style, &isFixedWidth, NULL)) { + if (!fScanner.scanFont(stream, 0, NULL, &style, &isFixedWidth)) { return NULL; } diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp index 89402f10a5..0afdb9b616 100644 --- a/src/pdf/SkPDFFont.cpp +++ b/src/pdf/SkPDFFont.cpp @@ -887,7 +887,9 @@ SkPDFFont* SkPDFFont::Create(SkPDFCanon* canon, SkAdvancedTypefaceMetrics::FontType type = info ? info->fType : SkAdvancedTypefaceMetrics::kOther_Font; - if (info && (info->fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag)) { + if (info && + (info->fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag)) { + NOT_IMPLEMENTED(true, true); return new SkPDFType3Font(info, typeface, glyphID); } if (type == SkAdvancedTypefaceMetrics::kType1CID_Font || diff --git a/src/ports/SkFontConfigParser_android.cpp b/src/ports/SkFontConfigParser_android.cpp index 3825a72903..73e4c47738 100644 --- a/src/ports/SkFontConfigParser_android.cpp +++ b/src/ports/SkFontConfigParser_android.cpp @@ -14,7 +14,9 @@ #include <expat.h> #include <dirent.h> +#include <stdio.h> +#include <limits> #include <stdlib.h> #define LMP_SYSTEM_FONTS_FILE "/system/etc/fonts.xml" @@ -109,6 +111,32 @@ struct FamilyData { SkTDArray<const TagHandler*> fHandler; // The stack of current tag handlers. }; +/** Parses a null terminated string into an integer type, checking for overflow. + * http://www.w3.org/TR/html-markup/datatypes.html#common.data.integer.non-negative-def + * + * If the string cannot be parsed into 'value', returns false and does not change 'value'. + */ +template <typename T> static bool parse_non_negative_integer(const char* s, T* value) { + SK_COMPILE_ASSERT(std::numeric_limits<T>::is_integer, T_must_be_integer); + const T nMax = std::numeric_limits<T>::max() / 10; + const T dMax = std::numeric_limits<T>::max() - (nMax * 10); + T n = 0; + for (; *s; ++s) { + // Check if digit + if (*s < '0' || '9' < *s) { + return false; + } + int d = *s - '0'; + // Check for overflow + if (n > nMax || (n == nMax && d > dMax)) { + return false; + } + n = (n * 10) + d; + } + *value = n; + return true; +} + static bool memeq(const char* s1, const char* s2, size_t n1, size_t n2) { return n1 == n2 && 0 == memcmp(s1, s2, n1); } @@ -146,43 +174,6 @@ static void trim_string(SkString* s) { namespace lmpParser { -static const TagHandler axisHandler = { - /*start*/[](FamilyData* self, const char* tag, const char** attributes) { - FontFileInfo& file = *self->fCurrentFontInfo; - FontFileInfo::Axis& axis = file.fAxes.push_back(); - for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { - const char* name = attributes[i]; - const char* value = attributes[i+1]; - size_t nameLen = strlen(name); - if (MEMEQ("tag", name, nameLen)) { - size_t valueLen = strlen(value); - if (valueLen == 4) { - SkFourByteTag tag = SkSetFourByteTag(value[0], value[1], value[2], value[3]); - for (int j = 0; j < file.fAxes.count() - 1; ++j) { - if (file.fAxes[j].fTag == tag) { - SK_FONTCONFIGPARSER_WARNING("'%c%c%c%c' axis specified more than once", - (tag >> 24) & 0xFF, - (tag >> 16) & 0xFF, - (tag >> 8) & 0xFF, - (tag ) & 0xFF); - } - } - axis.fTag = SkSetFourByteTag(value[0], value[1], value[2], value[3]); - } else { - SK_FONTCONFIGPARSER_WARNING("'%s' is an invalid axis tag", value); - } - } else if (MEMEQ("stylevalue", name, nameLen)) { - if (!parse_fixed<16>(value, &axis.fValue)) { - SK_FONTCONFIGPARSER_WARNING("'%s' is an invalid axis stylevalue", value); - } - } - } - }, - /*end*/NULL, - /*tag*/NULL, - /*chars*/NULL, -}; - static const TagHandler fontHandler = { /*start*/[](FamilyData* self, const char* tag, const char** attributes) { // 'weight' (non-negative integer) [default 0] @@ -216,13 +207,7 @@ static const TagHandler fontHandler = { /*end*/[](FamilyData* self, const char* tag) { trim_string(&self->fCurrentFontInfo->fFileName); }, - /*tag*/[](FamilyData* self, const char* tag, const char** attributes) -> const TagHandler* { - size_t len = strlen(tag); - if (MEMEQ("axis", tag, len)) { - return &axisHandler; - } - return NULL; - }, + /*tag*/NULL, /*chars*/[](void* data, const char* s, int len) { FamilyData* self = static_cast<FamilyData*>(data); self->fCurrentFontInfo->fFileName.append(s, len); diff --git a/src/ports/SkFontConfigParser_android.h b/src/ports/SkFontConfigParser_android.h index c1327ff74e..dd856bf733 100644 --- a/src/ports/SkFontConfigParser_android.h +++ b/src/ports/SkFontConfigParser_android.h @@ -12,9 +12,6 @@ #include "SkString.h" #include "SkTDArray.h" -#include <climits> -#include <limits> - /** \class SkLanguage The SkLanguage class represents a human written language, and is used by @@ -71,12 +68,6 @@ struct FontFileInfo { int fIndex; int fWeight; enum class Style { kAuto, kNormal, kItalic } fStyle; - struct Axis { - Axis() : fTag(SkSetFourByteTag('\0','\0','\0','\0')), fValue(0) { } - SkFourByteTag fTag; - SkFixed fValue; - }; - SkSTArray<4, Axis, true> fAxes; }; /** @@ -117,100 +108,4 @@ void GetCustomFontFamilies(SkTDArray<FontFamily*>& fontFamilies, } // SkFontConfigParser namespace - -/** Parses a null terminated string into an integer type, checking for overflow. - * http://www.w3.org/TR/html-markup/datatypes.html#common.data.integer.non-negative-def - * - * If the string cannot be parsed into 'value', returns false and does not change 'value'. - */ -template <typename T> static bool parse_non_negative_integer(const char* s, T* value) { - SK_COMPILE_ASSERT(std::numeric_limits<T>::is_integer, T_must_be_integer); - - if (*s == '\0') { - return false; - } - - const T nMax = std::numeric_limits<T>::max() / 10; - const T dMax = std::numeric_limits<T>::max() - (nMax * 10); - T n = 0; - for (; *s; ++s) { - // Check if digit - if (*s < '0' || '9' < *s) { - return false; - } - T d = *s - '0'; - // Check for overflow - if (n > nMax || (n == nMax && d > dMax)) { - return false; - } - n = (n * 10) + d; - } - *value = n; - return true; -} - -/** Parses a null terminated string into a signed fixed point value with bias N. - * - * Like http://www.w3.org/TR/html-markup/datatypes.html#common.data.float-def , - * but may start with '.' and does not support 'e'. '-?((:digit:+(.:digit:+)?)|(.:digit:+))' - * - * Checks for overflow. - * Low bit rounding is not defined (is currently truncate). - * Bias (N) required to allow for the sign bit and 4 bits of integer. - * - * If the string cannot be parsed into 'value', returns false and does not change 'value'. - */ -template <int N, typename T> static bool parse_fixed(const char* s, T* value) { - SK_COMPILE_ASSERT(std::numeric_limits<T>::is_integer, T_must_be_integer); - SK_COMPILE_ASSERT(std::numeric_limits<T>::is_signed, T_must_be_signed); - SK_COMPILE_ASSERT(sizeof(T) * CHAR_BIT - N >= 5, N_must_leave_four_bits_plus_sign); - - bool negate = false; - if (*s == '-') { - ++s; - negate = true; - } - if (*s == '\0') { - return false; - } - - const T nMax = (std::numeric_limits<T>::max() >> N) / 10; - const T dMax = (std::numeric_limits<T>::max() >> N) - (nMax * 10); - T n = 0; - T frac = 0; - for (; *s; ++s) { - // Check if digit - if (*s < '0' || '9' < *s) { - // If it wasn't a digit, check if it is a '.' followed by something. - if (*s != '.' || s[1] == '\0') { - return false; - } - // Find the end, verify digits. - for (++s; *s; ++s) { - if (*s < '0' || '9' < *s) { - return false; - } - } - // Read back toward the '.'. - for (--s; *s != '.'; --s) { - T d = *s - '0'; - frac = (frac + (d << N)) / 10; // This requires four bits overhead. - } - break; - } - T d = *s - '0'; - // Check for overflow - if (n > nMax || (n == nMax && d > dMax)) { - return false; - } - n = (n * 10) + d; - } - if (negate) { - n = -n; - frac = -frac; - } - *value = (n << N) + frac; - return true; -} - #endif /* SKFONTCONFIGPARSER_ANDROID_H_ */ diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp index a4305bfa87..5c53b9d913 100644 --- a/src/ports/SkFontHost_FreeType.cpp +++ b/src/ports/SkFontHost_FreeType.cpp @@ -11,7 +11,6 @@ #include "SkColorPriv.h" #include "SkDescriptor.h" #include "SkFDot6.h" -#include "SkFontDescriptor.h" #include "SkFontHost_FreeType_common.h" #include "SkGlyph.h" #include "SkMask.h" @@ -34,7 +33,6 @@ #include FT_FREETYPE_H #include FT_LCD_FILTER_H #include FT_MODULE_H -#include FT_MULTIPLE_MASTERS_H #include FT_OUTLINE_H #include FT_SIZES_H #include FT_SYSTEM_H @@ -275,37 +273,6 @@ SkFaceRec::SkFaceRec(SkStreamAsset* stream, uint32_t fontID) fFTStream.close = sk_ft_stream_close; } -static void ft_face_setup_axes(FT_Face face, const SkFontData& data) { - if (!(face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS)) { - return; - } - - SkDEBUGCODE( - FT_MM_Var* variations = NULL; - if (FT_Get_MM_Var(face, &variations)) { - SkDEBUGF(("INFO: font %s claims variations, but none found.\n", face->family_name)); - return; - } - SkAutoFree autoFreeVariations(variations); - - if (static_cast<FT_UInt>(data.getAxisCount()) != variations->num_axis) { - SkDEBUGF(("INFO: font %s has %d variations, but %d were specified.\n", - face->family_name, variations->num_axis, data.getAxisCount())); - return; - } - ) - - SkAutoSTMalloc<4, FT_Fixed> coords(data.getAxisCount()); - for (int i = 0; i < data.getAxisCount(); ++i) { - coords[i] = data.getAxis()[i]; - } - if (FT_Set_Var_Design_Coordinates(face, data.getAxisCount(), coords.get())) { - SkDEBUGF(("INFO: font %s has variations, but specified variations could not be set.\n", - face->family_name)); - return; - } -} - // Will return 0 on failure // Caller must lock gFTMutex before calling this function. static SkFaceRec* ref_ft_face(const SkTypeface* typeface) { @@ -322,36 +289,34 @@ static SkFaceRec* ref_ft_face(const SkTypeface* typeface) { rec = rec->fNext; } - SkAutoTDelete<SkFontData> data(typeface->createFontData()); - if (NULL == data || !data->hasStream()) { + int face_index; + SkStreamAsset* stream = typeface->openStream(&face_index); + if (NULL == stream) { return NULL; } // this passes ownership of stream to the rec - rec = SkNEW_ARGS(SkFaceRec, (data->detachStream(), fontID)); + rec = SkNEW_ARGS(SkFaceRec, (stream, fontID)); FT_Open_Args args; memset(&args, 0, sizeof(args)); - const void* memoryBase = rec->fSkStream->getMemoryBase(); + const void* memoryBase = stream->getMemoryBase(); if (memoryBase) { args.flags = FT_OPEN_MEMORY; args.memory_base = (const FT_Byte*)memoryBase; - args.memory_size = rec->fSkStream->getLength(); + args.memory_size = stream->getLength(); } else { args.flags = FT_OPEN_STREAM; args.stream = &rec->fFTStream; } - FT_Error err = FT_Open_Face(gFTLibrary->library(), &args, data->getIndex(), &rec->fFace); - if (err) { + FT_Error err = FT_Open_Face(gFTLibrary->library(), &args, face_index, &rec->fFace); + if (err) { // bad filename, try the default font SkDEBUGF(("ERROR: unable to open font '%x'\n", fontID)); SkDELETE(rec); return NULL; } SkASSERT(rec->fFace); - - ft_face_setup_axes(rec->fFace, *data); - rec->fNext = gFaceRecHead; gFaceRecHead = rec; return rec; @@ -1684,8 +1649,7 @@ bool SkTypeface_FreeType::Scanner::recognizedFont(SkStream* stream, int* numFace #include "SkTSearch.h" bool SkTypeface_FreeType::Scanner::scanFont( - SkStream* stream, int ttcIndex, - SkString* name, SkFontStyle* style, bool* isFixedPitch, AxisDefinitions* axes) const + SkStream* stream, int ttcIndex, SkString* name, SkFontStyle* style, bool* isFixedPitch) const { SkAutoMutexAcquire libraryLock(fLibraryMutex); @@ -1761,26 +1725,6 @@ bool SkTypeface_FreeType::Scanner::scanFont( *isFixedPitch = FT_IS_FIXED_WIDTH(face); } - if (axes && face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) { - FT_MM_Var* variations = NULL; - FT_Error err = FT_Get_MM_Var(face, &variations); - if (err) { - SkDEBUGF(("INFO: font %s claims to have variations, but none found.\n", - face->family_name)); - return false; - } - SkAutoFree autoFreeVariations(variations); - - axes->reset(variations->num_axis); - for (FT_UInt i = 0; i < variations->num_axis; ++i) { - const FT_Var_Axis& ftAxis = variations->axis[i]; - (*axes)[i].fTag = ftAxis.tag; - (*axes)[i].fMinimum = ftAxis.minimum; - (*axes)[i].fDefault = ftAxis.def; - (*axes)[i].fMaximum = ftAxis.maximum; - } - } - FT_Done_Face(face); return true; } diff --git a/src/ports/SkFontHost_FreeType_common.h b/src/ports/SkFontHost_FreeType_common.h index 8ae872c1da..857d2c8990 100644 --- a/src/ports/SkFontHost_FreeType_common.h +++ b/src/ports/SkFontHost_FreeType_common.h @@ -43,17 +43,9 @@ public: public: Scanner(); ~Scanner(); - struct AxisDefinition { - SkFourByteTag fTag; - SkFixed fMinimum; - SkFixed fDefault; - SkFixed fMaximum; - }; - using AxisDefinitions = SkSTArray<4, AxisDefinition, true>; bool recognizedFont(SkStream* stream, int* numFonts) const; bool scanFont(SkStream* stream, int ttcIndex, - SkString* name, SkFontStyle* style, bool* isFixedPitch, - AxisDefinitions* axes) const; + SkString* name, SkFontStyle* style, bool* isFixedPitch) const; private: FT_Face openFace(SkStream* stream, int ttcIndex, FT_Stream ftStream) const; FT_Library fLibrary; diff --git a/src/ports/SkFontHost_fontconfig.cpp b/src/ports/SkFontHost_fontconfig.cpp index 2fdb16e364..fa74f5121f 100644 --- a/src/ports/SkFontHost_fontconfig.cpp +++ b/src/ports/SkFontHost_fontconfig.cpp @@ -155,5 +155,6 @@ void FontConfigTypeface::onGetFontDescriptor(SkFontDescriptor* desc, SkString name; this->getFamilyName(&name); desc->setFamilyName(name.c_str()); + desc->setFontIndex(this->getIdentity().fTTCIndex); *isLocalStream = SkToBool(this->getLocalStream()); } diff --git a/src/ports/SkFontHost_linux.cpp b/src/ports/SkFontHost_linux.cpp index b4404ca745..da2c2d00d1 100644 --- a/src/ports/SkFontHost_linux.cpp +++ b/src/ports/SkFontHost_linux.cpp @@ -39,6 +39,7 @@ protected: void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const override { desc->setFamilyName(fFamilyName.c_str()); + desc->setFontIndex(fIndex); *isLocal = !this->isSysFont(); } @@ -305,7 +306,7 @@ protected: bool isFixedPitch; SkFontStyle style; SkString name; - if (fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedPitch, NULL)) { + if (fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedPitch)) { return SkNEW_ARGS(SkTypeface_Stream, (style, isFixedPitch, false, name, stream.detach(), ttcIndex)); } else { @@ -404,7 +405,7 @@ private: bool isFixedPitch; SkString realname; SkFontStyle style = SkFontStyle(); // avoid uninitialized warning - if (!scanner.scanFont(stream, faceIndex, &realname, &style, &isFixedPitch, NULL)) { + if (!scanner.scanFont(stream, faceIndex, &realname, &style, &isFixedPitch)) { SkDebugf("---- failed to open <%s> <%d> as a font\n", filename.c_str(), faceIndex); continue; @@ -490,7 +491,7 @@ private: bool isFixedPitch; SkString realname; SkFontStyle style = SkFontStyle(); // avoid uninitialized warning - if (!scanner.scanFont(stream, faceIndex, &realname, &style, &isFixedPitch, NULL)) { + if (!scanner.scanFont(stream, faceIndex, &realname, &style, &isFixedPitch)) { SkDebugf("---- failed to open <%d> <%d> as a font\n", index, faceIndex); return; } diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp index 2ef5f49913..3c7be46364 100755 --- a/src/ports/SkFontHost_mac.cpp +++ b/src/ports/SkFontHost_mac.cpp @@ -428,12 +428,10 @@ static const uint32_t SkCTFontColorGlyphsTrait = (1 << 13); class SkTypeface_Mac : public SkTypeface { public: SkTypeface_Mac(const SkFontStyle& fs, bool isFixedPitch, - CTFontRef fontRef, const char requestedName[], bool isLocalStream, - CGFontRef originatingCGFontRef = NULL) + CTFontRef fontRef, const char requestedName[], bool isLocalStream) : SkTypeface(fs, SkTypefaceCache::NewFontID(), isFixedPitch) , fRequestedName(requestedName) , fFontRef(fontRef) // caller has already called CFRetain for us - , fOriginatingCGFontRef(originatingCGFontRef) , fHasColorGlyphs(SkToBool(CTFontGetSymbolicTraits(fFontRef) & SkCTFontColorGlyphsTrait)) , fIsLocalStream(isLocalStream) { @@ -442,13 +440,11 @@ public: SkString fRequestedName; AutoCFRelease<CTFontRef> fFontRef; - AutoCFRelease<CGFontRef> fOriginatingCGFontRef; const bool fHasColorGlyphs; protected: int onGetUPEM() const override; SkStreamAsset* onOpenStream(int* ttcIndex) const override; - SkFontData* onCreateFontData() const override; void onGetFamilyName(SkString* familyName) const override; SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override; int onGetTableTags(SkFontTableTag tags[]) const override; @@ -471,15 +467,12 @@ private: }; /** Creates a typeface without searching the cache. Takes ownership of the CTFontRef. */ -static SkTypeface* NewFromFontRef(CTFontRef fontRef, const char name[], bool isLocalStream, - CGFontRef originatingCGFontRef = NULL) -{ +static SkTypeface* NewFromFontRef(CTFontRef fontRef, const char name[], bool isLocalStream) { SkASSERT(fontRef); bool isFixedPitch; SkFontStyle style = SkFontStyle(computeStyleBits(fontRef, &isFixedPitch)); - return new SkTypeface_Mac(style, isFixedPitch, fontRef, name, isLocalStream, - originatingCGFontRef); + return new SkTypeface_Mac(style, isFixedPitch, fontRef, name, isLocalStream); } static bool find_by_CTFontRef(SkTypeface* cached, const SkFontStyle&, void* context) { @@ -1759,116 +1752,6 @@ SkStreamAsset* SkTypeface_Mac::onOpenStream(int* ttcIndex) const { return stream; } -struct NonDefaultAxesContext { - SkFixed* axisValue; - CFArrayRef cgAxes; -}; -static void set_non_default_axes(CFTypeRef key, CFTypeRef value, void* context) { - NonDefaultAxesContext* self = static_cast<NonDefaultAxesContext*>(context); - - if (CFGetTypeID(key) != CFStringGetTypeID() || CFGetTypeID(value) != CFNumberGetTypeID()) { - return; - } - - // The key is a CFString which is a string from the 'name' table. - // Search the cgAxes for an axis with this name, and use its index to store the value. - CFIndex keyIndex = -1; - CFStringRef keyString = static_cast<CFStringRef>(key); - for (CFIndex i = 0; i < CFArrayGetCount(self->cgAxes); ++i) { - CFTypeRef cgAxis = CFArrayGetValueAtIndex(self->cgAxes, i); - if (CFGetTypeID(cgAxis) != CFDictionaryGetTypeID()) { - continue; - } - - CFDictionaryRef cgAxisDict = static_cast<CFDictionaryRef>(cgAxis); - CFTypeRef cgAxisName = CFDictionaryGetValue(cgAxisDict, kCGFontVariationAxisName); - if (!cgAxisName || CFGetTypeID(cgAxisName) != CFStringGetTypeID()) { - continue; - } - CFStringRef cgAxisNameString = static_cast<CFStringRef>(cgAxisName); - if (CFStringCompare(keyString, cgAxisNameString, 0) == kCFCompareEqualTo) { - keyIndex = i; - break; - } - } - if (keyIndex == -1) { - return; - } - - CFNumberRef valueNumber = static_cast<CFNumberRef>(value); - double valueDouble; - if (!CFNumberGetValue(valueNumber, CFNumberType::kCFNumberDoubleType, &valueDouble) || - valueDouble < SkFixedToDouble(SK_FixedMin) || SkFixedToDouble(SK_FixedMax) < valueDouble) - { - return; - } - self->axisValue[keyIndex] = SkDoubleToFixed(valueDouble); -} -static bool get_variations(CTFontRef fFontRef, CFIndex* cgAxisCount, - SkAutoSTMalloc<4, SkFixed>* axisValues) -{ - // CTFontCopyVariationAxes and CTFontCopyVariation do not work when applied to fonts which - // started life with CGFontCreateWithDataProvider (they simply always return NULL). - // As a result, we are limited to CGFontCopyVariationAxes and CGFontCopyVariations. - AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef, NULL)); - - AutoCFRelease<CFDictionaryRef> cgVariations(CGFontCopyVariations(cgFont)); - // If a font has no variations CGFontCopyVariations returns NULL (instead of an empty dict). - if (!cgVariations.get()) { - return false; - } - - AutoCFRelease<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cgFont)); - *cgAxisCount = CFArrayGetCount(cgAxes); - axisValues->reset(*cgAxisCount); - - // Set all of the axes to their default values. - // Fail if any default value cannot be determined. - for (CFIndex i = 0; i < *cgAxisCount; ++i) { - CFTypeRef cgAxis = CFArrayGetValueAtIndex(cgAxes, i); - if (CFGetTypeID(cgAxis) != CFDictionaryGetTypeID()) { - return false; - } - - CFDictionaryRef cgAxisDict = static_cast<CFDictionaryRef>(cgAxis); - CFTypeRef axisDefaultValue = CFDictionaryGetValue(cgAxisDict, - kCGFontVariationAxisDefaultValue); - if (!axisDefaultValue || CFGetTypeID(axisDefaultValue) != CFNumberGetTypeID()) { - return false; - } - CFNumberRef axisDefaultValueNumber = static_cast<CFNumberRef>(axisDefaultValue); - double axisDefaultValueDouble; - if (!CFNumberGetValue(axisDefaultValueNumber, CFNumberType::kCFNumberDoubleType, - &axisDefaultValueDouble)) - { - return false; - } - if (axisDefaultValueDouble < SkFixedToDouble(SK_FixedMin) || - SkFixedToDouble(SK_FixedMax) < axisDefaultValueDouble) - { - return false; - } - (*axisValues)[(int)i] = SkDoubleToFixed(axisDefaultValueDouble); - } - - // Override the default values with the given font's stated axis values. - NonDefaultAxesContext c = { axisValues->get(), cgAxes.get() }; - CFDictionaryApplyFunction(cgVariations, set_non_default_axes, &c); - - return true; -} -SkFontData* SkTypeface_Mac::onCreateFontData() const { - int index; - SkAutoTDelete<SkStreamAsset> stream(this->onOpenStream(&index)); - - CFIndex cgAxisCount; - SkAutoSTMalloc<4, SkFixed> axisValues; - if (get_variations(fFontRef, &cgAxisCount, &axisValues)) { - return new SkFontData(stream.detach(), index, axisValues.get(), cgAxisCount); - } - return new SkFontData(stream.detach(), index, NULL, 0); -} - /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// @@ -2364,89 +2247,6 @@ protected: return create_from_dataProvider(pr); } - static CFDictionaryRef get_axes(CGFontRef cg, SkFontData* fontData) { - AutoCFRelease<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cg)); - if (!cgAxes) { - return NULL; - } - - CFIndex axisCount = CFArrayGetCount(cgAxes); - if (0 == axisCount || axisCount != fontData->getAxisCount()) { - return NULL; - } - - CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, axisCount, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - for (int i = 0; i < fontData->getAxisCount(); ++i) { - CFTypeRef axisInfo = CFArrayGetValueAtIndex(cgAxes, i); - if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) { - return NULL; - } - CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo); - - CFTypeRef axisName = CFDictionaryGetValue(axisInfoDict, kCGFontVariationAxisName); - if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) { - return NULL; - } - - // The variation axes can be set to any value, but cg will effectively pin them. - // Pin them here to normalize. - CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCGFontVariationAxisMinValue); - CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCGFontVariationAxisMaxValue); - if (!min || CFGetTypeID(min) != CFNumberGetTypeID() || - !max || CFGetTypeID(max) != CFNumberGetTypeID()) - { - return NULL; - } - CFNumberRef minNumber = static_cast<CFNumberRef>(min); - CFNumberRef maxNumber = static_cast<CFNumberRef>(max); - double minDouble; - double maxDouble; - if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) || - !CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble)) - { - return NULL; - } - double value = SkTPin(SkFixedToDouble(fontData->getAxis()[i]), minDouble, maxDouble); - CFNumberRef valueNumber = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, - &value); - - CFDictionaryAddValue(dict, axisName, valueNumber); - CFRelease(valueNumber); - } - return dict; - } - SkTypeface* onCreateFromFontData(SkFontData* data) const override { - SkAutoTDelete<SkFontData> fontData(data); - SkStreamAsset* stream = fontData->detachStream(); - AutoCFRelease<CGDataProviderRef> provider(SkCreateDataProviderFromStream(stream)); - if (NULL == provider) { - return NULL; - } - AutoCFRelease<CGFontRef> cg(CGFontCreateWithDataProvider(provider)); - if (NULL == cg) { - return NULL; - } - - AutoCFRelease<CFDictionaryRef> cgVariations(get_axes(cg, fontData)); - // The CGFontRef returned by CGFontCreateCopyWithVariations when the passed CGFontRef was - // created from a data provider does not appear to have any ownership of the underlying - // data. The original CGFontRef must be kept alive until the copy will no longer be used. - AutoCFRelease<CGFontRef> cgVariant; - if (cgVariations) { - cgVariant.reset(CGFontCreateCopyWithVariations(cg, cgVariations)); - } else { - cgVariant.reset(cg.detach()); - } - - CTFontRef ct = CTFontCreateWithGraphicsFont(cgVariant, 0, NULL, NULL); - if (!ct) { - return NULL; - } - return NewFromFontRef(ct, NULL, true, cg.detach()); - } - SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override { AutoCFRelease<CGDataProviderRef> pr(CGDataProviderCreateWithFilename(path)); if (NULL == pr) { diff --git a/src/ports/SkFontMgr_android.cpp b/src/ports/SkFontMgr_android.cpp index a67c6814ea..ae1b663e26 100644 --- a/src/ports/SkFontMgr_android.cpp +++ b/src/ports/SkFontMgr_android.cpp @@ -27,18 +27,20 @@ static const char* gTestBasePath = NULL; class SkTypeface_Android : public SkTypeface_FreeType { public: - SkTypeface_Android(const SkFontStyle& style, + SkTypeface_Android(int index, + const SkFontStyle& style, bool isFixedPitch, const SkString& familyName) : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch) - , fFamilyName(familyName) - { } + , fIndex(index) + , fFamilyName(familyName) { } protected: void onGetFamilyName(SkString* familyName) const override { *familyName = fFamilyName; } + int fIndex; SkString fFamilyName; private: @@ -49,37 +51,30 @@ class SkTypeface_AndroidSystem : public SkTypeface_Android { public: SkTypeface_AndroidSystem(const SkString& pathName, int index, - const SkFixed* axes, int axesCount, const SkFontStyle& style, bool isFixedPitch, const SkString& familyName, const SkLanguage& lang, FontVariant variantStyle) - : INHERITED(style, isFixedPitch, familyName) + : INHERITED(index, style, isFixedPitch, familyName) , fPathName(pathName) - , fIndex(index) - , fAxes(axes, axesCount) , fLang(lang) , fVariantStyle(variantStyle) { } - virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override { + virtual void onGetFontDescriptor(SkFontDescriptor* desc, + bool* serialize) const override { SkASSERT(desc); SkASSERT(serialize); desc->setFamilyName(fFamilyName.c_str()); + desc->setFontIndex(fIndex); *serialize = false; } SkStreamAsset* onOpenStream(int* ttcIndex) const override { *ttcIndex = fIndex; return SkStream::NewFromFile(fPathName.c_str()); } - SkFontData* onCreateFontData() const override { - return new SkFontData(SkStream::NewFromFile(fPathName.c_str()), fIndex, - fAxes.begin(), fAxes.count()); - } const SkString fPathName; - int fIndex; - const SkSTArray<4, SkFixed, true> fAxes; const SkLanguage fLang; const FontVariant fVariantStyle; @@ -88,13 +83,13 @@ public: class SkTypeface_AndroidStream : public SkTypeface_Android { public: - SkTypeface_AndroidStream(SkFontData* data, + SkTypeface_AndroidStream(SkStreamAsset* stream, + int index, const SkFontStyle& style, bool isFixedPitch, const SkString& familyName) - : INHERITED(style, isFixedPitch, familyName) - , fData(data) - { } + : INHERITED(index, style, isFixedPitch, familyName) + , fStream(stream) { } virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override { @@ -105,24 +100,21 @@ public: } SkStreamAsset* onOpenStream(int* ttcIndex) const override { - *ttcIndex = fData->getIndex(); - return fData->duplicateStream(); - } - - SkFontData* onCreateFontData() const override { - return new SkFontData(*fData.get()); + *ttcIndex = fIndex; + return fStream->duplicate(); } private: - const SkAutoTDelete<const SkFontData> fData; + SkAutoTDelete<SkStreamAsset> fStream; + typedef SkTypeface_Android INHERITED; }; class SkFontStyleSet_Android : public SkFontStyleSet { - typedef SkTypeface_FreeType::Scanner Scanner; - public: - explicit SkFontStyleSet_Android(const FontFamily& family, const Scanner& scanner) { + explicit SkFontStyleSet_Android(const FontFamily& family, + const SkTypeface_FreeType::Scanner& scanner) + { const SkString* cannonicalFamilyName = NULL; if (family.fNames.count() > 0) { cannonicalFamilyName = &family.fNames[0]; @@ -145,10 +137,7 @@ public: SkString familyName; SkFontStyle style; bool isFixedWidth; - Scanner::AxisDefinitions axisDefinitions; - if (!scanner.scanFont(stream.get(), ttcIndex, - &familyName, &style, &isFixedWidth, &axisDefinitions)) - { + if (!scanner.scanFont(stream.get(), ttcIndex, &familyName, &style, &isFixedWidth)) { SkDEBUGF(("Requested font file %s exists, but is not a valid font.\n", pathName.c_str())); continue; @@ -177,57 +166,8 @@ public: familyName = *cannonicalFamilyName; } - SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count()); - for (int i = 0; i < axisDefinitions.count(); ++i) { - const Scanner::AxisDefinition& axisDefinition = axisDefinitions[i]; - axisValues[i] = axisDefinition.fDefault; - for (int j = 0; j < fontFile.fAxes.count(); ++j) { - const FontFileInfo::Axis& axisSpecified = fontFile.fAxes[j]; - if (axisDefinition.fTag == axisSpecified.fTag) { - axisValues[i] = SkTPin(axisSpecified.fValue, axisDefinition.fMinimum, - axisDefinition.fMaximum); - if (axisValues[i] != axisSpecified.fValue) { - SkDEBUGF(("Requested font axis value out of range: " - "%s '%c%c%c%c' %f; pinned to %f.\n", - familyName.c_str(), - (axisDefinition.fTag >> 24) & 0xFF, - (axisDefinition.fTag >> 16) & 0xFF, - (axisDefinition.fTag >> 8) & 0xFF, - (axisDefinition.fTag ) & 0xFF, - SkFixedToDouble(axisSpecified.fValue), - SkFixedToDouble(axisValues[i]))); - } - break; - } - } - // TODO: warn on defaulted axis? - } - - SkDEBUGCODE ( - // Check for axis specified, but not matched in font. - for (int i = 0; i < fontFile.fAxes.count(); ++i) { - SkFourByteTag skTag = fontFile.fAxes[i].fTag; - bool found = false; - for (int j = 0; j < axisDefinitions.count(); ++j) { - if (skTag == axisDefinitions[j].fTag) { - found = true; - break; - } - } - if (!found) { - SkDEBUGF(("Requested font axis not found: %s '%c%c%c%c'\n", - familyName.c_str(), - (skTag >> 24) & 0xFF, - (skTag >> 16) & 0xFF, - (skTag >> 8) & 0xFF, - (skTag ) & 0xFF)); - } - } - ) - fStyles.push_back().reset(SkNEW_ARGS(SkTypeface_AndroidSystem, (pathName, ttcIndex, - axisValues.get(), axisDefinitions.count(), style, isFixedWidth, familyName, lang, variant))); } @@ -471,22 +411,11 @@ protected: bool isFixedPitch; SkFontStyle style; SkString name; - if (!fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedPitch, NULL)) { - return NULL; - } - SkFontData* data(new SkFontData(stream.detach(), ttcIndex, NULL, 0)); - return SkNEW_ARGS(SkTypeface_AndroidStream, (data, style, isFixedPitch, name)); - } - - SkTypeface* onCreateFromFontData(SkFontData* data) const override { - SkStreamAsset* stream(data->getStream()); - bool isFixedPitch; - SkFontStyle style; - SkString name; - if (!fScanner.scanFont(stream, data->getIndex(), &name, &style, &isFixedPitch, NULL)) { + if (!fScanner.scanFont(stream, ttcIndex, &name, &style, &isFixedPitch)) { return NULL; } - return SkNEW_ARGS(SkTypeface_AndroidStream, (data, style, isFixedPitch, name)); + return SkNEW_ARGS(SkTypeface_AndroidStream, (stream.detach(), ttcIndex, + style, isFixedPitch, name)); } diff --git a/src/ports/SkFontMgr_fontconfig.cpp b/src/ports/SkFontMgr_fontconfig.cpp index 3baec41cb5..f03e5acaf1 100644 --- a/src/ports/SkFontMgr_fontconfig.cpp +++ b/src/ports/SkFontMgr_fontconfig.cpp @@ -375,10 +375,11 @@ static void fcpattern_from_skfontstyle(SkFontStyle style, FcPattern* pattern) { class SkTypeface_stream : public SkTypeface_FreeType { public: - /** @param data takes ownership of the font data.*/ - SkTypeface_stream(SkFontData* data, const SkFontStyle& style, bool fixedWidth) + /** @param stream does not take ownership of the reference, does take ownership of the stream.*/ + SkTypeface_stream(const SkFontStyle& style, bool fixedWidth, int index, SkStreamAsset* stream) : INHERITED(style, SkTypefaceCache::NewFontID(), fixedWidth) - , fData(data) + , fStream(stream) + , fIndex(index) { }; void onGetFamilyName(SkString* familyName) const override { @@ -386,20 +387,18 @@ public: } void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override { + desc->setFontIndex(fIndex); *serialize = true; } SkStreamAsset* onOpenStream(int* ttcIndex) const override { - *ttcIndex = fData->getIndex(); - return fData->duplicateStream(); - } - - SkFontData* onCreateFontData() const override { - return new SkFontData(*fData.get()); + *ttcIndex = fIndex; + return fStream->duplicate(); } private: - const SkAutoTDelete<const SkFontData> fData; + SkAutoTDelete<SkStreamAsset> fStream; + int fIndex; typedef SkTypeface_FreeType INHERITED; }; @@ -421,6 +420,7 @@ public: desc->setFamilyName(get_string(fPattern, FC_FAMILY)); desc->setFullName(get_string(fPattern, FC_FULLNAME)); desc->setPostscriptName(get_string(fPattern, FC_POSTSCRIPT_NAME)); + desc->setFontIndex(get_int(fPattern, FC_INDEX, 0)); *serialize = false; } @@ -822,12 +822,12 @@ protected: SkFontStyle style; bool isFixedWidth = false; - if (!fScanner.scanFont(stream, ttcIndex, NULL, &style, &isFixedWidth, NULL)) { + if (!fScanner.scanFont(stream, ttcIndex, NULL, &style, &isFixedWidth)) { return NULL; } - return SkNEW_ARGS(SkTypeface_stream, (new SkFontData(stream.detach(), ttcIndex, NULL, 0), - style, isFixedWidth)); + return SkNEW_ARGS(SkTypeface_stream, (style, isFixedWidth, ttcIndex, + static_cast<SkStreamAsset*>(stream.detach()))); } SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override { @@ -838,23 +838,6 @@ protected: return this->createFromStream(SkStream::NewFromFile(path), ttcIndex); } - SkTypeface* onCreateFromFontData(SkFontData* fontData) const override { - SkStreamAsset* stream(fontData->getStream()); - const size_t length = stream->getLength(); - if (length <= 0 || (1u << 30) < length) { - return NULL; - } - - const int ttcIndex = fontData->getIndex(); - SkFontStyle style; - bool isFixedWidth = false; - if (!fScanner.scanFont(stream, ttcIndex, NULL, &style, &isFixedWidth, NULL)) { - return NULL; - } - - return SkNEW_ARGS(SkTypeface_stream, (fontData, style, isFixedWidth)); - } - virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], unsigned styleBits) const override { bool bold = styleBits & SkTypeface::kBold; diff --git a/src/ports/SkTypeface_win_dw.cpp b/src/ports/SkTypeface_win_dw.cpp index 25de1b6578..cf45c16b80 100644 --- a/src/ports/SkTypeface_win_dw.cpp +++ b/src/ports/SkTypeface_win_dw.cpp @@ -42,6 +42,7 @@ void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc, sk_get_locale_string(familyNames.get(), NULL/*fMgr->fLocaleName.get()*/, &utf8FamilyName); desc->setFamilyName(utf8FamilyName.c_str()); + desc->setFontIndex(fDWriteFontFace->GetIndex()); *isLocalStream = SkToBool(fDWriteFontFileLoader.get()); } diff --git a/tests/FontConfigParser.cpp b/tests/FontConfigParser.cpp index 218aa9a09a..e58d35c625 100644 --- a/tests/FontConfigParser.cpp +++ b/tests/FontConfigParser.cpp @@ -10,9 +10,6 @@ #include "SkFontConfigParser_android.h" #include "Test.h" -#include <cmath> -#include <cstdio> - DECLARE_bool(verboseFontMgr); int CountFallbacks(SkTDArray<FontFamily*> fontFamilies) { @@ -94,55 +91,7 @@ void DumpLoadedFonts(SkTDArray<FontFamily*> fontFamilies, const char* label) { SkDebugf("\n\n"); } -template <int N, typename T> static double test_parse_fixed_r(skiatest::Reporter* reporter, - double low, double high, double inc) -{ - double SK_FixedMax_double = nextafter(1 << (sizeof(T) * CHAR_BIT - N - 1), 0.0); - double SK_FixedEpsilon_double = (1.0 / (1 << N)); - double maxError = 0; - char buffer[64]; - for (double f = low; f < high; f += inc) { - SkString s; - // 'sprintf' formatting as expected depends on the current locale being "C". - // We currently expect tests and tools to run in the "C" locale. - sprintf(buffer, "%.20f", f); - T fix; - bool b = parse_fixed<N>(buffer, &fix); - if (b) { - double f2 = fix * SK_FixedEpsilon_double; - double error = fabs(f - f2); - REPORTER_ASSERT(reporter, error <= SK_FixedEpsilon_double); - maxError = SkTMax(maxError, error); - } else { - REPORTER_ASSERT(reporter, f < -SK_FixedMax_double || SK_FixedMax_double < f); - } - } - - //SkDebugf("maxError: %.20f\n", maxError); - return maxError; -} - -static void test_parse_fixed(skiatest::Reporter* reporter) { - test_parse_fixed_r<27, int32_t>(reporter, -8.1, -7.9, 0.000001); - test_parse_fixed_r<27, int32_t>(reporter, -0.1, 0.1, 0.000001); - test_parse_fixed_r<27, int32_t>(reporter, 7.9, 8.1, 0.000001); - test_parse_fixed_r<16, int32_t>(reporter, -0.125, 0.125, 1.0 / (1 << 19)); - test_parse_fixed_r<16, int32_t>(reporter, -32768.125, -32766.875, 1.0 / (1 << 17)); - test_parse_fixed_r<16, int32_t>(reporter, 32766.875, 32768.125, 1.0 / (1 << 17)); - test_parse_fixed_r<16, int32_t>(reporter, -1.1, 1.1, 0.0001); - - SkFixed fix; - REPORTER_ASSERT(reporter, !parse_fixed<27>("-17.1", &fix)); - REPORTER_ASSERT(reporter, !parse_fixed<16>("32768", &fix)); - REPORTER_ASSERT(reporter, !parse_fixed<16>("", &fix)); - REPORTER_ASSERT(reporter, !parse_fixed<16>(".", &fix)); - REPORTER_ASSERT(reporter, !parse_fixed<16>("123.", &fix)); - REPORTER_ASSERT(reporter, !parse_fixed<16>("a", &fix)); - REPORTER_ASSERT(reporter, !parse_fixed<16>(".123a", &fix)); -} - DEF_TEST(FontConfigParserAndroid, reporter) { - test_parse_fixed(reporter); bool resourcesMissing = false; @@ -188,7 +137,7 @@ DEF_TEST(FontConfigParserAndroid, reporter) { NULL); if (v22FontFamilies.count() > 0) { - REPORTER_ASSERT(reporter, v22FontFamilies.count() == 54); + REPORTER_ASSERT(reporter, v22FontFamilies.count() == 53); REPORTER_ASSERT(reporter, CountFallbacks(v22FontFamilies) == 42); DumpLoadedFonts(v22FontFamilies, "version 22"); diff --git a/tests/SerializationTest.cpp b/tests/SerializationTest.cpp index 31dbbe8ad9..f7e298305f 100644 --- a/tests/SerializationTest.cpp +++ b/tests/SerializationTest.cpp @@ -8,8 +8,6 @@ #include "Resources.h" #include "SkBitmapSource.h" #include "SkCanvas.h" -#include "SkFixed.h" -#include "SkFontDescriptor.h" #include "SkMallocPixelRef.h" #include "SkOSFile.h" #include "SkPictureRecorder.h" @@ -317,14 +315,21 @@ static void compare_bitmaps(skiatest::Reporter* reporter, } REPORTER_ASSERT(reporter, 0 == pixelErrors); } -static void serialize_and_compare_typeface(SkTypeface* typeface, const char* text, - skiatest::Reporter* reporter) -{ - // Create a paint with the typeface. + +static void TestPictureTypefaceSerialization(skiatest::Reporter* reporter) { + // Load typeface form file to test CreateFromFile with index. + SkString filename = GetResourcePath("/fonts/test.ttc"); + SkTypeface* typeface = SkTypeface::CreateFromFile(filename.c_str(), 1); + if (!typeface) { + SkDebugf("Could not run fontstream test because test.ttc not found."); + return; + } + + // Create a paint with the typeface we loaded. SkPaint paint; paint.setColor(SK_ColorGRAY); paint.setTextSize(SkIntToScalar(30)); - paint.setTypeface(typeface); + SkSafeUnref(paint.setTypeface(typeface)); // Paint some text. SkPictureRecorder recorder; @@ -333,7 +338,7 @@ static void serialize_and_compare_typeface(SkTypeface* typeface, const char* tex SkIntToScalar(canvasRect.height()), NULL, 0); canvas->drawColor(SK_ColorWHITE); - canvas->drawText(text, 2, 24, 32, paint); + canvas->drawText("A!", 2, 24, 32, paint); SkAutoTUnref<SkPicture> picture(recorder.endRecording()); // Serlialize picture and create its clone from stream. @@ -348,36 +353,6 @@ static void serialize_and_compare_typeface(SkTypeface* typeface, const char* tex compare_bitmaps(reporter, origBitmap, destBitmap); } -static void TestPictureTypefaceSerialization(skiatest::Reporter* reporter) { - { - // Load typeface from file to test CreateFromFile with index. - SkString filename = GetResourcePath("/fonts/test.ttc"); - SkAutoTUnref<SkTypeface> typeface(SkTypeface::CreateFromFile(filename.c_str(), 1)); - if (!typeface) { - SkDebugf("Could not run fontstream test because test.ttc not found."); - } else { - serialize_and_compare_typeface(typeface, "A!", reporter); - } - } - - { - // Load typeface as stream to create with axis settings. - SkAutoTDelete<SkStreamAsset> distortable(GetResourceAsStream("/fonts/Distortable.ttf")); - if (!distortable) { - SkDebugf("Could not run fontstream test because Distortable.ttf not found."); - } else { - SkFixed axis = SK_FixedSqrt2; - SkAutoTUnref<SkTypeface> typeface(SkTypeface::CreateFromFontData( - new SkFontData(distortable.detach(), 0, &axis, 1))); - if (!typeface) { - SkDebugf("Could not run fontstream test because Distortable.ttf not created."); - } else { - serialize_and_compare_typeface(typeface, "abc", reporter); - } - } - } -} - static void setup_bitmap_for_canvas(SkBitmap* bitmap) { bitmap->allocN32Pixels(kBitmapSize, kBitmapSize); } |