| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "GrDashingEffect.h" | 8 #include "GrDashingEffect.h" |
| 9 | 9 |
| 10 #include "../GrAARectRenderer.h" |
| 11 |
| 12 #include "effects/GrVertexEffect.h" |
| 10 #include "gl/GrGLEffect.h" | 13 #include "gl/GrGLEffect.h" |
| 14 #include "gl/GrGLVertexEffect.h" |
| 11 #include "gl/GrGLSL.h" | 15 #include "gl/GrGLSL.h" |
| 12 #include "GrContext.h" | 16 #include "GrContext.h" |
| 13 #include "GrCoordTransform.h" | 17 #include "GrCoordTransform.h" |
| 18 #include "GrDrawTarget.h" |
| 14 #include "GrDrawTargetCaps.h" | 19 #include "GrDrawTargetCaps.h" |
| 15 #include "GrEffect.h" | 20 #include "GrEffect.h" |
| 21 #include "GrGpu.h" |
| 22 #include "GrStrokeInfo.h" |
| 16 #include "GrTBackendEffectFactory.h" | 23 #include "GrTBackendEffectFactory.h" |
| 17 #include "SkGr.h" | 24 #include "SkGr.h" |
| 18 | 25 |
| 19 /////////////////////////////////////////////////////////////////////////////// | 26 /////////////////////////////////////////////////////////////////////////////// |
| 20 | 27 |
| 28 // Returns whether or not the gpu can fast path the dash line effect. |
| 29 static bool can_fast_path_dash(const SkPoint pts[2], const GrStrokeInfo& strokeI
nfo, |
| 30 const GrDrawTarget& target, const SkMatrix& viewM
atrix) { |
| 31 if (target.getDrawState().getRenderTarget()->isMultisampled()) { |
| 32 return false; |
| 33 } |
| 34 |
| 35 // Pts must be either horizontal or vertical in src space |
| 36 if (pts[0].fX != pts[1].fX && pts[0].fY != pts[1].fY) { |
| 37 return false; |
| 38 } |
| 39 |
| 40 // May be able to relax this to include skew. As of now cannot do perspectiv
e |
| 41 // because of the non uniform scaling of bloating a rect |
| 42 if (!viewMatrix.preservesRightAngles()) { |
| 43 return false; |
| 44 } |
| 45 |
| 46 if (!strokeInfo.isDashed() || 2 != strokeInfo.dashCount()) { |
| 47 return false; |
| 48 } |
| 49 |
| 50 const SkPathEffect::DashInfo& info = strokeInfo.getDashInfo(); |
| 51 if (0 == info.fIntervals[0] && 0 == info.fIntervals[1]) { |
| 52 return false; |
| 53 } |
| 54 |
| 55 SkPaint::Cap cap = strokeInfo.getStrokeRec().getCap(); |
| 56 // Current we do don't handle Round or Square cap dashes |
| 57 if (SkPaint::kRound_Cap == cap) { |
| 58 return false; |
| 59 } |
| 60 |
| 61 return true; |
| 62 } |
| 63 |
| 64 namespace { |
| 65 |
| 66 struct DashLineVertex { |
| 67 SkPoint fPos; |
| 68 SkPoint fDashPos; |
| 69 }; |
| 70 |
| 71 extern const GrVertexAttrib gDashLineVertexAttribs[] = { |
| 72 { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBind
ing }, |
| 73 { kVec2f_GrVertexAttribType, sizeof(SkPoint), kEffect_GrVertexAttribBindin
g }, |
| 74 }; |
| 75 |
| 76 }; |
| 21 static void calc_dash_scaling(SkScalar* parallelScale, SkScalar* perpScale, | 77 static void calc_dash_scaling(SkScalar* parallelScale, SkScalar* perpScale, |
| 22 const SkMatrix& viewMatrix, const SkPoint pts[2]) { | 78 const SkMatrix& viewMatrix, const SkPoint pts[2]) { |
| 23 SkVector vecSrc = pts[1] - pts[0]; | 79 SkVector vecSrc = pts[1] - pts[0]; |
| 24 SkScalar magSrc = vecSrc.length(); | 80 SkScalar magSrc = vecSrc.length(); |
| 25 SkScalar invSrc = magSrc ? SkScalarInvert(magSrc) : 0; | 81 SkScalar invSrc = magSrc ? SkScalarInvert(magSrc) : 0; |
| 26 vecSrc.scale(invSrc); | 82 vecSrc.scale(invSrc); |
| 27 | 83 |
| 28 SkVector vecSrcPerp; | 84 SkVector vecSrcPerp; |
| 29 vecSrc.rotateCW(&vecSrcPerp); | 85 vecSrc.rotateCW(&vecSrcPerp); |
| 30 viewMatrix.mapVectors(&vecSrc, 1); | 86 viewMatrix.mapVectors(&vecSrc, 1); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 55 // Assumes phase < sum of all intervals | 111 // Assumes phase < sum of all intervals |
| 56 static SkScalar calc_start_adjustment(const SkPathEffect::DashInfo& info) { | 112 static SkScalar calc_start_adjustment(const SkPathEffect::DashInfo& info) { |
| 57 SkASSERT(info.fPhase < info.fIntervals[0] + info.fIntervals[1]); | 113 SkASSERT(info.fPhase < info.fIntervals[0] + info.fIntervals[1]); |
| 58 if (info.fPhase >= info.fIntervals[0] && info.fPhase != 0) { | 114 if (info.fPhase >= info.fIntervals[0] && info.fPhase != 0) { |
| 59 SkScalar srcIntervalLen = info.fIntervals[0] + info.fIntervals[1]; | 115 SkScalar srcIntervalLen = info.fIntervals[0] + info.fIntervals[1]; |
| 60 return srcIntervalLen - info.fPhase; | 116 return srcIntervalLen - info.fPhase; |
| 61 } | 117 } |
| 62 return 0; | 118 return 0; |
| 63 } | 119 } |
| 64 | 120 |
| 65 static SkScalar calc_end_adjustment(const SkPathEffect::DashInfo& info, const Sk
Point pts[2], SkScalar* endingInt) { | 121 static SkScalar calc_end_adjustment(const SkPathEffect::DashInfo& info, const Sk
Point pts[2], |
| 122 SkScalar phase, SkScalar* endingInt) { |
| 66 if (pts[1].fX <= pts[0].fX) { | 123 if (pts[1].fX <= pts[0].fX) { |
| 67 return 0; | 124 return 0; |
| 68 } | 125 } |
| 69 SkScalar srcIntervalLen = info.fIntervals[0] + info.fIntervals[1]; | 126 SkScalar srcIntervalLen = info.fIntervals[0] + info.fIntervals[1]; |
| 70 SkScalar totalLen = pts[1].fX - pts[0].fX; | 127 SkScalar totalLen = pts[1].fX - pts[0].fX; |
| 71 SkScalar temp = SkScalarDiv(totalLen, srcIntervalLen); | 128 SkScalar temp = SkScalarDiv(totalLen, srcIntervalLen); |
| 72 SkScalar numFullIntervals = SkScalarFloorToScalar(temp); | 129 SkScalar numFullIntervals = SkScalarFloorToScalar(temp); |
| 73 *endingInt = totalLen - numFullIntervals * srcIntervalLen + info.fPhase; | 130 *endingInt = totalLen - numFullIntervals * srcIntervalLen + phase; |
| 74 temp = SkScalarDiv(*endingInt, srcIntervalLen); | 131 temp = SkScalarDiv(*endingInt, srcIntervalLen); |
| 75 *endingInt = *endingInt - SkScalarFloorToScalar(temp) * srcIntervalLen; | 132 *endingInt = *endingInt - SkScalarFloorToScalar(temp) * srcIntervalLen; |
| 76 if (0 == *endingInt) { | 133 if (0 == *endingInt) { |
| 77 *endingInt = srcIntervalLen; | 134 *endingInt = srcIntervalLen; |
| 78 } | 135 } |
| 79 if (*endingInt > info.fIntervals[0]) { | 136 if (*endingInt > info.fIntervals[0]) { |
| 80 if (0 == info.fIntervals[0]) { | 137 if (0 == info.fIntervals[0]) { |
| 81 *endingInt -= 0.01f; // make sure we capture the last zero size pnt
(used if has caps) | 138 *endingInt -= 0.01f; // make sure we capture the last zero size pnt
(used if has caps) |
| 82 } | 139 } |
| 83 return *endingInt - info.fIntervals[0]; | 140 return *endingInt - info.fIntervals[0]; |
| 84 } | 141 } |
| 85 return 0; | 142 return 0; |
| 86 } | 143 } |
| 87 | 144 |
| 88 | 145 static void setup_dashed_rect(const SkRect& rect, DashLineVertex* verts, int idx
, const SkMatrix& matrix, |
| 89 bool GrDashingEffect::DrawDashLine(const SkPoint pts[2], const SkPaint& paint, G
rContext* context) { | 146 SkScalar offset, SkScalar bloat, SkScalar len, SkScalar s
troke) { |
| 90 if (context->getRenderTarget()->isMultisampled()) { | 147 |
| 148 SkScalar startDashX = offset - bloat; |
| 149 SkScalar endDashX = offset + len + bloat; |
| 150 SkScalar startDashY = -stroke - bloat; |
| 151 SkScalar endDashY = stroke + bloat; |
| 152 verts[idx].fDashPos = SkPoint::Make(startDashX , startDashY); |
| 153 verts[idx + 1].fDashPos = SkPoint::Make(startDashX, endDashY); |
| 154 verts[idx + 2].fDashPos = SkPoint::Make(endDashX, endDashY); |
| 155 verts[idx + 3].fDashPos = SkPoint::Make(endDashX, startDashY); |
| 156 |
| 157 verts[idx].fPos = SkPoint::Make(rect.fLeft, rect.fTop); |
| 158 verts[idx + 1].fPos = SkPoint::Make(rect.fLeft, rect.fBottom); |
| 159 verts[idx + 2].fPos = SkPoint::Make(rect.fRight, rect.fBottom); |
| 160 verts[idx + 3].fPos = SkPoint::Make(rect.fRight, rect.fTop); |
| 161 |
| 162 matrix.mapPointsWithStride(&verts[idx].fPos, sizeof(DashLineVertex), 4); |
| 163 } |
| 164 |
| 165 |
| 166 bool GrDashingEffect::DrawDashLine(const SkPoint pts[2], const GrPaint& paint, |
| 167 const GrStrokeInfo& strokeInfo, GrGpu* gpu, |
| 168 GrDrawTarget* target, const SkMatrix& vm) { |
| 169 |
| 170 if (!can_fast_path_dash(pts, strokeInfo, *target, vm)) { |
| 91 return false; | 171 return false; |
| 92 } | 172 } |
| 93 | 173 |
| 94 const SkMatrix& viewMatrix = context->getMatrix(); | 174 const SkPathEffect::DashInfo& info = strokeInfo.getDashInfo(); |
| 95 if (!viewMatrix.preservesRightAngles()) { | 175 |
| 96 return false; | 176 SkPaint::Cap cap = strokeInfo.getStrokeRec().getCap(); |
| 97 } | 177 |
| 98 | 178 SkScalar srcStrokeWidth = strokeInfo.getStrokeRec().getWidth(); |
| 99 const SkPathEffect* pe = paint.getPathEffect(); | |
| 100 SkPathEffect::DashInfo info; | |
| 101 SkPathEffect::DashType dashType = pe->asADash(&info); | |
| 102 // Must be a dash effect with 2 intervals (1 on and 1 off) | |
| 103 if (SkPathEffect::kDash_DashType != dashType || 2 != info.fCount) { | |
| 104 return false; | |
| 105 } | |
| 106 | |
| 107 SkPaint::Cap cap = paint.getStrokeCap(); | |
| 108 // Current we do don't handle Round or Square cap dashes | |
| 109 if (SkPaint::kRound_Cap == cap) { | |
| 110 return false; | |
| 111 } | |
| 112 | |
| 113 SkScalar srcStrokeWidth = paint.getStrokeWidth(); | |
| 114 | |
| 115 // Get all info about the dash effect | |
| 116 SkAutoTArray<SkScalar> intervals(info.fCount); | |
| 117 info.fIntervals = intervals.get(); | |
| 118 pe->asADash(&info); | |
| 119 | 179 |
| 120 // the phase should be normalized to be [0, sum of all intervals) | 180 // the phase should be normalized to be [0, sum of all intervals) |
| 121 SkASSERT(info.fPhase >= 0 && info.fPhase < info.fIntervals[0] + info.fInterv
als[1]); | 181 SkASSERT(info.fPhase >= 0 && info.fPhase < info.fIntervals[0] + info.fInterv
als[1]); |
| 122 | 182 |
| 123 SkMatrix coordTrans; | 183 SkScalar srcPhase = info.fPhase; |
| 124 | 184 |
| 125 // Rotate the src pts so they are aligned horizontally with pts[0].fX < pts[
1].fX | 185 // Rotate the src pts so they are aligned horizontally with pts[0].fX < pts[
1].fX |
| 126 SkMatrix srcRotInv; | 186 SkMatrix srcRotInv; |
| 127 SkPoint ptsRot[2]; | 187 SkPoint ptsRot[2]; |
| 128 if (pts[0].fY != pts[1].fY || pts[0].fX > pts[1].fX) { | 188 if (pts[0].fY != pts[1].fY || pts[0].fX > pts[1].fX) { |
| 129 align_to_x_axis(pts, &coordTrans, ptsRot); | 189 SkMatrix rotMatrix; |
| 130 if(!coordTrans.invert(&srcRotInv)) { | 190 align_to_x_axis(pts, &rotMatrix, ptsRot); |
| 191 if(!rotMatrix.invert(&srcRotInv)) { |
| 192 GrPrintf("Failed to create invertible rotation matrix!\n"); |
| 131 return false; | 193 return false; |
| 132 } | 194 } |
| 133 } else { | 195 } else { |
| 134 coordTrans.reset(); | |
| 135 srcRotInv.reset(); | 196 srcRotInv.reset(); |
| 136 memcpy(ptsRot, pts, 2 * sizeof(SkPoint)); | 197 memcpy(ptsRot, pts, 2 * sizeof(SkPoint)); |
| 137 } | 198 } |
| 138 | 199 |
| 139 GrPaint grPaint; | |
| 140 SkPaint2GrPaintShader(context, paint, true, &grPaint); | |
| 141 | |
| 142 bool useAA = paint.isAntiAlias(); | 200 bool useAA = paint.isAntiAlias(); |
| 143 | 201 |
| 144 // Scale corrections of intervals and stroke from view matrix | 202 // Scale corrections of intervals and stroke from view matrix |
| 145 SkScalar parallelScale; | 203 SkScalar parallelScale; |
| 146 SkScalar perpScale; | 204 SkScalar perpScale; |
| 147 calc_dash_scaling(¶llelScale, &perpScale, viewMatrix, ptsRot); | 205 calc_dash_scaling(¶llelScale, &perpScale, vm, ptsRot); |
| 148 | 206 |
| 149 bool hasCap = SkPaint::kSquare_Cap == cap && 0 != srcStrokeWidth; | 207 bool hasCap = SkPaint::kSquare_Cap == cap && 0 != srcStrokeWidth; |
| 150 | 208 |
| 151 // We always want to at least stroke out half a pixel on each side in device
space | 209 // We always want to at least stroke out half a pixel on each side in device
space |
| 152 // so 0.5f / perpScale gives us this min in src space | 210 // so 0.5f / perpScale gives us this min in src space |
| 153 SkScalar halfStroke = SkMaxScalar(srcStrokeWidth * 0.5f, 0.5f / perpScale); | 211 SkScalar halfSrcStroke = SkMaxScalar(srcStrokeWidth * 0.5f, 0.5f / perpScale
); |
| 154 | 212 |
| 155 SkScalar xStroke; | 213 SkScalar strokeAdj; |
| 156 if (!hasCap) { | 214 if (!hasCap) { |
| 157 xStroke = 0.f; | 215 strokeAdj = 0.f; |
| 158 } else { | 216 } else { |
| 159 xStroke = halfStroke; | 217 strokeAdj = halfSrcStroke; |
| 160 } | 218 } |
| 161 | 219 |
| 220 SkScalar startAdj = 0; |
| 221 |
| 222 SkMatrix combinedMatrix = srcRotInv; |
| 223 combinedMatrix.postConcat(vm); |
| 224 |
| 225 bool lineDone = false; |
| 226 SkRect startRect; |
| 227 bool hasStartRect = false; |
| 162 // If we are using AA, check to see if we are drawing a partial dash at the
start. If so | 228 // If we are using AA, check to see if we are drawing a partial dash at the
start. If so |
| 163 // draw it separately here and adjust our start point accordingly | 229 // draw it separately here and adjust our start point accordingly |
| 164 if (useAA) { | 230 if (useAA) { |
| 165 if (info.fPhase > 0 && info.fPhase < info.fIntervals[0]) { | 231 if (srcPhase > 0 && srcPhase < info.fIntervals[0]) { |
| 166 SkPoint startPts[2]; | 232 SkPoint startPts[2]; |
| 167 startPts[0] = ptsRot[0]; | 233 startPts[0] = ptsRot[0]; |
| 168 startPts[1].fY = startPts[0].fY; | 234 startPts[1].fY = startPts[0].fY; |
| 169 startPts[1].fX = SkMinScalar(startPts[0].fX + info.fIntervals[0] - i
nfo.fPhase, | 235 startPts[1].fX = SkMinScalar(startPts[0].fX + info.fIntervals[0] - s
rcPhase, |
| 170 ptsRot[1].fX); | 236 ptsRot[1].fX); |
| 171 SkRect startRect; | |
| 172 startRect.set(startPts, 2); | 237 startRect.set(startPts, 2); |
| 173 startRect.outset(xStroke, halfStroke); | 238 startRect.outset(strokeAdj, halfSrcStroke); |
| 174 context->drawRect(grPaint, startRect, NULL, &srcRotInv); | 239 |
| 175 | 240 hasStartRect = true; |
| 176 ptsRot[0].fX += info.fIntervals[0] + info.fIntervals[1] - info.fPhas
e; | 241 startAdj = info.fIntervals[0] + info.fIntervals[1] - srcPhase; |
| 177 info.fPhase = 0; | |
| 178 } | 242 } |
| 179 } | 243 } |
| 180 | 244 |
| 181 // adjustments for start and end of bounding rect so we only draw dash inter
vals | 245 // adjustments for start and end of bounding rect so we only draw dash inter
vals |
| 182 // contained in the original line segment. | 246 // contained in the original line segment. |
| 183 SkScalar startAdj = calc_start_adjustment(info); | 247 startAdj += calc_start_adjustment(info); |
| 248 if (startAdj != 0) { |
| 249 ptsRot[0].fX += startAdj; |
| 250 srcPhase = 0; |
| 251 } |
| 184 SkScalar endingInterval = 0; | 252 SkScalar endingInterval = 0; |
| 185 SkScalar endAdj = calc_end_adjustment(info, ptsRot, &endingInterval); | 253 SkScalar endAdj = calc_end_adjustment(info, ptsRot, srcPhase, &endingInterva
l); |
| 186 if (ptsRot[0].fX + startAdj >= ptsRot[1].fX - endAdj) { | 254 ptsRot[1].fX -= endAdj; |
| 187 // Nothing left to draw so just return | 255 if (ptsRot[0].fX >= ptsRot[1].fX) { |
| 188 return true; | 256 lineDone = true; |
| 189 } | 257 } |
| 190 | 258 |
| 259 SkRect endRect; |
| 260 bool hasEndRect = false; |
| 191 // If we are using AA, check to see if we are drawing a partial dash at then
end. If so | 261 // If we are using AA, check to see if we are drawing a partial dash at then
end. If so |
| 192 // draw it separately here and adjust our end point accordingly | 262 // draw it separately here and adjust our end point accordingly |
| 193 if (useAA) { | 263 if (useAA && !lineDone) { |
| 194 // If we adjusted the end then we will not be drawing a partial dash at
the end. | 264 // If we adjusted the end then we will not be drawing a partial dash at
the end. |
| 195 // If we didn't adjust the end point then we just need to make sure the
ending | 265 // If we didn't adjust the end point then we just need to make sure the
ending |
| 196 // dash isn't a full dash | 266 // dash isn't a full dash |
| 197 if (0 == endAdj && endingInterval != info.fIntervals[0]) { | 267 if (0 == endAdj && endingInterval != info.fIntervals[0]) { |
| 198 | |
| 199 SkPoint endPts[2]; | 268 SkPoint endPts[2]; |
| 200 endPts[1] = ptsRot[1]; | 269 endPts[1] = ptsRot[1]; |
| 201 endPts[0].fY = endPts[1].fY; | 270 endPts[0].fY = endPts[1].fY; |
| 202 endPts[0].fX = endPts[1].fX - endingInterval; | 271 endPts[0].fX = endPts[1].fX - endingInterval; |
| 203 | 272 |
| 204 SkRect endRect; | |
| 205 endRect.set(endPts, 2); | 273 endRect.set(endPts, 2); |
| 206 endRect.outset(xStroke, halfStroke); | 274 endRect.outset(strokeAdj, halfSrcStroke); |
| 207 context->drawRect(grPaint, endRect, NULL, &srcRotInv); | 275 |
| 208 | 276 hasEndRect = true; |
| 209 ptsRot[1].fX -= endingInterval + info.fIntervals[1]; | 277 endAdj = endingInterval + info.fIntervals[1]; |
| 278 |
| 279 ptsRot[1].fX -= endAdj; |
| 210 if (ptsRot[0].fX >= ptsRot[1].fX) { | 280 if (ptsRot[0].fX >= ptsRot[1].fX) { |
| 211 // Nothing left to draw so just return | 281 lineDone = true; |
| 212 return true; | |
| 213 } | 282 } |
| 214 } | 283 } |
| 215 } | 284 } |
| 216 coordTrans.postConcat(viewMatrix); | 285 |
| 217 | 286 if (startAdj != 0) { |
| 218 SkPoint devicePts[2]; | 287 srcPhase = 0; |
| 219 viewMatrix.mapPoints(devicePts, ptsRot, 2); | 288 } |
| 220 | 289 |
| 221 info.fIntervals[0] *= parallelScale; | 290 // Change the dashing info from src space into device space |
| 222 info.fIntervals[1] *= parallelScale; | 291 SkScalar devIntervals[2]; |
| 223 info.fPhase *= parallelScale; | 292 devIntervals[0] = info.fIntervals[0] * parallelScale; |
| 293 devIntervals[1] = info.fIntervals[1] * parallelScale; |
| 294 SkScalar devPhase = srcPhase * parallelScale; |
| 224 SkScalar strokeWidth = srcStrokeWidth * perpScale; | 295 SkScalar strokeWidth = srcStrokeWidth * perpScale; |
| 225 | 296 |
| 226 if ((strokeWidth < 1.f && !useAA) || 0.f == strokeWidth) { | 297 if ((strokeWidth < 1.f && !useAA) || 0.f == strokeWidth) { |
| 227 strokeWidth = 1.f; | 298 strokeWidth = 1.f; |
| 228 } | 299 } |
| 229 | 300 |
| 230 // Set up coordTransform for device space transforms | 301 SkScalar halfDevStroke = strokeWidth * 0.5f; |
| 231 // We rotate the dashed line such that it is horizontal with the start point
at smaller x | |
| 232 // then we translate the start point to the origin | |
| 233 if (devicePts[0].fY != devicePts[1].fY || devicePts[0].fX > devicePts[1].fX)
{ | |
| 234 SkMatrix rot; | |
| 235 align_to_x_axis(devicePts, &rot); | |
| 236 coordTrans.postConcat(rot); | |
| 237 } | |
| 238 coordTrans.postTranslate(-devicePts[0].fX, -devicePts[0].fY); | |
| 239 coordTrans.postTranslate(info.fIntervals[1] * 0.5f + info.fPhase, 0); | |
| 240 | 302 |
| 241 if (SkPaint::kSquare_Cap == cap && 0 != srcStrokeWidth) { | 303 if (SkPaint::kSquare_Cap == cap && 0 != srcStrokeWidth) { |
| 242 // add cap to on interveal and remove from off interval | 304 // add cap to on interveal and remove from off interval |
| 243 info.fIntervals[0] += strokeWidth; | 305 devIntervals[0] += strokeWidth; |
| 244 info.fIntervals[1] -= strokeWidth; | 306 devIntervals[1] -= strokeWidth; |
| 245 } | 307 } |
| 246 | 308 SkScalar startOffset = devIntervals[1] * 0.5f + devPhase; |
| 247 if (info.fIntervals[1] > 0.f) { | 309 |
| 310 SkScalar bloatX = useAA ? 0.5f / parallelScale : 0.f; |
| 311 SkScalar bloatY = useAA ? 0.5f / perpScale : 0.f; |
| 312 |
| 313 SkScalar devBloat = useAA ? 0.5f : 0.f; |
| 314 |
| 315 GrDrawState* drawState = target->drawState(); |
| 316 if (devIntervals[1] <= 0.f && useAA) { |
| 317 // Case when we end up drawing a solid AA rect |
| 318 // Reset the start rect to draw this single solid rect |
| 319 // but it requires to upload a new intervals uniform so we can mimic |
| 320 // one giant dash |
| 321 ptsRot[0].fX -= hasStartRect ? startAdj : 0; |
| 322 ptsRot[1].fX += hasEndRect ? endAdj : 0; |
| 323 startRect.set(ptsRot, 2); |
| 324 startRect.outset(strokeAdj, halfSrcStroke); |
| 325 hasStartRect = true; |
| 326 hasEndRect = false; |
| 327 lineDone = true; |
| 328 |
| 329 SkPoint devicePts[2]; |
| 330 vm.mapPoints(devicePts, ptsRot, 2); |
| 331 SkScalar lineLength = SkPoint::Distance(devicePts[0], devicePts[1]); |
| 332 if (hasCap) { |
| 333 lineLength += 2.f * halfDevStroke; |
| 334 } |
| 335 devIntervals[0] = lineLength; |
| 336 } |
| 337 if (devIntervals[1] > 0.f || useAA) { |
| 338 SkPathEffect::DashInfo devInfo; |
| 339 devInfo.fPhase = devPhase; |
| 340 devInfo.fCount = 2; |
| 341 devInfo.fIntervals = devIntervals; |
| 248 GrEffectEdgeType edgeType= useAA ? kFillAA_GrEffectEdgeType : | 342 GrEffectEdgeType edgeType= useAA ? kFillAA_GrEffectEdgeType : |
| 249 kFillBW_GrEffectEdgeType; | 343 kFillBW_GrEffectEdgeType; |
| 250 grPaint.addCoverageEffect( | 344 drawState->addCoverageEffect( |
| 251 GrDashingEffect::Create(edgeType, info, coordTrans, strokeWidth))->u
nref(); | 345 GrDashingEffect::Create(edgeType, devInfo, strokeWidth), 1)->unref()
; |
| 252 grPaint.setAntiAlias(false); | 346 } |
| 253 } | 347 |
| 254 | 348 // Set up the vertex data for the line and start/end dashes |
| 255 SkRect rect; | 349 drawState->setVertexAttribs<gDashLineVertexAttribs>(SK_ARRAY_COUNT(gDashLine
VertexAttribs)); |
| 256 bool bloat = useAA && info.fIntervals[1] > 0.f; | 350 |
| 257 SkScalar bloatX = bloat ? 0.5f / parallelScale : 0.f; | 351 int totalRectCnt = 0; |
| 258 SkScalar bloatY = bloat ? 0.5f / perpScale : 0.f; | 352 |
| 259 ptsRot[0].fX += startAdj; | 353 totalRectCnt += !lineDone ? 1 : 0; |
| 260 ptsRot[1].fX -= endAdj; | 354 totalRectCnt += hasStartRect ? 1 : 0; |
| 261 if (!hasCap) { | 355 totalRectCnt += hasEndRect ? 1 : 0; |
| 262 xStroke = 0.f; | 356 |
| 263 } else { | 357 GrDrawTarget::AutoReleaseGeometry geo(target, totalRectCnt * 4, 0); |
| 264 xStroke = halfStroke; | 358 if (!geo.succeeded()) { |
| 265 } | 359 GrPrintf("Failed to get space for vertices!\n"); |
| 266 rect.set(ptsRot, 2); | 360 return false; |
| 267 rect.outset(bloatX + xStroke, bloatY + halfStroke); | 361 } |
| 268 context->drawRect(grPaint, rect, NULL, &srcRotInv); | 362 |
| 269 | 363 DashLineVertex* verts = reinterpret_cast<DashLineVertex*>(geo.vertices()); |
| 364 |
| 365 int curVIdx = 0; |
| 366 |
| 367 // Draw interior part of dashed line |
| 368 if (!lineDone) { |
| 369 SkPoint devicePts[2]; |
| 370 vm.mapPoints(devicePts, ptsRot, 2); |
| 371 SkScalar lineLength = SkPoint::Distance(devicePts[0], devicePts[1]); |
| 372 if (hasCap) { |
| 373 lineLength += 2.f * halfDevStroke; |
| 374 } |
| 375 |
| 376 SkRect bounds; |
| 377 bounds.set(ptsRot[0].fX, ptsRot[0].fY, ptsRot[1].fX, ptsRot[1].fY); |
| 378 bounds.outset(bloatX + strokeAdj, bloatY + halfSrcStroke); |
| 379 setup_dashed_rect(bounds, verts, curVIdx, combinedMatrix, startOffset, d
evBloat, |
| 380 lineLength, halfDevStroke); |
| 381 curVIdx += 4; |
| 382 } |
| 383 |
| 384 if (hasStartRect) { |
| 385 SkASSERT(useAA); // so that we know bloatX and bloatY have been set |
| 386 startRect.outset(bloatX, bloatY); |
| 387 setup_dashed_rect(startRect, verts, curVIdx, combinedMatrix, startOffset
, devBloat, |
| 388 devIntervals[0], halfDevStroke); |
| 389 curVIdx += 4; |
| 390 } |
| 391 |
| 392 if (hasEndRect) { |
| 393 SkASSERT(useAA); // so that we know bloatX and bloatY have been set |
| 394 endRect.outset(bloatX, bloatY); |
| 395 setup_dashed_rect(endRect, verts, curVIdx, combinedMatrix, startOffset,
devBloat, |
| 396 devIntervals[0], halfDevStroke); |
| 397 } |
| 398 |
| 399 target->setIndexSourceToBuffer(gpu->getContext()->getQuadIndexBuffer()); |
| 400 target->drawIndexedInstances(kTriangles_GrPrimitiveType, totalRectCnt, 4, 6)
; |
| 401 target->resetIndexSource(); |
| 270 return true; | 402 return true; |
| 271 } | 403 } |
| 272 | 404 |
| 273 ////////////////////////////////////////////////////////////////////////////// | 405 ////////////////////////////////////////////////////////////////////////////// |
| 274 | 406 |
| 275 class GLDashingLineEffect; | 407 class GLDashingLineEffect; |
| 276 | 408 |
| 277 class DashingLineEffect : public GrEffect { | 409 class DashingLineEffect : public GrVertexEffect { |
| 278 public: | 410 public: |
| 279 typedef SkPathEffect::DashInfo DashInfo; | 411 typedef SkPathEffect::DashInfo DashInfo; |
| 280 | 412 |
| 281 /** | 413 /** |
| 282 * The effect calculates the coverage for the case of a horizontal line in d
evice space. | 414 * The effect calculates the coverage for the case of a horizontal line in d
evice space. |
| 283 * The matrix that is passed in should be able to convert a line in source s
pace to a | 415 * The matrix that is passed in should be able to convert a line in source s
pace to a |
| 284 * horizontal line in device space. Additionally, the coord transform matrix
should translate | 416 * horizontal line in device space. Additionally, the coord transform matrix
should translate |
| 285 * the the start of line to origin, and the shift it along the positive x-ax
is by the phase | 417 * the the start of line to origin, and the shift it along the positive x-ax
is by the phase |
| 286 * and half the off interval. | 418 * and half the off interval. |
| 287 */ | 419 */ |
| 288 static GrEffectRef* Create(GrEffectEdgeType edgeType, const DashInfo& info, | 420 static GrEffectRef* Create(GrEffectEdgeType edgeType, const DashInfo& info, |
| 289 const SkMatrix& matrix, SkScalar strokeWidth); | 421 SkScalar strokeWidth); |
| 290 | 422 |
| 291 virtual ~DashingLineEffect(); | 423 virtual ~DashingLineEffect(); |
| 292 | 424 |
| 293 static const char* Name() { return "DashingEffect"; } | 425 static const char* Name() { return "DashingEffect"; } |
| 294 | 426 |
| 295 GrEffectEdgeType getEdgeType() const { return fEdgeType; } | 427 GrEffectEdgeType getEdgeType() const { return fEdgeType; } |
| 296 | 428 |
| 297 const SkRect& getRect() const { return fRect; } | 429 const SkRect& getRect() const { return fRect; } |
| 298 | 430 |
| 299 SkScalar getIntervalLength() const { return fIntervalLength; } | 431 SkScalar getIntervalLength() const { return fIntervalLength; } |
| 300 | 432 |
| 301 typedef GLDashingLineEffect GLEffect; | 433 typedef GLDashingLineEffect GLEffect; |
| 302 | 434 |
| 303 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags
) const SK_OVERRIDE; | 435 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags
) const SK_OVERRIDE; |
| 304 | 436 |
| 305 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; | 437 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; |
| 306 | 438 |
| 307 private: | 439 private: |
| 308 DashingLineEffect(GrEffectEdgeType edgeType, const DashInfo& info, const SkM
atrix& matrix, | 440 DashingLineEffect(GrEffectEdgeType edgeType, const DashInfo& info, SkScalar
strokeWidth); |
| 309 SkScalar strokeWidth); | |
| 310 | 441 |
| 311 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE; | 442 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE; |
| 312 | 443 |
| 313 GrEffectEdgeType fEdgeType; | 444 GrEffectEdgeType fEdgeType; |
| 314 GrCoordTransform fCoordTransform; | |
| 315 SkRect fRect; | 445 SkRect fRect; |
| 316 SkScalar fIntervalLength; | 446 SkScalar fIntervalLength; |
| 317 | 447 |
| 318 GR_DECLARE_EFFECT_TEST; | 448 GR_DECLARE_EFFECT_TEST; |
| 319 | 449 |
| 320 typedef GrEffect INHERITED; | 450 typedef GrEffect INHERITED; |
| 321 }; | 451 }; |
| 322 | 452 |
| 323 ////////////////////////////////////////////////////////////////////////////// | 453 ////////////////////////////////////////////////////////////////////////////// |
| 324 | 454 |
| 325 class GLDashingLineEffect : public GrGLEffect { | 455 class GLDashingLineEffect : public GrGLVertexEffect { |
| 326 public: | 456 public: |
| 327 GLDashingLineEffect(const GrBackendEffectFactory&, const GrDrawEffect&); | 457 GLDashingLineEffect(const GrBackendEffectFactory&, const GrDrawEffect&); |
| 328 | 458 |
| 329 virtual void emitCode(GrGLShaderBuilder* builder, | 459 virtual void emitCode(GrGLFullShaderBuilder* builder, |
| 330 const GrDrawEffect& drawEffect, | 460 const GrDrawEffect& drawEffect, |
| 331 EffectKey key, | 461 EffectKey key, |
| 332 const char* outputColor, | 462 const char* outputColor, |
| 333 const char* inputColor, | 463 const char* inputColor, |
| 334 const TransformedCoordsArray&, | 464 const TransformedCoordsArray&, |
| 335 const TextureSamplerArray&) SK_OVERRIDE; | 465 const TextureSamplerArray&) SK_OVERRIDE; |
| 336 | 466 |
| 337 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); | 467 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); |
| 338 | 468 |
| 339 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER
RIDE; | 469 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER
RIDE; |
| 340 | 470 |
| 341 private: | 471 private: |
| 342 GrGLUniformManager::UniformHandle fRectUniform; | 472 GrGLUniformManager::UniformHandle fRectUniform; |
| 343 GrGLUniformManager::UniformHandle fIntervalUniform; | 473 GrGLUniformManager::UniformHandle fIntervalUniform; |
| 344 SkRect fPrevRect; | 474 SkRect fPrevRect; |
| 345 SkScalar fPrevIntervalLength; | 475 SkScalar fPrevIntervalLength; |
| 346 typedef GrGLEffect INHERITED; | 476 typedef GrGLVertexEffect INHERITED; |
| 347 }; | 477 }; |
| 348 | 478 |
| 349 GLDashingLineEffect::GLDashingLineEffect(const GrBackendEffectFactory& factory, | 479 GLDashingLineEffect::GLDashingLineEffect(const GrBackendEffectFactory& factory, |
| 350 const GrDrawEffect& drawEffect) | 480 const GrDrawEffect& drawEffect) |
| 351 : INHERITED (factory) { | 481 : INHERITED (factory) { |
| 352 fPrevRect.fLeft = SK_ScalarNaN; | 482 fPrevRect.fLeft = SK_ScalarNaN; |
| 353 fPrevIntervalLength = SK_ScalarMax; | 483 fPrevIntervalLength = SK_ScalarMax; |
| 354 | 484 |
| 355 } | 485 } |
| 356 | 486 |
| 357 void GLDashingLineEffect::emitCode(GrGLShaderBuilder* builder, | 487 void GLDashingLineEffect::emitCode(GrGLFullShaderBuilder* builder, |
| 358 const GrDrawEffect& drawEffect, | 488 const GrDrawEffect& drawEffect, |
| 359 EffectKey key, | 489 EffectKey key, |
| 360 const char* outputColor, | 490 const char* outputColor, |
| 361 const char* inputColor, | 491 const char* inputColor, |
| 362 const TransformedCoordsArray& coords, | 492 const TransformedCoordsArray&, |
| 363 const TextureSamplerArray& samplers) { | 493 const TextureSamplerArray& samplers) { |
| 364 const DashingLineEffect& de = drawEffect.castEffect<DashingLineEffect>(); | 494 const DashingLineEffect& de = drawEffect.castEffect<DashingLineEffect>(); |
| 365 const char *rectName; | 495 const char *rectName; |
| 366 // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bot
tom - 0.5), | 496 // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bot
tom - 0.5), |
| 367 // respectively. | 497 // respectively. |
| 368 fRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, | 498 fRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, |
| 369 kVec4f_GrSLType, | 499 kVec4f_GrSLType, |
| 370 "rect", | 500 "rect", |
| 371 &rectName); | 501 &rectName); |
| 372 const char *intervalName; | 502 const char *intervalName; |
| 373 // The interval uniform's refers to the total length of the interval (on + o
ff) | 503 // The interval uniform's refers to the total length of the interval (on + o
ff) |
| 374 fIntervalUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibili
ty, | 504 fIntervalUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibili
ty, |
| 375 kFloat_GrSLType, | 505 kFloat_GrSLType, |
| 376 "interval", | 506 "interval", |
| 377 &intervalName); | 507 &intervalName); |
| 508 |
| 509 const char *vsCoordName, *fsCoordName; |
| 510 builder->addVarying(kVec2f_GrSLType, "Coord", &vsCoordName, &fsCoordName); |
| 511 const SkString* attr0Name = |
| 512 builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); |
| 513 builder->vsCodeAppendf("\t%s = %s;\n", vsCoordName, attr0Name->c_str()); |
| 514 |
| 378 // transforms all points so that we can compare them to our test rect | 515 // transforms all points so that we can compare them to our test rect |
| 379 builder->fsCodeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s) * %s;\n
", | 516 builder->fsCodeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s) * %s;\n
", |
| 380 coords[0].c_str(), coords[0].c_str(), intervalName, i
ntervalName); | 517 fsCoordName, fsCoordName, intervalName, intervalName)
; |
| 381 builder->fsCodeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n",
coords[0].c_str()); | 518 builder->fsCodeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n",
fsCoordName); |
| 382 if (GrEffectEdgeTypeIsAA(de.getEdgeType())) { | 519 if (GrEffectEdgeTypeIsAA(de.getEdgeType())) { |
| 383 // The amount of coverage removed in x and y by the edges is computed as
a pair of negative | 520 // The amount of coverage removed in x and y by the edges is computed as
a pair of negative |
| 384 // numbers, xSub and ySub. | 521 // numbers, xSub and ySub. |
| 385 builder->fsCodeAppend("\t\tfloat xSub, ySub;\n"); | 522 builder->fsCodeAppend("\t\tfloat xSub, ySub;\n"); |
| 386 builder->fsCodeAppendf("\t\txSub = min(fragPosShifted.x - %s.x, 0.0);\n"
, rectName); | 523 builder->fsCodeAppendf("\t\txSub = min(fragPosShifted.x - %s.x, 0.0);\n"
, rectName); |
| 387 builder->fsCodeAppendf("\t\txSub += min(%s.z - fragPosShifted.x, 0.0);\n
", rectName); | 524 builder->fsCodeAppendf("\t\txSub += min(%s.z - fragPosShifted.x, 0.0);\n
", rectName); |
| 388 builder->fsCodeAppendf("\t\tySub = min(fragPosShifted.y - %s.y, 0.0);\n"
, rectName); | 525 builder->fsCodeAppendf("\t\tySub = min(fragPosShifted.y - %s.y, 0.0);\n"
, rectName); |
| 389 builder->fsCodeAppendf("\t\tySub += min(%s.w - fragPosShifted.y, 0.0);\n
", rectName); | 526 builder->fsCodeAppendf("\t\tySub += min(%s.w - fragPosShifted.y, 0.0);\n
", rectName); |
| 390 // Now compute coverage in x and y and multiply them to get the fraction
of the pixel | 527 // Now compute coverage in x and y and multiply them to get the fraction
of the pixel |
| 391 // covered. | 528 // covered. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 415 | 552 |
| 416 GrGLEffect::EffectKey GLDashingLineEffect::GenKey(const GrDrawEffect& drawEffect
, | 553 GrGLEffect::EffectKey GLDashingLineEffect::GenKey(const GrDrawEffect& drawEffect
, |
| 417 const GrGLCaps&) { | 554 const GrGLCaps&) { |
| 418 const DashingLineEffect& de = drawEffect.castEffect<DashingLineEffect>(); | 555 const DashingLineEffect& de = drawEffect.castEffect<DashingLineEffect>(); |
| 419 return de.getEdgeType(); | 556 return de.getEdgeType(); |
| 420 } | 557 } |
| 421 | 558 |
| 422 ////////////////////////////////////////////////////////////////////////////// | 559 ////////////////////////////////////////////////////////////////////////////// |
| 423 | 560 |
| 424 GrEffectRef* DashingLineEffect::Create(GrEffectEdgeType edgeType, const DashInfo
& info, | 561 GrEffectRef* DashingLineEffect::Create(GrEffectEdgeType edgeType, const DashInfo
& info, |
| 425 const SkMatrix& matrix, SkScalar strokeWidt
h) { | 562 SkScalar strokeWidth) { |
| 426 if (info.fCount != 2) { | 563 if (info.fCount != 2) { |
| 427 return NULL; | 564 return NULL; |
| 428 } | 565 } |
| 429 | 566 |
| 430 return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(DashingLineEffect, | 567 return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(DashingLineEffect, |
| 431 (edgeType, info, matrix, s
trokeWidth)))); | 568 (edgeType, info, strokeWid
th)))); |
| 432 } | 569 } |
| 433 | 570 |
| 434 DashingLineEffect::~DashingLineEffect() {} | 571 DashingLineEffect::~DashingLineEffect() {} |
| 435 | 572 |
| 436 void DashingLineEffect::getConstantColorComponents(GrColor* color, uint32_t* val
idFlags) const { | 573 void DashingLineEffect::getConstantColorComponents(GrColor* color, uint32_t* val
idFlags) const { |
| 437 *validFlags = 0; | 574 *validFlags = 0; |
| 438 } | 575 } |
| 439 | 576 |
| 440 const GrBackendEffectFactory& DashingLineEffect::getFactory() const { | 577 const GrBackendEffectFactory& DashingLineEffect::getFactory() const { |
| 441 return GrTBackendEffectFactory<DashingLineEffect>::getInstance(); | 578 return GrTBackendEffectFactory<DashingLineEffect>::getInstance(); |
| 442 } | 579 } |
| 443 | 580 |
| 444 DashingLineEffect::DashingLineEffect(GrEffectEdgeType edgeType, const DashInfo&
info, | 581 DashingLineEffect::DashingLineEffect(GrEffectEdgeType edgeType, const DashInfo&
info, |
| 445 const SkMatrix& matrix, SkScalar strokeWidth) | 582 SkScalar strokeWidth) |
| 446 : fEdgeType(edgeType) | 583 : fEdgeType(edgeType) { |
| 447 , fCoordTransform(kLocal_GrCoordSet, matrix) { | |
| 448 SkScalar onLen = info.fIntervals[0]; | 584 SkScalar onLen = info.fIntervals[0]; |
| 449 SkScalar offLen = info.fIntervals[1]; | 585 SkScalar offLen = info.fIntervals[1]; |
| 450 SkScalar halfOffLen = SkScalarHalf(offLen); | 586 SkScalar halfOffLen = SkScalarHalf(offLen); |
| 451 SkScalar halfStroke = SkScalarHalf(strokeWidth); | 587 SkScalar halfStroke = SkScalarHalf(strokeWidth); |
| 452 fIntervalLength = onLen + offLen; | 588 fIntervalLength = onLen + offLen; |
| 453 fRect.set(halfOffLen, -halfStroke, halfOffLen + onLen, halfStroke); | 589 fRect.set(halfOffLen, -halfStroke, halfOffLen + onLen, halfStroke); |
| 454 | 590 |
| 455 addCoordTransform(&fCoordTransform); | 591 this->addVertexAttrib(kVec2f_GrSLType); |
| 456 } | 592 } |
| 457 | 593 |
| 458 bool DashingLineEffect::onIsEqual(const GrEffect& other) const { | 594 bool DashingLineEffect::onIsEqual(const GrEffect& other) const { |
| 459 const DashingLineEffect& de = CastEffect<DashingLineEffect>(other); | 595 const DashingLineEffect& de = CastEffect<DashingLineEffect>(other); |
| 460 return (fEdgeType == de.fEdgeType && | 596 return (fEdgeType == de.fEdgeType && |
| 461 fCoordTransform == de.fCoordTransform && | |
| 462 fRect == de.fRect && | 597 fRect == de.fRect && |
| 463 fIntervalLength == de.fIntervalLength); | 598 fIntervalLength == de.fIntervalLength); |
| 464 } | 599 } |
| 465 | 600 |
| 466 GR_DEFINE_EFFECT_TEST(DashingLineEffect); | 601 GR_DEFINE_EFFECT_TEST(DashingLineEffect); |
| 467 | 602 |
| 468 GrEffectRef* DashingLineEffect::TestCreate(SkRandom* random, | 603 GrEffectRef* DashingLineEffect::TestCreate(SkRandom* random, |
| 469 GrContext*, | 604 GrContext*, |
| 470 const GrDrawTargetCaps& caps, | 605 const GrDrawTargetCaps& caps, |
| 471 GrTexture*[]) { | 606 GrTexture*[]) { |
| 472 GrEffectRef* effect; | 607 GrEffectRef* effect; |
| 473 SkMatrix m; | |
| 474 m.reset(); | |
| 475 GrEffectEdgeType edgeType = static_cast<GrEffectEdgeType>(random->nextULessT
han( | 608 GrEffectEdgeType edgeType = static_cast<GrEffectEdgeType>(random->nextULessT
han( |
| 476 kGrEffectEdgeTypeCnt)); | 609 kGrEffectEdgeTypeCnt)); |
| 477 SkScalar strokeWidth = random->nextRangeScalar(0, 100.f); | 610 SkScalar strokeWidth = random->nextRangeScalar(0, 100.f); |
| 478 DashInfo info; | 611 DashInfo info; |
| 479 info.fCount = 2; | 612 info.fCount = 2; |
| 480 SkAutoTArray<SkScalar> intervals(info.fCount); | 613 SkAutoTArray<SkScalar> intervals(info.fCount); |
| 481 info.fIntervals = intervals.get(); | 614 info.fIntervals = intervals.get(); |
| 482 info.fIntervals[0] = random->nextRangeScalar(0, 10.f); | 615 info.fIntervals[0] = random->nextRangeScalar(0, 10.f); |
| 483 info.fIntervals[1] = random->nextRangeScalar(0, 10.f); | 616 info.fIntervals[1] = random->nextRangeScalar(0, 10.f); |
| 484 info.fPhase = random->nextRangeScalar(0, info.fIntervals[0] + info.fInterval
s[1]); | 617 info.fPhase = random->nextRangeScalar(0, info.fIntervals[0] + info.fInterval
s[1]); |
| 485 | 618 |
| 486 effect = DashingLineEffect::Create(edgeType, info, m, strokeWidth); | 619 effect = DashingLineEffect::Create(edgeType, info, strokeWidth); |
| 487 return effect; | 620 return effect; |
| 488 } | 621 } |
| 489 | 622 |
| 490 ////////////////////////////////////////////////////////////////////////////// | 623 ////////////////////////////////////////////////////////////////////////////// |
| 491 | 624 |
| 492 GrEffectRef* GrDashingEffect::Create(GrEffectEdgeType edgeType, const SkPathEffe
ct::DashInfo& info, | 625 GrEffectRef* GrDashingEffect::Create(GrEffectEdgeType edgeType, const SkPathEffe
ct::DashInfo& info, |
| 493 const SkMatrix& matrix, SkScalar strokeWidt
h) { | 626 SkScalar strokeWidth) { |
| 494 return DashingLineEffect::Create(edgeType, info, matrix, strokeWidth); | 627 return DashingLineEffect::Create(edgeType, info, strokeWidth); |
| 495 } | 628 } |
| OLD | NEW |