Home | History | Annotate | Download | only in core
      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     SkScalar fHalfSampleX;
     28     /** Half the sampling frequency of the rasterized glyph in y. */
     29     SkScalar 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&, Sk48Dot16 x, Sk48Dot16 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 glyph position, which may be rounded or not by the caller
     97     //   e.g. subpixel doesn't round.
     98     void operator()(const SkPoint& loc, const SkGlyph& glyph, SkPoint* dst) {
     99         if (SkPaint::kLeft_Align == fAlign) {
    100             dst->set(loc.fX, loc.fY);
    101         } else if (SkPaint::kCenter_Align == fAlign) {
    102             dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX >> 1),
    103                      loc.fY - SkFixedToScalar(glyph.fAdvanceY >> 1));
    104         } else {
    105             SkASSERT(SkPaint::kRight_Align == fAlign);
    106             dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX),
    107                      loc.fY - SkFixedToScalar(glyph.fAdvanceY));
    108         }
    109     }
    110 private:
    111     const SkPaint::Align fAlign;
    112 };
    113 
    114 #endif
    115