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 "SkFontDescriptor.h" 12 #include "SkFontMetrics.h" 13 #include "SkFontPriv.h" 14 #include "SkGlyph.h" 15 #include "SkImageInfo.h" 16 #include "SkMatrix.h" 17 #include "SkOTUtils.h" 18 #include "SkPaintPriv.h" 19 #include "SkPath.h" 20 #include "SkPoint.h" 21 #include "SkRect.h" 22 #include "SkScalerContext.h" 23 #include "SkString.h" 24 #include "SkTDArray.h" 25 #include "SkTestTypeface.h" 26 #include "SkTo.h" 27 #include "SkUtils.h" 28 29 #include <utility> 30 31 class SkDescriptor; 32 33 SkTestFont::SkTestFont(const SkTestFontData& fontData) 34 : INHERITED() 35 , fCharCodes(fontData.fCharCodes) 36 , fCharCodesCount(fontData.fCharCodes ? fontData.fCharCodesCount : 0) 37 , fWidths(fontData.fWidths) 38 , fMetrics(fontData.fMetrics) 39 , fName(fontData.fName) 40 , fPaths(nullptr) 41 { 42 init(fontData.fPoints, fontData.fVerbs); 43 } 44 45 SkTestFont::~SkTestFont() { 46 for (unsigned index = 0; index < fCharCodesCount; ++index) { 47 delete fPaths[index]; 48 } 49 delete[] fPaths; 50 } 51 52 SkGlyphID SkTestFont::glyphForUnichar(SkUnichar charCode) const { 53 for (size_t index = 0; index < fCharCodesCount; ++index) { 54 if (fCharCodes[index] == charCode) { 55 return SkTo<SkGlyphID>(index); 56 } 57 } 58 return 0; 59 } 60 61 void SkTestFont::init(const SkScalar* pts, const unsigned char* verbs) { 62 fPaths = new SkPath* [fCharCodesCount]; 63 for (unsigned index = 0; index < fCharCodesCount; ++index) { 64 SkPath* path = new SkPath; 65 SkPath::Verb verb; 66 while ((verb = (SkPath::Verb) *verbs++) != SkPath::kDone_Verb) { 67 switch (verb) { 68 case SkPath::kMove_Verb: 69 path->moveTo(pts[0], pts[1]); 70 pts += 2; 71 break; 72 case SkPath::kLine_Verb: 73 path->lineTo(pts[0], pts[1]); 74 pts += 2; 75 break; 76 case SkPath::kQuad_Verb: 77 path->quadTo(pts[0], pts[1], pts[2], pts[3]); 78 pts += 4; 79 break; 80 case SkPath::kCubic_Verb: 81 path->cubicTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]); 82 pts += 6; 83 break; 84 case SkPath::kClose_Verb: 85 path->close(); 86 break; 87 default: 88 SkDEBUGFAIL("bad verb"); 89 return; 90 } 91 } 92 // This should make SkPath::getBounds() queries threadsafe. 93 path->updateBoundsCache(); 94 fPaths[index] = path; 95 } 96 } 97 98 SkTestTypeface::SkTestTypeface(sk_sp<SkTestFont> testFont, const SkFontStyle& style) 99 : SkTypeface(style, false) 100 , fTestFont(std::move(testFont)) { 101 } 102 103 void SkTestTypeface::getAdvance(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 112 void SkTestTypeface::getFontMetrics(SkFontMetrics* metrics) { 113 *metrics = fTestFont->fMetrics; 114 } 115 116 void SkTestTypeface::getPath(SkGlyphID glyphID, SkPath* path) { 117 glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0; 118 *path = *fTestFont->fPaths[glyphID]; 119 } 120 121 void SkTestTypeface::onFilterRec(SkScalerContextRec* rec) const { 122 rec->setHinting(kNo_SkFontHinting); 123 } 124 125 void SkTestTypeface::getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const { 126 unsigned glyphCount = fTestFont->fCharCodesCount; 127 for (unsigned gid = 0; gid < glyphCount; ++gid) { 128 glyphToUnicode[gid] = SkTo<SkUnichar>(fTestFont->fCharCodes[gid]); 129 } 130 } 131 132 std::unique_ptr<SkAdvancedTypefaceMetrics> SkTestTypeface::onGetAdvancedMetrics() const { // pdf only 133 std::unique_ptr<SkAdvancedTypefaceMetrics> info(new SkAdvancedTypefaceMetrics); 134 info->fFontName.set(fTestFont->fName); 135 return info; 136 } 137 138 void SkTestTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const { 139 desc->setFamilyName(fTestFont->fName); 140 desc->setStyle(this->fontStyle()); 141 *isLocal = false; 142 } 143 144 int SkTestTypeface::onCharsToGlyphs(const void* chars, Encoding encoding, 145 SkGlyphID glyphs[], int glyphCount) const { 146 auto utf8 = (const char*)chars; 147 auto utf16 = (const uint16_t*)chars; 148 auto utf32 = (const SkUnichar*)chars; 149 150 for (int i = 0; i < glyphCount; ++i) { 151 SkUnichar ch; 152 switch (encoding) { 153 case kUTF8_Encoding: ch = SkUTF8_NextUnichar(&utf8 ); break; 154 case kUTF16_Encoding: ch = SkUTF16_NextUnichar(&utf16); break; 155 case kUTF32_Encoding: ch = *utf32++; break; 156 } 157 if (glyphs) { 158 glyphs[i] = fTestFont->glyphForUnichar(ch); 159 } 160 } 161 return glyphCount; 162 } 163 164 void SkTestTypeface::onGetFamilyName(SkString* familyName) const { 165 *familyName = fTestFont->fName; 166 } 167 168 SkTypeface::LocalizedStrings* SkTestTypeface::onCreateFamilyNameIterator() const { 169 SkString familyName(fTestFont->fName); 170 SkString language("und"); //undetermined 171 return new SkOTUtils::LocalizedStrings_SingleName(familyName, language); 172 } 173 174 class SkTestScalerContext : public SkScalerContext { 175 public: 176 SkTestScalerContext(sk_sp<SkTestTypeface> face, const SkScalerContextEffects& effects, 177 const SkDescriptor* desc) 178 : SkScalerContext(std::move(face), effects, desc) 179 { 180 fRec.getSingleMatrix(&fMatrix); 181 this->forceGenerateImageFromPath(); 182 } 183 184 protected: 185 SkTestTypeface* getTestTypeface() const { 186 return static_cast<SkTestTypeface*>(this->getTypeface()); 187 } 188 189 unsigned generateGlyphCount() override { 190 return this->getTestTypeface()->onCountGlyphs(); 191 } 192 193 uint16_t generateCharToGlyph(SkUnichar uni) override { 194 uint16_t glyph; 195 (void) this->getTestTypeface()->onCharsToGlyphs((const void *) &uni, 196 SkTypeface::kUTF32_Encoding, &glyph, 1); 197 return glyph; 198 } 199 200 bool generateAdvance(SkGlyph* glyph) override { 201 this->getTestTypeface()->getAdvance(glyph); 202 203 const SkVector advance = fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX), 204 SkFloatToScalar(glyph->fAdvanceY)); 205 glyph->fAdvanceX = SkScalarToFloat(advance.fX); 206 glyph->fAdvanceY = SkScalarToFloat(advance.fY); 207 return true; 208 } 209 210 void generateMetrics(SkGlyph* glyph) override { 211 glyph->zeroMetrics(); 212 this->generateAdvance(glyph); 213 // Always generates from paths, so SkScalerContext::getMetrics will figure the bounds. 214 } 215 216 void generateImage(const SkGlyph&) override { 217 SK_ABORT("Should have generated from path."); 218 } 219 220 bool generatePath(SkGlyphID glyph, SkPath* path) override { 221 this->getTestTypeface()->getPath(glyph, path); 222 path->transform(fMatrix); 223 return true; 224 } 225 226 void generateFontMetrics(SkFontMetrics* metrics) override { 227 this->getTestTypeface()->getFontMetrics(metrics); 228 SkFontPriv::ScaleFontMetrics(metrics, fMatrix.getScaleY()); 229 } 230 231 private: 232 SkMatrix fMatrix; 233 }; 234 235 SkScalerContext* SkTestTypeface::onCreateScalerContext( 236 const SkScalerContextEffects& effects, const SkDescriptor* desc) const 237 { 238 return new SkTestScalerContext(sk_ref_sp(const_cast<SkTestTypeface*>(this)), effects, desc); 239 } 240