From c66cd987f7c0e71eaf3a5239ae4e89228f490cab Mon Sep 17 00:00:00 2001 From: Brian Osman Date: Thu, 7 May 2020 18:45:13 +0000 Subject: [PATCH] Reland "Revert "custom typeface"" This reverts commit 61642b33663b968c22b5479cfde162cd5ae4b5ae. Reason for revert: ../../src/utils/SkCustomTypeface.cpp(179,20): error: cannot decompose this type; 'std::tuple_size::value' is not a valid integral constant expression Original change's description: > Revert "Revert "custom typeface"" > > Fix: implement onComputeBounds() and generateFontMetrics() > > This reverts commit 0066adefa97dccddf75a73d0cecf2cf7374cd146. > > Change-Id: Idb59336a3d201bb97e494ee0e0bb189e0a7186f1 > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/288536 > Commit-Queue: Mike Reed > Reviewed-by: Ben Wagner TBR=bungeman@google.com,reed@google.com # Not skipping CQ checks because this is a reland. Change-Id: I6845bb96a00a0c9ee54704a4c299556cc32e6438 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/288557 Reviewed-by: Brian Osman Commit-Queue: Brian Osman --- gm/userfont.cpp | 89 -------- gn/gm.gni | 1 - gn/utils.gni | 2 - include/utils/SkCustomTypeface.h | 42 ---- src/core/SkGlyph.h | 1 - src/core/SkTypeface.cpp | 7 - src/utils/SkCustomTypeface.cpp | 376 ------------------------------- 7 files changed, 518 deletions(-) delete mode 100644 gm/userfont.cpp delete mode 100644 include/utils/SkCustomTypeface.h delete mode 100644 src/utils/SkCustomTypeface.cpp diff --git a/gm/userfont.cpp b/gm/userfont.cpp deleted file mode 100644 index c80337315b8bc..0000000000000 --- a/gm/userfont.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "gm/gm.h" -#include "include/core/SkCanvas.h" -#include "include/core/SkFont.h" -#include "include/core/SkPaint.h" -#include "include/core/SkPath.h" -#include "include/core/SkSize.h" -#include "include/core/SkString.h" -#include "include/utils/SkCustomTypeface.h" -#include "tools/Resources.h" - -static sk_sp make_tf() { - SkCustomTypefaceBuilder builder(128); - SkFont font; - font.setSize(1.0f); - font.setHinting(SkFontHinting::kNone); - - // Steal the first 128 chars from the default font - for (SkGlyphID index = 0; index <= 127; ++index) { - SkGlyphID glyph = font.unicharToGlyph(index); - - SkScalar width; - font.getWidths(&glyph, 1, &width); - SkPath path; - font.getPath(glyph, &path); - - // we use the charcode to be our glyph index, since we have no cmap table - builder.setGlyph(index, width, path); - } - - return builder.detach(); -} - -#include "include/core/SkTextBlob.h" - -class UserFontGM : public skiagm::GM { - sk_sp fTF; - sk_sp fBlob; - - SkPath fPath; -public: - UserFontGM() {} - - void onOnceBeforeDraw() override { - fTF = make_tf(); - - SkFont font(fTF); - font.setSize(100); - font.setEdging(SkFont::Edging::kAntiAlias); - - std::vector array; - auto expand8to16 = [&](const char str[]) { - for (int i = 0; str[i]; ++i) { - array.push_back(str[i]); - } - }; - - expand8to16("User Typeface"); - fBlob = SkTextBlob::MakeFromText(array.data(), array.size() * sizeof(SkGlyphID), - font, SkTextEncoding::kGlyphID); - - } - - bool runAsBench() const override { return true; } - - SkString onShortName() override { return SkString("user_typeface"); } - - SkISize onISize() override { return {512, 512}; } - - void onDraw(SkCanvas* canvas) override { - SkScalar x = 20, - y = 250; - - SkPaint paint; - paint.setStyle(SkPaint::kStroke_Style); - canvas->drawRect(fBlob->bounds().makeOffset(x, y), paint); - - paint.setStyle(SkPaint::kFill_Style); - paint.setColor(SK_ColorRED); - canvas->drawTextBlob(fBlob, x, y, paint); - } -}; -DEF_GM(return new UserFontGM;) diff --git a/gn/gm.gni b/gn/gm.gni index c4266a17e0edf..9702843d4210b 100644 --- a/gn/gm.gni +++ b/gn/gm.gni @@ -378,7 +378,6 @@ gm_sources = [ "$_gm/trickycubicstrokes.cpp", "$_gm/typeface.cpp", "$_gm/unpremul.cpp", - "$_gm/userfont.cpp", "$_gm/variedtext.cpp", "$_gm/verifiers/gmverifier.cpp", "$_gm/vertices.cpp", diff --git a/gn/utils.gni b/gn/utils.gni index 1b968fc3c139f..9eb6769b1c6b0 100644 --- a/gn/utils.gni +++ b/gn/utils.gni @@ -12,7 +12,6 @@ skia_utils_public = [ "$_include/utils/SkBase64.h", "$_include/utils/SkCamera.h", "$_include/utils/SkCanvasStateUtils.h", - "$_include/utils/SkCustomTypeface.h", "$_include/utils/SkEventTracer.h", "$_include/utils/SkInterpolator.h", "$_include/utils/SkNWayCanvas.h", @@ -41,7 +40,6 @@ skia_utils_sources = [ "$_src/utils/SkCharToGlyphCache.h", "$_src/utils/SkClipStackUtils.cpp", "$_src/utils/SkClipStackUtils.h", - "$_src/utils/SkCustomTypeface.cpp", "$_src/utils/SkDashPath.cpp", "$_src/utils/SkDashPathPriv.h", "$_src/utils/SkEventTracer.cpp", diff --git a/include/utils/SkCustomTypeface.h b/include/utils/SkCustomTypeface.h deleted file mode 100644 index 366409998988a..0000000000000 --- a/include/utils/SkCustomTypeface.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SkCustomTypeface_DEFINED -#define SkCustomTypeface_DEFINED - -#include "include/core/SkImage.h" -#include "include/core/SkPaint.h" -#include "include/core/SkPath.h" -#include "include/core/SkPicture.h" -#include "include/core/SkTypeface.h" - -#include - -class SkStream; - -class SkCustomTypefaceBuilder { -public: - SkCustomTypefaceBuilder(int numGlyphs); - - void setGlyph(SkGlyphID, float advance, const SkPath&); - void setGlyph(SkGlyphID, float advance, const SkPath&, const SkPaint&); - void setGlyph(SkGlyphID, float advance, sk_sp, float scale); - void setGlyph(SkGlyphID, float advance, sk_sp); - - sk_sp detach(); - -private: - int fGlyphCount; - std::vector fPaths; - std::vector fAdvances; - - static sk_sp Deserialize(SkStream*); - - friend class SkTypeface; -}; - -#endif diff --git a/src/core/SkGlyph.h b/src/core/SkGlyph.h index eb22413d46309..773dad6b72f46 100644 --- a/src/core/SkGlyph.h +++ b/src/core/SkGlyph.h @@ -296,7 +296,6 @@ class SkGlyph { friend class SkStrikeServer; friend class SkTestScalerContext; friend class SkTestSVGScalerContext; - friend class SkUserScalerContext; friend class TestSVGTypeface; friend class TestTypeface; diff --git a/src/core/SkTypeface.cpp b/src/core/SkTypeface.cpp index 57bf5eef57430..2cfa6b74c97fd 100644 --- a/src/core/SkTypeface.cpp +++ b/src/core/SkTypeface.cpp @@ -11,7 +11,6 @@ #include "include/core/SkTypeface.h" #include "include/private/SkMutex.h" #include "include/private/SkOnce.h" -#include "include/utils/SkCustomTypeface.h" #include "src/core/SkAdvancedTypefaceMetrics.h" #include "src/core/SkEndian.h" #include "src/core/SkFontDescriptor.h" @@ -162,12 +161,6 @@ sk_sp SkTypeface::MakeFromData(sk_sp data, int index) { } sk_sp SkTypeface::MakeFromFontData(std::unique_ptr data) { - if (data->hasStream()) { - if (auto tf = SkCustomTypefaceBuilder::Deserialize(data->getStream())) { - return tf; - } - } - return SkFontMgr::RefDefault()->makeFromFontData(std::move(data)); } diff --git a/src/utils/SkCustomTypeface.cpp b/src/utils/SkCustomTypeface.cpp deleted file mode 100644 index 7d1b4f5ba71d8..0000000000000 --- a/src/utils/SkCustomTypeface.cpp +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "include/core/SkCanvas.h" -#include "include/core/SkData.h" -#include "include/core/SkFontMetrics.h" -#include "include/utils/SkCustomTypeface.h" -#include "src/core/SkAdvancedTypefaceMetrics.h" - -class SkUserTypeface : public SkTypeface { - friend class SkCustomTypefaceBuilder; - friend class SkUserScalerContext; - - SkUserTypeface(int count) - : SkTypeface(SkFontStyle()) - , fGlyphCount(count) - {} - - const int fGlyphCount; - std::vector fPaths; - std::vector fAdvances; - SkRect fBounds; - -protected: - SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&, - const SkDescriptor* desc) const override; - void onFilterRec(SkScalerContextRec* rec) const override; - void getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const override; - std::unique_ptr onGetAdvancedMetrics() const override; - - void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const override; - - void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override; - - void onGetFamilyName(SkString* familyName) const override; - SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override; - - std::unique_ptr onOpenStream(int*) const override; - - // trivial - - sk_sp onMakeClone(const SkFontArguments& args) const override { - return sk_ref_sp(this); - } - int onCountGlyphs() const override { return fGlyphCount; } - int onGetUPEM() const override { return 2048; /* ?? */ } - bool onComputeBounds(SkRect* bounds) const override { *bounds = fBounds; return true; } - - // noops - - void getPostScriptGlyphNames(SkString*) const override {} - int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate[], - int) const override { return 0; } - int onGetVariationDesignParameters(SkFontParameters::Variation::Axis[], - int) const override { return 0; } - int onGetTableTags(SkFontTableTag tags[]) const override { return 0; } - size_t onGetTableData(SkFontTableTag, size_t, size_t, void*) const override { return 0; } -}; - -SkCustomTypefaceBuilder::SkCustomTypefaceBuilder(int numGlyphs) : fGlyphCount(numGlyphs) { - fAdvances.resize(numGlyphs); - fPaths.resize(numGlyphs); -} - -void SkCustomTypefaceBuilder::setGlyph(SkGlyphID index, float advance, const SkPath& path) { - if (index >= (unsigned)fGlyphCount) { - return; - } - fAdvances[index] = advance; - fPaths[index] = path; -} - -sk_sp SkCustomTypefaceBuilder::detach() { - if (fGlyphCount <= 0) return nullptr; - - SkUserTypeface* tf = new SkUserTypeface(fGlyphCount); - tf->fAdvances = std::move(fAdvances); - tf->fPaths = std::move(fPaths); - - // initially inverted, so that any "union" will overwrite the first time - SkRect bounds = {SK_ScalarMax, SK_ScalarMax, -SK_ScalarMax, -SK_ScalarMax}; - - for (const auto& path : tf->fPaths) { - if (!path.isEmpty()) { - bounds.join(path.getBounds()); - } - } - tf->fBounds = bounds; - - return sk_sp(tf); -} - -///////////// - -#include "src/core/SkScalerContext.h" - -void SkUserTypeface::onFilterRec(SkScalerContextRec* rec) const { - rec->setHinting(SkFontHinting::kNone); -} - -void SkUserTypeface::getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const { - for (int gid = 0; gid < fGlyphCount; ++gid) { - glyphToUnicode[gid] = 0; - } -} - -std::unique_ptr SkUserTypeface::onGetAdvancedMetrics() const { - return nullptr; -} - -void SkUserTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const { - *isLocal = true; -} - -void SkUserTypeface::onCharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const { - for (int i = 0; i < count; ++i) { - glyphs[i] = 0; - } -} - -void SkUserTypeface::onGetFamilyName(SkString* familyName) const { - *familyName = ""; -} - -SkTypeface::LocalizedStrings* SkUserTypeface::onCreateFamilyNameIterator() const { - return nullptr; -} - -////////////// - -#include "src/core/SkScalerContext.h" - -class SkUserScalerContext : public SkScalerContext { -public: - SkUserScalerContext(sk_sp face, - const SkScalerContextEffects& effects, - const SkDescriptor* desc) - : SkScalerContext(std::move(face), effects, desc) { - fRec.getSingleMatrix(&fMatrix); - this->forceGenerateImageFromPath(); - } - - const SkUserTypeface* userTF() const { - return static_cast(this->getTypeface()); - } - -protected: - unsigned generateGlyphCount() override { - return this->userTF()->fGlyphCount; - } - - bool generateAdvance(SkGlyph* glyph) override { - const SkUserTypeface* tf = this->userTF(); - auto advance = fMatrix.mapXY(tf->fAdvances[glyph->getGlyphID()], 0); - - glyph->fAdvanceX = advance.fX; - glyph->fAdvanceY = advance.fY; - return true; - } - - void generateMetrics(SkGlyph* glyph) override { - glyph->zeroMetrics(); - this->generateAdvance(glyph); - // Always generates from paths, so SkScalerContext::getMetrics will figure the bounds. - } - - void generateImage(const SkGlyph&) override { SK_ABORT("Should have generated from path."); } - - bool generatePath(SkGlyphID glyph, SkPath* path) override { - this->userTF()->fPaths[glyph].transform(fMatrix, path); - return true; - } - - void generateFontMetrics(SkFontMetrics* metrics) override { - const auto [_, sy] = fMatrix.mapXY(0, 1); - - sk_bzero(metrics, sizeof(*metrics)); - metrics->fTop = this->userTF()->fBounds.fTop * sy; - metrics->fBottom = this->userTF()->fBounds.fBottom * sy; - - // todo: get these from the creator of the typeface? - metrics->fAscent = metrics->fTop; - metrics->fDescent = metrics->fBottom; - } - -private: - SkMatrix fMatrix; -}; - -SkScalerContext* SkUserTypeface::onCreateScalerContext(const SkScalerContextEffects& effects, - const SkDescriptor* desc) const { - return new SkUserScalerContext(sk_ref_sp(const_cast(this)), effects, desc); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -#include "include/private/SkFloatingPoint.h" -#include "src/core/SkAutoMalloc.h" -#include "src/core/SkPathPriv.h" - -static void write_scaled_float_to_16(SkWStream* stream, float x, float scale) { - stream->write16(SkToS16(sk_float_round2int(x * scale)) & 0xFFFF); -} - -enum PVerb { - kMove, - kLine, - kCurve, - kClose, -}; - -static void compress_write(SkWStream* stream, const SkPath& path, int upem) { - int pCount = 0; - std::vector verbs; - for (auto [v, p, w] : SkPathPriv::Iterate(path)) { - switch (v) { - default: SkASSERT(!"oops"); break; - case SkPathVerb::kMove: verbs.push_back(kMove); pCount += 1; break; - case SkPathVerb::kQuad: verbs.push_back(kCurve); pCount += 2; break; - case SkPathVerb::kLine: verbs.push_back(kLine); pCount += 1; break; - case SkPathVerb::kClose: verbs.push_back(kClose); break; - } - } - - int vCount = verbs.size(); - - stream->write16(upem); // share w/ other paths? - stream->write16(vCount); - stream->write16(pCount); - for (int i = 0; i < (vCount & ~3); i += 4) { - stream->write8((verbs[i+0]<<6) | (verbs[i+1]<<4) | (verbs[i+2]<<2) | verbs[i+3]); - } - if (vCount & 3) { - uint8_t b = 0; - int shift = 6; - for (int i = vCount & ~3; i < vCount; ++i) { - b |= verbs[i] << shift; - shift >>= 2; - } - stream->write8(b); - } - if (vCount & 1) { - stream->write8(0); - } - - const float scale = (float)upem; - auto write_pts = [&](const SkPoint pts[], int count) { - for (int i = 0; i < count; ++i) { - write_scaled_float_to_16(stream, pts[i].fX, scale); - write_scaled_float_to_16(stream, pts[i].fY, scale); - } - }; - - for (auto [v, p, w] : SkPathPriv::Iterate(path)) { - switch (v) { - default: SkASSERT(!"oops"); break; - case SkPathVerb::kMove: write_pts(&p[0], 1); break; - case SkPathVerb::kQuad: write_pts(&p[1], 2); break; - case SkPathVerb::kLine: write_pts(&p[1], 1); break; - case SkPathVerb::kClose: break; - } - } -} - -static constexpr int kMaxGlyphCount = 65536; -static constexpr size_t kHeaderSize = 16; -static const char gHeaderString[] = "SkUserTypeface00"; -static_assert(sizeof(gHeaderString) == 1 + kHeaderSize, "need header to be 16 bytes"); - -std::unique_ptr SkUserTypeface::onOpenStream(int* ttcIndex) const { - SkDynamicMemoryWStream wstream; - - wstream.write(gHeaderString, kHeaderSize); - - SkASSERT(fAdvances.size() == (unsigned)fGlyphCount); - SkASSERT(fPaths.size() == (unsigned)fGlyphCount); - - // just hacking around -- this makes the serialized font 1/2 size - const bool use_compression = false; - - wstream.write32(fGlyphCount); - - if (use_compression) { - for (float a : fAdvances) { - write_scaled_float_to_16(&wstream, a, 2048); - } - } else { - wstream.write(fAdvances.data(), fGlyphCount * sizeof(float)); - } - - for (const auto& p : fPaths) { - if (use_compression) { - compress_write(&wstream, p, 2048); - } else { - auto data = p.serialize(); - SkASSERT(SkIsAlign4(data->size())); - wstream.write(data->data(), data->size()); - } - } -// SkDebugf("%d glyphs, %d bytes\n", fGlyphCount, wstream.bytesWritten()); - *ttcIndex = 0; - return wstream.detachAsStream(); -} - -class AutoRestorePosition { - SkStream* fStream; - size_t fPosition; -public: - AutoRestorePosition(SkStream* stream) : fStream(stream) { - fPosition = stream->getPosition(); - } - - ~AutoRestorePosition() { - if (fStream) { - fStream->seek(fPosition); - } - } - - // So we don't restore the position - void markDone() { fStream = nullptr; } -}; - -sk_sp SkCustomTypefaceBuilder::Deserialize(SkStream* stream) { - AutoRestorePosition arp(stream); - - char header[kHeaderSize]; - if (stream->read(header, kHeaderSize) != kHeaderSize || - memcmp(header, gHeaderString, kHeaderSize) != 0) - { - return nullptr; - } - - int glyphCount; - if (!stream->readS32(&glyphCount) || glyphCount < 0 || glyphCount > kMaxGlyphCount) { - return nullptr; - } - - SkCustomTypefaceBuilder builder(glyphCount); - - std::vector advances(glyphCount); - if (stream->read(advances.data(), glyphCount * sizeof(float)) != glyphCount * sizeof(float)) { - return nullptr; - } - - // SkPath can read from a stream, so we have to page the rest into ram - const size_t offset = stream->getPosition(); - const size_t length = stream->getLength() - offset; - SkAutoMalloc ram(length); - char* buffer = (char*)ram.get(); - - if (stream->read(buffer, length) != length) { - return nullptr; - } - - size_t totalUsed = 0; - for (int i = 0; i < glyphCount; ++i) { - SkPath path; - size_t used = path.readFromMemory(buffer + totalUsed, length - totalUsed); - if (used == 0) { - return nullptr; - } - builder.setGlyph(i, advances[i], path); - totalUsed += used; - SkASSERT(length >= totalUsed); - } - - // all done, update the stream to only reflect the bytes we needed - stream->seek(offset + totalUsed); - - arp.markDone(); - return builder.detach(); -}