diff options
-rw-r--r-- | include/core/SkFont.h | 115 | ||||
-rw-r--r-- | src/core/SkFont.cpp | 73 | ||||
-rw-r--r-- | tests/FontMgrTest.cpp | 28 | ||||
-rw-r--r-- | tests/FontObjTest.cpp | 70 |
4 files changed, 112 insertions, 174 deletions
diff --git a/include/core/SkFont.h b/include/core/SkFont.h index 6aba230854..0d3ad76134 100644 --- a/include/core/SkFont.h +++ b/include/core/SkFont.h @@ -8,8 +8,8 @@ #ifndef SkFont_DEFINED #define SkFont_DEFINED -#include "SkRefCnt.h" #include "SkScalar.h" +#include "SkRefCnt.h" class SkPaint; class SkTypeface; @@ -21,119 +21,60 @@ enum SkTextEncoding { kGlyphID_SkTextEncoding, }; -/* - 1. The Hinting enum in SkPaint is gone entirely, absorbed into SkFont's flags. - - 2. SkPaint Flags look like this today - - enum Flags { - kAntiAlias_Flag = 0x01, //!< mask to enable antialiasing - kDither_Flag = 0x04, //!< mask to enable dithering - kFakeBoldText_Flag = 0x20, //!< mask to enable fake-bold text - kLinearText_Flag = 0x40, //!< mask to enable linear-text - kSubpixelText_Flag = 0x80, //!< mask to enable subpixel text positioning - kLCDRenderText_Flag = 0x200, //!< mask to enable subpixel glyph renderering - kEmbeddedBitmapText_Flag = 0x400, //!< mask to enable embedded bitmap strikes - kAutoHinting_Flag = 0x800, //!< mask to force Freetype's autohinter - kVerticalText_Flag = 0x1000, - }; - - SkFont would absorb these: - - kFakeBoldText_Flag = 0x20, //!< mask to enable fake-bold text - kLinearText_Flag = 0x40, //!< mask to enable linear-text - kSubpixelText_Flag = 0x80, //!< mask to enable subpixel text positioning - kLCDRenderText_Flag = 0x200, //!< mask to enable subpixel glyph renderering - kEmbeddedBitmapText_Flag = 0x400, //!< mask to enable embedded bitmap strikes - kAutoHinting_Flag = 0x800, //!< mask to force Freetype's autohinter - kVerticalText_Flag = 0x1000, - - leaving these still in paint - - kAntiAlias_Flag = 0x01, //!< mask to enable antialiasing - kDither_Flag = 0x04, //!< mask to enable dithering - - 3. Antialiasing - - SkFont has a mask-type: BW, AA, LCD - SkPaint has antialias boolean - - What to do if the font's mask-type disagrees with the paint? - - */ - -class SkFont : public SkRefCnt { +class SkFont { public: enum Flags { /** * Use the system's automatic hinting mechanism to hint the typeface. - * This is a last resort hinting method applied only if other hinting methods do not apply. - * TODO: where to put auto-normal vs auto-light? - */ - kEnableAutoHints_Flag = 1 << 0, - - /** - * If the typeface contains explicit bytecodes for hinting, use them. - * If both bytecode and auto hints are specified, attempt to use the bytecodes first; - * if that fails (e.g. there are no codes), then attempt to autohint. */ - kEnableByteCodeHints_Flag = 1 << 1, + kForceAutoHinting_Flag = 1 << 0, /** * If the typeface contains explicit bitmaps for hinting, use them. * If both bytecode and auto hints are also specified, attempt to use the bitmaps first; * if that fails (e.g. there are no bitmaps), then attempt to bytecode or autohint. */ - kEmbeddedBitmaps_Flag = 1 << 2, + kEmbeddedBitmaps_Flag = 1 << 1, - /** - * Use rounded metric values (e.g. advance). - * If either auto or bytecode hinting was used, apply those results to the metrics of the - * glyphs as well. If no hinting was applied, the metrics will just be rounded to the - * nearest integer. - * - * This applies to calls that return metrics (e.g. measureText) and to drawing the glyphs - * (see SkCanvas drawText and drawPosText). - */ - kUseNonlinearMetrics_Flag = 1 << 3, + kSubpixel_Flag = 1 << 2, + kLinearMetrics_Flag = 1 << 3, kVertical_Flag = 1 << 4, + kEmbolden_Flag = 1 << 5, - kEmbolden_Flag = 1 << 6, - }; + kHinting_FlagShift = 6, + kHinting_FlagMask = 3, // 2 bits - enum MaskType { - kBW_MaskType, - kA8_MaskType, - kLCD_MaskType, + kDEPRECATED_Antialias_Flag = 1 << 8, // want to rely on paint for this }; - static sk_sp<SkFont> Make(sk_sp<SkTypeface>, SkScalar size, MaskType, uint32_t flags); - static sk_sp<SkFont> Make(sk_sp<SkTypeface>, SkScalar size, SkScalar scaleX, SkScalar skewX, - MaskType, uint32_t flags); + SkFont(sk_sp<SkTypeface>, SkScalar size, uint32_t flags); + SkFont(sk_sp<SkTypeface>, SkScalar size, SkScalar scaleX, SkScalar skewX, uint32_t flags); /** * Return a font with the same attributes of this font, but with the specified size. * If size is not supported (e.g. <= 0 or non-finite) NULL will be returned. */ - sk_sp<SkFont> makeWithSize(SkScalar size) const; + SkFont makeWithSize(SkScalar size) const; + /** * Return a font with the same attributes of this font, but with the flags. */ - sk_sp<SkFont> makeWithFlags(uint32_t newFlags) const; + SkFont makeWithFlags(uint32_t newFlags) const; SkTypeface* getTypeface() const { return fTypeface.get(); } SkScalar getSize() const { return fSize; } SkScalar getScaleX() const { return fScaleX; } SkScalar getSkewX() const { return fSkewX; } uint32_t getFlags() const { return fFlags; } - MaskType getMaskType() const { return (MaskType)fMaskType; } - bool isVertical() const { return SkToBool(fFlags & kVertical_Flag); } - bool isEmbolden() const { return SkToBool(fFlags & kEmbolden_Flag); } - bool isEnableAutoHints() const { return SkToBool(fFlags & kEnableAutoHints_Flag); } - bool isEnableByteCodeHints() const { return SkToBool(fFlags & kEnableByteCodeHints_Flag); } - bool isUseNonLinearMetrics() const { return SkToBool(fFlags & kUseNonlinearMetrics_Flag); } + sk_sp<SkTypeface> refTypeface() const { return fTypeface; } + + void setTypeface(sk_sp<SkTypeface>); + void setSize(SkScalar); + void setScaleX(SkScalar); + void setSkewX(SkScalar); + void setFlags(uint32_t); int textToGlyphs(const void* text, size_t byteLength, SkTextEncoding, SkGlyphID glyphs[], int maxGlyphCount) const; @@ -144,21 +85,17 @@ public: SkScalar measureText(const void* text, size_t byteLength, SkTextEncoding) const; - static sk_sp<SkFont> Testing_CreateFromPaint(const SkPaint&); + void LEGACY_applyToPaint(SkPaint*) const; + static SkFont LEGACY_ExtractFromPaint(const SkPaint&); private: - static constexpr int kAllFlags = 0xFF; - - SkFont(sk_sp<SkTypeface>, SkScalar size, SkScalar scaleX, SkScalar skewX, MaskType, - uint32_t flags); + static constexpr unsigned kAllFlags = 0x1FF; sk_sp<SkTypeface> fTypeface; SkScalar fSize; SkScalar fScaleX; SkScalar fSkewX; - uint16_t fFlags; - uint8_t fMaskType; -// uint8_t fPad; + uint32_t fFlags; }; #endif diff --git a/src/core/SkFont.cpp b/src/core/SkFont.cpp index f9423a27e0..821c020c58 100644 --- a/src/core/SkFont.cpp +++ b/src/core/SkFont.cpp @@ -11,14 +11,13 @@ #include "SkTypeface.h" #include "SkUTF.h" -SkFont::SkFont(sk_sp<SkTypeface> face, SkScalar size, SkScalar scaleX, SkScalar skewX, MaskType mt, +SkFont::SkFont(sk_sp<SkTypeface> face, SkScalar size, SkScalar scaleX, SkScalar skewX, uint32_t flags) : fTypeface(face ? std::move(face) : SkTypeface::MakeDefault()) , fSize(size) , fScaleX(scaleX) , fSkewX(skewX) , fFlags(flags) - , fMaskType(SkToU8(mt)) { SkASSERT(size > 0); SkASSERT(scaleX > 0); @@ -26,33 +25,15 @@ SkFont::SkFont(sk_sp<SkTypeface> face, SkScalar size, SkScalar scaleX, SkScalar SkASSERT(0 == (flags & ~kAllFlags)); } -sk_sp<SkFont> SkFont::Make(sk_sp<SkTypeface> face, SkScalar size, SkScalar scaleX, SkScalar skewX, - MaskType mt, uint32_t flags) { - if (size <= 0 || !SkScalarIsFinite(size)) { - return nullptr; - } - if (scaleX <= 0 || !SkScalarIsFinite(scaleX)) { - return nullptr; - } - if (!SkScalarIsFinite(skewX)) { - return nullptr; - } - flags &= kAllFlags; - return sk_sp<SkFont>(new SkFont(std::move(face), size, scaleX, skewX, mt, flags)); -} +SkFont::SkFont(sk_sp<SkTypeface> face, SkScalar size, uint32_t flags) + : SkFont(std::move(face), size, 1, 0, flags) {} -sk_sp<SkFont> SkFont::Make(sk_sp<SkTypeface> face, SkScalar size, MaskType mt, uint32_t flags) { - return SkFont::Make(std::move(face), size, 1, 0, mt, flags); +SkFont SkFont::makeWithSize(SkScalar newSize) const { + return {this->refTypeface(), newSize, this->getScaleX(), this->getSkewX(), this->getFlags()}; } -sk_sp<SkFont> SkFont::makeWithSize(SkScalar newSize) const { - return SkFont::Make(sk_ref_sp(this->getTypeface()), newSize, this->getScaleX(), - this->getSkewX(), this->getMaskType(), this->getFlags()); -} - -sk_sp<SkFont> SkFont::makeWithFlags(uint32_t newFlags) const { - return SkFont::Make(sk_ref_sp(this->getTypeface()), this->getSize(), this->getScaleX(), - this->getSkewX(), this->getMaskType(), newFlags); +SkFont SkFont::makeWithFlags(uint32_t newFlags) const { + return {this->refTypeface(), this->getSize(), this->getScaleX(), this->getSkewX(), newFlags}; } /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -116,7 +97,20 @@ SkScalar SkFont::measureText(const void* text, size_t byteLength, SkTextEncoding #include "SkPaint.h" -sk_sp<SkFont> SkFont::Testing_CreateFromPaint(const SkPaint& paint) { +void SkFont::LEGACY_applyToPaint(SkPaint* paint) const { + paint->setEmbeddedBitmapText(SkToBool(fFlags & kEmbeddedBitmaps_Flag)); + paint->setFakeBoldText(SkToBool(fFlags & kEmbolden_Flag)); + paint->setAutohinted(SkToBool(fFlags & kForceAutoHinting_Flag)); + paint->setSubpixelText(SkToBool(fFlags & kSubpixel_Flag)); + paint->setLinearText(SkToBool(fFlags & kLinearMetrics_Flag)); + + unsigned hinting = (fFlags >> kHinting_FlagShift) & kHinting_FlagMask; + paint->setHinting((SkPaint::Hinting)hinting); + + paint->setAntiAlias(SkToBool(fFlags & kDEPRECATED_Antialias_Flag)); +} + +SkFont SkFont::LEGACY_ExtractFromPaint(const SkPaint& paint) { uint32_t flags = 0; if (paint.isVerticalText()) { flags |= kVertical_Flag; @@ -127,24 +121,23 @@ sk_sp<SkFont> SkFont::Testing_CreateFromPaint(const SkPaint& paint) { if (paint.isFakeBoldText()) { flags |= kEmbolden_Flag; } - - if (SkPaint::kFull_Hinting == paint.getHinting()) { - flags |= kEnableByteCodeHints_Flag; - } if (paint.isAutohinted()) { - flags |= kEnableAutoHints_Flag; + flags |= kForceAutoHinting_Flag; + } + if (paint.isSubpixelText()) { + flags |= kSubpixel_Flag; } - if (paint.isSubpixelText() || paint.isLinearText()) { - // this is our default - } else { - flags |= kUseNonlinearMetrics_Flag; + if (paint.isLinearText()) { + flags |= kLinearMetrics_Flag; } - MaskType maskType = SkFont::kBW_MaskType; if (paint.isAntiAlias()) { - maskType = paint.isLCDRenderText() ? kLCD_MaskType : kA8_MaskType; + flags |= kDEPRECATED_Antialias_Flag; } - return Make(sk_ref_sp(paint.getTypeface()), paint.getTextSize(), paint.getTextScaleX(), - paint.getTextSkewX(), maskType, flags); + unsigned hinting = (unsigned)paint.getHinting(); + flags |= (hinting << kHinting_FlagShift); + + return SkFont(sk_ref_sp(paint.getTypeface()), paint.getTextSize(), paint.getTextScaleX(), + paint.getTextSkewX(), flags); } diff --git a/tests/FontMgrTest.cpp b/tests/FontMgrTest.cpp index 4abbd19fb9..1ef97ee6ff 100644 --- a/tests/FontMgrTest.cpp +++ b/tests/FontMgrTest.cpp @@ -19,18 +19,17 @@ static void test_font(skiatest::Reporter* reporter) { uint32_t flags = 0; - sk_sp<SkFont> font(SkFont::Make(nullptr, 24, SkFont::kA8_MaskType, flags)); + SkFont font(nullptr, 24, flags); - REPORTER_ASSERT(reporter, font->getTypeface()); - REPORTER_ASSERT(reporter, 24 == font->getSize()); - REPORTER_ASSERT(reporter, 1 == font->getScaleX()); - REPORTER_ASSERT(reporter, 0 == font->getSkewX()); - REPORTER_ASSERT(reporter, SkFont::kA8_MaskType == font->getMaskType()); + REPORTER_ASSERT(reporter, font.getTypeface()); + REPORTER_ASSERT(reporter, 24 == font.getSize()); + REPORTER_ASSERT(reporter, 1 == font.getScaleX()); + REPORTER_ASSERT(reporter, 0 == font.getSkewX()); uint16_t glyphs[5]; sk_bzero(glyphs, sizeof(glyphs)); - int count = font->textToGlyphs("Hello", 5, kUTF8_SkTextEncoding, glyphs, SK_ARRAY_COUNT(glyphs)); + int count = font.textToGlyphs("Hello", 5, kUTF8_SkTextEncoding, glyphs, SK_ARRAY_COUNT(glyphs)); REPORTER_ASSERT(reporter, 5 == count); for (int i = 0; i < count; ++i) { @@ -39,18 +38,15 @@ static void test_font(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, glyphs[0] != glyphs[1]); // 'h' != 'e' REPORTER_ASSERT(reporter, glyphs[2] == glyphs[3]); // 'l' == 'l' - sk_sp<SkFont> newFont(font->makeWithSize(36)); - REPORTER_ASSERT(reporter, newFont.get()); - REPORTER_ASSERT(reporter, font->getTypeface() == newFont->getTypeface()); - REPORTER_ASSERT(reporter, 36 == newFont->getSize()); // double check we haven't changed - REPORTER_ASSERT(reporter, 24 == font->getSize()); // double check we haven't changed + const SkFont newFont(font.makeWithSize(36)); + REPORTER_ASSERT(reporter, font.getTypeface() == newFont.getTypeface()); + REPORTER_ASSERT(reporter, 36 == newFont.getSize()); // double check we haven't changed + REPORTER_ASSERT(reporter, 24 == font.getSize()); // double check we haven't changed SkPaint paint; paint.setTextSize(18); - font = SkFont::Testing_CreateFromPaint(paint); - REPORTER_ASSERT(reporter, font.get()); - REPORTER_ASSERT(reporter, font->getSize() == paint.getTextSize()); - REPORTER_ASSERT(reporter, SkFont::kBW_MaskType == font->getMaskType()); + font = SkFont::LEGACY_ExtractFromPaint(paint); + REPORTER_ASSERT(reporter, font.getSize() == paint.getTextSize()); } /* diff --git a/tests/FontObjTest.cpp b/tests/FontObjTest.cpp index 44f799ece1..fa96112ed6 100644 --- a/tests/FontObjTest.cpp +++ b/tests/FontObjTest.cpp @@ -10,35 +10,28 @@ #include "SkTypeface.h" #include "Test.h" -static bool is_use_nonlinear_metrics(const SkPaint& paint) { - return !paint.isSubpixelText() && !paint.isLinearText(); -} - -static bool is_enable_auto_hints(const SkPaint& paint) { - return paint.isAutohinted(); -} - -static bool is_enable_bytecode_hints(const SkPaint& paint) { - return paint.getHinting() >= SkPaint::kFull_Hinting; -} - -static void test_cachedfont(skiatest::Reporter* reporter, const SkPaint& paint) { - sk_sp<SkFont> font(SkFont::Testing_CreateFromPaint(paint)); - +static void test_cachedfont(skiatest::Reporter* reporter, + const SkPaint& paint, const SkFont& font) { // Currently SkFont resolves null into the default, so only test if paint's is not null if (paint.getTypeface()) { - REPORTER_ASSERT(reporter, font->getTypeface() == paint.getTypeface()); + REPORTER_ASSERT(reporter, font.getTypeface() == paint.getTypeface()); } - REPORTER_ASSERT(reporter, font->getSize() == paint.getTextSize()); - REPORTER_ASSERT(reporter, font->getScaleX() == paint.getTextScaleX()); - REPORTER_ASSERT(reporter, font->getSkewX() == paint.getTextSkewX()); - - REPORTER_ASSERT(reporter, font->isVertical() == paint.isVerticalText()); - REPORTER_ASSERT(reporter, font->isEmbolden() == paint.isFakeBoldText()); - - REPORTER_ASSERT(reporter, font->isUseNonLinearMetrics() == is_use_nonlinear_metrics(paint)); - REPORTER_ASSERT(reporter, font->isEnableAutoHints() == is_enable_auto_hints(paint)); - REPORTER_ASSERT(reporter, font->isEnableByteCodeHints() == is_enable_bytecode_hints(paint)); + REPORTER_ASSERT(reporter, font.getSize() == paint.getTextSize()); + REPORTER_ASSERT(reporter, font.getScaleX() == paint.getTextScaleX()); + REPORTER_ASSERT(reporter, font.getSkewX() == paint.getTextSkewX()); + + uint32_t mask = SkPaint::kLinearText_Flag | + SkPaint::kSubpixelText_Flag | + SkPaint::kFakeBoldText_Flag | + SkPaint::kEmbeddedBitmapText_Flag | + SkPaint::kAutoHinting_Flag; + + SkPaint p; + font.LEGACY_applyToPaint(&p); + uint32_t oldFlags = paint.getFlags() & mask; + uint32_t newFlags = p.getFlags() & mask; + REPORTER_ASSERT(reporter, oldFlags == newFlags); + REPORTER_ASSERT(reporter, paint.getHinting() == p.getHinting()); } static void test_cachedfont(skiatest::Reporter* reporter) { @@ -89,7 +82,9 @@ static void test_cachedfont(skiatest::Reporter* reporter) { paint.setTextScaleX(gScaleRec[k].fScaleX); paint.setTextSkewX(gScaleRec[k].fSkewX); - test_cachedfont(reporter, paint); + const SkFont font(SkFont::LEGACY_ExtractFromPaint(paint)); + + test_cachedfont(reporter, paint, font); SkRect bounds; @@ -102,8 +97,7 @@ static void test_cachedfont(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, width1 == width2); - sk_sp<SkFont> font(SkFont::Testing_CreateFromPaint(paint)); - SkScalar font_width1 = font->measureText(txt, strlen(txt), kUTF8_SkTextEncoding); + SkScalar font_width1 = font.measureText(txt, strlen(txt), kUTF8_SkTextEncoding); // measureText not yet implemented... REPORTER_ASSERT(reporter, font_width1 == -1); // REPORTER_ASSERT(reporter, width1 == font_width1); @@ -112,8 +106,26 @@ static void test_cachedfont(skiatest::Reporter* reporter) { } } +static void test_aa_hinting(skiatest::Reporter* reporter) { + SkPaint paint; + + for (bool aa : {false, true}) { + paint.setAntiAlias(aa); + for (int hint = 0; hint <= 3; ++hint) { + paint.setHinting((SkPaint::Hinting)hint); + SkFont font = SkFont::LEGACY_ExtractFromPaint(paint); + + SkPaint p2; + font.LEGACY_applyToPaint(&p2); + REPORTER_ASSERT(reporter, paint.isAntiAlias() == p2.isAntiAlias()); + REPORTER_ASSERT(reporter, paint.getHinting() == p2.getHinting()); + } + } +} + DEF_TEST(FontObj, reporter) { test_cachedfont(reporter); + test_aa_hinting(reporter); } // need tests for SkStrSearch |