1 /* 2 * Copyright 2010 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 #ifndef GrGlyph_DEFINED 9 #define GrGlyph_DEFINED 10 11 #include "GrDrawOpAtlas.h" 12 #include "GrRect.h" 13 #include "GrTypes.h" 14 15 #include "SkChecksum.h" 16 #include "SkFixed.h" 17 #include "SkPath.h" 18 19 struct GrGlyph { 20 enum MaskStyle { 21 kCoverage_MaskStyle, 22 kDistance_MaskStyle 23 }; 24 25 static GrMaskFormat FormatFromSkGlyph(const SkGlyph& glyph) { 26 SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat); 27 switch (format) { 28 case SkMask::kBW_Format: 29 case SkMask::kSDF_Format: 30 // fall through to kA8 -- we store BW and SDF glyphs in our 8-bit cache 31 case SkMask::kA8_Format: 32 return kA8_GrMaskFormat; 33 case SkMask::k3D_Format: 34 return kA8_GrMaskFormat; // ignore the mul and add planes, just use the mask 35 case SkMask::kLCD16_Format: 36 return kA565_GrMaskFormat; 37 case SkMask::kARGB32_Format: 38 return kARGB_GrMaskFormat; 39 default: 40 SkDEBUGFAIL("unsupported SkMask::Format"); 41 return kA8_GrMaskFormat; 42 } 43 } 44 45 static GrIRect16 BoundsFromSkGlyph(const SkGlyph& glyph) { 46 return GrIRect16::MakeXYWH(glyph.fLeft, 47 glyph.fTop, 48 glyph.fWidth, 49 glyph.fHeight); 50 } 51 52 static MaskStyle MaskStyleFromSkGlyph(const SkGlyph& skGlyph) { 53 return (SkMask::Format)skGlyph.fMaskFormat == SkMask::kSDF_Format 54 ? GrGlyph::MaskStyle::kDistance_MaskStyle 55 : GrGlyph::MaskStyle::kCoverage_MaskStyle; 56 } 57 58 GrGlyph(const SkGlyph& skGlyph) 59 : fPackedID{skGlyph.getPackedID()} 60 , fMaskFormat{FormatFromSkGlyph(skGlyph)} 61 , fMaskStyle{MaskStyleFromSkGlyph(skGlyph)} 62 , fBounds{BoundsFromSkGlyph(skGlyph)} {} 63 64 65 SkRect destRect(SkPoint origin) { 66 return SkRect::MakeXYWH( 67 SkIntToScalar(fBounds.fLeft) + origin.x(), 68 SkIntToScalar(fBounds.fTop) + origin.y(), 69 SkIntToScalar(fBounds.width()), 70 SkIntToScalar(fBounds.height())); 71 } 72 73 SkRect destRect(SkPoint origin, SkScalar textScale) { 74 if (fMaskStyle == kCoverage_MaskStyle) { 75 return SkRect::MakeXYWH( 76 SkIntToScalar(fBounds.fLeft) * textScale + origin.x(), 77 SkIntToScalar(fBounds.fTop) * textScale + origin.y(), 78 SkIntToScalar(fBounds.width()) * textScale, 79 SkIntToScalar(fBounds.height()) * textScale); 80 } else { 81 return SkRect::MakeXYWH( 82 (SkIntToScalar(fBounds.fLeft) + SK_DistanceFieldInset) * textScale + origin.x(), 83 (SkIntToScalar(fBounds.fTop) + SK_DistanceFieldInset) * textScale + origin.y(), 84 (SkIntToScalar(fBounds.width()) - 2 * SK_DistanceFieldInset) * textScale, 85 (SkIntToScalar(fBounds.height()) - 2 * SK_DistanceFieldInset) * textScale); 86 } 87 } 88 89 int width() const { return fBounds.width(); } 90 int height() const { return fBounds.height(); } 91 uint32_t pageIndex() const { return GrDrawOpAtlas::GetPageIndexFromID(fID); } 92 MaskStyle maskStyle() const { return fMaskStyle; } 93 94 // GetKey and Hash for the the hash table. 95 static const SkPackedGlyphID& GetKey(const GrGlyph& glyph) { 96 return glyph.fPackedID; 97 } 98 99 static uint32_t Hash(SkPackedGlyphID key) { 100 return SkChecksum::Mix(key.hash()); 101 } 102 103 const SkPackedGlyphID fPackedID; 104 const GrMaskFormat fMaskFormat; 105 const MaskStyle fMaskStyle; 106 const GrIRect16 fBounds; 107 SkIPoint16 fAtlasLocation{0, 0}; 108 GrDrawOpAtlas::AtlasID fID{GrDrawOpAtlas::kInvalidAtlasID}; 109 }; 110 111 #endif 112