aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/batches/GrRectBatchFactory.cpp
blob: f01010b21b54e35b7460c92fa48c8cb1f61d7e86 (plain)
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
/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrRectBatchFactory.h"

#include "GrAAStrokeRectBatch.h"
#include "GrStrokeRectBatch.h"

#include "SkStrokeRec.h"

static GrDrawBatch* create_stroke_aa_batch(GrColor color,
                                           const SkMatrix& viewMatrix,
                                           const SkRect& devOutside,
                                           const SkRect& devOutsideAssist,
                                           const SkRect& devInside,
                                           bool miterStroke) {
    GrAAStrokeRectBatch::Geometry geometry;
    geometry.fColor = color;
    geometry.fDevOutside = devOutside;
    geometry.fDevOutsideAssist = devOutsideAssist;
    geometry.fDevInside = devInside;
    geometry.fMiterStroke = miterStroke;

    return GrAAStrokeRectBatch::Create(geometry, viewMatrix);
}

namespace GrRectBatchFactory {

GrDrawBatch* CreateNonAAStroke(GrColor color,
                            const SkMatrix& viewMatrix,
                            const SkRect& rect,
                            SkScalar strokeWidth,
                            bool snapToPixelCenters) {
    GrStrokeRectBatch::Geometry geometry;
    geometry.fColor = color;
    geometry.fViewMatrix = viewMatrix;
    geometry.fRect = rect;
    geometry.fStrokeWidth = strokeWidth;
    return GrStrokeRectBatch::Create(geometry, snapToPixelCenters);
}

GrDrawBatch* CreateAAStroke(GrColor color,
                            const SkMatrix& viewMatrix,
                            const SkRect& rect,
                            const SkRect& devRect,
                            const SkStrokeRec& stroke) {
    SkVector devStrokeSize;
    SkScalar width = stroke.getWidth();
    if (width > 0) {
        devStrokeSize.set(width, width);
        viewMatrix.mapVectors(&devStrokeSize, 1);
        devStrokeSize.setAbs(devStrokeSize);
    } else {
        devStrokeSize.set(SK_Scalar1, SK_Scalar1);
    }

    const SkScalar dx = devStrokeSize.fX;
    const SkScalar dy = devStrokeSize.fY;
    const SkScalar rx = SkScalarMul(dx, SK_ScalarHalf);
    const SkScalar ry = SkScalarMul(dy, SK_ScalarHalf);

    SkScalar spare;
    {
        SkScalar w = devRect.width() - dx;
        SkScalar h = devRect.height() - dy;
        spare = SkTMin(w, h);
    }

    SkRect devOutside(devRect);
    devOutside.outset(rx, ry);

    bool miterStroke = true;
    // For hairlines, make bevel and round joins appear the same as mitered ones.
    // small miter limit means right angles show bevel...
    if ((width > 0) && (stroke.getJoin() != SkPaint::kMiter_Join ||
                        stroke.getMiter() < SK_ScalarSqrt2)) {
        miterStroke = false;
    }

    if (spare <= 0 && miterStroke) {
        return CreateAAFill(color, viewMatrix, devOutside, devOutside);
    }

    SkRect devInside(devRect);
    devInside.inset(rx, ry);

    SkRect devOutsideAssist(devRect);

    // For bevel-stroke, use 2 SkRect instances(devOutside and devOutsideAssist)
    // to draw the outer of the rect. Because there are 8 vertices on the outer
    // edge, while vertex number of inner edge is 4, the same as miter-stroke.
    if (!miterStroke) {
        devOutside.inset(0, ry);
        devOutsideAssist.outset(0, ry);
    }

    return create_stroke_aa_batch(color, viewMatrix, devOutside, devOutsideAssist, devInside,
                                  miterStroke);
}

GrDrawBatch* CreateAAFillNestedRects(GrColor color,
                                     const SkMatrix& viewMatrix,
                                     const SkRect rects[2]) {
    SkASSERT(viewMatrix.rectStaysRect());
    SkASSERT(!rects[0].isEmpty() && !rects[1].isEmpty());

    SkRect devOutside, devInside;
    viewMatrix.mapRect(&devOutside, rects[0]);
    viewMatrix.mapRect(&devInside, rects[1]);

    if (devInside.isEmpty()) {
        return CreateAAFill(color, viewMatrix, devOutside, devOutside);
    }

    return create_stroke_aa_batch(color, viewMatrix, devOutside, devOutside, devInside, true);
}

};