1628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org/*
2628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org * Copyright 2014 Google Inc.
3628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org *
4628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org * Use of this source code is governed by a BSD-style license that can be
5628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org * found in the LICENSE file.
6628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org */
7628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
8628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org#include "GrDashingEffect.h"
9628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
10e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel#include "../GrAARectRenderer.h"
11e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
12e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel#include "effects/GrVertexEffect.h"
13628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org#include "gl/GrGLEffect.h"
14e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel#include "gl/GrGLVertexEffect.h"
15628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org#include "gl/GrGLSL.h"
16628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org#include "GrContext.h"
17628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org#include "GrCoordTransform.h"
18e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel#include "GrDrawTarget.h"
19628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org#include "GrDrawTargetCaps.h"
20628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org#include "GrEffect.h"
21e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel#include "GrGpu.h"
22e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel#include "GrStrokeInfo.h"
23628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org#include "GrTBackendEffectFactory.h"
24628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org#include "SkGr.h"
25628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
26628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
27628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
28e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel// Returns whether or not the gpu can fast path the dash line effect.
29e61c411c1258a323a010558c08de3d9f8d170dcaegdanielstatic bool can_fast_path_dash(const SkPoint pts[2], const GrStrokeInfo& strokeInfo,
30e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel                               const GrDrawTarget& target, const SkMatrix& viewMatrix) {
31e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    if (target.getDrawState().getRenderTarget()->isMultisampled()) {
32e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        return false;
33e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    }
34e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
35e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    // Pts must be either horizontal or vertical in src space
36e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    if (pts[0].fX != pts[1].fX && pts[0].fY != pts[1].fY) {
37e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        return false;
38e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    }
39e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
40e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    // May be able to relax this to include skew. As of now cannot do perspective
41e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    // because of the non uniform scaling of bloating a rect
42e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    if (!viewMatrix.preservesRightAngles()) {
43e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        return false;
44e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    }
45e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
46e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    if (!strokeInfo.isDashed() || 2 != strokeInfo.dashCount()) {
47e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        return false;
48e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    }
49e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
50e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    const SkPathEffect::DashInfo& info = strokeInfo.getDashInfo();
51e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    if (0 == info.fIntervals[0] && 0 == info.fIntervals[1]) {
52e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        return false;
53e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    }
54e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
55e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    SkPaint::Cap cap = strokeInfo.getStrokeRec().getCap();
56e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    // Current we do don't handle Round or Square cap dashes
57e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    if (SkPaint::kRound_Cap == cap) {
58e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        return false;
59e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    }
60e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
61e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    return true;
62e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel}
63e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
64e61c411c1258a323a010558c08de3d9f8d170dcaegdanielnamespace {
65e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
66e61c411c1258a323a010558c08de3d9f8d170dcaegdanielstruct DashLineVertex {
67e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    SkPoint fPos;
68e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    SkPoint fDashPos;
69e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel};
70e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
71e61c411c1258a323a010558c08de3d9f8d170dcaegdanielextern const GrVertexAttrib gDashLineVertexAttribs[] = {
72e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    { kVec2f_GrVertexAttribType, 0,                 kPosition_GrVertexAttribBinding },
73e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    { kVec2f_GrVertexAttribType, sizeof(SkPoint),   kEffect_GrVertexAttribBinding },
74e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel};
75e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
76e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel};
77628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.orgstatic void calc_dash_scaling(SkScalar* parallelScale, SkScalar* perpScale,
78628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                            const SkMatrix& viewMatrix, const SkPoint pts[2]) {
79628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkVector vecSrc = pts[1] - pts[0];
80628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkScalar magSrc = vecSrc.length();
81628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkScalar invSrc = magSrc ? SkScalarInvert(magSrc) : 0;
82628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    vecSrc.scale(invSrc);
83628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
84628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkVector vecSrcPerp;
85628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    vecSrc.rotateCW(&vecSrcPerp);
86628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    viewMatrix.mapVectors(&vecSrc, 1);
87628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    viewMatrix.mapVectors(&vecSrcPerp, 1);
88628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
89628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    // parallelScale tells how much to scale along the line parallel to the dash line
90628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    // perpScale tells how much to scale in the direction perpendicular to the dash line
91628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    *parallelScale = vecSrc.length();
92628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    *perpScale = vecSrcPerp.length();
93628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org}
94628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
95628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org// calculates the rotation needed to aligned pts to the x axis with pts[0] < pts[1]
96628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org// Stores the rotation matrix in rotMatrix, and the mapped points in ptsRot
97628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.orgstatic void align_to_x_axis(const SkPoint pts[2], SkMatrix* rotMatrix, SkPoint ptsRot[2] = NULL) {
98628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkVector vec = pts[1] - pts[0];
99628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkScalar mag = vec.length();
100628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkScalar inv = mag ? SkScalarInvert(mag) : 0;
101628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
102628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    vec.scale(inv);
103628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    rotMatrix->setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY);
104628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    if (ptsRot) {
105628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        rotMatrix->mapPoints(ptsRot, pts, 2);
106628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        // correction for numerical issues if map doesn't make ptsRot exactly horizontal
107628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        ptsRot[1].fY = pts[0].fY;
108628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    }
109628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org}
110628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
111628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org// Assumes phase < sum of all intervals
112628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.orgstatic SkScalar calc_start_adjustment(const SkPathEffect::DashInfo& info) {
113628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkASSERT(info.fPhase < info.fIntervals[0] + info.fIntervals[1]);
114628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    if (info.fPhase >= info.fIntervals[0] && info.fPhase != 0) {
115628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        SkScalar srcIntervalLen = info.fIntervals[0] + info.fIntervals[1];
116628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        return srcIntervalLen - info.fPhase;
117628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    }
118628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    return 0;
119628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org}
120628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
121e61c411c1258a323a010558c08de3d9f8d170dcaegdanielstatic SkScalar calc_end_adjustment(const SkPathEffect::DashInfo& info, const SkPoint pts[2],
122e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel                                    SkScalar phase, SkScalar* endingInt) {
123628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    if (pts[1].fX <= pts[0].fX) {
124628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        return 0;
125628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    }
126628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkScalar srcIntervalLen = info.fIntervals[0] + info.fIntervals[1];
127628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkScalar totalLen = pts[1].fX - pts[0].fX;
128628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkScalar temp = SkScalarDiv(totalLen, srcIntervalLen);
129628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkScalar numFullIntervals = SkScalarFloorToScalar(temp);
130e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    *endingInt = totalLen - numFullIntervals * srcIntervalLen + phase;
131628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    temp = SkScalarDiv(*endingInt, srcIntervalLen);
132628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    *endingInt = *endingInt - SkScalarFloorToScalar(temp) * srcIntervalLen;
133628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    if (0 == *endingInt) {
134628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        *endingInt = srcIntervalLen;
135628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    }
136628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    if (*endingInt > info.fIntervals[0]) {
137628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        if (0 == info.fIntervals[0]) {
138ad88340cf16162654ebddf4783ebb2ac56e1c3aacommit-bot@chromium.org            *endingInt -= 0.01f; // make sure we capture the last zero size pnt (used if has caps)
139628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        }
140628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        return *endingInt - info.fIntervals[0];
141628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    }
142628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    return 0;
143628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org}
144628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
145e61c411c1258a323a010558c08de3d9f8d170dcaegdanielstatic void setup_dashed_rect(const SkRect& rect, DashLineVertex* verts, int idx, const SkMatrix& matrix,
146e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel                       SkScalar offset, SkScalar bloat, SkScalar len, SkScalar stroke) {
147628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
148e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        SkScalar startDashX = offset - bloat;
149e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        SkScalar endDashX = offset + len + bloat;
150e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        SkScalar startDashY = -stroke - bloat;
151e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        SkScalar endDashY = stroke + bloat;
152e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        verts[idx].fDashPos = SkPoint::Make(startDashX , startDashY);
153e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        verts[idx + 1].fDashPos = SkPoint::Make(startDashX, endDashY);
154e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        verts[idx + 2].fDashPos = SkPoint::Make(endDashX, endDashY);
155e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        verts[idx + 3].fDashPos = SkPoint::Make(endDashX, startDashY);
156628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
157e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        verts[idx].fPos = SkPoint::Make(rect.fLeft, rect.fTop);
158e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        verts[idx + 1].fPos = SkPoint::Make(rect.fLeft, rect.fBottom);
159e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        verts[idx + 2].fPos = SkPoint::Make(rect.fRight, rect.fBottom);
160e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        verts[idx + 3].fPos = SkPoint::Make(rect.fRight, rect.fTop);
161628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
162e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        matrix.mapPointsWithStride(&verts[idx].fPos, sizeof(DashLineVertex), 4);
163e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel}
164628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
165e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
166e61c411c1258a323a010558c08de3d9f8d170dcaegdanielbool GrDashingEffect::DrawDashLine(const SkPoint pts[2], const GrPaint& paint,
167e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel                                   const GrStrokeInfo& strokeInfo, GrGpu* gpu,
168e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel                                   GrDrawTarget* target, const SkMatrix& vm) {
169e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
170e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    if (!can_fast_path_dash(pts, strokeInfo, *target, vm)) {
171628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        return false;
172628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    }
173628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
174e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    const SkPathEffect::DashInfo& info = strokeInfo.getDashInfo();
175628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
176e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    SkPaint::Cap cap = strokeInfo.getStrokeRec().getCap();
177e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
178e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    SkScalar srcStrokeWidth = strokeInfo.getStrokeRec().getWidth();
179628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
180628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    // the phase should be normalized to be [0, sum of all intervals)
181628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkASSERT(info.fPhase >= 0 && info.fPhase < info.fIntervals[0] + info.fIntervals[1]);
182628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
183e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    SkScalar srcPhase = info.fPhase;
184628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
185628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    // Rotate the src pts so they are aligned horizontally with pts[0].fX < pts[1].fX
186628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkMatrix srcRotInv;
187628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkPoint ptsRot[2];
188628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    if (pts[0].fY != pts[1].fY || pts[0].fX > pts[1].fX) {
189e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        SkMatrix rotMatrix;
190e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        align_to_x_axis(pts, &rotMatrix, ptsRot);
191e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        if(!rotMatrix.invert(&srcRotInv)) {
192e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel            GrPrintf("Failed to create invertible rotation matrix!\n");
193628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org            return false;
194628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        }
195628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    } else {
196628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        srcRotInv.reset();
197628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        memcpy(ptsRot, pts, 2 * sizeof(SkPoint));
198628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    }
199628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
200628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    bool useAA = paint.isAntiAlias();
2013b9e8be760ad0e576d5145e0aecf0dc73efcd640skia.committer@gmail.com
202628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    // Scale corrections of intervals and stroke from view matrix
203628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkScalar parallelScale;
204628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkScalar perpScale;
205e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    calc_dash_scaling(&parallelScale, &perpScale, vm, ptsRot);
206628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
207628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    bool hasCap = SkPaint::kSquare_Cap == cap && 0 != srcStrokeWidth;
208628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
209628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    // We always want to at least stroke out half a pixel on each side in device space
210628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    // so 0.5f / perpScale gives us this min in src space
211e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    SkScalar halfSrcStroke = SkMaxScalar(srcStrokeWidth * 0.5f, 0.5f / perpScale);
212628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
213e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    SkScalar strokeAdj;
214628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    if (!hasCap) {
215e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        strokeAdj = 0.f;
216628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    } else {
217e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        strokeAdj = halfSrcStroke;
218628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    }
219628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
220e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    SkScalar startAdj = 0;
221e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
222e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    SkMatrix combinedMatrix = srcRotInv;
223e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    combinedMatrix.postConcat(vm);
224e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
225e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    bool lineDone = false;
226e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    SkRect startRect;
227e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    bool hasStartRect = false;
228628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    // If we are using AA, check to see if we are drawing a partial dash at the start. If so
229628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    // draw it separately here and adjust our start point accordingly
230628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    if (useAA) {
231e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        if (srcPhase > 0 && srcPhase < info.fIntervals[0]) {
232628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org            SkPoint startPts[2];
233628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org            startPts[0] = ptsRot[0];
234628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org            startPts[1].fY = startPts[0].fY;
235e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel            startPts[1].fX = SkMinScalar(startPts[0].fX + info.fIntervals[0] - srcPhase,
236628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                                         ptsRot[1].fX);
237628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org            startRect.set(startPts, 2);
238e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel            startRect.outset(strokeAdj, halfSrcStroke);
239628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
240e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel            hasStartRect = true;
241e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel            startAdj = info.fIntervals[0] + info.fIntervals[1] - srcPhase;
242628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        }
243628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    }
244628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
245628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    // adjustments for start and end of bounding rect so we only draw dash intervals
246628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    // contained in the original line segment.
247e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    startAdj += calc_start_adjustment(info);
248e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    if (startAdj != 0) {
249e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        ptsRot[0].fX += startAdj;
250e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        srcPhase = 0;
251e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    }
252628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkScalar endingInterval = 0;
253e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    SkScalar endAdj = calc_end_adjustment(info, ptsRot, srcPhase, &endingInterval);
254e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    ptsRot[1].fX -= endAdj;
255e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    if (ptsRot[0].fX >= ptsRot[1].fX) {
256e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        lineDone = true;
257628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    }
258628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
259e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    SkRect endRect;
260e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    bool hasEndRect = false;
261628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    // If we are using AA, check to see if we are drawing a partial dash at then end. If so
262628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    // draw it separately here and adjust our end point accordingly
263e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    if (useAA && !lineDone) {
264628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        // If we adjusted the end then we will not be drawing a partial dash at the end.
265628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        // If we didn't adjust the end point then we just need to make sure the ending
266628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        // dash isn't a full dash
267628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        if (0 == endAdj && endingInterval != info.fIntervals[0]) {
268628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org            SkPoint endPts[2];
269628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org            endPts[1] = ptsRot[1];
270628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org            endPts[0].fY = endPts[1].fY;
2713b9e8be760ad0e576d5145e0aecf0dc73efcd640skia.committer@gmail.com            endPts[0].fX = endPts[1].fX - endingInterval;
272628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
273628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org            endRect.set(endPts, 2);
274e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel            endRect.outset(strokeAdj, halfSrcStroke);
275e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
276e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel            hasEndRect = true;
277e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel            endAdj = endingInterval + info.fIntervals[1];
2783b9e8be760ad0e576d5145e0aecf0dc73efcd640skia.committer@gmail.com
279e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel            ptsRot[1].fX -= endAdj;
280628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org            if (ptsRot[0].fX >= ptsRot[1].fX) {
281e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel                lineDone = true;
282628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org            }
283628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        }
284628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    }
285628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
286e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    if (startAdj != 0) {
287e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        srcPhase = 0;
288e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    }
289628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
290e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    // Change the dashing info from src space into device space
291e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    SkScalar devIntervals[2];
292e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    devIntervals[0] = info.fIntervals[0] * parallelScale;
293e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    devIntervals[1] = info.fIntervals[1] * parallelScale;
294e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    SkScalar devPhase = srcPhase * parallelScale;
295628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkScalar strokeWidth = srcStrokeWidth * perpScale;
296628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
297628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    if ((strokeWidth < 1.f && !useAA) || 0.f == strokeWidth) {
298628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        strokeWidth = 1.f;
299628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    }
300628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
301e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    SkScalar halfDevStroke = strokeWidth * 0.5f;
302628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
303628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    if (SkPaint::kSquare_Cap == cap && 0 != srcStrokeWidth) {
304628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        // add cap to on interveal and remove from off interval
305e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        devIntervals[0] += strokeWidth;
306e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        devIntervals[1] -= strokeWidth;
307628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    }
308e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    SkScalar startOffset = devIntervals[1] * 0.5f + devPhase;
309e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
310e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    SkScalar bloatX = useAA ? 0.5f / parallelScale : 0.f;
311e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    SkScalar bloatY = useAA ? 0.5f / perpScale : 0.f;
312e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
313e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    SkScalar devBloat = useAA ? 0.5f : 0.f;
314e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
315e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    GrDrawState* drawState = target->drawState();
316e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    if (devIntervals[1] <= 0.f && useAA) {
317e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        // Case when we end up drawing a solid AA rect
318e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        // Reset the start rect to draw this single solid rect
319e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        // but it requires to upload a new intervals uniform so we can mimic
320e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        // one giant dash
321e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        ptsRot[0].fX -= hasStartRect ? startAdj : 0;
322e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        ptsRot[1].fX += hasEndRect ? endAdj : 0;
323e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        startRect.set(ptsRot, 2);
324e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        startRect.outset(strokeAdj, halfSrcStroke);
325e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        hasStartRect = true;
326e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        hasEndRect = false;
327e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        lineDone = true;
328e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
329e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        SkPoint devicePts[2];
330e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        vm.mapPoints(devicePts, ptsRot, 2);
331e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        SkScalar lineLength = SkPoint::Distance(devicePts[0], devicePts[1]);
332e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        if (hasCap) {
333e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel            lineLength += 2.f * halfDevStroke;
334e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        }
335e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        devIntervals[0] = lineLength;
336e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    }
337e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    if (devIntervals[1] > 0.f || useAA) {
338e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        SkPathEffect::DashInfo devInfo;
339e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        devInfo.fPhase = devPhase;
340e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        devInfo.fCount = 2;
341e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        devInfo.fIntervals = devIntervals;
342628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        GrEffectEdgeType edgeType= useAA ? kFillAA_GrEffectEdgeType :
343628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org            kFillBW_GrEffectEdgeType;
344e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        drawState->addCoverageEffect(
345e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel            GrDashingEffect::Create(edgeType, devInfo, strokeWidth), 1)->unref();
346628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    }
347628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
348e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    // Set up the vertex data for the line and start/end dashes
349e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    drawState->setVertexAttribs<gDashLineVertexAttribs>(SK_ARRAY_COUNT(gDashLineVertexAttribs));
350e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
351e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    int totalRectCnt = 0;
352e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
353e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    totalRectCnt += !lineDone ? 1 : 0;
354e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    totalRectCnt += hasStartRect ? 1 : 0;
355e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    totalRectCnt += hasEndRect ? 1 : 0;
356e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
357e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    GrDrawTarget::AutoReleaseGeometry geo(target, totalRectCnt * 4, 0);
358e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    if (!geo.succeeded()) {
359e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        GrPrintf("Failed to get space for vertices!\n");
360e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        return false;
361628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    }
362628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
363e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    DashLineVertex* verts = reinterpret_cast<DashLineVertex*>(geo.vertices());
364e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
365e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    int curVIdx = 0;
366e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
367e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    // Draw interior part of dashed line
368e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    if (!lineDone) {
369e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        SkPoint devicePts[2];
370e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        vm.mapPoints(devicePts, ptsRot, 2);
371e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        SkScalar lineLength = SkPoint::Distance(devicePts[0], devicePts[1]);
372e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        if (hasCap) {
373e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel            lineLength += 2.f * halfDevStroke;
374e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        }
375e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
376e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        SkRect bounds;
377e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        bounds.set(ptsRot[0].fX, ptsRot[0].fY, ptsRot[1].fX, ptsRot[1].fY);
378e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        bounds.outset(bloatX + strokeAdj, bloatY + halfSrcStroke);
379e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        setup_dashed_rect(bounds, verts, curVIdx, combinedMatrix, startOffset, devBloat,
380e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel                          lineLength, halfDevStroke);
381e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        curVIdx += 4;
382e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    }
383e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
384e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    if (hasStartRect) {
385e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        SkASSERT(useAA);  // so that we know bloatX and bloatY have been set
386e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        startRect.outset(bloatX, bloatY);
387e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        setup_dashed_rect(startRect, verts, curVIdx, combinedMatrix, startOffset, devBloat,
388e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel                          devIntervals[0], halfDevStroke);
389e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        curVIdx += 4;
390e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    }
391e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
392e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    if (hasEndRect) {
393e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        SkASSERT(useAA);  // so that we know bloatX and bloatY have been set
394e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        endRect.outset(bloatX, bloatY);
395e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        setup_dashed_rect(endRect, verts, curVIdx, combinedMatrix, startOffset, devBloat,
396e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel                          devIntervals[0], halfDevStroke);
397e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    }
398e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
399e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    target->setIndexSourceToBuffer(gpu->getContext()->getQuadIndexBuffer());
400e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    target->drawIndexedInstances(kTriangles_GrPrimitiveType, totalRectCnt, 4, 6);
401e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    target->resetIndexSource();
402628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    return true;
403628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org}
404628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
405628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org//////////////////////////////////////////////////////////////////////////////
406628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
407628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.orgclass GLDashingLineEffect;
408628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
409e61c411c1258a323a010558c08de3d9f8d170dcaegdanielclass DashingLineEffect : public GrVertexEffect {
410628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.orgpublic:
411628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    typedef SkPathEffect::DashInfo DashInfo;
412628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
413628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    /**
414628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org     * The effect calculates the coverage for the case of a horizontal line in device space.
415628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org     * The matrix that is passed in should be able to convert a line in source space to a
416628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org     * horizontal line in device space. Additionally, the coord transform matrix should translate
417628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org     * the the start of line to origin, and the shift it along the positive x-axis by the phase
418628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org     * and half the off interval.
419628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org     */
420628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    static GrEffectRef* Create(GrEffectEdgeType edgeType, const DashInfo& info,
421e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel                               SkScalar strokeWidth);
422628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
423628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    virtual ~DashingLineEffect();
424628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
425628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    static const char* Name() { return "DashingEffect"; }
426628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
427628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    GrEffectEdgeType getEdgeType() const { return fEdgeType; }
428628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
429628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    const SkRect& getRect() const { return fRect; }
430628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
431628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkScalar getIntervalLength() const { return fIntervalLength; }
432628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
433628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    typedef GLDashingLineEffect GLEffect;
434628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
435628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
436628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
437628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
438628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
439628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.orgprivate:
440e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    DashingLineEffect(GrEffectEdgeType edgeType, const DashInfo& info, SkScalar strokeWidth);
441628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
442628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
443628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
444628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    GrEffectEdgeType    fEdgeType;
445628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkRect              fRect;
446628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkScalar            fIntervalLength;
447628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
448628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    GR_DECLARE_EFFECT_TEST;
449628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
450628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    typedef GrEffect INHERITED;
451628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org};
452628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
453628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org//////////////////////////////////////////////////////////////////////////////
454628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
455e61c411c1258a323a010558c08de3d9f8d170dcaegdanielclass GLDashingLineEffect : public GrGLVertexEffect {
456628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.orgpublic:
457628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    GLDashingLineEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
458628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
459e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    virtual void emitCode(GrGLFullShaderBuilder* builder,
460628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                          const GrDrawEffect& drawEffect,
461628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                          EffectKey key,
462628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                          const char* outputColor,
463628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                          const char* inputColor,
464628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                          const TransformedCoordsArray&,
465628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                          const TextureSamplerArray&) SK_OVERRIDE;
466628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
467628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
468628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
469628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
470628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
471628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.orgprivate:
472628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    GrGLUniformManager::UniformHandle   fRectUniform;
473628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    GrGLUniformManager::UniformHandle   fIntervalUniform;
474628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkRect                              fPrevRect;
475628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkScalar                            fPrevIntervalLength;
476e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    typedef GrGLVertexEffect INHERITED;
477628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org};
478628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
4793b9e8be760ad0e576d5145e0aecf0dc73efcd640skia.committer@gmail.comGLDashingLineEffect::GLDashingLineEffect(const GrBackendEffectFactory& factory,
480628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                                     const GrDrawEffect& drawEffect)
481628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    : INHERITED (factory) {
482628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    fPrevRect.fLeft = SK_ScalarNaN;
483628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    fPrevIntervalLength = SK_ScalarMax;
484628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
485628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org}
486628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
487e61c411c1258a323a010558c08de3d9f8d170dcaegdanielvoid GLDashingLineEffect::emitCode(GrGLFullShaderBuilder* builder,
488628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                                    const GrDrawEffect& drawEffect,
489628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                                    EffectKey key,
490628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                                    const char* outputColor,
491628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                                    const char* inputColor,
492e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel                                    const TransformedCoordsArray&,
493628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                                    const TextureSamplerArray& samplers) {
494628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    const DashingLineEffect& de = drawEffect.castEffect<DashingLineEffect>();
495628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    const char *rectName;
496628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5),
497628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    // respectively.
498628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    fRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
499628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                                       kVec4f_GrSLType,
500628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                                       "rect",
501628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                                       &rectName);
502628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    const char *intervalName;
503628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    // The interval uniform's refers to the total length of the interval (on + off)
504628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    fIntervalUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
505628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                                       kFloat_GrSLType,
506628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                                       "interval",
507628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                                       &intervalName);
508e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
509e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    const char *vsCoordName, *fsCoordName;
510e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    builder->addVarying(kVec2f_GrSLType, "Coord", &vsCoordName, &fsCoordName);
511e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    const SkString* attr0Name =
512e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
513e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    builder->vsCodeAppendf("\t%s = %s;\n", vsCoordName, attr0Name->c_str());
514e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
515628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    // transforms all points so that we can compare them to our test rect
516628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    builder->fsCodeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s) * %s;\n",
517e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel                           fsCoordName, fsCoordName, intervalName, intervalName);
518e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    builder->fsCodeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", fsCoordName);
519628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    if (GrEffectEdgeTypeIsAA(de.getEdgeType())) {
520628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        // The amount of coverage removed in x and y by the edges is computed as a pair of negative
521628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        // numbers, xSub and ySub.
522628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        builder->fsCodeAppend("\t\tfloat xSub, ySub;\n");
523628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        builder->fsCodeAppendf("\t\txSub = min(fragPosShifted.x - %s.x, 0.0);\n", rectName);
524628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        builder->fsCodeAppendf("\t\txSub += min(%s.z - fragPosShifted.x, 0.0);\n", rectName);
525628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        builder->fsCodeAppendf("\t\tySub = min(fragPosShifted.y - %s.y, 0.0);\n", rectName);
526628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        builder->fsCodeAppendf("\t\tySub += min(%s.w - fragPosShifted.y, 0.0);\n", rectName);
527628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        // Now compute coverage in x and y and multiply them to get the fraction of the pixel
528628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        // covered.
529628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        builder->fsCodeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n");
530628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    } else {
531628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        // Assuming the bounding geometry is tight so no need to check y values
532628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        builder->fsCodeAppendf("\t\tfloat alpha = 1.0;\n");
533628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        builder->fsCodeAppendf("\t\talpha *= (fragPosShifted.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName);
534628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        builder->fsCodeAppendf("\t\talpha *= (%s.z - fragPosShifted.x) >= -0.5 ? 1.0 : 0.0;\n", rectName);
535628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    }
536628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor,
537628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                           (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
538628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org}
539628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
540628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.orgvoid GLDashingLineEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) {
541628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    const DashingLineEffect& de = drawEffect.castEffect<DashingLineEffect>();
542628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    const SkRect& rect = de.getRect();
543628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkScalar intervalLength = de.getIntervalLength();
544628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    if (rect != fPrevRect || intervalLength != fPrevIntervalLength) {
545628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        uman.set4f(fRectUniform, rect.fLeft + 0.5f, rect.fTop + 0.5f,
546628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                   rect.fRight - 0.5f, rect.fBottom - 0.5f);
547628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        uman.set1f(fIntervalUniform, intervalLength);
548628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        fPrevRect = rect;
549628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        fPrevIntervalLength = intervalLength;
550628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    }
551628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org}
552628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
553628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.orgGrGLEffect::EffectKey GLDashingLineEffect::GenKey(const GrDrawEffect& drawEffect,
554628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                                                const GrGLCaps&) {
555628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    const DashingLineEffect& de = drawEffect.castEffect<DashingLineEffect>();
556628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    return de.getEdgeType();
557628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org}
558628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
559628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org//////////////////////////////////////////////////////////////////////////////
5603b9e8be760ad0e576d5145e0aecf0dc73efcd640skia.committer@gmail.com
561628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.orgGrEffectRef* DashingLineEffect::Create(GrEffectEdgeType edgeType, const DashInfo& info,
562e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel                                       SkScalar strokeWidth) {
563628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    if (info.fCount != 2) {
564628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org        return NULL;
565628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    }
566628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
567628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(DashingLineEffect,
568e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel                                                      (edgeType, info, strokeWidth))));
569628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org}
570628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
571628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.orgDashingLineEffect::~DashingLineEffect() {}
572628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
573628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.orgvoid DashingLineEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
574628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    *validFlags = 0;
575628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org}
576628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
577628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.orgconst GrBackendEffectFactory& DashingLineEffect::getFactory() const {
578628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    return GrTBackendEffectFactory<DashingLineEffect>::getInstance();
579628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org}
580628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
581628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.orgDashingLineEffect::DashingLineEffect(GrEffectEdgeType edgeType, const DashInfo& info,
582e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel                                     SkScalar strokeWidth)
583e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    : fEdgeType(edgeType) {
584628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkScalar onLen = info.fIntervals[0];
585628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkScalar offLen = info.fIntervals[1];
586628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkScalar halfOffLen = SkScalarHalf(offLen);
587628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkScalar halfStroke = SkScalarHalf(strokeWidth);
588628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    fIntervalLength = onLen + offLen;
589628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    fRect.set(halfOffLen, -halfStroke, halfOffLen + onLen, halfStroke);
590628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
591e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    this->addVertexAttrib(kVec2f_GrSLType);
592628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org}
593628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
594628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.orgbool DashingLineEffect::onIsEqual(const GrEffect& other) const {
595628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    const DashingLineEffect& de = CastEffect<DashingLineEffect>(other);
596628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    return (fEdgeType == de.fEdgeType &&
597628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org            fRect == de.fRect &&
598628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org            fIntervalLength == de.fIntervalLength);
599628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org}
600628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
601628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.orgGR_DEFINE_EFFECT_TEST(DashingLineEffect);
602628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
603628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.orgGrEffectRef* DashingLineEffect::TestCreate(SkRandom* random,
604628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                                         GrContext*,
605628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                                         const GrDrawTargetCaps& caps,
606628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org                                         GrTexture*[]) {
607628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    GrEffectRef* effect;
608628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    GrEffectEdgeType edgeType = static_cast<GrEffectEdgeType>(random->nextULessThan(
609628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org            kGrEffectEdgeTypeCnt));
610628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkScalar strokeWidth = random->nextRangeScalar(0, 100.f);
611628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    DashInfo info;
612628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    info.fCount = 2;
613628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    SkAutoTArray<SkScalar> intervals(info.fCount);
614628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    info.fIntervals = intervals.get();
615628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    info.fIntervals[0] = random->nextRangeScalar(0, 10.f);
616628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    info.fIntervals[1] = random->nextRangeScalar(0, 10.f);
617628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    info.fPhase = random->nextRangeScalar(0, info.fIntervals[0] + info.fIntervals[1]);
618628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
619e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    effect = DashingLineEffect::Create(edgeType, info, strokeWidth);
620628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org    return effect;
621628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org}
622628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
623628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org//////////////////////////////////////////////////////////////////////////////
624628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org
625628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.orgGrEffectRef* GrDashingEffect::Create(GrEffectEdgeType edgeType, const SkPathEffect::DashInfo& info,
626e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel                                     SkScalar strokeWidth) {
627e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    return DashingLineEffect::Create(edgeType, info, strokeWidth);
628628ed0b22045a9544b56e00e73137d6050ce900ccommit-bot@chromium.org}
629