joshualitt | ecd1a69 | 2015-08-10 10:08:26 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2015 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 | #include "GrRectBatchFactory.h" |
| 9 | |
joshualitt | 14205b1 | 2015-08-10 11:40:56 -0700 | [diff] [blame^] | 10 | #include "GrAAFillRectBatch.h" |
| 11 | #include "GrAAStrokeRectBatch.h" |
joshualitt | ecd1a69 | 2015-08-10 10:08:26 -0700 | [diff] [blame] | 12 | #include "GrRectBatch.h" |
joshualitt | 7fc2a26 | 2015-08-10 10:30:14 -0700 | [diff] [blame] | 13 | #include "GrStrokeRectBatch.h" |
joshualitt | ecd1a69 | 2015-08-10 10:08:26 -0700 | [diff] [blame] | 14 | |
joshualitt | 14205b1 | 2015-08-10 11:40:56 -0700 | [diff] [blame^] | 15 | #include "SkStrokeRec.h" |
| 16 | |
| 17 | static GrBatch* create_stroke_aa_batch(GrColor color, |
| 18 | const SkMatrix& viewMatrix, |
| 19 | const SkRect& devOutside, |
| 20 | const SkRect& devOutsideAssist, |
| 21 | const SkRect& devInside, |
| 22 | bool miterStroke) { |
| 23 | GrAAStrokeRectBatch::Geometry geometry; |
| 24 | geometry.fColor = color; |
| 25 | geometry.fDevOutside = devOutside; |
| 26 | geometry.fDevOutsideAssist = devOutsideAssist; |
| 27 | geometry.fDevInside = devInside; |
| 28 | geometry.fMiterStroke = miterStroke; |
| 29 | |
| 30 | return GrAAStrokeRectBatch::Create(geometry, viewMatrix); |
| 31 | } |
| 32 | |
joshualitt | ecd1a69 | 2015-08-10 10:08:26 -0700 | [diff] [blame] | 33 | namespace GrRectBatchFactory { |
| 34 | |
joshualitt | 7fc2a26 | 2015-08-10 10:30:14 -0700 | [diff] [blame] | 35 | GrBatch* CreateFillBW(GrColor color, |
| 36 | const SkMatrix& viewMatrix, |
| 37 | const SkRect& rect, |
| 38 | const SkRect* localRect, |
| 39 | const SkMatrix* localMatrix) { |
joshualitt | ecd1a69 | 2015-08-10 10:08:26 -0700 | [diff] [blame] | 40 | GrRectBatch::Geometry geometry; |
| 41 | geometry.fColor = color; |
| 42 | geometry.fViewMatrix = viewMatrix; |
| 43 | geometry.fRect = rect; |
| 44 | |
| 45 | if (localRect) { |
| 46 | geometry.fHasLocalRect = true; |
| 47 | geometry.fLocalRect = *localRect; |
| 48 | } else { |
| 49 | geometry.fHasLocalRect = false; |
| 50 | } |
| 51 | |
| 52 | if (localMatrix) { |
| 53 | geometry.fHasLocalMatrix = true; |
| 54 | geometry.fLocalMatrix = *localMatrix; |
| 55 | } else { |
| 56 | geometry.fHasLocalMatrix = false; |
| 57 | } |
| 58 | |
| 59 | return GrRectBatch::Create(geometry); |
| 60 | } |
| 61 | |
joshualitt | 14205b1 | 2015-08-10 11:40:56 -0700 | [diff] [blame^] | 62 | GrBatch* CreateFillAA(GrColor color, |
| 63 | const SkMatrix& viewMatrix, |
| 64 | const SkRect& rect, |
| 65 | const SkRect& devRect) { |
| 66 | GrAAFillRectBatch::Geometry geometry; |
| 67 | geometry.fRect = rect; |
| 68 | geometry.fViewMatrix = viewMatrix; |
| 69 | geometry.fDevRect = devRect; |
| 70 | geometry.fColor = color; |
| 71 | |
| 72 | return GrAAFillRectBatch::Create(geometry); |
| 73 | } |
| 74 | |
joshualitt | 7fc2a26 | 2015-08-10 10:30:14 -0700 | [diff] [blame] | 75 | GrBatch* CreateStrokeBW(GrColor color, |
| 76 | const SkMatrix& viewMatrix, |
| 77 | const SkRect& rect, |
| 78 | SkScalar strokeWidth, |
| 79 | bool snapToPixelCenters) { |
| 80 | GrStrokeRectBatch::Geometry geometry; |
| 81 | geometry.fColor = color; |
| 82 | geometry.fViewMatrix = viewMatrix; |
| 83 | geometry.fRect = rect; |
| 84 | geometry.fStrokeWidth = strokeWidth; |
| 85 | return GrStrokeRectBatch::Create(geometry, snapToPixelCenters); |
| 86 | } |
| 87 | |
joshualitt | 14205b1 | 2015-08-10 11:40:56 -0700 | [diff] [blame^] | 88 | GrBatch* CreateStrokeAA(GrColor color, |
| 89 | const SkMatrix& viewMatrix, |
| 90 | const SkRect& rect, |
| 91 | const SkRect& devRect, |
| 92 | const SkStrokeRec& stroke) { |
| 93 | SkVector devStrokeSize; |
| 94 | SkScalar width = stroke.getWidth(); |
| 95 | if (width > 0) { |
| 96 | devStrokeSize.set(width, width); |
| 97 | viewMatrix.mapVectors(&devStrokeSize, 1); |
| 98 | devStrokeSize.setAbs(devStrokeSize); |
| 99 | } else { |
| 100 | devStrokeSize.set(SK_Scalar1, SK_Scalar1); |
| 101 | } |
| 102 | |
| 103 | const SkScalar dx = devStrokeSize.fX; |
| 104 | const SkScalar dy = devStrokeSize.fY; |
| 105 | const SkScalar rx = SkScalarMul(dx, SK_ScalarHalf); |
| 106 | const SkScalar ry = SkScalarMul(dy, SK_ScalarHalf); |
| 107 | |
| 108 | SkScalar spare; |
| 109 | { |
| 110 | SkScalar w = devRect.width() - dx; |
| 111 | SkScalar h = devRect.height() - dy; |
| 112 | spare = SkTMin(w, h); |
| 113 | } |
| 114 | |
| 115 | SkRect devOutside(devRect); |
| 116 | devOutside.outset(rx, ry); |
| 117 | |
| 118 | bool miterStroke = true; |
| 119 | // For hairlines, make bevel and round joins appear the same as mitered ones. |
| 120 | // small miter limit means right angles show bevel... |
| 121 | if ((width > 0) && (stroke.getJoin() != SkPaint::kMiter_Join || |
| 122 | stroke.getMiter() < SK_ScalarSqrt2)) { |
| 123 | miterStroke = false; |
| 124 | } |
| 125 | |
| 126 | if (spare <= 0 && miterStroke) { |
| 127 | return CreateFillAA(color, viewMatrix, devOutside, devOutside); |
| 128 | } |
| 129 | |
| 130 | SkRect devInside(devRect); |
| 131 | devInside.inset(rx, ry); |
| 132 | |
| 133 | SkRect devOutsideAssist(devRect); |
| 134 | |
| 135 | // For bevel-stroke, use 2 SkRect instances(devOutside and devOutsideAssist) |
| 136 | // to draw the outer of the rect. Because there are 8 vertices on the outer |
| 137 | // edge, while vertex number of inner edge is 4, the same as miter-stroke. |
| 138 | if (!miterStroke) { |
| 139 | devOutside.inset(0, ry); |
| 140 | devOutsideAssist.outset(0, ry); |
| 141 | } |
| 142 | |
| 143 | return create_stroke_aa_batch(color, viewMatrix, devOutside, devOutsideAssist, devInside, |
| 144 | miterStroke); |
| 145 | } |
| 146 | |
| 147 | GrBatch* CreateFillNestedRectsAA(GrColor color, |
| 148 | const SkMatrix& viewMatrix, |
| 149 | const SkRect rects[2]) { |
| 150 | SkASSERT(viewMatrix.rectStaysRect()); |
| 151 | SkASSERT(!rects[0].isEmpty() && !rects[1].isEmpty()); |
| 152 | |
| 153 | SkRect devOutside, devInside; |
| 154 | viewMatrix.mapRect(&devOutside, rects[0]); |
| 155 | viewMatrix.mapRect(&devInside, rects[1]); |
| 156 | |
| 157 | if (devInside.isEmpty()) { |
| 158 | return CreateFillAA(color, viewMatrix, devOutside, devOutside); |
| 159 | } |
| 160 | |
| 161 | return create_stroke_aa_batch(color, viewMatrix, devOutside, devOutside, devInside, true); |
| 162 | } |
| 163 | |
joshualitt | ecd1a69 | 2015-08-10 10:08:26 -0700 | [diff] [blame] | 164 | }; |