1/* 2 * Copyright 2014 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "SkAdvancedTypefaceMetrics.h" 9#include "SkBitmap.h" 10#include "SkCanvas.h" 11#include "SkDescriptor.h" 12#include "SkFontDescriptor.h" 13#include "SkGlyph.h" 14#include "SkMakeUnique.h" 15#include "SkMask.h" 16#include "SkOTUtils.h" 17#include "SkPaintPriv.h" 18#include "SkScalerContext.h" 19#include "SkTestScalerContext.h" 20#include "SkTypefaceCache.h" 21#include "SkUtils.h" 22 23SkTestFont::SkTestFont(const SkTestFontData& fontData) 24 : INHERITED() 25 , fCharCodes(fontData.fCharCodes) 26 , fCharCodesCount(fontData.fCharCodes ? fontData.fCharCodesCount : 0) 27 , fWidths(fontData.fWidths) 28 , fMetrics(fontData.fMetrics) 29 , fName(fontData.fName) 30 , fPaths(nullptr) 31{ 32 init(fontData.fPoints, fontData.fVerbs); 33} 34 35SkTestFont::~SkTestFont() { 36 for (unsigned index = 0; index < fCharCodesCount; ++index) { 37 delete fPaths[index]; 38 } 39 delete[] fPaths; 40} 41 42int SkTestFont::codeToIndex(SkUnichar charCode) const { 43 for (unsigned index = 0; index < fCharCodesCount; ++index) { 44 if (fCharCodes[index] == (unsigned) charCode) { 45 return (int) index; 46 } 47 } 48 return 0; 49} 50 51void SkTestFont::init(const SkScalar* pts, const unsigned char* verbs) { 52 fPaths = new SkPath* [fCharCodesCount]; 53 for (unsigned index = 0; index < fCharCodesCount; ++index) { 54 SkPath* path = new SkPath; 55 SkPath::Verb verb; 56 while ((verb = (SkPath::Verb) *verbs++) != SkPath::kDone_Verb) { 57 switch (verb) { 58 case SkPath::kMove_Verb: 59 path->moveTo(pts[0], pts[1]); 60 pts += 2; 61 break; 62 case SkPath::kLine_Verb: 63 path->lineTo(pts[0], pts[1]); 64 pts += 2; 65 break; 66 case SkPath::kQuad_Verb: 67 path->quadTo(pts[0], pts[1], pts[2], pts[3]); 68 pts += 4; 69 break; 70 case SkPath::kCubic_Verb: 71 path->cubicTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]); 72 pts += 6; 73 break; 74 case SkPath::kClose_Verb: 75 path->close(); 76 break; 77 default: 78 SkDEBUGFAIL("bad verb"); 79 return; 80 } 81 } 82 // This should make SkPath::getBounds() queries threadsafe. 83 path->updateBoundsCache(); 84 fPaths[index] = path; 85 } 86} 87 88SkTestTypeface::SkTestTypeface(sk_sp<SkTestFont> testFont, const SkFontStyle& style) 89 : SkTypeface(style, false) 90 , fTestFont(std::move(testFont)) { 91} 92 93void SkTestTypeface::getAdvance(SkGlyph* glyph) { 94 // TODO(benjaminwagner): Update users to use floats. 95 glyph->fAdvanceX = SkFixedToFloat(fTestFont->fWidths[glyph->getGlyphID()]); 96 glyph->fAdvanceY = 0; 97} 98 99void SkTestTypeface::getFontMetrics(SkPaint::FontMetrics* metrics) { 100 *metrics = fTestFont->fMetrics; 101} 102 103void SkTestTypeface::getMetrics(SkGlyph* glyph) { 104 SkGlyphID glyphID = glyph->getGlyphID(); 105 glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0; 106 107 // TODO(benjaminwagner): Update users to use floats. 108 glyph->fAdvanceX = SkFixedToFloat(fTestFont->fWidths[glyphID]); 109 glyph->fAdvanceY = 0; 110} 111 112void SkTestTypeface::getPath(SkGlyphID glyphID, SkPath* path) { 113 glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0; 114 *path = *fTestFont->fPaths[glyphID]; 115} 116 117void SkTestTypeface::onFilterRec(SkScalerContextRec* rec) const { 118 rec->setHinting(SkPaint::kNo_Hinting); 119} 120 121std::unique_ptr<SkAdvancedTypefaceMetrics> SkTestTypeface::onGetAdvancedMetrics() const { // pdf only 122 std::unique_ptr<SkAdvancedTypefaceMetrics> info(new SkAdvancedTypefaceMetrics); 123 info->fFontName.set(fTestFont->fName); 124 int glyphCount = this->onCountGlyphs(); 125 126 SkTDArray<SkUnichar>& toUnicode = info->fGlyphToUnicode; 127 toUnicode.setCount(glyphCount); 128 SkASSERT(glyphCount == SkToInt(fTestFont->fCharCodesCount)); 129 for (int gid = 0; gid < glyphCount; ++gid) { 130 toUnicode[gid] = SkToS32(fTestFont->fCharCodes[gid]); 131 } 132 return info; 133} 134 135void SkTestTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const { 136 desc->setFamilyName(fTestFont->fName); 137 desc->setStyle(this->fontStyle()); 138 *isLocal = false; 139} 140 141int SkTestTypeface::onCharsToGlyphs(const void* chars, Encoding encoding, 142 uint16_t glyphs[], int glyphCount) const { 143 auto utf8 = (const char*)chars; 144 auto utf16 = (const uint16_t*)chars; 145 auto utf32 = (const SkUnichar*)chars; 146 147 for (int i = 0; i < glyphCount; i++) { 148 SkUnichar ch; 149 switch (encoding) { 150 case kUTF8_Encoding: ch = SkUTF8_NextUnichar(&utf8 ); break; 151 case kUTF16_Encoding: ch = SkUTF16_NextUnichar(&utf16); break; 152 case kUTF32_Encoding: ch = *utf32++; break; 153 } 154 if (glyphs) { 155 glyphs[i] = fTestFont->codeToIndex(ch); 156 } 157 } 158 return glyphCount; 159} 160 161void SkTestTypeface::onGetFamilyName(SkString* familyName) const { 162 *familyName = fTestFont->fName; 163} 164 165SkTypeface::LocalizedStrings* SkTestTypeface::onCreateFamilyNameIterator() const { 166 SkString familyName(fTestFont->fName); 167 SkString language("und"); //undetermined 168 return new SkOTUtils::LocalizedStrings_SingleName(familyName, language); 169} 170 171class SkTestScalerContext : public SkScalerContext { 172public: 173 SkTestScalerContext(sk_sp<SkTestTypeface> face, const SkScalerContextEffects& effects, 174 const SkDescriptor* desc) 175 : SkScalerContext(std::move(face), effects, desc) 176 { 177 fRec.getSingleMatrix(&fMatrix); 178 this->forceGenerateImageFromPath(); 179 } 180 181protected: 182 SkTestTypeface* getTestTypeface() const { 183 return static_cast<SkTestTypeface*>(this->getTypeface()); 184 } 185 186 unsigned generateGlyphCount() override { 187 return this->getTestTypeface()->onCountGlyphs(); 188 } 189 190 uint16_t generateCharToGlyph(SkUnichar uni) override { 191 uint16_t glyph; 192 (void) this->getTestTypeface()->onCharsToGlyphs((const void *) &uni, 193 SkTypeface::kUTF32_Encoding, &glyph, 1); 194 return glyph; 195 } 196 197 void generateAdvance(SkGlyph* glyph) override { 198 this->getTestTypeface()->getAdvance(glyph); 199 200 const SkVector advance = fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX), 201 SkFloatToScalar(glyph->fAdvanceY)); 202 glyph->fAdvanceX = SkScalarToFloat(advance.fX); 203 glyph->fAdvanceY = SkScalarToFloat(advance.fY); 204 } 205 206 void generateMetrics(SkGlyph* glyph) override { 207 this->getTestTypeface()->getMetrics(glyph); 208 209 const SkVector advance = fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX), 210 SkFloatToScalar(glyph->fAdvanceY)); 211 glyph->fAdvanceX = SkScalarToFloat(advance.fX); 212 glyph->fAdvanceY = SkScalarToFloat(advance.fY); 213 214 SkPath path; 215 this->getTestTypeface()->getPath(glyph->getGlyphID(), &path); 216 path.transform(fMatrix); 217 218 SkRect storage; 219 const SkPaint paint; 220 const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(), 221 &storage, 222 SkPaint::kFill_Style); 223 SkIRect ibounds; 224 newBounds.roundOut(&ibounds); 225 glyph->fLeft = ibounds.fLeft; 226 glyph->fTop = ibounds.fTop; 227 glyph->fWidth = ibounds.width(); 228 glyph->fHeight = ibounds.height(); 229 } 230 231 void generateImage(const SkGlyph& glyph) override { 232 SkPath path; 233 this->getTestTypeface()->getPath(glyph.getGlyphID(), &path); 234 235 SkBitmap bm; 236 bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight), 237 glyph.fImage, glyph.rowBytes()); 238 bm.eraseColor(0); 239 240 SkCanvas canvas(bm); 241 canvas.translate(-SkIntToScalar(glyph.fLeft), 242 -SkIntToScalar(glyph.fTop)); 243 canvas.concat(fMatrix); 244 SkPaint paint; 245 paint.setAntiAlias(true); 246 canvas.drawPath(path, paint); 247 } 248 249 void generatePath(SkGlyphID glyph, SkPath* path) override { 250 this->getTestTypeface()->getPath(glyph, path); 251 path->transform(fMatrix); 252 } 253 254 void generateFontMetrics(SkPaint::FontMetrics* metrics) override { 255 this->getTestTypeface()->getFontMetrics(metrics); 256 SkPaintPriv::ScaleFontMetrics(metrics, fMatrix.getScaleY()); 257 } 258 259private: 260 SkMatrix fMatrix; 261}; 262 263SkScalerContext* SkTestTypeface::onCreateScalerContext( 264 const SkScalerContextEffects& effects, const SkDescriptor* desc) const 265{ 266 return new SkTestScalerContext(sk_ref_sp(const_cast<SkTestTypeface*>(this)), effects, desc); 267} 268