Index: src/fonts/SkGScalerContext.cpp |
diff --git a/src/fonts/SkGScalerContext.cpp b/src/fonts/SkGScalerContext.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4de261b3946a09da7cad18187b44aa7fc9cd31a1 |
--- /dev/null |
+++ b/src/fonts/SkGScalerContext.cpp |
@@ -0,0 +1,249 @@ |
+/* |
+ * Copyright 2013 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+#include "SkGScalerContext.h" |
+#include "SkGlyph.h" |
+#include "SkPath.h" |
+#include "SkCanvas.h" |
+ |
+class SkGScalerContext : public SkScalerContext { |
+public: |
+ SkGScalerContext(SkGTypeface*, const SkDescriptor*); |
+ virtual ~SkGScalerContext(); |
+ |
+protected: |
+ virtual unsigned generateGlyphCount() SK_OVERRIDE; |
+ virtual uint16_t generateCharToGlyph(SkUnichar) SK_OVERRIDE; |
+ virtual void generateAdvance(SkGlyph*) SK_OVERRIDE; |
+ virtual void generateMetrics(SkGlyph*) SK_OVERRIDE; |
+ virtual void generateImage(const SkGlyph&) SK_OVERRIDE; |
+ virtual void generatePath(const SkGlyph&, SkPath*) SK_OVERRIDE; |
+ virtual void generateFontMetrics(SkPaint::FontMetrics* mX, |
+ SkPaint::FontMetrics* mY) SK_OVERRIDE; |
+ |
+private: |
+ SkGTypeface* fFace; |
+ SkScalerContext* fProxy; |
+ SkMatrix fMatrix; |
+}; |
+ |
+#define STD_SIZE 1 |
+ |
+#include "SkDescriptor.h" |
+ |
+SkGScalerContext::SkGScalerContext(SkGTypeface* face, const SkDescriptor* desc) |
+ : SkScalerContext(face, desc) |
+ , fFace(face) |
+{ |
+ |
+ size_t descSize = SkDescriptor::ComputeOverhead(1) + sizeof(SkScalerContext::Rec); |
+ SkAutoDescriptor ad(descSize); |
+ SkDescriptor* newDesc = ad.getDesc(); |
+ |
+ newDesc->init(); |
+ void* entry = newDesc->addEntry(kRec_SkDescriptorTag, |
+ sizeof(SkScalerContext::Rec), &fRec); |
+ { |
+ SkScalerContext::Rec* rec = (SkScalerContext::Rec*)entry; |
+ rec->fTextSize = STD_SIZE; |
+ rec->fPreScaleX = SK_Scalar1; |
+ rec->fPreSkewX = 0; |
+ rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1; |
+ rec->fPost2x2[1][0] = rec->fPost2x2[0][1] = 0; |
+ } |
+ SkASSERT(descSize == newDesc->getLength()); |
+ newDesc->computeChecksum(); |
+ |
+ fProxy = face->proxy()->createScalerContext(newDesc); |
+ |
+ fRec.getSingleMatrix(&fMatrix); |
+ fMatrix.preScale(SK_Scalar1 / STD_SIZE, SK_Scalar1 / STD_SIZE); |
+} |
+ |
+SkGScalerContext::~SkGScalerContext() { |
+ SkDELETE(fProxy); |
+} |
+ |
+unsigned SkGScalerContext::generateGlyphCount() { |
+ return fProxy->getGlyphCount(); |
+} |
+ |
+uint16_t SkGScalerContext::generateCharToGlyph(SkUnichar uni) { |
+ return fProxy->charToGlyphID(uni); |
+} |
+ |
+void SkGScalerContext::generateAdvance(SkGlyph* glyph) { |
+ fProxy->getAdvance(glyph); |
+ |
+ SkVector advance; |
+ fMatrix.mapXY(SkFixedToScalar(glyph->fAdvanceX), |
+ SkFixedToScalar(glyph->fAdvanceY), &advance); |
+ glyph->fAdvanceX = SkScalarToFixed(advance.fX); |
+ glyph->fAdvanceY = SkScalarToFixed(advance.fY); |
+} |
+ |
+void SkGScalerContext::generateMetrics(SkGlyph* glyph) { |
+ fProxy->getMetrics(glyph); |
+ |
+ SkVector advance; |
+ fMatrix.mapXY(SkFixedToScalar(glyph->fAdvanceX), |
+ SkFixedToScalar(glyph->fAdvanceY), &advance); |
+ glyph->fAdvanceX = SkScalarToFixed(advance.fX); |
+ glyph->fAdvanceY = SkScalarToFixed(advance.fY); |
+ |
+ SkPath path; |
+ fProxy->getPath(*glyph, &path); |
+ path.transform(fMatrix); |
+ |
+ SkRect storage; |
+ const SkPaint& paint = fFace->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(); |
+ glyph->fMaskFormat = SkMask::kARGB32_Format; |
+} |
+ |
+void SkGScalerContext::generateImage(const SkGlyph& glyph) { |
+ if (SkMask::kARGB32_Format == glyph.fMaskFormat) { |
+ SkPath path; |
+ fProxy->getPath(glyph, &path); |
+ |
+ SkBitmap bm; |
+ bm.setConfig(SkBitmap::kARGB_8888_Config, glyph.fWidth, glyph.fHeight, |
+ glyph.rowBytes()); |
+ bm.setPixels(glyph.fImage); |
+ bm.eraseColor(0); |
+ |
+ SkCanvas canvas(bm); |
+ canvas.translate(-glyph.fLeft, -glyph.fTop); |
+ canvas.concat(fMatrix); |
+ canvas.drawPath(path, fFace->paint()); |
+ } else { |
+ fProxy->getImage(glyph); |
+ } |
+} |
+ |
+void SkGScalerContext::generatePath(const SkGlyph& glyph, SkPath* path) { |
+ fProxy->getPath(glyph, path); |
+ path->transform(fMatrix); |
+} |
+ |
+void SkGScalerContext::generateFontMetrics(SkPaint::FontMetrics*, |
+ SkPaint::FontMetrics* metrics) { |
+ fProxy->getFontMetrics(metrics); |
+ if (metrics) { |
+ SkScalar scale = fMatrix.getScaleY(); |
+ metrics->fTop = SkScalarMul(metrics->fTop, scale); |
+ metrics->fAscent = SkScalarMul(metrics->fAscent, scale); |
+ metrics->fDescent = SkScalarMul(metrics->fDescent, scale); |
+ metrics->fBottom = SkScalarMul(metrics->fBottom, scale); |
+ metrics->fLeading = SkScalarMul(metrics->fLeading, scale); |
+ metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale); |
+ metrics->fXMin = SkScalarMul(metrics->fXMin, scale); |
+ metrics->fXMax = SkScalarMul(metrics->fXMax, scale); |
+ metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale); |
+ } |
+} |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+ |
+#include "SkTypefaceCache.h" |
+ |
+SkGTypeface::SkGTypeface(SkTypeface* proxy, const SkPaint& paint) |
+ : SkTypeface(proxy->style(), SkTypefaceCache::NewFontID(), false) |
+ , fProxy(SkRef(proxy)) |
+ , fPaint(paint) {} |
+ |
+SkGTypeface::~SkGTypeface() { |
+ fProxy->unref(); |
+} |
+ |
+SkScalerContext* SkGTypeface::onCreateScalerContext( |
+ const SkDescriptor* desc) const { |
+ return SkNEW_ARGS(SkGScalerContext, (const_cast<SkGTypeface*>(this), desc)); |
+} |
+ |
+void SkGTypeface::onFilterRec(SkScalerContextRec* rec) const { |
+ fProxy->filterRec(rec); |
+} |
+ |
+SkAdvancedTypefaceMetrics* SkGTypeface::onGetAdvancedTypefaceMetrics( |
+ SkAdvancedTypefaceMetrics::PerGlyphInfo info, |
+ const uint32_t* glyphIDs, |
+ uint32_t glyphIDsCount) const { |
+ return fProxy->getAdvancedTypefaceMetrics(info, glyphIDs, glyphIDsCount); |
+} |
+ |
+SkStream* SkGTypeface::onOpenStream(int* ttcIndex) const { |
+ return fProxy->openStream(ttcIndex); |
+} |
+ |
+void SkGTypeface::onGetFontDescriptor(SkFontDescriptor* desc, |
+ bool* isLocal) const { |
+ fProxy->getFontDescriptor(desc, isLocal); |
+} |
+ |
+int SkGTypeface::onGetUPEM() const { |
+ return fProxy->getUnitsPerEm(); |
+} |
+ |
+int SkGTypeface::onGetTableTags(SkFontTableTag tags[]) const { |
+ return fProxy->getTableTags(tags); |
+} |
+ |
+size_t SkGTypeface::onGetTableData(SkFontTableTag tag, size_t offset, |
+ size_t length, void* data) const { |
+ return fProxy->getTableData(tag, offset, length, data); |
+} |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+ |
+#if 0 |
+// under construction -- defining a font purely in terms of skia primitives |
+// ala an SVG-font. |
+class SkGFont : public SkRefCnt { |
+public: |
+ virtual ~SkGFont(); |
+ |
+ int unicharToGlyph(SkUnichar) const; |
+ |
+ int countGlyphs() const { return fCount; } |
+ |
+ float getAdvance(int index) const { |
+ SkASSERT((unsigned)index < (unsigned)fCount); |
+ return fGlyphs[index].fAdvance; |
+ } |
+ |
+ const SkPath& getPath(int index) const { |
+ SkASSERT((unsigned)index < (unsigned)fCount); |
+ return fGlyphs[index].fPath; |
+ } |
+ |
+private: |
+ struct Glyph { |
+ SkUnichar fUni; |
+ float fAdvance; |
+ SkPath fPath; |
+ }; |
+ int fCount; |
+ Glyph* fGlyphs; |
+ |
+ friend class SkGFontBuilder; |
+ SkGFont(int count, Glyph* array); |
+}; |
+ |
+class SkGFontBuilder { |
+public: |
+ |
+}; |
+#endif |