| 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 |