OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 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 "GrAAHairLinePathRenderer.h" | 8 #include "GrAAHairLinePathRenderer.h" |
9 | 9 |
10 #include "GrContext.h" | 10 #include "GrContext.h" |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 if (dsqd <= SkScalarMul(gSubdivTol, gSubdivTol)) { | 295 if (dsqd <= SkScalarMul(gSubdivTol, gSubdivTol)) { |
296 return 0; | 296 return 0; |
297 } else { | 297 } else { |
298 static const int kMaxSub = 4; | 298 static const int kMaxSub = 4; |
299 // subdividing the quad reduces d by 4. so we want x = log4(d/tol) | 299 // subdividing the quad reduces d by 4. so we want x = log4(d/tol) |
300 // = log4(d*d/tol*tol)/2 | 300 // = log4(d*d/tol*tol)/2 |
301 // = log2(d*d/tol*tol) | 301 // = log2(d*d/tol*tol) |
302 | 302 |
303 // +1 since we're ignoring the mantissa contribution. | 303 // +1 since we're ignoring the mantissa contribution. |
304 int log = get_float_exp(dsqd/(gSubdivTol*gSubdivTol)) + 1; | 304 int log = get_float_exp(dsqd/(gSubdivTol*gSubdivTol)) + 1; |
305 log = GrMin(GrMax(0, log), kMaxSub); | 305 log = SkTMin(SkTMax(0, log), kMaxSub); |
306 return log; | 306 return log; |
307 } | 307 } |
308 } | 308 } |
309 | 309 |
310 /** | 310 /** |
311 * Generates the lines and quads to be rendered. Lines are always recorded in | 311 * Generates the lines and quads to be rendered. Lines are always recorded in |
312 * device space. We will do a device space bloat to account for the 1pixel | 312 * device space. We will do a device space bloat to account for the 1pixel |
313 * thickness. | 313 * thickness. |
314 * Quads are recorded in device space unless m contains | 314 * Quads are recorded in device space unless m contains |
315 * perspective, then in they are in src space. We do this because we will | 315 * perspective, then in they are in src space. We do this because we will |
(...skipping 10 matching lines...) Expand all Loading... |
326 GrAAHairLinePathRenderer::FloatArray* conicWeights)
{ | 326 GrAAHairLinePathRenderer::FloatArray* conicWeights)
{ |
327 SkPath::Iter iter(path, false); | 327 SkPath::Iter iter(path, false); |
328 | 328 |
329 int totalQuadCount = 0; | 329 int totalQuadCount = 0; |
330 SkRect bounds; | 330 SkRect bounds; |
331 SkIRect ibounds; | 331 SkIRect ibounds; |
332 | 332 |
333 bool persp = m.hasPerspective(); | 333 bool persp = m.hasPerspective(); |
334 | 334 |
335 for (;;) { | 335 for (;;) { |
336 GrPoint pathPts[4]; | 336 SkPoint pathPts[4]; |
337 GrPoint devPts[4]; | 337 SkPoint devPts[4]; |
338 SkPath::Verb verb = iter.next(pathPts); | 338 SkPath::Verb verb = iter.next(pathPts); |
339 switch (verb) { | 339 switch (verb) { |
340 case SkPath::kConic_Verb: { | 340 case SkPath::kConic_Verb: { |
341 SkConic dst[4]; | 341 SkConic dst[4]; |
342 // We chop the conics to create tighter clipping to hide error | 342 // We chop the conics to create tighter clipping to hide error |
343 // that appears near max curvature of very thin conics. Thin | 343 // that appears near max curvature of very thin conics. Thin |
344 // hyperbolas with high weight still show error. | 344 // hyperbolas with high weight still show error. |
345 int conicCnt = chop_conic(pathPts, dst, iter.conicWeight()); | 345 int conicCnt = chop_conic(pathPts, dst, iter.conicWeight()); |
346 for (int i = 0; i < conicCnt; ++i) { | 346 for (int i = 0; i < conicCnt; ++i) { |
347 SkPoint* chopPnts = dst[i].fPts; | 347 SkPoint* chopPnts = dst[i].fPts; |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
479 break; | 479 break; |
480 case SkPath::kClose_Verb: | 480 case SkPath::kClose_Verb: |
481 break; | 481 break; |
482 case SkPath::kDone_Verb: | 482 case SkPath::kDone_Verb: |
483 return totalQuadCount; | 483 return totalQuadCount; |
484 } | 484 } |
485 } | 485 } |
486 } | 486 } |
487 | 487 |
488 struct LineVertex { | 488 struct LineVertex { |
489 GrPoint fPos; | 489 SkPoint fPos; |
490 GrColor fCoverage; | 490 GrColor fCoverage; |
491 }; | 491 }; |
492 | 492 |
493 struct BezierVertex { | 493 struct BezierVertex { |
494 GrPoint fPos; | 494 SkPoint fPos; |
495 union { | 495 union { |
496 struct { | 496 struct { |
497 SkScalar fK; | 497 SkScalar fK; |
498 SkScalar fL; | 498 SkScalar fL; |
499 SkScalar fM; | 499 SkScalar fM; |
500 } fConic; | 500 } fConic; |
501 GrVec fQuadCoord; | 501 SkVector fQuadCoord; |
502 struct { | 502 struct { |
503 SkScalar fBogus[4]; | 503 SkScalar fBogus[4]; |
504 }; | 504 }; |
505 }; | 505 }; |
506 }; | 506 }; |
507 | 507 |
508 GR_STATIC_ASSERT(sizeof(BezierVertex) == 3 * sizeof(GrPoint)); | 508 GR_STATIC_ASSERT(sizeof(BezierVertex) == 3 * sizeof(SkPoint)); |
509 | 509 |
510 void intersect_lines(const SkPoint& ptA, const SkVector& normA, | 510 void intersect_lines(const SkPoint& ptA, const SkVector& normA, |
511 const SkPoint& ptB, const SkVector& normB, | 511 const SkPoint& ptB, const SkVector& normB, |
512 SkPoint* result) { | 512 SkPoint* result) { |
513 | 513 |
514 SkScalar lineAW = -normA.dot(ptA); | 514 SkScalar lineAW = -normA.dot(ptA); |
515 SkScalar lineBW = -normB.dot(ptB); | 515 SkScalar lineBW = -normB.dot(ptB); |
516 | 516 |
517 SkScalar wInv = SkScalarMul(normA.fX, normB.fY) - | 517 SkScalar wInv = SkScalarMul(normA.fX, normB.fY) - |
518 SkScalarMul(normA.fY, normB.fX); | 518 SkScalarMul(normA.fY, normB.fX); |
519 wInv = SkScalarInvert(wInv); | 519 wInv = SkScalarInvert(wInv); |
520 | 520 |
521 result->fX = SkScalarMul(normA.fY, lineBW) - SkScalarMul(lineAW, normB.fY); | 521 result->fX = SkScalarMul(normA.fY, lineBW) - SkScalarMul(lineAW, normB.fY); |
522 result->fX = SkScalarMul(result->fX, wInv); | 522 result->fX = SkScalarMul(result->fX, wInv); |
523 | 523 |
524 result->fY = SkScalarMul(lineAW, normB.fX) - SkScalarMul(normA.fX, lineBW); | 524 result->fY = SkScalarMul(lineAW, normB.fX) - SkScalarMul(normA.fX, lineBW); |
525 result->fY = SkScalarMul(result->fY, wInv); | 525 result->fY = SkScalarMul(result->fY, wInv); |
526 } | 526 } |
527 | 527 |
528 void set_uv_quad(const SkPoint qpts[3], BezierVertex verts[kVertsPerQuad]) { | 528 void set_uv_quad(const SkPoint qpts[3], BezierVertex verts[kVertsPerQuad]) { |
529 // this should be in the src space, not dev coords, when we have perspective | 529 // this should be in the src space, not dev coords, when we have perspective |
530 GrPathUtils::QuadUVMatrix DevToUV(qpts); | 530 GrPathUtils::QuadUVMatrix DevToUV(qpts); |
531 DevToUV.apply<kVertsPerQuad, sizeof(BezierVertex), sizeof(GrPoint)>(verts); | 531 DevToUV.apply<kVertsPerQuad, sizeof(BezierVertex), sizeof(SkPoint)>(verts); |
532 } | 532 } |
533 | 533 |
534 void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice, | 534 void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice, |
535 const SkMatrix* toSrc, BezierVertex verts[kVertsPerQuad], | 535 const SkMatrix* toSrc, BezierVertex verts[kVertsPerQuad], |
536 SkRect* devBounds) { | 536 SkRect* devBounds) { |
537 SkASSERT(!toDevice == !toSrc); | 537 SkASSERT(!toDevice == !toSrc); |
538 // original quad is specified by tri a,b,c | 538 // original quad is specified by tri a,b,c |
539 SkPoint a = qpts[0]; | 539 SkPoint a = qpts[0]; |
540 SkPoint b = qpts[1]; | 540 SkPoint b = qpts[1]; |
541 SkPoint c = qpts[2]; | 541 SkPoint c = qpts[2]; |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
701 | 701 |
702 } | 702 } |
703 | 703 |
704 /////////////////////////////////////////////////////////////////////////////// | 704 /////////////////////////////////////////////////////////////////////////////// |
705 | 705 |
706 namespace { | 706 namespace { |
707 | 707 |
708 // position + edge | 708 // position + edge |
709 extern const GrVertexAttrib gHairlineBezierAttribs[] = { | 709 extern const GrVertexAttrib gHairlineBezierAttribs[] = { |
710 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBind
ing}, | 710 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBind
ing}, |
711 {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBindin
g} | 711 {kVec4f_GrVertexAttribType, sizeof(SkPoint), kEffect_GrVertexAttribBindin
g} |
712 }; | 712 }; |
713 | 713 |
714 // position + coverage | 714 // position + coverage |
715 extern const GrVertexAttrib gHairlineLineAttribs[] = { | 715 extern const GrVertexAttrib gHairlineLineAttribs[] = { |
716 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBindin
g}, | 716 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBindin
g}, |
717 {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kCoverage_GrVertexAttribBindin
g}, | 717 {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kCoverage_GrVertexAttribBindin
g}, |
718 }; | 718 }; |
719 | 719 |
720 }; | 720 }; |
721 | 721 |
722 bool GrAAHairLinePathRenderer::createLineGeom(const SkPath& path, | 722 bool GrAAHairLinePathRenderer::createLineGeom(const SkPath& path, |
723 GrDrawTarget* target, | 723 GrDrawTarget* target, |
724 const PtArray& lines, | 724 const PtArray& lines, |
725 int lineCnt, | 725 int lineCnt, |
726 GrDrawTarget::AutoReleaseGeometry*
arg, | 726 GrDrawTarget::AutoReleaseGeometry*
arg, |
727 SkRect* devBounds) { | 727 SkRect* devBounds) { |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
942 | 942 |
943 // Check devBounds | 943 // Check devBounds |
944 SkASSERT(check_bounds<LineVertex>(drawState, devBounds, arg.vertices(), | 944 SkASSERT(check_bounds<LineVertex>(drawState, devBounds, arg.vertices(), |
945 kVertsPerLineSeg * lineCnt)); | 945 kVertsPerLineSeg * lineCnt)); |
946 | 946 |
947 { | 947 { |
948 GrDrawState::AutoRestoreEffects are(drawState); | 948 GrDrawState::AutoRestoreEffects are(drawState); |
949 target->setIndexSourceToBuffer(fLinesIndexBuffer); | 949 target->setIndexSourceToBuffer(fLinesIndexBuffer); |
950 int lines = 0; | 950 int lines = 0; |
951 while (lines < lineCnt) { | 951 while (lines < lineCnt) { |
952 int n = GrMin(lineCnt - lines, kNumLineSegsInIdxBuffer); | 952 int n = SkTMin(lineCnt - lines, kNumLineSegsInIdxBuffer); |
953 target->drawIndexed(kTriangles_GrPrimitiveType, | 953 target->drawIndexed(kTriangles_GrPrimitiveType, |
954 kVertsPerLineSeg*lines, // startV | 954 kVertsPerLineSeg*lines, // startV |
955 0, // startI | 955 0, // startI |
956 kVertsPerLineSeg*n, // vCount | 956 kVertsPerLineSeg*n, // vCount |
957 kIdxsPerLineSeg*n, // iCount | 957 kIdxsPerLineSeg*n, // iCount |
958 &devBounds); | 958 &devBounds); |
959 lines += n; | 959 lines += n; |
960 } | 960 } |
961 } | 961 } |
962 } | 962 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
998 | 998 |
999 if (quadCnt > 0) { | 999 if (quadCnt > 0) { |
1000 GrEffectRef* hairQuadEffect = GrQuadEffect::Create(kHairlineAA_GrEff
ectEdgeType, | 1000 GrEffectRef* hairQuadEffect = GrQuadEffect::Create(kHairlineAA_GrEff
ectEdgeType, |
1001 *target->caps()); | 1001 *target->caps()); |
1002 SkASSERT(NULL != hairQuadEffect); | 1002 SkASSERT(NULL != hairQuadEffect); |
1003 GrDrawState::AutoRestoreEffects are(drawState); | 1003 GrDrawState::AutoRestoreEffects are(drawState); |
1004 target->setIndexSourceToBuffer(fQuadsIndexBuffer); | 1004 target->setIndexSourceToBuffer(fQuadsIndexBuffer); |
1005 drawState->addCoverageEffect(hairQuadEffect, kEdgeAttrIndex)->unref(
); | 1005 drawState->addCoverageEffect(hairQuadEffect, kEdgeAttrIndex)->unref(
); |
1006 int quads = 0; | 1006 int quads = 0; |
1007 while (quads < quadCnt) { | 1007 while (quads < quadCnt) { |
1008 int n = GrMin(quadCnt - quads, kNumQuadsInIdxBuffer); | 1008 int n = SkTMin(quadCnt - quads, kNumQuadsInIdxBuffer); |
1009 target->drawIndexed(kTriangles_GrPrimitiveType, | 1009 target->drawIndexed(kTriangles_GrPrimitiveType, |
1010 kVertsPerQuad*quads, // startV | 1010 kVertsPerQuad*quads, // startV |
1011 0, // startI | 1011 0, // startI |
1012 kVertsPerQuad*n, // vCount | 1012 kVertsPerQuad*n, // vCount |
1013 kIdxsPerQuad*n, // iCount | 1013 kIdxsPerQuad*n, // iCount |
1014 &devBounds); | 1014 &devBounds); |
1015 quads += n; | 1015 quads += n; |
1016 } | 1016 } |
1017 } | 1017 } |
1018 | 1018 |
1019 if (conicCnt > 0) { | 1019 if (conicCnt > 0) { |
1020 GrDrawState::AutoRestoreEffects are(drawState); | 1020 GrDrawState::AutoRestoreEffects are(drawState); |
1021 GrEffectRef* hairConicEffect = GrConicEffect::Create(kHairlineAA_GrE
ffectEdgeType, | 1021 GrEffectRef* hairConicEffect = GrConicEffect::Create(kHairlineAA_GrE
ffectEdgeType, |
1022 *target->caps()
); | 1022 *target->caps()
); |
1023 SkASSERT(NULL != hairConicEffect); | 1023 SkASSERT(NULL != hairConicEffect); |
1024 drawState->addCoverageEffect(hairConicEffect, 1, 2)->unref(); | 1024 drawState->addCoverageEffect(hairConicEffect, 1, 2)->unref(); |
1025 int conics = 0; | 1025 int conics = 0; |
1026 while (conics < conicCnt) { | 1026 while (conics < conicCnt) { |
1027 int n = GrMin(conicCnt - conics, kNumQuadsInIdxBuffer); | 1027 int n = SkTMin(conicCnt - conics, kNumQuadsInIdxBuffer); |
1028 target->drawIndexed(kTriangles_GrPrimitiveType, | 1028 target->drawIndexed(kTriangles_GrPrimitiveType, |
1029 kVertsPerQuad*(quadCnt + conics), // startV | 1029 kVertsPerQuad*(quadCnt + conics), // startV |
1030 0, // startI | 1030 0, // startI |
1031 kVertsPerQuad*n, // vCount | 1031 kVertsPerQuad*n, // vCount |
1032 kIdxsPerQuad*n, // iCount | 1032 kIdxsPerQuad*n, // iCount |
1033 &devBounds); | 1033 &devBounds); |
1034 conics += n; | 1034 conics += n; |
1035 } | 1035 } |
1036 } | 1036 } |
1037 } | 1037 } |
1038 | 1038 |
1039 target->resetIndexSource(); | 1039 target->resetIndexSource(); |
1040 | 1040 |
1041 return true; | 1041 return true; |
1042 } | 1042 } |
OLD | NEW |