diff options
-rw-r--r-- | BUILD.gn | 18 | ||||
-rw-r--r-- | gm/fontmgr.cpp | 7 | ||||
-rw-r--r-- | public.bzl | 6 | ||||
-rw-r--r-- | resources/fonts/cbdt.ttf | bin | 18020 -> 0 bytes | |||
-rw-r--r-- | resources/fonts/colr.ttf | bin | 2996 -> 0 bytes | |||
-rw-r--r-- | resources/fonts/sbix.ttf | bin | 17956 -> 0 bytes | |||
-rw-r--r-- | resources/fonts/svg/diamond.svg | 22 | ||||
-rw-r--r-- | resources/fonts/svg/empty.svg | 10 | ||||
-rw-r--r-- | resources/fonts/svg/notdef.svg | 29 | ||||
-rw-r--r-- | resources/fonts/svg/smile.svg | 44 | ||||
-rw-r--r-- | src/ports/SkFontHost_win.cpp | 7 | ||||
-rw-r--r-- | tools/fonts/SkTestFontMgr.cpp | 28 | ||||
-rw-r--r-- | tools/fonts/SkTestSVGTypeface.cpp | 1300 | ||||
-rw-r--r-- | tools/fonts/SkTestSVGTypeface.h | 135 | ||||
-rw-r--r-- | tools/fonts/SkTestScalerContext.cpp (renamed from tools/fonts/SkTestTypeface.cpp) | 17 | ||||
-rw-r--r-- | tools/fonts/SkTestScalerContext.h (renamed from tools/fonts/SkTestTypeface.h) | 22 | ||||
-rw-r--r-- | tools/fonts/create_test_font_color.cpp | 37 | ||||
-rw-r--r-- | tools/fonts/sk_tool_utils_font.cpp | 41 | ||||
-rw-r--r-- | tools/sk_tool_utils.cpp | 24 | ||||
-rw-r--r-- | tools/sk_tool_utils.h | 13 |
20 files changed, 54 insertions, 1706 deletions
@@ -1278,11 +1278,7 @@ if (skia_enable_tools) { "tools/debugger/SkObjectParser.cpp", "tools/fonts/SkRandomScalerContext.cpp", "tools/fonts/SkTestFontMgr.cpp", - "tools/fonts/SkTestFontMgr.h", - "tools/fonts/SkTestSVGTypeface.cpp", - "tools/fonts/SkTestSVGTypeface.h", - "tools/fonts/SkTestTypeface.cpp", - "tools/fonts/SkTestTypeface.h", + "tools/fonts/SkTestScalerContext.cpp", "tools/fonts/sk_tool_utils_font.cpp", "tools/picture_utils.cpp", "tools/random_parse_path.cpp", @@ -1302,7 +1298,6 @@ if (skia_enable_tools) { } deps = [ ":common_flags", - ":experimental_svg_model", ":flags", "//third_party/libpng", ] @@ -1674,17 +1669,6 @@ if (skia_enable_tools) { ] } - test_app("create_test_font_color") { - sources = [ - "tools/fonts/create_test_font_color.cpp", - ] - deps = [ - ":flags", - ":skia", - ":tool_utils" - ] - } - test_app("get_images_from_skps") { sources = [ "tools/get_images_from_skps.cpp", diff --git a/gm/fontmgr.cpp b/gm/fontmgr.cpp index 58c569c300..a0b2f5b44a 100644 --- a/gm/fontmgr.cpp +++ b/gm/fontmgr.cpp @@ -9,7 +9,6 @@ #include "sk_tool_utils.h" #include "SkCanvas.h" #include "SkFontMgr.h" -#include "SkPath.h" #include "SkGraphics.h" #include "SkTypeface.h" @@ -225,7 +224,6 @@ public: fontBounds.offset(x, y); SkPaint boundsPaint(glyphPaint); boundsPaint.setColor(boundsColor); - boundsPaint.setStyle(SkPaint::kStroke_Style); canvas->drawRect(fontBounds, boundsPaint); SkPaint::FontMetrics fm; @@ -266,10 +264,6 @@ public: } SkGlyphID str[] = { left, right, top, bottom }; for (size_t i = 0; i < SK_ARRAY_COUNT(str); ++i) { - SkPath path; - glyphPaint.getTextPath(&str[i], sizeof(str[0]), x, y, &path); - SkPaint::Style style = path.isEmpty() ? SkPaint::kFill_Style : SkPaint::kStroke_Style; - glyphPaint.setStyle(style); canvas->drawText(&str[i], sizeof(str[0]), x, y, glyphPaint); } } @@ -288,6 +282,7 @@ protected: paint.setAntiAlias(true); paint.setSubpixelText(true); paint.setTextSize(100); + paint.setStyle(SkPaint::kStroke_Style); paint.setTextScaleX(fScaleX); paint.setTextSkewX(fSkewX); diff --git a/public.bzl b/public.bzl index ecae59d394..dc798c8046 100644 --- a/public.bzl +++ b/public.bzl @@ -461,10 +461,8 @@ DM_SRCS_ALL = struct( "tools/fonts/SkRandomScalerContext.h", "tools/fonts/SkTestFontMgr.cpp", "tools/fonts/SkTestFontMgr.h", - "tools/fonts/SkTestSVGTypeface.cpp", - "tools/fonts/SkTestSVGTypeface.h", - "tools/fonts/SkTestTypeface.cpp", - "tools/fonts/SkTestTypeface.h", + "tools/fonts/SkTestScalerContext.cpp", + "tools/fonts/SkTestScalerContext.h", "tools/fonts/sk_tool_utils_font.cpp", "tools/fonts/test_font_monospace.inc", "tools/fonts/test_font_sans_serif.inc", diff --git a/resources/fonts/cbdt.ttf b/resources/fonts/cbdt.ttf Binary files differdeleted file mode 100644 index bed498f07e..0000000000 --- a/resources/fonts/cbdt.ttf +++ /dev/null diff --git a/resources/fonts/colr.ttf b/resources/fonts/colr.ttf Binary files differdeleted file mode 100644 index 42e2a08096..0000000000 --- a/resources/fonts/colr.ttf +++ /dev/null diff --git a/resources/fonts/sbix.ttf b/resources/fonts/sbix.ttf Binary files differdeleted file mode 100644 index 5eed8a917b..0000000000 --- a/resources/fonts/sbix.ttf +++ /dev/null diff --git a/resources/fonts/svg/diamond.svg b/resources/fonts/svg/diamond.svg deleted file mode 100644 index 826cb749f3..0000000000 --- a/resources/fonts/svg/diamond.svg +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- The default glyf will be much smaller than the colr glyf layers. --> -<svg - version="1.1" - viewBox="0 0 158.75 211.66667" - height="800" - width="600"> - <g - transform="translate(0,-85.333351)" - id="layer1"> - <path - transform="matrix(1,0,0,1.3773044,0.80180858,-33.549844)" - d="m 79.11178,236.39392 c -5.497887,0 -73.0286729,-67.53078 -73.028673,-73.02867 -2e-7,-5.49789 67.530782,-73.028671 73.028669,-73.028672 5.497888,0 73.028674,67.530782 73.028674,73.028672 0,5.49789 -67.530782,73.02867 -73.02867,73.02867 z" - id="path5299" - style="fill:#ff2a2a;stroke:none;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - transform="matrix(0.60436993,0,0,0.81236352,32.100808,58.741857)" - d="m 79.11178,236.39392 c -5.497887,0 -73.0286729,-67.53078 -73.028673,-73.02867 -2e-7,-5.49789 67.530782,-73.028671 73.028669,-73.028672 5.497888,0 73.028674,67.530782 73.028674,73.028672 0,5.49789 -67.530782,73.02867 -73.02867,73.02867 z" - id="path5299-5" - style="fill:none;stroke:#2b0000;stroke-width:14.19605827;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - </g> -</svg> diff --git a/resources/fonts/svg/empty.svg b/resources/fonts/svg/empty.svg deleted file mode 100644 index d470cc5a4c..0000000000 --- a/resources/fonts/svg/empty.svg +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Empty, so will not produce a glyf or bitmap entry. --> -<svg - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - version="1.1" - viewBox="0 0 0 0" - height="0" - width="0"> -</svg> diff --git a/resources/fonts/svg/notdef.svg b/resources/fonts/svg/notdef.svg deleted file mode 100644 index 3fbb9a02ff..0000000000 --- a/resources/fonts/svg/notdef.svg +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- In the colr format should be filled with the current paint. --> -<svg - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - version="1.1" - viewBox="0 0 158.75 211.66667" - height="800" - width="600"> - <g - transform="translate(0,-85.333351)" - id="layer1"> - <rect - y="97.374527" - x="4.3011618" - height="195.32433" - width="150.42305" - id="rect4639" - style="fill:none;stroke:#2b0000;stroke-width:6.61458349;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - id="path5186" - d="M 14.967094,109.37681 144.05828,283.63654" - style="fill:none;stroke:#2b0000;stroke-width:6.61458349;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - id="path5188" - d="M 146.19643,107.77319 14.699822,282.83473" - style="fill:none;stroke:#2b0000;stroke-width:6.61458349;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - </g> -</svg> diff --git a/resources/fonts/svg/smile.svg b/resources/fonts/svg/smile.svg deleted file mode 100644 index 41d26b5e29..0000000000 --- a/resources/fonts/svg/smile.svg +++ /dev/null @@ -1,44 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- In the colr format the eyes and mouth should be filled with the current paint. --> -<svg - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - version="1.1" - viewBox="0 0 211.66666 211.66667" - height="800" - width="800"> - <g - transform="translate(0,-85.333317)" - id="layer1"> - <circle - r="98.273819" - cy="192.76852" - cx="104.81271" - id="path10" - style="fill:#000000;stroke-width:0.3084828" /> - <circle - r="90.782074" - cy="192.32785" - cx="104.37203" - id="path12" - style="fill:#ffcc00;stroke-width:0.3084828" /> - <ellipse - ry="20.032738" - rx="20.410715" - cy="159.88458" - cx="74.574615" - id="path62" - style="fill:#2b0000;stroke-width:0.26458332" /> - <ellipse - ry="20.032738" - rx="20.410715" - cy="158.13309" - cx="138.02272" - id="path62-7" - style="fill:#2b0000;stroke-width:0.26458332" /> - <path - d="m 163.09897,220.67157 a 58.248119,31.234499 0 0 1 -26.87407,29.28648 58.248119,31.234499 0 0 1 -60.863188,0.45572 58.248119,31.234499 0 0 1 -28.388544,-28.87269 l 58.126712,2.01564 z" - id="path113" - style="fill:#2b0000;stroke-width:0.26458332" /> - </g> -</svg> diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp index abe1550a01..f0eb7b7d9b 100644 --- a/src/ports/SkFontHost_win.cpp +++ b/src/ports/SkFontHost_win.cpp @@ -830,13 +830,6 @@ uint16_t SkScalerContext_GDI::generateCharToGlyph(SkUnichar utf32) { HRZM(ScriptItemize(utf16, numWCHAR, maxItems, &sc, nullptr, si, &numItems), "Could not itemize character."); - // Disable any attempt at shaping. - // Without this ScriptShape may return 0x80040200 (USP_E_SCRIPT_NOT_IN_FONT) - // when all that is desired here is a simple cmap lookup. - for (SCRIPT_ITEM& item : si) { - item.a.eScript = SCRIPT_UNDEFINED; - } - // Sometimes ScriptShape cannot find a glyph for a non-BMP and returns 2 space glyphs. static const int maxGlyphs = 2; SCRIPT_VISATTR vsa[maxGlyphs]; diff --git a/tools/fonts/SkTestFontMgr.cpp b/tools/fonts/SkTestFontMgr.cpp index 4513a2f8d1..3b5d1589f2 100644 --- a/tools/fonts/SkTestFontMgr.cpp +++ b/tools/fonts/SkTestFontMgr.cpp @@ -8,8 +8,6 @@ #include "SkFontDescriptor.h" #include "SkTestFontMgr.h" #include "sk_tool_utils.h" -#include "SkTestTypeface.h" -#include "SkTestSVGTypeface.h" namespace { @@ -17,28 +15,6 @@ static constexpr const char* kFamilyNames[] = { "Toy Liberation Sans", "Toy Liberation Serif", "Toy Liberation Mono", - "Emoji", -}; - -class JustOneTypefaceStyleSet final : public SkFontStyleSet { -public: - explicit JustOneTypefaceStyleSet(sk_sp<SkTypeface> typeface) : fTypeface(std::move(typeface)) {} - int count() override { return 1; } - - void getStyle(int index, SkFontStyle* style, SkString* name) override { - if (style) { *style = SkFontStyle::Normal(); } - if (name) { *name = "Normal"; } - } - - SkTypeface* createTypeface(int index) override { - return SkRef(fTypeface.get()); - } - - SkTypeface* matchStyle(const SkFontStyle& pattern) override { - return this->matchStyleCSS3(pattern); - } -private: - sk_sp<SkTypeface> fTypeface; }; class FontStyleSet final : public SkFontStyleSet { @@ -93,7 +69,6 @@ public: fFamilies[0] = sk_make_sp<FontStyleSet>(0); fFamilies[1] = sk_make_sp<FontStyleSet>(1); fFamilies[2] = sk_make_sp<FontStyleSet>(2); - fFamilies[3] = sk_make_sp<JustOneTypefaceStyleSet>(SkTestSVGTypeface::Default()); } int onCountFamilies() const override { return SK_ARRAY_COUNT(fFamilies); } @@ -111,7 +86,6 @@ public: if (strstr(familyName, "ans")) { return this->createStyleSet(0); } if (strstr(familyName, "erif")) { return this->createStyleSet(1); } if (strstr(familyName, "ono")) { return this->createStyleSet(2); } - if (strstr(familyName, "oji")) { return this->createStyleSet(3); } } return this->createStyleSet(0); } @@ -164,7 +138,7 @@ public: } private: - sk_sp<SkFontStyleSet> fFamilies[4]; + sk_sp<FontStyleSet> fFamilies[3]; }; } diff --git a/tools/fonts/SkTestSVGTypeface.cpp b/tools/fonts/SkTestSVGTypeface.cpp deleted file mode 100644 index 715a28c5f0..0000000000 --- a/tools/fonts/SkTestSVGTypeface.cpp +++ /dev/null @@ -1,1300 +0,0 @@ -/* - * Copyright 2014 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "Resources.h" -#include "SkAdvancedTypefaceMetrics.h" -#include "SkBitmap.h" -#include "SkCanvas.h" -#include "SkColor.h" -#include "SkData.h" -#include "SkEncodedImageFormat.h" -#include "SkFontDescriptor.h" -#include "SkFontStyle.h" -#include "SkGeometry.h" -#include "SkGlyph.h" -#include "SkImage.h" -#include "SkImageInfo.h" -#include "SkMask.h" -#include "SkMatrix.h" -#include "SkNoDrawCanvas.h" -#include "SkOTUtils.h" -#include "SkPaintPriv.h" -#include "SkPath.h" -#include "SkPathPriv.h" -#include "SkPathEffect.h" -#include "SkPathOps.h" -#include "SkPixmap.h" -#include "SkPointPriv.h" -#include "SkRRect.h" -#include "SkSVGDOM.h" -#include "SkScalerContext.h" -#include "SkSize.h" -#include "SkStream.h" -#include "SkSurface.h" -#include "SkTestSVGTypeface.h" -#include "SkTDArray.h" -#include "SkTemplates.h" -#include "SkUtils.h" - -#include <utility> - -class SkDescriptor; - -SkTestSVGTypeface::SkTestSVGTypeface(const char* name, - int upem, - const SkPaint::FontMetrics& fontMetrics, - const SkSVGTestTypefaceGlyphData* data, int dataCount, - const SkFontStyle& style) - : SkTypeface(style, false) - , fName(name) - , fUpem(upem) - , fFontMetrics(fontMetrics) - , fGlyphs(new Glyph[dataCount]) - , fGlyphCount(dataCount) -{ - for (int i = 0; i < dataCount; ++i) { - const SkSVGTestTypefaceGlyphData& datum = data[i]; - std::unique_ptr<SkStreamAsset> stream = GetResourceAsStream(datum.fSvgResourcePath); - fCMap.set(datum.fUnicode, i); - fGlyphs[i].fAdvance = datum.fAdvance; - fGlyphs[i].fOrigin = datum.fOrigin; - if (!stream) { - continue; - } - sk_sp<SkSVGDOM> svg = SkSVGDOM::MakeFromStream(*stream.get()); - if (!svg) { - continue; - } - - const SkSize& sz = svg->containerSize(); - if (sz.isEmpty()) { - continue; - } - - fGlyphs[i].fSvg = std::move(svg); - } -} - -SkTestSVGTypeface::~SkTestSVGTypeface() {} - -SkTestSVGTypeface::Glyph::Glyph() : fOrigin{0,0}, fAdvance(0) {} -SkTestSVGTypeface::Glyph::~Glyph() {} - -void SkTestSVGTypeface::getAdvance(SkGlyph* glyph) const { - SkGlyphID glyphID = glyph->getGlyphID(); - glyphID = glyphID < fGlyphCount ? glyphID : 0; - - glyph->fAdvanceX = fGlyphs[glyphID].fAdvance; - glyph->fAdvanceY = 0; -} - -void SkTestSVGTypeface::getFontMetrics(SkPaint::FontMetrics* metrics) const { - *metrics = fFontMetrics; -} - -void SkTestSVGTypeface::getPath(SkGlyphID glyphID, SkPath* path) const { - path->reset(); -} - -void SkTestSVGTypeface::onFilterRec(SkScalerContextRec* rec) const { - rec->setHinting(SkPaint::kNo_Hinting); -} - -std::unique_ptr<SkAdvancedTypefaceMetrics> SkTestSVGTypeface::onGetAdvancedMetrics() const { - std::unique_ptr<SkAdvancedTypefaceMetrics> info(new SkAdvancedTypefaceMetrics); - info->fFontName.set(fName); - - SkTDArray<SkUnichar>& toUnicode = info->fGlyphToUnicode; - toUnicode.setCount(fGlyphCount); - fCMap.foreach([&toUnicode](const SkUnichar& c, const SkGlyphID& g) { - toUnicode[g] = c; - }); - return info; -} - -void SkTestSVGTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const { - desc->setFamilyName(fName.c_str()); - desc->setStyle(this->fontStyle()); - *isLocal = false; -} - -int SkTestSVGTypeface::onCharsToGlyphs(const void* chars, Encoding encoding, - uint16_t glyphs[], int glyphCount) const { - auto utf8 = (const char*)chars; - auto utf16 = (const uint16_t*)chars; - auto utf32 = (const SkUnichar*)chars; - - for (int i = 0; i < glyphCount; i++) { - SkUnichar ch; - switch (encoding) { - case kUTF8_Encoding: ch = SkUTF8_NextUnichar(&utf8 ); break; - case kUTF16_Encoding: ch = SkUTF16_NextUnichar(&utf16); break; - case kUTF32_Encoding: ch = *utf32++; break; - } - if (glyphs) { - SkGlyphID* g = fCMap.find(ch); - glyphs[i] = g ? *g : 0; - } - } - return glyphCount; -} - -void SkTestSVGTypeface::onGetFamilyName(SkString* familyName) const { - *familyName = fName; -} - -SkTypeface::LocalizedStrings* SkTestSVGTypeface::onCreateFamilyNameIterator() const { - SkString familyName(fName); - SkString language("und"); //undetermined - return new SkOTUtils::LocalizedStrings_SingleName(familyName, language); -} - -class SkTestSVGScalerContext : public SkScalerContext { -public: - SkTestSVGScalerContext(sk_sp<SkTestSVGTypeface> face, const SkScalerContextEffects& effects, - const SkDescriptor* desc) - : SkScalerContext(std::move(face), effects, desc) - { - fRec.getSingleMatrix(&fMatrix); - SkScalar upem = this->geTestSVGTypeface()->fUpem; - fMatrix.preScale(1.f/upem, 1.f/upem); - } - -protected: - SkTestSVGTypeface* geTestSVGTypeface() const { - return static_cast<SkTestSVGTypeface*>(this->getTypeface()); - } - - unsigned generateGlyphCount() override { - return this->geTestSVGTypeface()->onCountGlyphs(); - } - - uint16_t generateCharToGlyph(SkUnichar u) override { - uint16_t g; - (void) this->geTestSVGTypeface()->onCharsToGlyphs(&u, SkTypeface::kUTF32_Encoding, &g, 1); - return g; - } - - void generateAdvance(SkGlyph* glyph) override { - this->geTestSVGTypeface()->getAdvance(glyph); - - const SkVector advance = fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX), - SkFloatToScalar(glyph->fAdvanceY)); - glyph->fAdvanceX = SkScalarToFloat(advance.fX); - glyph->fAdvanceY = SkScalarToFloat(advance.fY); - } - - void generateMetrics(SkGlyph* glyph) override { - SkGlyphID glyphID = glyph->getGlyphID(); - glyphID = glyphID < this->geTestSVGTypeface()->fGlyphCount ? glyphID : 0; - - glyph->zeroMetrics(); - glyph->fMaskFormat = SkMask::kARGB32_Format; - this->generateAdvance(glyph); - - SkTestSVGTypeface::Glyph& glyphData = this->geTestSVGTypeface()->fGlyphs[glyphID]; - if (!glyphData.fSvg) { - return; - } - - SkSize containerSize = glyphData.fSvg->containerSize(); - SkRect newBounds = SkRect::MakeXYWH(glyphData.fOrigin.fX, -glyphData.fOrigin.fY, - containerSize.fWidth, containerSize.fHeight); - fMatrix.mapRect(&newBounds); - SkScalar dx = SkFixedToScalar(glyph->getSubXFixed()); - SkScalar dy = SkFixedToScalar(glyph->getSubYFixed()); - newBounds.offset(dx, dy); - - SkIRect ibounds; - newBounds.roundOut(&ibounds); - glyph->fLeft = ibounds.fLeft; - glyph->fTop = ibounds.fTop; - glyph->fWidth = ibounds.width(); - glyph->fHeight = ibounds.height(); - } - - void generateImage(const SkGlyph& glyph) override { - SkGlyphID glyphID = glyph.getGlyphID(); - glyphID = glyphID < this->geTestSVGTypeface()->fGlyphCount ? glyphID : 0; - - SkBitmap bm; - // TODO: this should be SkImageInfo::MakeS32 when that passes all the tests. - bm.installPixels(SkImageInfo::MakeN32(glyph.fWidth, glyph.fHeight, kPremul_SkAlphaType), - glyph.fImage, glyph.rowBytes()); - bm.eraseColor(0); - - SkTestSVGTypeface::Glyph& glyphData = this->geTestSVGTypeface()->fGlyphs[glyphID]; - - SkScalar dx = SkFixedToScalar(glyph.getSubXFixed()); - SkScalar dy = SkFixedToScalar(glyph.getSubYFixed()); - - SkCanvas canvas(bm); - canvas.translate(-glyph.fLeft, -glyph.fTop); - canvas.translate(dx, dy); - canvas.concat(fMatrix); - canvas.translate(glyphData.fOrigin.fX, -glyphData.fOrigin.fY); - - if (glyphData.fSvg) { - SkAutoExclusive lock(glyphData.fSvgMutex); - glyphData.fSvg->render(&canvas); - } - } - - void generatePath(SkGlyphID glyph, SkPath* path) override { - this->geTestSVGTypeface()->getPath(glyph, path); - path->transform(fMatrix); - } - - void generateFontMetrics(SkPaint::FontMetrics* metrics) override { - this->geTestSVGTypeface()->getFontMetrics(metrics); - SkPaintPriv::ScaleFontMetrics(metrics, fMatrix.getScaleY()); - } - -private: - SkMatrix fMatrix; -}; - -SkScalerContext* SkTestSVGTypeface::onCreateScalerContext( - const SkScalerContextEffects& e, const SkDescriptor* desc) const -{ - return new SkTestSVGScalerContext(sk_ref_sp(const_cast<SkTestSVGTypeface*>(this)), e, desc); -} - -// Recommended that the first four be .notdef, .null, CR, space -constexpr const static SkSVGTestTypefaceGlyphData gGlyphs[] = { - {"fonts/svg/notdef.svg", {100,800}, 800, 0x0}, // .notdef - {"fonts/svg/empty.svg", {0,0}, 800, 0x0020}, // space - {"fonts/svg/diamond.svg", {100, 800}, 800, 0x2662}, // β’ - {"fonts/svg/smile.svg", {0,800}, 800, 0x1F600}, // π -}; - -sk_sp<SkTestSVGTypeface> SkTestSVGTypeface::Default() { - SkPaint::FontMetrics metrics; - metrics.fFlags = SkPaint::FontMetrics::kUnderlineThicknessIsValid_Flag | - SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag | - SkPaint::FontMetrics::kStrikeoutThicknessIsValid_Flag | - SkPaint::FontMetrics::kStrikeoutPositionIsValid_Flag; - metrics.fTop = -800; - metrics.fAscent = -800; - metrics.fDescent = 200; - metrics.fBottom = 200; - metrics.fLeading = 100; - metrics.fAvgCharWidth = 1000; - metrics.fMaxCharWidth = 1000; - metrics.fXMin = 0; - metrics.fXMax = 1000; - metrics.fXHeight = 500; - metrics.fCapHeight = 700; - metrics.fUnderlineThickness = 40; - metrics.fUnderlinePosition = 20; - metrics.fStrikeoutThickness = 20; - metrics.fStrikeoutPosition = -400; - return sk_make_sp<SkTestSVGTypeface>("Emoji", 1000, metrics, gGlyphs, SK_ARRAY_COUNT(gGlyphs), - SkFontStyle::Normal()); -} - -void SkTestSVGTypeface::exportTtxCommon(SkWStream* out, const char* type, - const SkTArray<GlyfInfo>* glyfInfo) const -{ - int totalGlyphs = fGlyphCount; - out->writeText(" <GlyphOrder>\n"); - for (int i = 0; i < fGlyphCount; ++i) { - out->writeText(" <GlyphID name=\"glyf"); - out->writeHexAsText(i, 4); - out->writeText("\"/>\n"); - } - if (glyfInfo) { - for (int i = 0; i < fGlyphCount; ++i) { - for (int j = 0; j < (*glyfInfo)[i].fLayers.count(); ++j) { - out->writeText(" <GlyphID name=\"glyf"); - out->writeHexAsText(i, 4); - out->writeText("l"); - out->writeHexAsText(j, 4); - out->writeText("\"/>\n"); - ++totalGlyphs; - } - } - } - out->writeText(" </GlyphOrder>\n"); - - out->writeText(" <head>\n"); - out->writeText(" <tableVersion value=\"1.0\"/>\n"); - out->writeText(" <fontRevision value=\"1.0\"/>\n"); - out->writeText(" <checkSumAdjustment value=\"0xa9c3274\"/>\n"); - out->writeText(" <magicNumber value=\"0x5f0f3cf5\"/>\n"); - out->writeText(" <flags value=\"00000000 00011011\"/>\n"); - out->writeText(" <unitsPerEm value=\""); - out->writeDecAsText(fUpem); - out->writeText("\"/>\n"); - out->writeText(" <created value=\"Thu Feb 15 12:55:49 2018\"/>\n"); - out->writeText(" <modified value=\"Thu Feb 15 12:55:49 2018\"/>\n"); - // TODO: not recalculated for bitmap fonts? - out->writeText(" <xMin value=\""); - out->writeScalarAsText(fFontMetrics.fXMin); - out->writeText("\"/>\n"); - out->writeText(" <yMin value=\""); - out->writeScalarAsText(-fFontMetrics.fBottom); - out->writeText("\"/>\n"); - out->writeText(" <xMax value=\""); - out->writeScalarAsText(fFontMetrics.fXMax); - out->writeText("\"/>\n"); - out->writeText(" <yMax value=\""); - out->writeScalarAsText(-fFontMetrics.fTop); - out->writeText("\"/>\n"); - - char macStyle[16] = {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; - if (this->fontStyle().weight() >= SkFontStyle::Bold().weight()) { - macStyle[0xF - 0x0] = '1'; // Bold - } - switch (this->fontStyle().slant()) { - case SkFontStyle::kUpright_Slant: - break; - case SkFontStyle::kItalic_Slant: - macStyle[0xF - 0x1] = '1'; // Italic - break; - case SkFontStyle::kOblique_Slant: - macStyle[0xF - 0x1] = '1'; // Italic - break; - default: - SK_ABORT("Unknown slant."); - } - if (this->fontStyle().width() <= SkFontStyle::kCondensed_Width) { - macStyle[0xF - 0x5] = '1'; // Condensed - } else if (this->fontStyle().width() >= SkFontStyle::kExpanded_Width) { - macStyle[0xF - 0x6] = '1'; // Extended - } - out->writeText(" <macStyle value=\""); - out->write(macStyle, 8); - out->writeText(" "); - out->write(macStyle + 8, 8); - out->writeText("\"/>\n"); - out->writeText(" <lowestRecPPEM value=\"8\"/>\n"); - out->writeText(" <fontDirectionHint value=\"2\"/>\n"); - out->writeText(" <indexToLocFormat value=\"0\"/>\n"); - out->writeText(" <glyphDataFormat value=\"0\"/>\n"); - out->writeText(" </head>\n"); - - out->writeText(" <hhea>\n"); - out->writeText(" <tableVersion value=\"0x00010000\"/>\n"); - out->writeText(" <ascent value=\""); - out->writeDecAsText(-fFontMetrics.fAscent); - out->writeText("\"/>\n"); - out->writeText(" <descent value=\""); - out->writeDecAsText(-fFontMetrics.fDescent); - out->writeText("\"/>\n"); - out->writeText(" <lineGap value=\""); - out->writeDecAsText(fFontMetrics.fLeading); - out->writeText("\"/>\n"); - out->writeText(" <advanceWidthMax value=\"0\"/>\n"); - out->writeText(" <minLeftSideBearing value=\"0\"/>\n"); - out->writeText(" <minRightSideBearing value=\"0\"/>\n"); - out->writeText(" <xMaxExtent value=\""); - out->writeScalarAsText(fFontMetrics.fXMax - fFontMetrics.fXMin); - out->writeText("\"/>\n"); - out->writeText(" <caretSlopeRise value=\"1\"/>\n"); - out->writeText(" <caretSlopeRun value=\"0\"/>\n"); - out->writeText(" <caretOffset value=\"0\"/>\n"); - out->writeText(" <reserved0 value=\"0\"/>\n"); - out->writeText(" <reserved1 value=\"0\"/>\n"); - out->writeText(" <reserved2 value=\"0\"/>\n"); - out->writeText(" <reserved3 value=\"0\"/>\n"); - out->writeText(" <metricDataFormat value=\"0\"/>\n"); - out->writeText(" <numberOfHMetrics value=\"0\"/>\n"); - out->writeText(" </hhea>\n"); - - // Some of this table is going to be re-calculated, but we have to write it out anyway. - out->writeText(" <maxp>\n"); - out->writeText(" <tableVersion value=\"0x10000\"/>\n"); - out->writeText(" <numGlyphs value=\""); - out->writeDecAsText(totalGlyphs); - out->writeText("\"/>\n"); - out->writeText(" <maxPoints value=\"4\"/>\n"); - out->writeText(" <maxContours value=\"1\"/>\n"); - out->writeText(" <maxCompositePoints value=\"0\"/>\n"); - out->writeText(" <maxCompositeContours value=\"0\"/>\n"); - out->writeText(" <maxZones value=\"1\"/>\n"); - out->writeText(" <maxTwilightPoints value=\"0\"/>\n"); - out->writeText(" <maxStorage value=\"0\"/>\n"); - out->writeText(" <maxFunctionDefs value=\"10\"/>\n"); - out->writeText(" <maxInstructionDefs value=\"0\"/>\n"); - out->writeText(" <maxStackElements value=\"512\"/>\n"); - out->writeText(" <maxSizeOfInstructions value=\"24\"/>\n"); - out->writeText(" <maxComponentElements value=\"0\"/>\n"); - out->writeText(" <maxComponentDepth value=\"0\"/>\n"); - out->writeText(" </maxp>\n"); - - out->writeText(" <OS_2>\n"); - out->writeText(" <version value=\"4\"/>\n"); - out->writeText(" <xAvgCharWidth value=\""); - out->writeScalarAsText(fFontMetrics.fAvgCharWidth); - out->writeText("\"/>\n"); - out->writeText(" <usWeightClass value=\""); - out->writeDecAsText(this->fontStyle().weight()); - out->writeText("\"/>\n"); - out->writeText(" <usWidthClass value=\""); - out->writeDecAsText(this->fontStyle().width()); - out->writeText("\"/>\n"); - out->writeText(" <fsType value=\"00000000 00000000\"/>\n"); - out->writeText(" <ySubscriptXSize value=\"665\"/>\n"); - out->writeText(" <ySubscriptYSize value=\"716\"/>\n"); - out->writeText(" <ySubscriptXOffset value=\"0\"/>\n"); - out->writeText(" <ySubscriptYOffset value=\"143\"/>\n"); - out->writeText(" <ySuperscriptXSize value=\"665\"/>\n"); - out->writeText(" <ySuperscriptYSize value=\"716\"/>\n"); - out->writeText(" <ySuperscriptXOffset value=\"0\"/>\n"); - out->writeText(" <ySuperscriptYOffset value=\"491\"/>\n"); - out->writeText(" <yStrikeoutSize value=\""); - out->writeScalarAsText(fFontMetrics.fStrikeoutThickness); - out->writeText("\"/>\n"); - out->writeText(" <yStrikeoutPosition value=\""); - out->writeScalarAsText(-fFontMetrics.fStrikeoutPosition); - out->writeText("\"/>\n"); - out->writeText(" <sFamilyClass value=\"0\"/>\n"); - out->writeText(" <panose>\n"); - out->writeText(" <bFamilyType value=\"0\"/>\n"); - out->writeText(" <bSerifStyle value=\"0\"/>\n"); - out->writeText(" <bWeight value=\"0\"/>\n"); - out->writeText(" <bProportion value=\"0\"/>\n"); - out->writeText(" <bContrast value=\"0\"/>\n"); - out->writeText(" <bStrokeVariation value=\"0\"/>\n"); - out->writeText(" <bArmStyle value=\"0\"/>\n"); - out->writeText(" <bLetterForm value=\"0\"/>\n"); - out->writeText(" <bMidline value=\"0\"/>\n"); - out->writeText(" <bXHeight value=\"0\"/>\n"); - out->writeText(" </panose>\n"); - out->writeText(" <ulUnicodeRange1 value=\"00000000 00000000 00000000 00000001\"/>\n"); - out->writeText(" <ulUnicodeRange2 value=\"00010000 00000000 00000000 00000000\"/>\n"); - out->writeText(" <ulUnicodeRange3 value=\"00000000 00000000 00000000 00000000\"/>\n"); - out->writeText(" <ulUnicodeRange4 value=\"00000000 00000000 00000000 00000000\"/>\n"); - out->writeText(" <achVendID value=\"Skia\"/>\n"); - char fsSelection[16] = {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; - fsSelection[0xF - 0x7] = '1'; // Use typo metrics - if (this->fontStyle().weight() >= SkFontStyle::Bold().weight()) { - fsSelection[0xF - 0x5] = '1'; // Bold - } - switch (this->fontStyle().slant()) { - case SkFontStyle::kUpright_Slant: - if (this->fontStyle().weight() < SkFontStyle::Bold().weight()) { - fsSelection[0xF - 0x6] = '1'; // Not bold or italic, is regular - } - break; - case SkFontStyle::kItalic_Slant: - fsSelection[0xF - 0x0] = '1'; // Italic - break; - case SkFontStyle::kOblique_Slant: - fsSelection[0xF - 0x0] = '1'; // Italic - fsSelection[0xF - 0x9] = '1'; // Oblique - break; - default: - SK_ABORT("Unknown slant."); - } - out->writeText(" <fsSelection value=\""); - out->write(fsSelection, 8); - out->writeText(" "); - out->write(fsSelection + 8, 8); - out->writeText("\"/>\n"); - out->writeText(" <usFirstCharIndex value=\"0\"/>\n"); - out->writeText(" <usLastCharIndex value=\"0\"/>\n"); - out->writeText(" <sTypoAscender value=\""); - out->writeScalarAsText(-fFontMetrics.fAscent); - out->writeText("\"/>\n"); - out->writeText(" <sTypoDescender value=\""); - out->writeScalarAsText(-fFontMetrics.fDescent); - out->writeText("\"/>\n"); - out->writeText(" <sTypoLineGap value=\""); - out->writeScalarAsText(fFontMetrics.fLeading); - out->writeText("\"/>\n"); - out->writeText(" <usWinAscent value=\""); - out->writeScalarAsText(-fFontMetrics.fAscent); - out->writeText("\"/>\n"); - out->writeText(" <usWinDescent value=\""); - out->writeScalarAsText(fFontMetrics.fDescent); - out->writeText("\"/>\n"); - out->writeText(" <ulCodePageRange1 value=\"00000000 00000000 00000000 00000000\"/>\n"); - out->writeText(" <ulCodePageRange2 value=\"00000000 00000000 00000000 00000000\"/>\n"); - out->writeText(" <sxHeight value=\""); - out->writeScalarAsText(fFontMetrics.fXHeight); - out->writeText("\"/>\n"); - out->writeText(" <sCapHeight value=\""); - out->writeScalarAsText(fFontMetrics.fCapHeight); - out->writeText("\"/>\n"); - out->writeText(" <usDefaultChar value=\"0\"/>\n"); - out->writeText(" <usBreakChar value=\"32\"/>\n"); - out->writeText(" <usMaxContext value=\"0\"/>\n"); - out->writeText(" </OS_2>\n"); - - out->writeText(" <hmtx>\n"); - for (int i = 0; i < fGlyphCount; ++i) { - out->writeText(" <mtx name=\"glyf"); - out->writeHexAsText(i, 4); - out->writeText("\" width=\""); - out->writeDecAsText(fGlyphs[i].fAdvance); - out->writeText("\" lsb=\""); - int lsb = fGlyphs[i].fOrigin.fX; - if (glyfInfo) { - lsb += (*glyfInfo)[i].fBounds.fLeft; - } - out->writeDecAsText(lsb); - out->writeText("\"/>\n"); - } - if (glyfInfo) { - for (int i = 0; i < fGlyphCount; ++i) { - for (int j = 0; j < (*glyfInfo)[i].fLayers.count(); ++j) { - out->writeText(" <mtx name=\"glyf"); - out->writeHexAsText(i, 4); - out->writeText("l"); - out->writeHexAsText(j, 4); - out->writeText("\" width=\""); - out->writeDecAsText(fGlyphs[i].fAdvance); - out->writeText("\" lsb=\""); - int32_t lsb = fGlyphs[i].fOrigin.fX + (*glyfInfo)[i].fLayers[j].fBounds.fLeft; - out->writeDecAsText(lsb); - out->writeText("\"/>\n"); - } - } - } - out->writeText(" </hmtx>\n"); - - bool hasNonBMP = false; - out->writeText(" <cmap>\n"); - out->writeText(" <tableVersion version=\"0\"/>\n"); - out->writeText(" <cmap_format_4 platformID=\"3\" platEncID=\"1\" language=\"0\">\n"); - fCMap.foreach([&out, &hasNonBMP](const SkUnichar& c, const SkGlyphID& g) { - if (0xFFFF < c) { - hasNonBMP = true; - return; - } - out->writeText(" <map code=\"0x"); - out->writeHexAsText(c, 4); - out->writeText("\" name=\"glyf"); - out->writeHexAsText(g, 4); - out->writeText("\"/>\n"); - }); - out->writeText(" </cmap_format_4>\n"); - if (hasNonBMP) { - out->writeText(" <cmap_format_12 platformID=\"3\" platEncID=\"10\" format=\"12\" reserved=\"0\" length=\"1\" language=\"0\" nGroups=\"0\">\n"); - fCMap.foreach([&out](const SkUnichar& c, const SkGlyphID& g) { - out->writeText(" <map code=\"0x"); - out->writeHexAsText(c, 6); - out->writeText("\" name=\"glyf"); - out->writeHexAsText(g, 4); - out->writeText("\"/>\n"); - }); - out->writeText(" </cmap_format_12>\n"); - } - out->writeText(" </cmap>\n"); - - out->writeText(" <name>\n"); - out->writeText(" <namerecord nameID=\"1\" platformID=\"3\" platEncID=\"1\" langID=\"0x409\">\n"); - out->writeText(" "); - out->writeText(fName.c_str()); - out->writeText(" "); - out->writeText(type); - out->writeText("\n"); - out->writeText(" </namerecord>\n"); - out->writeText(" <namerecord nameID=\"2\" platformID=\"3\" platEncID=\"1\" langID=\"0x409\">\n"); - out->writeText(" Regular\n"); - out->writeText(" </namerecord>\n"); - out->writeText(" </name>\n"); - - out->writeText(" <post>\n"); - out->writeText(" <formatType value=\"3.0\"/>\n"); - out->writeText(" <italicAngle value=\"0.0\"/>\n"); - out->writeText(" <underlinePosition value=\""); - out->writeScalarAsText(fFontMetrics.fUnderlinePosition); - out->writeText("\"/>\n"); - out->writeText(" <underlineThickness value=\""); - out->writeScalarAsText(fFontMetrics.fUnderlineThickness); - out->writeText("\"/>\n"); - out->writeText(" <isFixedPitch value=\"0\"/>\n"); - out->writeText(" <minMemType42 value=\"0\"/>\n"); - out->writeText(" <maxMemType42 value=\"0\"/>\n"); - out->writeText(" <minMemType1 value=\"0\"/>\n"); - out->writeText(" <maxMemType1 value=\"0\"/>\n"); - out->writeText(" </post>\n"); -} - -void SkTestSVGTypeface::exportTtxCbdt(SkWStream* out) const { - out->writeText("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); - out->writeText("<ttFont sfntVersion=\"\\x00\\x01\\x00\\x00\" ttLibVersion=\"3.19\">\n"); - this->exportTtxCommon(out, "CBDT"); - - int strikeSizes[3] = { 16, 64, 128 }; - - SkPaint paint; - paint.setTypeface(sk_ref_sp(const_cast<SkTestSVGTypeface*>(this))); - paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); - - out->writeText(" <CBDT>\n"); - out->writeText(" <header version=\"2.0\"/>\n"); - for (size_t strikeIndex = 0; strikeIndex < SK_ARRAY_COUNT(strikeSizes); ++strikeIndex) { - paint.setTextSize(strikeSizes[strikeIndex]); - out->writeText(" <strikedata index=\""); - out->writeDecAsText(strikeIndex); - out->writeText("\">\n"); - for (int i = 0; i < fGlyphCount; ++i) { - SkGlyphID gid = i; - SkScalar advance; - SkRect bounds; - paint.getTextWidths(&gid, sizeof(gid), &advance, &bounds); - SkIRect ibounds = bounds.roundOut(); - if (ibounds.isEmpty()) { - continue; - } - SkImageInfo image_info = SkImageInfo::MakeN32Premul(ibounds.width(), ibounds.height()); - sk_sp<SkSurface> surface(SkSurface::MakeRaster(image_info)); - SkASSERT(surface); - SkCanvas* canvas = surface->getCanvas(); - canvas->clear(0); - SkPixmap pix; - surface->peekPixels(&pix); - canvas->drawText(&gid, sizeof(gid), -bounds.fLeft, -bounds.fTop, paint); - canvas->flush(); - sk_sp<SkImage> image = surface->makeImageSnapshot(); - sk_sp<SkData> data = image->encodeToData(SkEncodedImageFormat::kPNG, 100); - - out->writeText(" <cbdt_bitmap_format_17 name=\"glyf"); - out->writeHexAsText(i, 4); - out->writeText("\">\n"); - out->writeText(" <SmallGlyphMetrics>\n"); - out->writeText(" <height value=\""); - out->writeDecAsText(image->height()); - out->writeText("\"/>\n"); - out->writeText(" <width value=\""); - out->writeDecAsText(image->width()); - out->writeText("\"/>\n"); - out->writeText(" <BearingX value=\""); - out->writeDecAsText(bounds.fLeft); - out->writeText("\"/>\n"); - out->writeText(" <BearingY value=\""); - out->writeScalarAsText(-bounds.fTop); - out->writeText("\"/>\n"); - out->writeText(" <Advance value=\""); - out->writeScalarAsText(advance); - out->writeText("\"/>\n"); - out->writeText(" </SmallGlyphMetrics>\n"); - out->writeText(" <rawimagedata>"); - uint8_t const * bytes = data->bytes(); - for (size_t i = 0; i < data->size(); ++i) { - if ((i % 0x10) == 0x0) { - out->writeText("\n "); - } else if (((i - 1) % 0x4) == 0x3) { - out->writeText(" "); - } - out->writeHexAsText(bytes[i], 2); - } - out->writeText("\n"); - out->writeText(" </rawimagedata>\n"); - out->writeText(" </cbdt_bitmap_format_17>\n"); - } - out->writeText(" </strikedata>\n"); - } - out->writeText(" </CBDT>\n"); - - SkPaint::FontMetrics fm; - out->writeText(" <CBLC>\n"); - out->writeText(" <header version=\"2.0\"/>\n"); - for (size_t strikeIndex = 0; strikeIndex < SK_ARRAY_COUNT(strikeSizes); ++strikeIndex) { - paint.setTextSize(strikeSizes[strikeIndex]); - paint.getFontMetrics(&fm); - out->writeText(" <strike index=\""); - out->writeDecAsText(strikeIndex); - out->writeText("\">\n"); - out->writeText(" <bitmapSizeTable>\n"); - out->writeText(" <sbitLineMetrics direction=\"hori\">\n"); - out->writeText(" <ascender value=\""); - out->writeScalarAsText(-fm.fTop); - out->writeText("\"/>\n"); - out->writeText(" <descender value=\""); - out->writeScalarAsText(-fm.fBottom); - out->writeText("\"/>\n"); - out->writeText(" <widthMax value=\""); - out->writeScalarAsText(fm.fXMax - fm.fXMin); - out->writeText("\"/>\n"); - out->writeText(" <caretSlopeNumerator value=\"0\"/>\n"); - out->writeText(" <caretSlopeDenominator value=\"0\"/>\n"); - out->writeText(" <caretOffset value=\"0\"/>\n"); - out->writeText(" <minOriginSB value=\"0\"/>\n"); - out->writeText(" <minAdvanceSB value=\"0\"/>\n"); - out->writeText(" <maxBeforeBL value=\"0\"/>\n"); - out->writeText(" <minAfterBL value=\"0\"/>\n"); - out->writeText(" <pad1 value=\"0\"/>\n"); - out->writeText(" <pad2 value=\"0\"/>\n"); - out->writeText(" </sbitLineMetrics>\n"); - out->writeText(" <sbitLineMetrics direction=\"vert\">\n"); - out->writeText(" <ascender value=\""); - out->writeScalarAsText(-fm.fTop); - out->writeText("\"/>\n"); - out->writeText(" <descender value=\""); - out->writeScalarAsText(-fm.fBottom); - out->writeText("\"/>\n"); - out->writeText(" <widthMax value=\""); - out->writeScalarAsText(fm.fXMax - fm.fXMin); - out->writeText("\"/>\n"); - out->writeText(" <caretSlopeNumerator value=\"0\"/>\n"); - out->writeText(" <caretSlopeDenominator value=\"0\"/>\n"); - out->writeText(" <caretOffset value=\"0\"/>\n"); - out->writeText(" <minOriginSB value=\"0\"/>\n"); - out->writeText(" <minAdvanceSB value=\"0\"/>\n"); - out->writeText(" <maxBeforeBL value=\"0\"/>\n"); - out->writeText(" <minAfterBL value=\"0\"/>\n"); - out->writeText(" <pad1 value=\"0\"/>\n"); - out->writeText(" <pad2 value=\"0\"/>\n"); - out->writeText(" </sbitLineMetrics>\n"); - out->writeText(" <colorRef value=\"0\"/>\n"); - out->writeText(" <startGlyphIndex value=\"1\"/>\n"); - out->writeText(" <endGlyphIndex value=\"1\"/>\n"); - out->writeText(" <ppemX value=\""); - out->writeDecAsText(strikeSizes[strikeIndex]); - out->writeText("\"/>\n"); - out->writeText(" <ppemY value=\""); - out->writeDecAsText(strikeSizes[strikeIndex]); - out->writeText("\"/>\n"); - out->writeText(" <bitDepth value=\"32\"/>\n"); - out->writeText(" <flags value=\"1\"/>\n"); - out->writeText(" </bitmapSizeTable>\n"); - out->writeText(" <eblc_index_sub_table_1 imageFormat=\"17\" firstGlyphIndex=\"1\" lastGlyphIndex=\"1\">\n"); - for (int i = 0; i < fGlyphCount; ++i) { - SkGlyphID gid = i; - SkRect bounds; - paint.getTextWidths(&gid, sizeof(gid), nullptr, &bounds); - if (bounds.isEmpty()) { - continue; - } - out->writeText(" <glyphLoc name=\"glyf"); - out->writeHexAsText(i, 4); - out->writeText("\"/>\n"); - } - out->writeText(" </eblc_index_sub_table_1>\n"); - out->writeText(" </strike>\n"); - } - out->writeText(" </CBLC>\n"); - - out->writeText("</ttFont>\n"); -} - -/** - * UnitsPerEm is generally 1000 here. Versions of macOS older than 10.13 - * have problems in CoreText determining the glyph bounds of bitmap glyphs - * with unitsPerEm set to 1024 or numbers not divisible by 100 when the - * contour is not closed. The bounds of sbix fonts on macOS appear to be those - * of the outline in the 'glyf' table. If this countour is closed it will be - * drawn, as the 'glyf' outline is to be drawn on top of any bitmap. (There is - * a bit which is supposed to control this, but it cannot be relied on.) So - * make the glyph contour a degenerate line with points at the edge of the - * bounding box of the glyph. - */ -void SkTestSVGTypeface::exportTtxSbix(SkWStream* out) const { - out->writeText("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); - out->writeText("<ttFont sfntVersion=\"\\x00\\x01\\x00\\x00\" ttLibVersion=\"3.19\">\n"); - this->exportTtxCommon(out, "sbix"); - - SkPaint paint; - paint.setTypeface(sk_ref_sp(const_cast<SkTestSVGTypeface*>(this))); - paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); - - out->writeText(" <glyf>\n"); - for (int i = 0; i < fGlyphCount; ++i) { - const SkTestSVGTypeface::Glyph& glyphData = this->fGlyphs[i]; - - SkSize containerSize = glyphData.fSvg ? glyphData.fSvg->containerSize() - : SkSize::MakeEmpty(); - SkRect bounds = SkRect::MakeXYWH(glyphData.fOrigin.fX, -glyphData.fOrigin.fY, - containerSize.fWidth, containerSize.fHeight); - SkIRect ibounds = bounds.roundOut(); - out->writeText(" <TTGlyph name=\"glyf"); - out->writeHexAsText(i, 4); - out->writeText("\" xMin=\""); - out->writeDecAsText(ibounds.fLeft); - out->writeText("\" yMin=\""); - out->writeDecAsText(-ibounds.fBottom); - out->writeText("\" xMax=\""); - out->writeDecAsText(ibounds.fRight); - out->writeText("\" yMax=\""); - out->writeDecAsText(-ibounds.fTop); - out->writeText("\">\n"); - out->writeText(" <contour>\n"); - out->writeText(" <pt x=\""); - out->writeDecAsText(ibounds.fLeft); - out->writeText("\" y=\""); - out->writeDecAsText(-ibounds.fBottom); - out->writeText("\" on=\"1\"/>\n"); - out->writeText(" </contour>\n"); - out->writeText(" <contour>\n"); - out->writeText(" <pt x=\""); - out->writeDecAsText(ibounds.fRight); - out->writeText("\" y=\""); - out->writeDecAsText(-ibounds.fTop); - out->writeText("\" on=\"1\"/>\n"); - out->writeText(" </contour>\n"); - out->writeText(" <instructions/>\n"); - out->writeText(" </TTGlyph>\n"); - } - out->writeText(" </glyf>\n"); - - // The loca table will be re-calculated, but if we don't write one we don't get one. - out->writeText(" <loca/>\n"); - - int strikeSizes[3] = { 16, 64, 128 }; - - out->writeText(" <sbix>\n"); - out->writeText(" <version value=\"1\"/>\n"); - out->writeText(" <flags value=\"00000000 00000001\"/>\n"); - for (size_t strikeIndex = 0; strikeIndex < SK_ARRAY_COUNT(strikeSizes); ++strikeIndex) { - paint.setTextSize(strikeSizes[strikeIndex]); - out->writeText(" <strike>\n"); - out->writeText(" <ppem value=\""); - out->writeDecAsText(strikeSizes[strikeIndex]); - out->writeText("\"/>\n"); - out->writeText(" <resolution value=\"72\"/>\n"); - for (int i = 0; i < fGlyphCount; ++i) { - SkGlyphID gid = i; - SkScalar advance; - SkRect bounds; - paint.getTextWidths(&gid, sizeof(gid), &advance, &bounds); - SkIRect ibounds = bounds.roundOut(); - if (ibounds.isEmpty()) { - continue; - } - SkImageInfo image_info = SkImageInfo::MakeN32Premul(ibounds.width(), ibounds.height()); - sk_sp<SkSurface> surface(SkSurface::MakeRaster(image_info)); - SkASSERT(surface); - SkCanvas* canvas = surface->getCanvas(); - canvas->clear(0); - SkPixmap pix; - surface->peekPixels(&pix); - canvas->drawText(&gid, sizeof(gid), -bounds.fLeft, -bounds.fTop, paint); - canvas->flush(); - sk_sp<SkImage> image = surface->makeImageSnapshot(); - sk_sp<SkData> data = image->encodeToData(SkEncodedImageFormat::kPNG, 100); - - out->writeText(" <glyph name=\"glyf"); - out->writeHexAsText(i, 4); - out->writeText("\" graphicType=\"png \" originOffsetX=\""); - out->writeDecAsText(bounds.fLeft); - out->writeText("\" originOffsetY=\""); - out->writeScalarAsText(bounds.fBottom); - out->writeText("\">\n"); - - out->writeText(" <hexdata>"); - uint8_t const * bytes = data->bytes(); - for (size_t i = 0; i < data->size(); ++i) { - if ((i % 0x10) == 0x0) { - out->writeText("\n "); - } else if (((i - 1) % 0x4) == 0x3) { - out->writeText(" "); - } - out->writeHexAsText(bytes[i], 2); - } - out->writeText("\n"); - out->writeText(" </hexdata>\n"); - out->writeText(" </glyph>\n"); - } - out->writeText(" </strike>\n"); - } - out->writeText(" </sbix>\n"); - out->writeText("</ttFont>\n"); -} - -namespace { - -void convert_noninflect_cubic_to_quads(const SkPoint p[4], - SkScalar toleranceSqd, - SkTArray<SkPoint, true>* quads, - int sublevel = 0) -{ - // Notation: Point a is always p[0]. Point b is p[1] unless p[1] == p[0], in which case it is - // p[2]. Point d is always p[3]. Point c is p[2] unless p[2] == p[3], in which case it is p[1]. - - SkVector ab = p[1] - p[0]; - SkVector dc = p[2] - p[3]; - - if (SkPointPriv::LengthSqd(ab) < SK_ScalarNearlyZero) { - if (SkPointPriv::LengthSqd(dc) < SK_ScalarNearlyZero) { - SkPoint* degQuad = quads->push_back_n(3); - degQuad[0] = p[0]; - degQuad[1] = p[0]; - degQuad[2] = p[3]; - return; - } - ab = p[2] - p[0]; - } - if (SkPointPriv::LengthSqd(dc) < SK_ScalarNearlyZero) { - dc = p[1] - p[3]; - } - - static const SkScalar kLengthScale = 3 * SK_Scalar1 / 2; - static const int kMaxSubdivs = 10; - - ab.scale(kLengthScale); - dc.scale(kLengthScale); - - // e0 and e1 are extrapolations along vectors ab and dc. - SkVector c0 = p[0]; - c0 += ab; - SkVector c1 = p[3]; - c1 += dc; - - SkScalar dSqd = sublevel > kMaxSubdivs ? 0 : SkPointPriv::DistanceToSqd(c0, c1); - if (dSqd < toleranceSqd) { - SkPoint cAvg = c0; - cAvg += c1; - cAvg.scale(SK_ScalarHalf); - - SkPoint* pts = quads->push_back_n(3); - pts[0] = p[0]; - pts[1] = cAvg; - pts[2] = p[3]; - return; - } - SkPoint choppedPts[7]; - SkChopCubicAtHalf(p, choppedPts); - convert_noninflect_cubic_to_quads(choppedPts + 0, toleranceSqd, quads, sublevel + 1); - convert_noninflect_cubic_to_quads(choppedPts + 3, toleranceSqd, quads, sublevel + 1); -} - -void convertCubicToQuads(const SkPoint p[4], SkScalar tolScale, SkTArray<SkPoint, true>* quads) { - if (!p[0].isFinite() || !p[1].isFinite() || !p[2].isFinite() || !p[3].isFinite()) { - return; - } - SkPoint chopped[10]; - int count = SkChopCubicAtInflections(p, chopped); - - const SkScalar tolSqd = SkScalarSquare(tolScale); - - for (int i = 0; i < count; ++i) { - SkPoint* cubic = chopped + 3*i; - convert_noninflect_cubic_to_quads(cubic, tolSqd, quads); - } -} - -void path_to_quads(const SkPath& path, SkPath* quadPath) { - quadPath->reset(); - SkTArray<SkPoint, true> qPts; - SkAutoConicToQuads converter; - const SkPoint* quadPts; - SkPath::RawIter iter(path); - uint8_t verb; - SkPoint pts[4]; - while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { - switch (verb) { - case SkPath::kMove_Verb: - quadPath->moveTo(pts[0].fX, pts[0].fY); - break; - case SkPath::kLine_Verb: - quadPath->lineTo(pts[1].fX, pts[1].fY); - break; - case SkPath::kQuad_Verb: - quadPath->quadTo(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY); - break; - case SkPath::kCubic_Verb: - qPts.reset(); - convertCubicToQuads(pts, SK_Scalar1, &qPts); - for (int i = 0; i < qPts.count(); i += 3) { - quadPath->quadTo(qPts[i+1].fX, qPts[i+1].fY, qPts[i+2].fX, qPts[i+2].fY); - } - break; - case SkPath::kConic_Verb: - quadPts = converter.computeQuads(pts, iter.conicWeight(), SK_Scalar1); - for (int i = 0; i < converter.countQuads(); ++i) { - quadPath->quadTo(quadPts[i*2+1].fX, quadPts[i*2+1].fY, - quadPts[i*2+2].fX, quadPts[i*2+2].fY); - } - break; - case SkPath::kClose_Verb: - quadPath->close(); - break; - default: - SkDEBUGFAIL("bad verb"); - return; - } - } -} - -class SkCOLRCanvas : public SkNoDrawCanvas { -public: - SkCOLRCanvas(SkRect glyphBounds, SkGlyphID glyphId, - SkTestSVGTypeface::GlyfInfo* glyf, SkTHashMap<SkColor, int>* colors, - SkWStream* out) - : SkNoDrawCanvas(glyphBounds.roundOut().width(), glyphBounds.roundOut().height()) - , fOut(out) - , fGlyphId(glyphId) - , fBaselineOffset(glyphBounds.top()) - , fLayerId(0) - , fGlyf(glyf) - , fColors(colors) - { } - - void writePoint(SkScalar x, SkScalar y, bool on) { - fOut->writeText(" <pt x=\""); - fOut->writeDecAsText(SkScalarRoundToInt(x)); - fOut->writeText("\" y=\""); - fOut->writeDecAsText(SkScalarRoundToInt(y)); - fOut->writeText("\" on=\""); - fOut->write8(on ? '1' : '0'); - fOut->writeText("\"/>\n"); - } - SkIRect writePath(const SkPath& path, bool layer) { - // Convert to quads. - SkPath quads; - path_to_quads(path, &quads); - - SkRect bounds = quads.computeTightBounds(); - SkIRect ibounds = bounds.roundOut(); - // The bounds will be re-calculated anyway. - fOut->writeText(" <TTGlyph name=\"glyf"); - fOut->writeHexAsText(fGlyphId, 4); - if (layer) { - fOut->writeText("l"); - fOut->writeHexAsText(fLayerId, 4); - } - fOut->writeText("\" xMin=\""); - fOut->writeDecAsText(ibounds.fLeft); - fOut->writeText("\" yMin=\""); - fOut->writeDecAsText(ibounds.fTop); - fOut->writeText("\" xMax=\""); - fOut->writeDecAsText(ibounds.fRight); - fOut->writeText("\" yMax=\""); - fOut->writeDecAsText(ibounds.fBottom); - fOut->writeText("\">\n"); - - SkPath::RawIter iter(quads); - uint8_t verb; - SkPoint pts[4]; - bool contourOpen = false; - while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { - switch (verb) { - case SkPath::kMove_Verb: - if (contourOpen) { - fOut->writeText(" </contour>\n"); - contourOpen = false; - } - break; - case SkPath::kLine_Verb: - if (!contourOpen) { - fOut->writeText(" <contour>\n"); - this->writePoint(pts[0].fX, pts[0].fY, true); - contourOpen = true; - } - this->writePoint(pts[1].fX, pts[1].fY, true); - break; - case SkPath::kQuad_Verb: - if (!contourOpen) { - fOut->writeText(" <contour>\n"); - this->writePoint(pts[0].fX, pts[0].fY, true); - contourOpen = true; - } - this->writePoint(pts[1].fX, pts[1].fY, false); - this->writePoint(pts[2].fX, pts[2].fY, true); - break; - case SkPath::kClose_Verb: - if (contourOpen) { - fOut->writeText(" </contour>\n"); - contourOpen = false; - } - break; - default: - SkDEBUGFAIL("bad verb"); - return ibounds; - } - } - if (contourOpen) { - fOut->writeText(" </contour>\n"); - } - - // Required to write out an instructions tag. - fOut->writeText(" <instructions/>\n"); - fOut->writeText(" </TTGlyph>\n"); - return ibounds; - } - - void onDrawRect(const SkRect& rect, const SkPaint& paint) override { - SkPath path; - path.addRect(rect); - this->drawPath(path, paint); - } - - void onDrawOval(const SkRect& oval, const SkPaint& paint) override { - SkPath path; - path.addOval(oval); - this->drawPath(path, paint); - } - - void onDrawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, - const SkPaint& paint) override - { - SkPath path; - bool fillNoPathEffect = SkPaint::kFill_Style == paint.getStyle() && !paint.getPathEffect(); - SkPathPriv::CreateDrawArcPath(&path, oval, startAngle, sweepAngle, useCenter, - fillNoPathEffect); - this->drawPath(path, paint); - } - - void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override { - SkPath path; - path.addRRect(rrect); - this->drawPath(path, paint); - } - - void onDrawPath(const SkPath& platonicPath, const SkPaint& originalPaint) override { - SkPaint paint = originalPaint; - SkPath path = platonicPath; - - // Apply the path effect. - if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { - bool fill = paint.getFillPath(path, &path); - - paint.setPathEffect(nullptr); - if (fill) { - paint.setStyle(SkPaint::kFill_Style); - } else { - paint.setStyle(SkPaint::kStroke_Style); - paint.setStrokeWidth(0); - } - } - - // Apply the matrix. - SkMatrix m = this->getTotalMatrix(); - // If done to the canvas then everything would get clipped out. - m.postTranslate(0, fBaselineOffset); // put the baseline at 0 - m.postScale(1, -1); // and flip it since OpenType is y-up. - path.transform(m); - - // While creating the default glyf, union with dark colors and intersect with bright colors. - SkColor color = paint.getColor(); - if ((SkColorGetR(color) + SkColorGetG(color) + SkColorGetB(color)) / 3 > 0x20) { - fBasePath.add(path, SkPathOp::kDifference_SkPathOp); - } else { - fBasePath.add(path, SkPathOp::kUnion_SkPathOp); - } - - SkIRect bounds = this->writePath(path, true); - - // The CPAL table has the concept of a 'current color' which is index 0xFFFF. - // Mark any layer drawn in 'currentColor' as having this special index. - // The value of 'currentColor' here should a color which causes this layer to union into the - // default glyf. - constexpr SkColor currentColor = 0xFF2B0000; - - int colorIndex; - if (color == currentColor) { - colorIndex = 0xFFFF; - } else { - int* colorIndexPtr = fColors->find(color); - if (colorIndexPtr) { - colorIndex = *colorIndexPtr; - } else { - colorIndex = fColors->count(); - fColors->set(color, colorIndex); - } - } - fGlyf->fLayers.emplace_back(colorIndex, bounds); - - ++fLayerId; - } - - void finishGlyph() { - SkPath baseGlyph; - fBasePath.resolve(&baseGlyph); - fGlyf->fBounds = this->writePath(baseGlyph, false); - } - -private: - SkWStream * const fOut; - SkGlyphID fGlyphId; - SkScalar fBaselineOffset; - int fLayerId; - SkOpBuilder fBasePath; - SkTestSVGTypeface::GlyfInfo* fGlyf; - SkTHashMap<SkColor, int>* fColors; -}; - -} // namespace - -void SkTestSVGTypeface::exportTtxColr(SkWStream* out) const { - out->writeText("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); - out->writeText("<ttFont sfntVersion=\"\\x00\\x01\\x00\\x00\" ttLibVersion=\"3.19\">\n"); - - SkTHashMap<SkColor, int> colors; - SkTArray<GlyfInfo> glyfInfos(fGlyphCount); - - // Need to know all the glyphs up front for the common tables. - SkDynamicMemoryWStream glyfOut; - glyfOut.writeText(" <glyf>\n"); - for (int i = 0; i < fGlyphCount; ++i) { - const SkTestSVGTypeface::Glyph& glyphData = this->fGlyphs[i]; - - SkSize containerSize = glyphData.fSvg ? glyphData.fSvg->containerSize() - : SkSize::MakeEmpty(); - SkRect bounds = SkRect::MakeXYWH(glyphData.fOrigin.fX, -glyphData.fOrigin.fY, - containerSize.fWidth, containerSize.fHeight); - SkCOLRCanvas canvas(bounds, i, &glyfInfos.emplace_back(), &colors, &glyfOut); - if (glyphData.fSvg) { - glyphData.fSvg->render(&canvas); - } - canvas.finishGlyph(); - } - glyfOut.writeText(" </glyf>\n"); - - this->exportTtxCommon(out, "COLR", &glyfInfos); - - // The loca table will be re-calculated, but if we don't write one we don't get one. - out->writeText(" <loca/>\n"); - - std::unique_ptr<SkStreamAsset> glyfStream = glyfOut.detachAsStream(); - out->writeStream(glyfStream.get(), glyfStream->getLength()); - - out->writeText(" <COLR>\n"); - out->writeText(" <version value=\"0\"/>\n"); - for (int i = 0; i < fGlyphCount; ++i) { - if (glyfInfos[i].fBounds.isEmpty() || glyfInfos[i].fLayers.empty()) { - continue; - } - out->writeText(" <ColorGlyph name=\"glyf"); - out->writeHexAsText(i, 4); - out->writeText("\">\n"); - for (int j = 0; j < glyfInfos[i].fLayers.count(); ++j) { - const int colorIndex = glyfInfos[i].fLayers[j].fLayerColorIndex; - out->writeText(" <layer colorID=\""); - out->writeDecAsText(colorIndex); - out->writeText("\" name=\"glyf"); - out->writeHexAsText(i, 4); - out->writeText("l"); - out->writeHexAsText(j, 4); - out->writeText("\"/>\n"); - } - out->writeText(" </ColorGlyph>\n"); - } - out->writeText(" </COLR>\n"); - - // The colors must be written in order, the 'index' is ignored by ttx. - SkAutoTMalloc<SkColor> colorsInOrder(colors.count()); - colors.foreach([&colorsInOrder](const SkColor& c, const int* i) { - colorsInOrder[*i] = c; - }); - out->writeText(" <CPAL>\n"); - out->writeText(" <version value=\"0\"/>\n"); - out->writeText(" <numPaletteEntries value=\""); - out->writeDecAsText(colors.count()); - out->writeText("\"/>\n"); - out->writeText(" <palette index=\"0\">\n"); - for (int i = 0; i < colors.count(); ++i) { - SkColor c = colorsInOrder[i]; - out->writeText(" <color index=\""); - out->writeDecAsText(i); - out->writeText("\" value=\"#"); - out->writeHexAsText(SkColorGetR(c), 2); - out->writeHexAsText(SkColorGetG(c), 2); - out->writeHexAsText(SkColorGetB(c), 2); - out->writeHexAsText(SkColorGetA(c), 2); - out->writeText("\"/>\n"); - } - out->writeText(" </palette>\n"); - out->writeText(" </CPAL>\n"); - - out->writeText("</ttFont>\n"); -} diff --git a/tools/fonts/SkTestSVGTypeface.h b/tools/fonts/SkTestSVGTypeface.h deleted file mode 100644 index c6e9f4e2cf..0000000000 --- a/tools/fonts/SkTestSVGTypeface.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2014 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SkTestSVGTypeface_DEFINED -#define SkTestSVGTypeface_DEFINED - -#include "SkFontArguments.h" -#include "SkMutex.h" -#include "SkPaint.h" -#include "SkPoint.h" -#include "SkRect.h" -#include "SkRefCnt.h" -#include "SkScalar.h" -#include "SkString.h" -#include "SkTArray.h" -#include "SkTHash.h" -#include "SkTypeface.h" -#include "SkTypes.h" - -#include <memory> - -class SkDescriptor; -class SkFontDescriptor; -class SkFontStyle; -class SkGlyph; -class SkPath; -class SkScalerContext; -class SkStreamAsset; -class SkSVGDOM; -class SkWStream; -struct SkAdvancedTypefaceMetrics; -struct SkScalerContextEffects; -struct SkScalerContextRec; - -struct SkSVGTestTypefaceGlyphData { - const char* fSvgResourcePath; - SkPoint fOrigin; - SkScalar fAdvance; - SkUnichar fUnicode; //TODO: this limits to 1:1 -}; - -class SkTestSVGTypeface : public SkTypeface { -public: - SkTestSVGTypeface(const char* name, - int upem, - const SkPaint::FontMetrics& metrics, - const SkSVGTestTypefaceGlyphData* data, int dataCount, - const SkFontStyle& style); - ~SkTestSVGTypeface() override; - void getAdvance(SkGlyph* glyph) const; - void getFontMetrics(SkPaint::FontMetrics* metrics) const; - void getPath(SkGlyphID glyph, SkPath* path) const; - - static sk_sp<SkTestSVGTypeface> Default(); - void exportTtxCbdt(SkWStream*) const; - void exportTtxSbix(SkWStream*) const; - void exportTtxColr(SkWStream*) const; - - struct GlyfLayerInfo { - GlyfLayerInfo(int layerColorIndex, SkIRect bounds) - : fLayerColorIndex(layerColorIndex) - , fBounds(bounds) {} - int fLayerColorIndex; - SkIRect fBounds; - }; - struct GlyfInfo { - GlyfInfo() : fBounds(SkIRect::MakeEmpty()) {} - SkIRect fBounds; - SkTArray<GlyfLayerInfo> fLayers; - }; -protected: - void exportTtxCommon(SkWStream*, const char* type, const SkTArray<GlyfInfo>* = nullptr) const; - - SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&, - const SkDescriptor* desc) const override; - void onFilterRec(SkScalerContextRec* rec) const override; - std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override; - - SkStreamAsset* onOpenStream(int* ttcIndex) const override { - return nullptr; - } - - void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const override; - - int onCharsToGlyphs(const void* chars, Encoding encoding, - uint16_t glyphs[], int glyphCount) const override; - - int onCountGlyphs() const override { - return fGlyphCount; - } - - int onGetUPEM() const override { - return fUpem; - } - - void onGetFamilyName(SkString* familyName) const override; - SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override; - - int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[], - int coordinateCount) const override - { - return 0; - } - - int onGetTableTags(SkFontTableTag tags[]) const override { - return 0; - } - - size_t onGetTableData(SkFontTableTag tag, size_t offset, - size_t length, void* data) const override { - return 0; - } -private: - struct Glyph { - Glyph(); - ~Glyph(); - sk_sp<SkSVGDOM> fSvg; - SkMutex fSvgMutex; - SkPoint fOrigin; - SkScalar fAdvance; - }; - SkString fName; - int fUpem; - const SkPaint::FontMetrics fFontMetrics; - std::unique_ptr<Glyph[]> fGlyphs; - int fGlyphCount; - SkTHashMap<SkUnichar, SkGlyphID> fCMap; - friend class SkTestSVGScalerContext; -}; - -#endif diff --git a/tools/fonts/SkTestTypeface.cpp b/tools/fonts/SkTestScalerContext.cpp index 52751c9f59..f74b1bd57a 100644 --- a/tools/fonts/SkTestTypeface.cpp +++ b/tools/fonts/SkTestScalerContext.cpp @@ -8,25 +8,18 @@ #include "SkAdvancedTypefaceMetrics.h" #include "SkBitmap.h" #include "SkCanvas.h" +#include "SkDescriptor.h" #include "SkFontDescriptor.h" #include "SkGlyph.h" -#include "SkImageInfo.h" -#include "SkMatrix.h" +#include "SkMakeUnique.h" +#include "SkMask.h" #include "SkOTUtils.h" #include "SkPaintPriv.h" -#include "SkPath.h" -#include "SkPoint.h" -#include "SkRect.h" #include "SkScalerContext.h" -#include "SkString.h" -#include "SkTestTypeface.h" -#include "SkTDArray.h" +#include "SkTestScalerContext.h" +#include "SkTypefaceCache.h" #include "SkUtils.h" -#include <utility> - -class SkDescriptor; - SkTestFont::SkTestFont(const SkTestFontData& fontData) : INHERITED() , fCharCodes(fontData.fCharCodes) diff --git a/tools/fonts/SkTestTypeface.h b/tools/fonts/SkTestScalerContext.h index b520fb6e5c..e62210b2e3 100644 --- a/tools/fonts/SkTestTypeface.h +++ b/tools/fonts/SkTestScalerContext.h @@ -5,31 +5,17 @@ * found in the LICENSE file. */ -#ifndef SkTestTypeface_DEFINED -#define SkTestTypeface_DEFINED +#ifndef SkTestScalerContext_DEFINED +#define SkTestScalerContext_DEFINED #include "SkFixed.h" -#include "SkFontArguments.h" -#include "SkFontStyle.h" #include "SkPaint.h" +#include "SkPath.h" #include "SkRefCnt.h" -#include "SkScalar.h" +#include "SkTDArray.h" #include "SkTypeface.h" -#include "SkTypes.h" -#include <memory> - -class SkDescriptor; -class SkFontDescriptor; -class SkGlyph; -class SkPath; -class SkScalerContext; -class SkStreamAsset; -class SkString; class SkTestFont; -struct SkAdvancedTypefaceMetrics; -struct SkScalerContextEffects; -struct SkScalerContextRec; struct SkTestFontData { const SkScalar* fPoints; diff --git a/tools/fonts/create_test_font_color.cpp b/tools/fonts/create_test_font_color.cpp deleted file mode 100644 index c3f2e08f3f..0000000000 --- a/tools/fonts/create_test_font_color.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2014 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -// running create_test_font_color generates ./<cbdt|sbix|cpal>.ttx -// which are read by fonttools ttx to produce native fonts. - -#include "SkCommandLineFlags.h" -#include "SkRefCnt.h" -#include "SkStream.h" -#include "SkTestSVGTypeface.h" - -int main(int argc, char** argv) { - SkCommandLineFlags::Parse(argc, argv); - - sk_sp<SkTestSVGTypeface> typeface = SkTestSVGTypeface::Default(); - - SkFILEWStream cbdt("cbdt.ttx"); - typeface->exportTtxCbdt(&cbdt); - cbdt.flush(); - cbdt.fsync(); - - SkFILEWStream sbix("sbix.ttx"); - typeface->exportTtxSbix(&sbix); - sbix.flush(); - sbix.fsync(); - - SkFILEWStream colr("colr.ttx"); - typeface->exportTtxColr(&colr); - colr.flush(); - colr.fsync(); - - return 0; -} diff --git a/tools/fonts/sk_tool_utils_font.cpp b/tools/fonts/sk_tool_utils_font.cpp index 4d5b86aa0a..d2aac851bb 100644 --- a/tools/fonts/sk_tool_utils_font.cpp +++ b/tools/fonts/sk_tool_utils_font.cpp @@ -11,7 +11,7 @@ #include "SkFontStyle.h" #include "SkMutex.h" #include "SkOSFile.h" -#include "SkTestTypeface.h" +#include "SkTestScalerContext.h" #include "SkUtils.h" #include "sk_tool_utils.h" @@ -70,23 +70,42 @@ sk_sp<SkTypeface> create_font(const char* name, SkFontStyle style) { } sk_sp<SkTypeface> emoji_typeface() { - const char* filename; #if defined(SK_BUILD_FOR_WIN) - filename = "fonts/colr.ttf"; -#elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) - filename = "fonts/sbix.ttf"; -#else - filename = "fonts/cbdt.ttf"; -#endif - sk_sp<SkTypeface> typeface = MakeResourceAsTypeface(filename); + sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault()); + const char *colorEmojiFontName = "Segoe UI Emoji"; + sk_sp<SkTypeface> typeface(fm->matchFamilyStyle(colorEmojiFontName, SkFontStyle())); if (typeface) { return typeface; } - return SkTypeface::MakeFromName("Emoji", SkFontStyle()); + sk_sp<SkTypeface> fallback(fm->matchFamilyStyleCharacter( + colorEmojiFontName, SkFontStyle(), nullptr /* bcp47 */, 0 /* bcp47Count */, + 0x1f4b0 /* character: π° */)); + if (fallback) { + return fallback; + } + // If we don't have Segoe UI Emoji and can't find a fallback, try Segoe UI Symbol. + // Windows 7 does not have Segoe UI Emoji; Segoe UI Symbol has the (non - color) emoji. + return SkTypeface::MakeFromName("Segoe UI Symbol", SkFontStyle()); + +#elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) + return SkTypeface::MakeFromName("Apple Color Emoji", SkFontStyle()); + +#else + return MakeResourceAsTypeface("fonts/Funkster.ttf"); + +#endif } const char* emoji_sample_text() { - return "\xF0\x9F\x98\x80" " " "\xE2\x99\xA2"; // π β’ +#if defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) + return "\xF0\x9F\x92\xB0" "\xF0\x9F\x8F\xA1" "\xF0\x9F\x8E\x85" // π°π‘π
+ "\xF0\x9F\x8D\xAA" "\xF0\x9F\x8D\x95" "\xF0\x9F\x9A\x80" // πͺππ + "\xF0\x9F\x9A\xBB" "\xF0\x9F\x92\xA9" "\xF0\x9F\x93\xB7" // π»π©π· + "\xF0\x9F\x93\xA6" // π¦ + "\xF0\x9F\x87\xBA" "\xF0\x9F\x87\xB8" "\xF0\x9F\x87\xA6"; // πΊπΈπ¦ +#else + return "Hamburgefons"; +#endif } static const char* platform_os_name() { diff --git a/tools/sk_tool_utils.cpp b/tools/sk_tool_utils.cpp index 99b03a4391..2eb8dba833 100644 --- a/tools/sk_tool_utils.cpp +++ b/tools/sk_tool_utils.cpp @@ -5,29 +5,19 @@ * found in the LICENSE file. */ +#include "sk_tool_utils.h" + +#include "Resources.h" #include "SkBitmap.h" -#include "SkBlendMode.h" #include "SkCanvas.h" -#include "SkColorData.h" -#include "SkColorPriv.h" -#include "SkFloatingPoint.h" #include "SkImage.h" -#include "SkMatrix.h" -#include "SkPM4f.h" -#include "SkPaint.h" -#include "SkPath.h" #include "SkPixelRef.h" -#include "SkPixmap.h" -#include "SkPoint.h" -#include "SkRRect.h" +#include "SkPM4f.h" +#include "SkPoint3.h" #include "SkShader.h" #include "SkSurface.h" +#include "SkTestScalerContext.h" #include "SkTextBlob.h" -#include "sk_tool_utils.h" - -#include <cmath> -#include <cstring> -#include <memory> namespace sk_tool_utils { @@ -169,7 +159,7 @@ SkPath make_star(const SkRect& bounds, int numPts, int step) { #pragma optimize("", off) #endif void make_big_path(SkPath& path) { - #include "BigPathBench.inc" // IWYU pragma: keep + #include "BigPathBench.inc" } static float gaussian2d_value(int x, int y, float sigma) { diff --git a/tools/sk_tool_utils.h b/tools/sk_tool_utils.h index 30d195d479..6c1adf8e26 100644 --- a/tools/sk_tool_utils.h +++ b/tools/sk_tool_utils.h @@ -9,33 +9,26 @@ #define sk_tool_utils_DEFINED #include "SkColor.h" -#include "SkData.h" -#include "SkEncodedImageFormat.h" -#include "SkFontStyle.h" #include "SkImageEncoder.h" #include "SkImageInfo.h" #include "SkRandom.h" -#include "SkRect.h" #include "SkRefCnt.h" -#include "SkScalar.h" #include "SkStream.h" -#include "SkTArray.h" #include "SkTDArray.h" -#include "SkTypes.h" +#include "SkTypeface.h" class SkBitmap; class SkCanvas; -class SkFontStyle; +class SkColorFilter; class SkImage; class SkPaint; class SkPath; -class SkPixmap; class SkRRect; class SkShader; class SkSurface; class SkSurfaceProps; +class SkTestFont; class SkTextBlobBuilder; -class SkTypeface; namespace sk_tool_utils { |