DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (d8847129d134)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkDrawProcs_DEFINED
#define SkDrawProcs_DEFINED

#include "SkBlitter.h"
#include "SkDraw.h"
#include "SkGlyph.h"

class SkAAClip;
class SkBlitter;

struct SkDraw1Glyph {
    const SkDraw* fDraw;
    const SkRegion* fClip;
    const SkAAClip* fAAClip;
    SkBlitter* fBlitter;
    SkGlyphCache* fCache;
    const SkPaint* fPaint;
    SkIRect fClipBounds;
    /** Half the sampling frequency of the rasterized glyph in x. */
    SkFixed fHalfSampleX;
    /** Half the sampling frequency of the rasterized glyph in y. */
    SkFixed fHalfSampleY;

    /** Draws one glyph.
     *
     *  The x and y are pre-biased, so implementations may just truncate them.
     *  i.e. half the sampling frequency has been added.
     *  e.g. 1/2 or 1/(2^(SkGlyph::kSubBits+1)) has already been added.
     *  This added bias can be found in fHalfSampleX,Y.
     */
    typedef void (*Proc)(const SkDraw1Glyph&, SkFixed x, SkFixed y, const SkGlyph&);

    Proc init(const SkDraw* draw, SkBlitter* blitter, SkGlyphCache* cache,
              const SkPaint&);

    // call this instead of fBlitter->blitMask() since this wrapper will handle
    // the case when the mask is ARGB32_Format
    //
    void blitMask(const SkMask& mask, const SkIRect& clip) const {
        if (SkMask::kARGB32_Format == mask.fFormat) {
            this->blitMaskAsSprite(mask);
        } else {
            fBlitter->blitMask(mask, clip);
        }
    }

    // mask must be kARGB32_Format
    void blitMaskAsSprite(const SkMask& mask) const;
};

struct SkDrawProcs {
    SkDraw1Glyph::Proc  fD1GProc;
};

bool SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth, const SkMatrix&,
                                   SkScalar* coverage);

/**
 *  If the current paint is set to stroke and the stroke-width when applied to
 *  the matrix is <= 1.0, then this returns true, and sets coverage (simulating
 *  a stroke by drawing a hairline with partial coverage). If any of these
 *  conditions are false, then this returns false and coverage is ignored.
 */
inline bool SkDrawTreatAsHairline(const SkPaint& paint, const SkMatrix& matrix,
                                  SkScalar* coverage) {
    if (SkPaint::kStroke_Style != paint.getStyle()) {
        return false;
    }

    SkScalar strokeWidth = paint.getStrokeWidth();
    if (0 == strokeWidth) {
        *coverage = SK_Scalar1;
        return true;
    }

    if (!paint.isAntiAlias()) {
        return false;
    }

    return SkDrawTreatAAStrokeAsHairline(strokeWidth, matrix, coverage);
}

class SkTextAlignProc {
public:
    SkTextAlignProc(SkPaint::Align align)
        : fAlign(align) {
    }

    // Returns the position of the glyph in fixed point, which may be rounded or not
    //         by the caller e.g. subpixel doesn't round.
    // @param point interpreted as SkFixed [x, y].
    void operator()(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
        if (SkPaint::kLeft_Align == fAlign) {
            dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY));
        } else if (SkPaint::kCenter_Align == fAlign) {
            dst->set(SkScalarToFixed(loc.fX) - (glyph.fAdvanceX >> 1),
                     SkScalarToFixed(loc.fY) - (glyph.fAdvanceY >> 1));
        } else {
            SkASSERT(SkPaint::kRight_Align == fAlign);
            dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX,
                     SkScalarToFixed(loc.fY) - glyph.fAdvanceY);
        }
    }
private:
    const SkPaint::Align fAlign;
};

class SkTextAlignProcScalar {
public:
    SkTextAlignProcScalar(SkPaint::Align align)
        : fAlign(align) {
    }

    // Returns the glyph position, which may be rounded or not by the caller
    //   e.g. subpixel doesn't round.
    void operator()(const SkPoint& loc, const SkGlyph& glyph, SkPoint* dst) {
        if (SkPaint::kLeft_Align == fAlign) {
            dst->set(loc.fX, loc.fY);
        } else if (SkPaint::kCenter_Align == fAlign) {
            dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX >> 1),
                     loc.fY - SkFixedToScalar(glyph.fAdvanceY >> 1));
        } else {
            SkASSERT(SkPaint::kRight_Align == fAlign);
            dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX),
                     loc.fY - SkFixedToScalar(glyph.fAdvanceY));
        }
    }
private:
    const SkPaint::Align fAlign;
};

#endif