SkRandomScalerContext.cpp revision 209e4b1b70a5e9c2f504de15f038999ed9ee4ae5
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 17class SkDescriptor; 18 19class SkRandomScalerContext : public SkScalerContext { 20public: 21 SkRandomScalerContext(sk_sp<SkRandomTypeface>, const SkScalerContextEffects&, 22 const SkDescriptor*, bool fFakeIt); 23 24protected: 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 33private: 34 SkRandomTypeface* getRandomTypeface() const { 35 return static_cast<SkRandomTypeface*>(this->getTypeface()); 36 } 37 std::unique_ptr<SkScalerContext> fProxy; 38 bool fFakeIt; 39}; 40 41SkRandomScalerContext::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 50unsigned SkRandomScalerContext::generateGlyphCount() { 51 return fProxy->getGlyphCount(); 52} 53 54uint16_t SkRandomScalerContext::generateCharToGlyph(SkUnichar uni) { 55 return fProxy->charToGlyphID(uni); 56} 57 58void SkRandomScalerContext::generateAdvance(SkGlyph* glyph) { 59 fProxy->getAdvance(glyph); 60} 61 62void 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 136void 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 180void SkRandomScalerContext::generatePath(SkGlyphID glyph, SkPath* path) { 181 fProxy->generatePath(glyph, path); 182} 183 184void SkRandomScalerContext::generateFontMetrics(SkPaint::FontMetrics* metrics) { 185 fProxy->getFontMetrics(metrics); 186} 187 188/////////////////////////////////////////////////////////////////////////////// 189 190#include "SkTypefaceCache.h" 191 192SkRandomTypeface::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 198SkScalerContext* 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 204void SkRandomTypeface::onFilterRec(SkScalerContextRec* rec) const { 205 fProxy->filterRec(rec); 206 rec->setHinting(SkPaint::kNo_Hinting); 207 rec->fMaskFormat = SkMask::kARGB32_Format; 208} 209 210std::unique_ptr<SkAdvancedTypefaceMetrics> SkRandomTypeface::onGetAdvancedMetrics() const { 211 return fProxy->getAdvancedMetrics(); 212} 213 214SkStreamAsset* SkRandomTypeface::onOpenStream(int* ttcIndex) const { 215 return fProxy->openStream(ttcIndex); 216} 217 218void SkRandomTypeface::onGetFontDescriptor(SkFontDescriptor* desc, 219 bool* isLocal) const { 220 fProxy->getFontDescriptor(desc, isLocal); 221} 222 223int SkRandomTypeface::onCharsToGlyphs(const void* chars, Encoding encoding, 224 uint16_t glyphs[], int glyphCount) const { 225 return fProxy->charsToGlyphs(chars, encoding, glyphs, glyphCount); 226} 227 228int SkRandomTypeface::onCountGlyphs() const { 229 return fProxy->countGlyphs(); 230} 231 232int SkRandomTypeface::onGetUPEM() const { 233 return fProxy->getUnitsPerEm(); 234} 235 236void SkRandomTypeface::onGetFamilyName(SkString* familyName) const { 237 fProxy->getFamilyName(familyName); 238} 239 240SkTypeface::LocalizedStrings* SkRandomTypeface::onCreateFamilyNameIterator() const { 241 return fProxy->createFamilyNameIterator(); 242} 243 244int SkRandomTypeface::onGetVariationDesignPosition( 245 SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount) const 246{ 247 return fProxy->onGetVariationDesignPosition(coordinates, coordinateCount); 248} 249 250int SkRandomTypeface::onGetTableTags(SkFontTableTag tags[]) const { 251 return fProxy->getTableTags(tags); 252} 253 254size_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