1 /* 2 * Copyright 2015 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 "SkGlyph.h" 12 #include "SkMakeUnique.h" 13 #include "SkPath.h" 14 #include "SkRandomScalerContext.h" 15 16 class SkDescriptor; 17 18 class SkRandomScalerContext : public SkScalerContext { 19 public: 20 SkRandomScalerContext(sk_sp<SkRandomTypeface>, const SkScalerContextEffects&, 21 const SkDescriptor*, bool fFakeIt); 22 23 protected: 24 unsigned generateGlyphCount() override; 25 uint16_t generateCharToGlyph(SkUnichar) override; 26 void generateAdvance(SkGlyph*) override; 27 void generateMetrics(SkGlyph*) override; 28 void generateImage(const SkGlyph&) override; 29 void generatePath(SkGlyphID, SkPath*) override; 30 void generateFontMetrics(SkPaint::FontMetrics*) override; 31 32 private: 33 SkRandomTypeface* getRandomTypeface() const { 34 return static_cast<SkRandomTypeface*>(this->getTypeface()); 35 } 36 std::unique_ptr<SkScalerContext> fProxy; 37 bool fFakeIt; 38 }; 39 40 SkRandomScalerContext::SkRandomScalerContext(sk_sp<SkRandomTypeface> face, 41 const SkScalerContextEffects& effects, 42 const SkDescriptor* desc, 43 bool fakeIt) 44 : SkScalerContext(std::move(face), effects, desc) 45 , fFakeIt(fakeIt) { 46 fProxy = this->getRandomTypeface()->proxy()->createScalerContext(effects, desc); 47 } 48 49 unsigned SkRandomScalerContext::generateGlyphCount() { 50 return fProxy->getGlyphCount(); 51 } 52 53 uint16_t SkRandomScalerContext::generateCharToGlyph(SkUnichar uni) { 54 return fProxy->charToGlyphID(uni); 55 } 56 57 void SkRandomScalerContext::generateAdvance(SkGlyph* glyph) { 58 fProxy->getAdvance(glyph); 59 } 60 61 void SkRandomScalerContext::generateMetrics(SkGlyph* glyph) { 62 // Here we will change the mask format of the glyph 63 // NOTE this is being overridden by the base class 64 SkMask::Format format = SkMask::kARGB32_Format; // init to handle defective compilers 65 switch (glyph->getGlyphID() % 4) { 66 case 0: 67 format = SkMask::kLCD16_Format; 68 break; 69 case 1: 70 format = SkMask::kA8_Format; 71 break; 72 case 2: 73 format = SkMask::kARGB32_Format; 74 break; 75 case 3: 76 format = SkMask::kBW_Format; 77 break; 78 } 79 80 fProxy->getMetrics(glyph); 81 82 glyph->fMaskFormat = format; 83 if (fFakeIt) { 84 return; 85 } 86 if (SkMask::kARGB32_Format == format) { 87 SkPath path; 88 fProxy->getPath(glyph->getPackedID(), &path); 89 90 SkRect storage; 91 const SkPaint& paint = this->getRandomTypeface()->paint(); 92 const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(), 93 &storage, 94 SkPaint::kFill_Style); 95 SkIRect ibounds; 96 newBounds.roundOut(&ibounds); 97 glyph->fLeft = ibounds.fLeft; 98 glyph->fTop = ibounds.fTop; 99 glyph->fWidth = ibounds.width(); 100 glyph->fHeight = ibounds.height(); 101 } else { 102 SkPath devPath, fillPath; 103 SkMatrix fillToDevMatrix; 104 105 this->internalGetPath(glyph->getPackedID(), &fillPath, &devPath, &fillToDevMatrix); 106 107 // just use devPath 108 const SkIRect ir = devPath.getBounds().roundOut(); 109 110 if (ir.isEmpty() || !ir.is16Bit()) { 111 glyph->fLeft = 0; 112 glyph->fTop = 0; 113 glyph->fWidth = 0; 114 glyph->fHeight = 0; 115 return; 116 } 117 glyph->fLeft = ir.fLeft; 118 glyph->fTop = ir.fTop; 119 glyph->fWidth = SkToU16(ir.width()); 120 glyph->fHeight = SkToU16(ir.height()); 121 122 if (glyph->fWidth > 0) { 123 switch (glyph->fMaskFormat) { 124 case SkMask::kLCD16_Format: 125 glyph->fWidth += 2; 126 glyph->fLeft -= 1; 127 break; 128 default: 129 break; 130 } 131 } 132 } 133 } 134 135 void SkRandomScalerContext::generateImage(const SkGlyph& glyph) { 136 SkMask::Format format = (SkMask::Format)glyph.fMaskFormat; 137 switch (glyph.getGlyphID() % 4) { 138 case 0: 139 format = SkMask::kLCD16_Format; 140 break; 141 case 1: 142 format = SkMask::kA8_Format; 143 break; 144 case 2: 145 format = SkMask::kARGB32_Format; 146 break; 147 case 3: 148 format = SkMask::kBW_Format; 149 break; 150 } 151 const_cast<SkGlyph&>(glyph).fMaskFormat = format; 152 153 // if the format is ARGB, we just draw the glyph from path ourselves. Otherwise, we force 154 // our proxy context to generate the image from paths. 155 if (!fFakeIt) { 156 if (SkMask::kARGB32_Format == glyph.fMaskFormat) { 157 SkPath path; 158 fProxy->getPath(glyph.getPackedID(), &path); 159 160 SkBitmap bm; 161 bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight), 162 glyph.fImage, glyph.rowBytes()); 163 bm.eraseColor(0); 164 165 SkCanvas canvas(bm); 166 canvas.translate(-SkIntToScalar(glyph.fLeft), 167 -SkIntToScalar(glyph.fTop)); 168 canvas.drawPath(path, this->getRandomTypeface()->paint()); 169 } else { 170 fProxy->forceGenerateImageFromPath(); 171 fProxy->getImage(glyph); 172 fProxy->forceOffGenerateImageFromPath(); 173 } 174 } else { 175 sk_bzero(glyph.fImage, glyph.computeImageSize()); 176 } 177 } 178 179 void SkRandomScalerContext::generatePath(SkGlyphID glyph, SkPath* path) { 180 fProxy->generatePath(glyph, path); 181 } 182 183 void SkRandomScalerContext::generateFontMetrics(SkPaint::FontMetrics* metrics) { 184 fProxy->getFontMetrics(metrics); 185 } 186 187 /////////////////////////////////////////////////////////////////////////////// 188 189 #include "SkTypefaceCache.h" 190 191 SkRandomTypeface::SkRandomTypeface(sk_sp<SkTypeface> proxy, const SkPaint& paint, bool fakeIt) 192 : SkTypeface(proxy->fontStyle(), false) 193 , fProxy(std::move(proxy)) 194 , fPaint(paint) 195 , fFakeIt(fakeIt) {} 196 197 SkScalerContext* SkRandomTypeface::onCreateScalerContext(const SkScalerContextEffects& effects, 198 const SkDescriptor* desc) const { 199 return new SkRandomScalerContext(sk_ref_sp(const_cast<SkRandomTypeface*>(this)), 200 effects, desc, fFakeIt); 201 } 202 203 void SkRandomTypeface::onFilterRec(SkScalerContextRec* rec) const { 204 fProxy->filterRec(rec); 205 rec->setHinting(SkPaint::kNo_Hinting); 206 rec->fMaskFormat = SkMask::kARGB32_Format; 207 } 208 209 std::unique_ptr<SkAdvancedTypefaceMetrics> SkRandomTypeface::onGetAdvancedMetrics() const { 210 return fProxy->getAdvancedMetrics(); 211 } 212 213 SkStreamAsset* SkRandomTypeface::onOpenStream(int* ttcIndex) const { 214 return fProxy->openStream(ttcIndex); 215 } 216 217 void SkRandomTypeface::onGetFontDescriptor(SkFontDescriptor* desc, 218 bool* isLocal) const { 219 fProxy->getFontDescriptor(desc, isLocal); 220 } 221 222 int SkRandomTypeface::onCharsToGlyphs(const void* chars, Encoding encoding, 223 uint16_t glyphs[], int glyphCount) const { 224 return fProxy->charsToGlyphs(chars, encoding, glyphs, glyphCount); 225 } 226 227 int SkRandomTypeface::onCountGlyphs() const { 228 return fProxy->countGlyphs(); 229 } 230 231 int SkRandomTypeface::onGetUPEM() const { 232 return fProxy->getUnitsPerEm(); 233 } 234 235 void SkRandomTypeface::onGetFamilyName(SkString* familyName) const { 236 fProxy->getFamilyName(familyName); 237 } 238 239 SkTypeface::LocalizedStrings* SkRandomTypeface::onCreateFamilyNameIterator() const { 240 return fProxy->createFamilyNameIterator(); 241 } 242 243 int SkRandomTypeface::onGetVariationDesignPosition( 244 SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount) const 245 { 246 return fProxy->onGetVariationDesignPosition(coordinates, coordinateCount); 247 } 248 249 int SkRandomTypeface::onGetTableTags(SkFontTableTag tags[]) const { 250 return fProxy->getTableTags(tags); 251 } 252 253 size_t SkRandomTypeface::onGetTableData(SkFontTableTag tag, size_t offset, 254 size_t length, void* data) const { 255 return fProxy->getTableData(tag, offset, length, data); 256 } 257 258