188 args.fVaryingHandler->emitAttributes(shader);
190 args.fVertBuilder->defineConstant(
"float",
"PI",
"3.141592653589793238");
196 float maxEdges =
args.fShaderCaps->fVertexIDSupport ? FixedCountStrokes::kMaxEdges
197 : FixedCountStrokes::kMaxEdgesNoVertexIDs;
198 args.fVertBuilder->defineConstant(
"NUM_TOTAL_EDGES", maxEdges);
201 if (shader.hasDynamicStroke()) {
202 args.fVertBuilder->insertFunction(kNumRadialSegmentsPerRadianFn);
204 args.fVertBuilder->insertFunction(kRobustNormalizeDiffFn);
205 args.fVertBuilder->insertFunction(kCosineBetweenUnitVectorsFn);
206 args.fVertBuilder->insertFunction(kMiterExtentFn);
207 args.fVertBuilder->insertFunction(kUncheckedMixFn);
211 if (!shader.hasDynamicStroke()) {
213 const char* tessArgsName;
214 fTessControlArgsUniform =
args.fUniformHandler->addUniform(
217 args.fVertBuilder->codeAppendf(
218 "float NUM_RADIAL_SEGMENTS_PER_RADIAN = %s.x;"
219 "float JOIN_TYPE = %s.y;"
220 "float STROKE_RADIUS = %s.z;", tessArgsName, tessArgsName, tessArgsName);
225 SkASSERT(!shader.stroke().isHairlineStyle());
226 const char* maxScaleName;
227 fTessControlArgsUniform =
args.fUniformHandler->addUniform(
230 args.fVertBuilder->codeAppendf(
231 "float STROKE_RADIUS = dynamicStrokeAttr.x;"
232 "float JOIN_TYPE = dynamicStrokeAttr.y;"
233 "float NUM_RADIAL_SEGMENTS_PER_RADIAN = num_radial_segments_per_radian("
234 "%s * STROKE_RADIUS);", maxScaleName);
238 if (shader.hasDynamicColor()) {
241 args.fVaryingHandler->addVarying(
"dynamicColor", &dynamicColor);
242 args.fVertBuilder->codeAppendf(
"%s = dynamicColorAttr;", dynamicColor.vsOut());
243 fDynamicColorName = dynamicColor.fsIn();
247 const char* translateName, *affineMatrixName;
254 args.fVertBuilder->codeAppendf(
"float2x2 AFFINE_MATRIX = float2x2(%s.xy, %s.zw);\n",
255 affineMatrixName, affineMatrixName);
256 args.fVertBuilder->codeAppendf(
"float2 TRANSLATE = %s;\n", translateName);
258 if (shader.hasExplicitCurveType()) {
260 "bool is_conic_curve() { return curveTypeAttr != %g; }",
263 args.fVertBuilder->insertFunction(
264 "bool is_conic_curve() { return isinf(pts23Attr.w); }");
268 args.fVertBuilder->codeAppend(
269 "float2 p0=pts01Attr.xy, p1=pts01Attr.zw, p2=pts23Attr.xy, p3=pts23Attr.zw;"
270 "float2 lastControlPoint = argsAttr.xy;"
272 "if (is_conic_curve()) {"
282 args.fVertBuilder->codeAppend(
284 "float numParametricSegments;"
286 "if (p0 == p1 && p2 == p3) {"
287 "numParametricSegments = 1;"
289 "numParametricSegments = wangs_formula_cubic(PRECISION, p0, p1, p2, p3, AFFINE_MATRIX);"
292 "numParametricSegments = wangs_formula_conic(PRECISION,"
293 "AFFINE_MATRIX * p0,"
294 "AFFINE_MATRIX * p1,"
295 "AFFINE_MATRIX * p2, w);"
299 if (shader.stroke().isHairlineStyle()) {
302 args.fVertBuilder->codeAppend(
303 "p0 = AFFINE_MATRIX * p0;"
304 "p1 = AFFINE_MATRIX * p1;"
305 "p2 = AFFINE_MATRIX * p2;"
306 "p3 = AFFINE_MATRIX * p3;"
307 "lastControlPoint = AFFINE_MATRIX * lastControlPoint;"
311 args.fVertBuilder->codeAppend(
313 "float2 tan0 = robust_normalize_diff((p0 == p1) ? ((p1 == p2) ? p3 : p2) : p1, p0);"
314 "float2 tan1 = robust_normalize_diff(p3, (p3 == p2) ? ((p2 == p1) ? p0 : p1) : p2);"
315 "if (tan0 == float2(0)) {"
318 "tan0 = float2(1,0);"
319 "tan1 = float2(-1,0);"
323 if (
args.fShaderCaps->fVertexIDSupport) {
325 args.fVertBuilder->codeAppend(
326 "float edgeID = float(sk_VertexID >> 1);"
327 "if ((sk_VertexID & 1) != 0) {"
335 args.fVertBuilder->codeAppend(
340 "float2 prevTan = robust_normalize_diff(p0, lastControlPoint);"
341 "float joinRads = acos(cosine_between_unit_vectors(prevTan, tan0));"
342 "float numRadialSegmentsInJoin = max(ceil(joinRads * NUM_RADIAL_SEGMENTS_PER_RADIAN), 1);"
344 "float numEdgesInJoin = numRadialSegmentsInJoin + 2;"
348 "numEdgesInJoin = min(numEdgesInJoin, NUM_TOTAL_EDGES - 2);");
349 if (shader.hasDynamicStroke()) {
350 args.fVertBuilder->codeAppend(
351 "if (JOIN_TYPE >= 0) {"
354 "numEdgesInJoin = sign(JOIN_TYPE) + 1 + 2;"
358 args.fVertBuilder->codeAppendf(
"float numEdgesInJoin = %i;",
362 args.fVertBuilder->codeAppend(
366 "float turn = cross_length_2d(p2 - p0, p3 - p1);"
367 "float combinedEdgeID = abs(edgeID) - numEdgesInJoin;"
368 "if (combinedEdgeID < 0) {"
373 "if (lastControlPoint != p0) {"
374 "tan0 = robust_normalize_diff(p0, lastControlPoint);"
376 "turn = cross_length_2d(tan0, tan1);"
380 "float cosTheta = cosine_between_unit_vectors(tan0, tan1);"
381 "float rotation = acos(cosTheta);"
384 "rotation = -rotation;"
387 "float numRadialSegments;"
388 "float strokeOutset = sign(edgeID);"
389 "if (combinedEdgeID < 0) {"
392 "numRadialSegments = numEdgesInJoin - 2;"
393 "numParametricSegments = 1;"
398 "combinedEdgeID += numRadialSegments + 1;"
403 " float sinEpsilon = 1e-2;"
404 "bool tangentsNearlyParallel ="
405 "(abs(turn) * inversesqrt(dot(tan0, tan0) * dot(tan1, tan1))) < sinEpsilon;"
406 "if (!tangentsNearlyParallel || dot(tan0, tan1) < 0) {"
410 "if (combinedEdgeID >= 0) {"
411 "strokeOutset = (turn < 0) ? min(strokeOutset, 0) : max(strokeOutset, 0);"
414 "combinedEdgeID = max(combinedEdgeID, 0);"
419 "float maxCombinedSegments = NUM_TOTAL_EDGES - numEdgesInJoin - 1;"
420 "numRadialSegments = max(ceil(abs(rotation) * NUM_RADIAL_SEGMENTS_PER_RADIAN), 1);"
421 "numRadialSegments = min(numRadialSegments, maxCombinedSegments);"
422 "numParametricSegments = min(numParametricSegments,"
423 "maxCombinedSegments - numRadialSegments + 1);"
427 "float radsPerSegment = rotation / numRadialSegments;"
428 "float numCombinedSegments = numParametricSegments + numRadialSegments - 1;"
429 "bool isFinalEdge = (combinedEdgeID >= numCombinedSegments);"
430 "if (combinedEdgeID > numCombinedSegments) {"
435 args.fVertBuilder->codeAppendf(
437 "if (abs(edgeID) == 2 && %s) {"
438 "strokeOutset *= miter_extent(cosTheta, JOIN_TYPE);"
439 "}", shader.hasDynamicStroke() ?
"JOIN_TYPE > 0" :
"true");
442 this->emitTessellationCode(shader, &
args.fVertBuilder->code(), gpArgs, *
args.fShaderCaps);
444 this->emitFragmentCode(shader,
args);
673 pdman.
set3f(fTessControlArgsUniform,
674 numRadialSegmentsPerRadian,
679 pdman.
set1f(fTessControlArgsUniform, maxScale);
684 pdman.
set2f(fTranslateUniform, m.getTranslateX(), m.getTranslateY());
685 pdman.
set4f(fAffineMatrixUniform, m.getScaleX(), m.getSkewY(), m.getSkewX(),