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