aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools
diff options
context:
space:
mode:
authorGravatar Mike Klein <mtklein@chromium.org>2017-11-10 11:33:43 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-11-10 17:02:20 +0000
commit10d66cc3f8624f2fc9825f38cb1b654f7bb00db9 (patch)
tree05d485a6ef42be2cf5734b22653c59804d140d5c /tools
parent8f7d4c3d86b252a68c9e9b45f69d741d4601a9e5 (diff)
move Sk{Test,Random}ScalerContext to tools
There's no need for Skia users to link this test code. Change-Id: I9d6ef2a053d0cf5cb916aa254389ca819c48bae1 Reviewed-on: https://skia-review.googlesource.com/69922 Reviewed-by: Ben Wagner <bungeman@google.com> Commit-Queue: Mike Klein <mtklein@chromium.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/SkRandomScalerContext.cpp258
-rw-r--r--tools/SkRandomScalerContext.h54
-rw-r--r--tools/SkTestScalerContext.cpp290
-rw-r--r--tools/SkTestScalerContext.h109
4 files changed, 711 insertions, 0 deletions
diff --git a/tools/SkRandomScalerContext.cpp b/tools/SkRandomScalerContext.cpp
new file mode 100644
index 0000000000..49d9ab43ff
--- /dev/null
+++ b/tools/SkRandomScalerContext.cpp
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkAdvancedTypefaceMetrics.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkGlyph.h"
+#include "SkMakeUnique.h"
+#include "SkPath.h"
+#include "SkRandomScalerContext.h"
+#include "SkRasterizer.h"
+
+class SkDescriptor;
+
+class SkRandomScalerContext : public SkScalerContext {
+public:
+ SkRandomScalerContext(sk_sp<SkRandomTypeface>, const SkScalerContextEffects&,
+ const SkDescriptor*, bool fFakeIt);
+
+protected:
+ unsigned generateGlyphCount() override;
+ uint16_t generateCharToGlyph(SkUnichar) override;
+ void generateAdvance(SkGlyph*) override;
+ void generateMetrics(SkGlyph*) override;
+ void generateImage(const SkGlyph&) override;
+ void generatePath(SkGlyphID, SkPath*) override;
+ void generateFontMetrics(SkPaint::FontMetrics*) override;
+
+private:
+ SkRandomTypeface* getRandomTypeface() const {
+ return static_cast<SkRandomTypeface*>(this->getTypeface());
+ }
+ std::unique_ptr<SkScalerContext> fProxy;
+ bool fFakeIt;
+};
+
+SkRandomScalerContext::SkRandomScalerContext(sk_sp<SkRandomTypeface> face,
+ const SkScalerContextEffects& effects,
+ const SkDescriptor* desc,
+ bool fakeIt)
+ : SkScalerContext(std::move(face), effects, desc)
+ , fFakeIt(fakeIt) {
+ fProxy = this->getRandomTypeface()->proxy()->createScalerContext(effects, desc);
+}
+
+unsigned SkRandomScalerContext::generateGlyphCount() {
+ return fProxy->getGlyphCount();
+}
+
+uint16_t SkRandomScalerContext::generateCharToGlyph(SkUnichar uni) {
+ return fProxy->charToGlyphID(uni);
+}
+
+void SkRandomScalerContext::generateAdvance(SkGlyph* glyph) {
+ fProxy->getAdvance(glyph);
+}
+
+void SkRandomScalerContext::generateMetrics(SkGlyph* glyph) {
+ // Here we will change the mask format of the glyph
+ // NOTE this is being overridden by the base class
+ SkMask::Format format = SkMask::kARGB32_Format; // init to handle defective compilers
+ switch (glyph->getGlyphID() % 4) {
+ case 0:
+ format = SkMask::kLCD16_Format;
+ break;
+ case 1:
+ format = SkMask::kA8_Format;
+ break;
+ case 2:
+ format = SkMask::kARGB32_Format;
+ break;
+ case 3:
+ format = SkMask::kBW_Format;
+ break;
+ }
+
+ fProxy->getMetrics(glyph);
+
+ glyph->fMaskFormat = format;
+ if (fFakeIt) {
+ return;
+ }
+ if (SkMask::kARGB32_Format == format) {
+ SkPath path;
+ fProxy->getPath(glyph->getPackedID(), &path);
+
+ SkRect storage;
+ const SkPaint& paint = this->getRandomTypeface()->paint();
+ const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
+ &storage,
+ SkPaint::kFill_Style);
+ SkIRect ibounds;
+ newBounds.roundOut(&ibounds);
+ glyph->fLeft = ibounds.fLeft;
+ glyph->fTop = ibounds.fTop;
+ glyph->fWidth = ibounds.width();
+ glyph->fHeight = ibounds.height();
+ } else {
+ SkPath devPath, fillPath;
+ SkMatrix fillToDevMatrix;
+
+ this->internalGetPath(glyph->getPackedID(), &fillPath, &devPath, &fillToDevMatrix);
+
+ // just use devPath
+ const SkIRect ir = devPath.getBounds().roundOut();
+
+ if (ir.isEmpty() || !ir.is16Bit()) {
+ glyph->fLeft = 0;
+ glyph->fTop = 0;
+ glyph->fWidth = 0;
+ glyph->fHeight = 0;
+ return;
+ }
+ glyph->fLeft = ir.fLeft;
+ glyph->fTop = ir.fTop;
+ glyph->fWidth = SkToU16(ir.width());
+ glyph->fHeight = SkToU16(ir.height());
+
+ if (glyph->fWidth > 0) {
+ switch (glyph->fMaskFormat) {
+ case SkMask::kLCD16_Format:
+ glyph->fWidth += 2;
+ glyph->fLeft -= 1;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+void SkRandomScalerContext::generateImage(const SkGlyph& glyph) {
+ SkMask::Format format = (SkMask::Format)glyph.fMaskFormat;
+ switch (glyph.getGlyphID() % 4) {
+ case 0:
+ format = SkMask::kLCD16_Format;
+ break;
+ case 1:
+ format = SkMask::kA8_Format;
+ break;
+ case 2:
+ format = SkMask::kARGB32_Format;
+ break;
+ case 3:
+ format = SkMask::kBW_Format;
+ break;
+ }
+ const_cast<SkGlyph&>(glyph).fMaskFormat = format;
+
+ // if the format is ARGB, we just draw the glyph from path ourselves. Otherwise, we force
+ // our proxy context to generate the image from paths.
+ if (!fFakeIt) {
+ if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
+ SkPath path;
+ fProxy->getPath(glyph.getPackedID(), &path);
+
+ SkBitmap bm;
+ bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
+ glyph.fImage, glyph.rowBytes());
+ bm.eraseColor(0);
+
+ SkCanvas canvas(bm);
+ canvas.translate(-SkIntToScalar(glyph.fLeft),
+ -SkIntToScalar(glyph.fTop));
+ canvas.drawPath(path, this->getRandomTypeface()->paint());
+ } else {
+ fProxy->forceGenerateImageFromPath();
+ fProxy->getImage(glyph);
+ fProxy->forceOffGenerateImageFromPath();
+ }
+ } else {
+ sk_bzero(glyph.fImage, glyph.computeImageSize());
+ }
+}
+
+void SkRandomScalerContext::generatePath(SkGlyphID glyph, SkPath* path) {
+ fProxy->generatePath(glyph, path);
+}
+
+void SkRandomScalerContext::generateFontMetrics(SkPaint::FontMetrics* metrics) {
+ fProxy->getFontMetrics(metrics);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SkTypefaceCache.h"
+
+SkRandomTypeface::SkRandomTypeface(sk_sp<SkTypeface> proxy, const SkPaint& paint, bool fakeIt)
+ : SkTypeface(proxy->fontStyle(), false)
+ , fProxy(std::move(proxy))
+ , fPaint(paint)
+ , fFakeIt(fakeIt) {}
+
+SkScalerContext* SkRandomTypeface::onCreateScalerContext(const SkScalerContextEffects& effects,
+ const SkDescriptor* desc) const {
+ return new SkRandomScalerContext(sk_ref_sp(const_cast<SkRandomTypeface*>(this)),
+ effects, desc, fFakeIt);
+}
+
+void SkRandomTypeface::onFilterRec(SkScalerContextRec* rec) const {
+ fProxy->filterRec(rec);
+ rec->setHinting(SkPaint::kNo_Hinting);
+ rec->fMaskFormat = SkMask::kARGB32_Format;
+}
+
+std::unique_ptr<SkAdvancedTypefaceMetrics> SkRandomTypeface::onGetAdvancedMetrics() const {
+ return fProxy->getAdvancedMetrics();
+}
+
+SkStreamAsset* SkRandomTypeface::onOpenStream(int* ttcIndex) const {
+ return fProxy->openStream(ttcIndex);
+}
+
+void SkRandomTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
+ bool* isLocal) const {
+ fProxy->getFontDescriptor(desc, isLocal);
+}
+
+int SkRandomTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
+ uint16_t glyphs[], int glyphCount) const {
+ return fProxy->charsToGlyphs(chars, encoding, glyphs, glyphCount);
+}
+
+int SkRandomTypeface::onCountGlyphs() const {
+ return fProxy->countGlyphs();
+}
+
+int SkRandomTypeface::onGetUPEM() const {
+ return fProxy->getUnitsPerEm();
+}
+
+void SkRandomTypeface::onGetFamilyName(SkString* familyName) const {
+ fProxy->getFamilyName(familyName);
+}
+
+SkTypeface::LocalizedStrings* SkRandomTypeface::onCreateFamilyNameIterator() const {
+ return fProxy->createFamilyNameIterator();
+}
+
+int SkRandomTypeface::onGetVariationDesignPosition(
+ SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount) const
+{
+ return fProxy->onGetVariationDesignPosition(coordinates, coordinateCount);
+}
+
+int SkRandomTypeface::onGetTableTags(SkFontTableTag tags[]) const {
+ return fProxy->getTableTags(tags);
+}
+
+size_t SkRandomTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
+ size_t length, void* data) const {
+ return fProxy->getTableData(tag, offset, length, data);
+}
+
diff --git a/tools/SkRandomScalerContext.h b/tools/SkRandomScalerContext.h
new file mode 100644
index 0000000000..b71689d9e2
--- /dev/null
+++ b/tools/SkRandomScalerContext.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkRandomScalerContext_DEFINED
+#define SkRandomScalerContext_DEFINED
+
+#include "SkScalerContext.h"
+#include "SkTypeface.h"
+
+/*
+ * This scaler context is for debug only purposes. It will 'randomly' but deterministically return
+ * LCD / A8 / BW / RBGA masks based off of the Glyph ID
+ */
+
+class SkRandomTypeface : public SkTypeface {
+public:
+ SkRandomTypeface(sk_sp<SkTypeface> proxy, const SkPaint&, bool fakeit);
+
+ SkTypeface* proxy() const { return fProxy.get(); }
+ const SkPaint& paint() const { return fPaint; }
+
+protected:
+ SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
+ const SkDescriptor*) const override;
+ void onFilterRec(SkScalerContextRec*) const override;
+ std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override;
+ SkStreamAsset* onOpenStream(int* ttcIndex) const override;
+ void onGetFontDescriptor(SkFontDescriptor*, bool* isLocal) const override;
+
+ int onCharsToGlyphs(const void* chars, Encoding encoding,
+ uint16_t glyphs[], int glyphCount) const override;
+ int onCountGlyphs() const override;
+ int onGetUPEM() const override;
+
+ void onGetFamilyName(SkString* familyName) const override;
+ SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override;
+
+ int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],
+ int coordinateCount) const override;
+ int onGetTableTags(SkFontTableTag tags[]) const override;
+ size_t onGetTableData(SkFontTableTag, size_t offset,
+ size_t length, void* data) const override;
+
+private:
+ sk_sp<SkTypeface> fProxy;
+ SkPaint fPaint;
+ bool fFakeIt;
+};
+
+#endif
diff --git a/tools/SkTestScalerContext.cpp b/tools/SkTestScalerContext.cpp
new file mode 100644
index 0000000000..34ec6af849
--- /dev/null
+++ b/tools/SkTestScalerContext.cpp
@@ -0,0 +1,290 @@
+/*
+ * 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 "SkAdvancedTypefaceMetrics.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkDescriptor.h"
+#include "SkFontDescriptor.h"
+#include "SkGlyph.h"
+#include "SkMakeUnique.h"
+#include "SkMask.h"
+#include "SkOTUtils.h"
+#include "SkPaintPriv.h"
+#include "SkScalerContext.h"
+#include "SkTestScalerContext.h"
+#include "SkTypefaceCache.h"
+
+SkTestFont::SkTestFont(const SkTestFontData& fontData)
+ : INHERITED()
+ , fCharCodes(fontData.fCharCodes)
+ , fCharCodesCount(fontData.fCharCodes ? fontData.fCharCodesCount : 0)
+ , fWidths(fontData.fWidths)
+ , fMetrics(fontData.fMetrics)
+ , fName(fontData.fName)
+ , fPaths(nullptr)
+{
+ init(fontData.fPoints, fontData.fVerbs);
+#ifdef SK_DEBUG
+ sk_bzero(fDebugBits, sizeof(fDebugBits));
+ sk_bzero(fDebugOverage, sizeof(fDebugOverage));
+#endif
+}
+
+SkTestFont::~SkTestFont() {
+ for (unsigned index = 0; index < fCharCodesCount; ++index) {
+ delete fPaths[index];
+ }
+ delete[] fPaths;
+}
+
+#ifdef SK_DEBUG
+
+#include "SkMutex.h"
+SK_DECLARE_STATIC_MUTEX(gUsedCharsMutex);
+
+#endif
+
+int SkTestFont::codeToIndex(SkUnichar charCode) const {
+#ifdef SK_DEBUG // detect missing test font data
+ {
+ SkAutoMutexAcquire ac(gUsedCharsMutex);
+ if (charCode >= ' ' && charCode <= '~') {
+ int bitOffset = charCode - ' ';
+ fDebugBits[bitOffset >> 3] |= 1 << (bitOffset & 7);
+ } else {
+ int index = 0;
+ while (fDebugOverage[index] != 0 && fDebugOverage[index] != charCode
+ && index < (int) sizeof(fDebugOverage)) {
+ ++index;
+ }
+ SkASSERT(index < (int) sizeof(fDebugOverage));
+ if (fDebugOverage[index] == 0) {
+ fDebugOverage[index] = charCode;
+ }
+ }
+ }
+#endif
+ for (unsigned index = 0; index < fCharCodesCount; ++index) {
+ if (fCharCodes[index] == (unsigned) charCode) {
+ return (int) index;
+ }
+ }
+
+ SkDEBUGF(("missing '%c' (%d) from %s (weight %d, width %d, slant %d)\n",
+ (char) charCode, charCode, fDebugName,
+ fDebugStyle.weight(), fDebugStyle.width(), fDebugStyle.slant()));
+ return 0;
+}
+
+void SkTestFont::init(const SkScalar* pts, const unsigned char* verbs) {
+ fPaths = new SkPath* [fCharCodesCount];
+ for (unsigned index = 0; index < fCharCodesCount; ++index) {
+ SkPath* path = new SkPath;
+ SkPath::Verb verb;
+ while ((verb = (SkPath::Verb) *verbs++) != SkPath::kDone_Verb) {
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ path->moveTo(pts[0], pts[1]);
+ pts += 2;
+ break;
+ case SkPath::kLine_Verb:
+ path->lineTo(pts[0], pts[1]);
+ pts += 2;
+ break;
+ case SkPath::kQuad_Verb:
+ path->quadTo(pts[0], pts[1], pts[2], pts[3]);
+ pts += 4;
+ break;
+ case SkPath::kCubic_Verb:
+ path->cubicTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]);
+ pts += 6;
+ break;
+ case SkPath::kClose_Verb:
+ path->close();
+ break;
+ default:
+ SkDEBUGFAIL("bad verb");
+ return;
+ }
+ }
+ // This should make SkPath::getBounds() queries threadsafe.
+ path->updateBoundsCache();
+ fPaths[index] = path;
+ }
+}
+
+SkTestTypeface::SkTestTypeface(sk_sp<SkTestFont> testFont, const SkFontStyle& style)
+ : SkTypeface(style, false)
+ , fTestFont(std::move(testFont)) {
+}
+
+void SkTestTypeface::getAdvance(SkGlyph* glyph) {
+ // TODO(benjaminwagner): Update users to use floats.
+ glyph->fAdvanceX = SkFixedToFloat(fTestFont->fWidths[glyph->getGlyphID()]);
+ glyph->fAdvanceY = 0;
+}
+
+void SkTestTypeface::getFontMetrics(SkPaint::FontMetrics* metrics) {
+ *metrics = fTestFont->fMetrics;
+}
+
+void SkTestTypeface::getMetrics(SkGlyph* glyph) {
+ SkGlyphID glyphID = glyph->getGlyphID();
+ glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0;
+
+ // TODO(benjaminwagner): Update users to use floats.
+ glyph->fAdvanceX = SkFixedToFloat(fTestFont->fWidths[glyphID]);
+ glyph->fAdvanceY = 0;
+}
+
+void SkTestTypeface::getPath(SkGlyphID glyphID, SkPath* path) {
+ glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0;
+ *path = *fTestFont->fPaths[glyphID];
+}
+
+void SkTestTypeface::onFilterRec(SkScalerContextRec* rec) const {
+ rec->setHinting(SkPaint::kNo_Hinting);
+}
+
+std::unique_ptr<SkAdvancedTypefaceMetrics> SkTestTypeface::onGetAdvancedMetrics() const { // pdf only
+ std::unique_ptr<SkAdvancedTypefaceMetrics> info(new SkAdvancedTypefaceMetrics);
+ info->fFontName.set(fTestFont->fName);
+ int glyphCount = this->onCountGlyphs();
+
+ SkTDArray<SkUnichar>& toUnicode = info->fGlyphToUnicode;
+ toUnicode.setCount(glyphCount);
+ SkASSERT(glyphCount == SkToInt(fTestFont->fCharCodesCount));
+ for (int gid = 0; gid < glyphCount; ++gid) {
+ toUnicode[gid] = SkToS32(fTestFont->fCharCodes[gid]);
+ }
+ return info;
+}
+
+void SkTestTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
+ desc->setFamilyName(fTestFont->fName);
+ desc->setStyle(this->fontStyle());
+ *isLocal = false;
+}
+
+int SkTestTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
+ uint16_t glyphs[], int glyphCount) const {
+ SkASSERT(encoding == kUTF32_Encoding);
+ for (int index = 0; index < glyphCount; ++index) {
+ SkUnichar ch = ((SkUnichar*) chars)[index];
+ glyphs[index] = fTestFont->codeToIndex(ch);
+ }
+ return glyphCount;
+}
+
+void SkTestTypeface::onGetFamilyName(SkString* familyName) const {
+ *familyName = fTestFont->fName;
+}
+
+SkTypeface::LocalizedStrings* SkTestTypeface::onCreateFamilyNameIterator() const {
+ SkString familyName(fTestFont->fName);
+ SkString language("und"); //undetermined
+ return new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
+}
+
+class SkTestScalerContext : public SkScalerContext {
+public:
+ SkTestScalerContext(sk_sp<SkTestTypeface> face, const SkScalerContextEffects& effects,
+ const SkDescriptor* desc)
+ : SkScalerContext(std::move(face), effects, desc)
+ {
+ fRec.getSingleMatrix(&fMatrix);
+ this->forceGenerateImageFromPath();
+ }
+
+protected:
+ SkTestTypeface* getTestTypeface() const {
+ return static_cast<SkTestTypeface*>(this->getTypeface());
+ }
+
+ unsigned generateGlyphCount() override {
+ return this->getTestTypeface()->onCountGlyphs();
+ }
+
+ uint16_t generateCharToGlyph(SkUnichar uni) override {
+ uint16_t glyph;
+ (void) this->getTestTypeface()->onCharsToGlyphs((const void *) &uni,
+ SkTypeface::kUTF32_Encoding, &glyph, 1);
+ return glyph;
+ }
+
+ void generateAdvance(SkGlyph* glyph) override {
+ this->getTestTypeface()->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 {
+ this->getTestTypeface()->getMetrics(glyph);
+
+ const SkVector advance = fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX),
+ SkFloatToScalar(glyph->fAdvanceY));
+ glyph->fAdvanceX = SkScalarToFloat(advance.fX);
+ glyph->fAdvanceY = SkScalarToFloat(advance.fY);
+
+ SkPath path;
+ this->getTestTypeface()->getPath(glyph->getGlyphID(), &path);
+ path.transform(fMatrix);
+
+ SkRect storage;
+ const SkPaint paint;
+ const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
+ &storage,
+ SkPaint::kFill_Style);
+ 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 {
+ SkPath path;
+ this->getTestTypeface()->getPath(glyph.getGlyphID(), &path);
+
+ SkBitmap bm;
+ bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
+ glyph.fImage, glyph.rowBytes());
+ bm.eraseColor(0);
+
+ SkCanvas canvas(bm);
+ canvas.translate(-SkIntToScalar(glyph.fLeft),
+ -SkIntToScalar(glyph.fTop));
+ canvas.concat(fMatrix);
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ canvas.drawPath(path, paint);
+ }
+
+ void generatePath(SkGlyphID glyph, SkPath* path) override {
+ this->getTestTypeface()->getPath(glyph, path);
+ path->transform(fMatrix);
+ }
+
+ void generateFontMetrics(SkPaint::FontMetrics* metrics) override {
+ this->getTestTypeface()->getFontMetrics(metrics);
+ SkPaintPriv::ScaleFontMetrics(metrics, fMatrix.getScaleY());
+ }
+
+private:
+ SkMatrix fMatrix;
+};
+
+SkScalerContext* SkTestTypeface::onCreateScalerContext(
+ const SkScalerContextEffects& effects, const SkDescriptor* desc) const
+{
+ return new SkTestScalerContext(sk_ref_sp(const_cast<SkTestTypeface*>(this)), effects, desc);
+}
diff --git a/tools/SkTestScalerContext.h b/tools/SkTestScalerContext.h
new file mode 100644
index 0000000000..1d362901eb
--- /dev/null
+++ b/tools/SkTestScalerContext.h
@@ -0,0 +1,109 @@
+/*
+ * 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 SkTestScalerContext_DEFINED
+#define SkTestScalerContext_DEFINED
+
+#include "SkFixed.h"
+#include "SkPaint.h"
+#include "SkPath.h"
+#include "SkRefCnt.h"
+#include "SkTDArray.h"
+#include "SkTypeface.h"
+
+class SkTestFont;
+
+struct SkTestFontData {
+ const SkScalar* fPoints;
+ const unsigned char* fVerbs;
+ const unsigned* fCharCodes;
+ const size_t fCharCodesCount;
+ const SkFixed* fWidths;
+ const SkPaint::FontMetrics& fMetrics;
+ const char* fName;
+ SkFontStyle fStyle;
+ sk_sp<SkTestFont> fCachedFont;
+};
+
+class SkTestFont : public SkRefCnt {
+public:
+ SkTestFont(const SkTestFontData& );
+ virtual ~SkTestFont();
+ int codeToIndex(SkUnichar charCode) const;
+ void init(const SkScalar* pts, const unsigned char* verbs);
+#ifdef SK_DEBUG // detect missing test font data
+ mutable unsigned char fDebugBits[16];
+ mutable SkUnichar fDebugOverage[8];
+ const char* fDebugName;
+ SkFontStyle fDebugStyle;
+ const char* debugFontName() const { return fName; }
+#endif
+private:
+ const unsigned* fCharCodes;
+ const size_t fCharCodesCount;
+ const SkFixed* fWidths;
+ const SkPaint::FontMetrics& fMetrics;
+ const char* fName;
+ SkPath** fPaths;
+ friend class SkTestTypeface;
+ typedef SkRefCnt INHERITED;
+};
+
+
+class SkTestTypeface : public SkTypeface {
+public:
+ SkTestTypeface(sk_sp<SkTestFont>, const SkFontStyle& style);
+ void getAdvance(SkGlyph* glyph);
+ void getFontMetrics(SkPaint::FontMetrics* metrics);
+ void getMetrics(SkGlyph* glyph);
+ void getPath(SkGlyphID glyph, SkPath* path);
+protected:
+ 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 (int) fTestFont->fCharCodesCount;
+ }
+
+ int onGetUPEM() const override {
+ return 2048;
+ }
+
+ 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:
+ sk_sp<SkTestFont> fTestFont;
+ friend class SkTestScalerContext;
+};
+
+#endif