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