1 /* 2 * Copyright 2011 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 SkDrawProcs_DEFINED 9 #define SkDrawProcs_DEFINED 10 11 #include "SkBlitter.h" 12 #include "SkDraw.h" 13 #include "SkGlyph.h" 14 15 class SkAAClip; 16 class SkBlitter; 17 18 struct SkDraw1Glyph { 19 const SkDraw* fDraw; 20 const SkRegion* fClip; 21 const SkAAClip* fAAClip; 22 SkBlitter* fBlitter; 23 SkGlyphCache* fCache; 24 const SkPaint* fPaint; 25 SkIRect fClipBounds; 26 /** Half the sampling frequency of the rasterized glyph in x. */ 27 SkFixed fHalfSampleX; 28 /** Half the sampling frequency of the rasterized glyph in y. */ 29 SkFixed fHalfSampleY; 30 31 /** Draws one glyph. 32 * 33 * The x and y are pre-biased, so implementations may just truncate them. 34 * i.e. half the sampling frequency has been added. 35 * e.g. 1/2 or 1/(2^(SkGlyph::kSubBits+1)) has already been added. 36 * This added bias can be found in fHalfSampleX,Y. 37 */ 38 typedef void (*Proc)(const SkDraw1Glyph&, SkFixed x, SkFixed y, const SkGlyph&); 39 40 Proc init(const SkDraw* draw, SkBlitter* blitter, SkGlyphCache* cache, 41 const SkPaint&); 42 43 // call this instead of fBlitter->blitMask() since this wrapper will handle 44 // the case when the mask is ARGB32_Format 45 // 46 void blitMask(const SkMask& mask, const SkIRect& clip) const { 47 if (SkMask::kARGB32_Format == mask.fFormat) { 48 this->blitMaskAsSprite(mask); 49 } else { 50 fBlitter->blitMask(mask, clip); 51 } 52 } 53 54 // mask must be kARGB32_Format 55 void blitMaskAsSprite(const SkMask& mask) const; 56 }; 57 58 struct SkDrawProcs { 59 SkDraw1Glyph::Proc fD1GProc; 60 }; 61 62 bool SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth, const SkMatrix&, 63 SkScalar* coverage); 64 65 /** 66 * If the current paint is set to stroke and the stroke-width when applied to 67 * the matrix is <= 1.0, then this returns true, and sets coverage (simulating 68 * a stroke by drawing a hairline with partial coverage). If any of these 69 * conditions are false, then this returns false and coverage is ignored. 70 */ 71 inline bool SkDrawTreatAsHairline(const SkPaint& paint, const SkMatrix& matrix, 72 SkScalar* coverage) { 73 if (SkPaint::kStroke_Style != paint.getStyle()) { 74 return false; 75 } 76 77 SkScalar strokeWidth = paint.getStrokeWidth(); 78 if (0 == strokeWidth) { 79 *coverage = SK_Scalar1; 80 return true; 81 } 82 83 if (!paint.isAntiAlias()) { 84 return false; 85 } 86 87 return SkDrawTreatAAStrokeAsHairline(strokeWidth, matrix, coverage); 88 } 89 90 class SkTextAlignProc { 91 public: 92 SkTextAlignProc(SkPaint::Align align) 93 : fAlign(align) { 94 } 95 96 // Returns the position of the glyph in fixed point, which may be rounded or not 97 // by the caller e.g. subpixel doesn't round. 98 // @param point interpreted as SkFixed [x, y]. 99 void operator()(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) { 100 if (SkPaint::kLeft_Align == fAlign) { 101 dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY)); 102 } else if (SkPaint::kCenter_Align == fAlign) { 103 dst->set(SkScalarToFixed(loc.fX) - (glyph.fAdvanceX >> 1), 104 SkScalarToFixed(loc.fY) - (glyph.fAdvanceY >> 1)); 105 } else { 106 SkASSERT(SkPaint::kRight_Align == fAlign); 107 dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX, 108 SkScalarToFixed(loc.fY) - glyph.fAdvanceY); 109 } 110 } 111 private: 112 const SkPaint::Align fAlign; 113 }; 114 115 class SkTextAlignProcScalar { 116 public: 117 SkTextAlignProcScalar(SkPaint::Align align) 118 : fAlign(align) { 119 } 120 121 // Returns the glyph position, which may be rounded or not by the caller 122 // e.g. subpixel doesn't round. 123 void operator()(const SkPoint& loc, const SkGlyph& glyph, SkPoint* dst) { 124 if (SkPaint::kLeft_Align == fAlign) { 125 dst->set(loc.fX, loc.fY); 126 } else if (SkPaint::kCenter_Align == fAlign) { 127 dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX >> 1), 128 loc.fY - SkFixedToScalar(glyph.fAdvanceY >> 1)); 129 } else { 130 SkASSERT(SkPaint::kRight_Align == fAlign); 131 dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX), 132 loc.fY - SkFixedToScalar(glyph.fAdvanceY)); 133 } 134 } 135 private: 136 const SkPaint::Align fAlign; 137 }; 138 139 #endif 140