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     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