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