Chromium Code Reviews| 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 "SkGpuDevice.h" | 8 #include "SkGpuDevice.h" |
| 9 | 9 |
| 10 #include "effects/GrBicubicEffect.h" | 10 #include "effects/GrBicubicEffect.h" |
| 11 #include "effects/GrDashingEffect.h" | |
| 11 #include "effects/GrTextureDomain.h" | 12 #include "effects/GrTextureDomain.h" |
| 12 #include "effects/GrSimpleTextureEffect.h" | 13 #include "effects/GrSimpleTextureEffect.h" |
| 13 | 14 |
| 14 #include "GrContext.h" | 15 #include "GrContext.h" |
| 15 #include "GrBitmapTextContext.h" | 16 #include "GrBitmapTextContext.h" |
| 16 #include "GrDistanceFieldTextContext.h" | 17 #include "GrDistanceFieldTextContext.h" |
| 17 #include "GrLayerCache.h" | 18 #include "GrLayerCache.h" |
| 18 #include "GrPictureUtils.h" | 19 #include "GrPictureUtils.h" |
| 19 | 20 |
| 20 #include "SkGrTexturePixelRef.h" | 21 #include "SkGrTexturePixelRef.h" |
| (...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 528 void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, | 529 void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, |
| 529 size_t count, const SkPoint pts[], const SkPaint& p aint) { | 530 size_t count, const SkPoint pts[], const SkPaint& p aint) { |
| 530 CHECK_FOR_ANNOTATION(paint); | 531 CHECK_FOR_ANNOTATION(paint); |
| 531 CHECK_SHOULD_DRAW(draw, false); | 532 CHECK_SHOULD_DRAW(draw, false); |
| 532 | 533 |
| 533 SkScalar width = paint.getStrokeWidth(); | 534 SkScalar width = paint.getStrokeWidth(); |
| 534 if (width < 0) { | 535 if (width < 0) { |
| 535 return; | 536 return; |
| 536 } | 537 } |
| 537 | 538 |
| 539 if (paint.getPathEffect() && 2 == count && SkCanvas::kLines_PointMode == mod e) { | |
| 540 if (this->drawDashLine(pts, paint)) { | |
| 541 return; | |
| 542 } | |
| 543 } | |
| 544 | |
| 538 // we only handle hairlines and paints without path effects or mask filters, | 545 // we only handle hairlines and paints without path effects or mask filters, |
| 539 // else we let the SkDraw call our drawPath() | 546 // else we let the SkDraw call our drawPath() |
| 540 if (width > 0 || paint.getPathEffect() || paint.getMaskFilter()) { | 547 if (width > 0 || paint.getPathEffect() || paint.getMaskFilter()) { |
| 541 draw.drawPoints(mode, count, pts, paint, true); | 548 draw.drawPoints(mode, count, pts, paint, true); |
| 542 return; | 549 return; |
| 543 } | 550 } |
| 544 | 551 |
| 545 GrPaint grPaint; | 552 GrPaint grPaint; |
| 546 if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) { | 553 if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) { |
| 547 return; | 554 return; |
| 548 } | 555 } |
| 549 | 556 |
| 550 fContext->drawVertices(grPaint, | 557 fContext->drawVertices(grPaint, |
| 551 gPointMode2PrimtiveType[mode], | 558 gPointMode2PrimtiveType[mode], |
| 552 SkToS32(count), | 559 SkToS32(count), |
| 553 (SkPoint*)pts, | 560 (SkPoint*)pts, |
| 554 NULL, | 561 NULL, |
| 555 NULL, | 562 NULL, |
| 556 NULL, | 563 NULL, |
| 557 0); | 564 0); |
| 558 } | 565 } |
| 559 | 566 |
| 560 /////////////////////////////////////////////////////////////////////////////// | 567 /////////////////////////////////////////////////////////////////////////////// |
| 561 | 568 |
| 569 static void calc_dash_scaling(SkScalar* parallelScale, SkScalar* perpScale, | |
| 570 const SkMatrix& viewMatrix, const SkPoint pts[2]) { | |
| 571 SkVector vecSrc = pts[1] - pts[0]; | |
| 572 SkScalar magSrc = vecSrc.length(); | |
| 573 SkScalar invSrc = magSrc ? SkScalarInvert(magSrc) : 0; | |
| 574 vecSrc.scale(invSrc); | |
| 575 | |
| 576 SkVector vecSrcPerp; | |
| 577 vecSrc.rotateCW(&vecSrcPerp); | |
| 578 viewMatrix.mapVectors(&vecSrc, 1); | |
| 579 viewMatrix.mapVectors(&vecSrcPerp, 1); | |
| 580 | |
| 581 // parallelScale tells how much to scale along the line parallel to the dash line | |
| 582 // perpScale tells how much to scale in the direction perpendicular to the d ash line | |
| 583 *parallelScale = vecSrc.length(); | |
| 584 *perpScale = vecSrcPerp.length(); | |
| 585 } | |
| 586 | |
| 587 // calculates the rotation needed to aligned pts to the x axis with pts[0] < pts [1] | |
| 588 // Stores the rotation matrix in rotMatrix, and the mapped points in ptsRot | |
| 589 static void align_to_x_axis(const SkPoint pts[2], SkMatrix* rotMatrix, SkPoint p tsRot[2] = NULL) { | |
| 590 SkVector vec = pts[1] - pts[0]; | |
| 591 SkScalar mag = vec.length(); | |
| 592 SkScalar inv = mag ? SkScalarInvert(mag) : 0; | |
| 593 | |
| 594 vec.scale(inv); | |
| 595 rotMatrix->setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY); | |
| 596 if (ptsRot) { | |
| 597 rotMatrix->mapPoints(ptsRot, pts, 2); | |
| 598 // correction for numerical issues if map doesn't make ptsRot exactly ho rizontal | |
| 599 ptsRot[1].fY = pts[0].fY; | |
| 600 } | |
| 601 } | |
| 602 | |
| 603 | |
| 604 // Assumes phase < sum of all intervals | |
| 605 static SkScalar calc_start_adjustment(const SkPathEffect::DashInfo& info) { | |
| 606 SkASSERT(info.fPhase < info.fIntervals[0] + info.fIntervals[1]); | |
| 607 if (info.fPhase >= info.fIntervals[0] && info.fPhase != 0) { | |
| 608 SkScalar srcIntervalLen = info.fIntervals[0] + info.fIntervals[1]; | |
| 609 return srcIntervalLen - info.fPhase; | |
| 610 } | |
| 611 return 0; | |
| 612 } | |
| 613 | |
| 614 static SkScalar calc_end_adjustment(const SkPathEffect::DashInfo& info, const Sk Point pts[2], SkScalar* endingInt) { | |
| 615 if (pts[1].fX <= pts[0].fX) { | |
| 616 return 0; | |
| 617 } | |
| 618 SkScalar srcIntervalLen = info.fIntervals[0] + info.fIntervals[1]; | |
| 619 SkScalar totalLen = pts[1].fX - pts[0].fX; | |
| 620 SkScalar temp = SkScalarDiv(totalLen, srcIntervalLen); | |
| 621 SkScalar numFullIntervals = SkScalarFloorToScalar(temp); | |
| 622 *endingInt = totalLen - numFullIntervals * srcIntervalLen + info.fPhase; | |
| 623 temp = SkScalarDiv(*endingInt, srcIntervalLen); | |
| 624 *endingInt = *endingInt - SkScalarFloorToScalar(temp) * srcIntervalLen; | |
| 625 if (0 == *endingInt) { | |
| 626 *endingInt = srcIntervalLen; | |
| 627 } | |
| 628 if (*endingInt > info.fIntervals[0]) { | |
| 629 if (0 == info.fIntervals[0]) { | |
| 630 *endingInt -= 0.01; // make sure we capture the last zero size pnt ( used if has caps) | |
| 631 } | |
| 632 return *endingInt - info.fIntervals[0]; | |
| 633 } | |
| 634 return 0; | |
| 635 } | |
| 636 | |
| 637 | |
|
bsalomon
2014/05/13 09:10:33
This file has gotten huge. It seems like the only
egdaniel
2014/05/13 14:00:11
Agree completely. Will move it out.
On 2014/05/13
| |
| 638 bool SkGpuDevice::drawDashLine(const SkPoint pts[2], const SkPaint& paint) { | |
|
bsalomon
2014/05/13 09:10:33
I think this function needs to check if the target
egdaniel
2014/05/13 14:00:11
is that not what the check below this comment is d
bsalomon
2014/05/13 14:14:36
dOn 2014/05/13 14:00:11, egdaniel wrote:
| |
| 639 if (fContext->getRenderTarget()->isMultisampled()) { | |
| 640 return false; | |
| 641 } | |
| 642 | |
| 643 const SkMatrix& viewMatrix = fContext->getMatrix(); | |
| 644 if (!viewMatrix.preservesRightAngles()) { | |
| 645 return false; | |
| 646 } | |
| 647 | |
| 648 const SkPathEffect* pe = paint.getPathEffect(); | |
| 649 SkPathEffect::DashInfo info; | |
| 650 SkPathEffect::DashType dashType = pe->asADash(&info); | |
| 651 // Must be a dash effect with 2 intervals (1 on and 1 off) | |
| 652 if (SkPathEffect::kDash_DashType != dashType || 2 != info.fCount) { | |
| 653 return false; | |
| 654 } | |
| 655 | |
| 656 SkPaint::Cap cap = paint.getStrokeCap(); | |
| 657 // Current we do don't handle Round or Square cap dashes | |
| 658 if (SkPaint::kRound_Cap == cap) { | |
| 659 return false; | |
| 660 } | |
| 661 | |
| 662 SkScalar srcStrokeWidth = paint.getStrokeWidth(); | |
| 663 | |
| 664 // Get all info about the dash effect | |
| 665 SkAutoTArray<SkScalar> intervals(info.fCount); | |
| 666 info.fIntervals = intervals.get(); | |
| 667 pe->asADash(&info); | |
| 668 | |
| 669 // the phase should be normalized to be [0, sum of all intervals) | |
| 670 SkASSERT(info.fPhase >= 0 && info.fPhase < info.fIntervals[0] + info.fInterv als[1]); | |
| 671 | |
| 672 SkMatrix coordTrans; | |
| 673 | |
| 674 // Rotate the src pts so they are aligned horizontally with pts[0].fX < pts[ 1].fX | |
| 675 SkMatrix srcRotInv; | |
| 676 SkPoint ptsRot[2]; | |
| 677 if (pts[0].fY != pts[1].fY || pts[0].fX > pts[1].fX) { | |
| 678 align_to_x_axis(pts, &coordTrans, ptsRot); | |
| 679 if(!coordTrans.invert(&srcRotInv)) { | |
| 680 return false; | |
| 681 } | |
| 682 } else { | |
| 683 coordTrans.reset(); | |
| 684 srcRotInv.reset(); | |
| 685 memcpy(ptsRot, pts, 2 * sizeof(SkPoint)); | |
| 686 } | |
| 687 | |
| 688 GrPaint grPaint; | |
| 689 if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) { | |
| 690 return false; | |
| 691 } | |
| 692 | |
| 693 bool useAA = paint.isAntiAlias(); | |
| 694 | |
| 695 // Scale corrections of intervals and stroke from view matrix | |
| 696 SkScalar parallelScale; | |
| 697 SkScalar perpScale; | |
| 698 calc_dash_scaling(¶llelScale, &perpScale, viewMatrix, ptsRot); | |
| 699 | |
| 700 bool hasCap =SkPaint::kSquare_Cap == cap && 0 != srcStrokeWidth; | |
|
bsalomon
2014/05/13 09:10:33
space after =
| |
| 701 | |
| 702 // We always want to at least stroke out half a pixel on each side in device space | |
| 703 // so 0.5f / perpScale gives us this min in src space | |
| 704 SkScalar halfStroke = SkMaxScalar(srcStrokeWidth * 0.5f, 0.5f / perpScale); | |
| 705 | |
| 706 SkScalar xStroke; | |
| 707 if (!hasCap) { | |
| 708 xStroke = 0.f; | |
| 709 } else { | |
| 710 xStroke = halfStroke; | |
| 711 } | |
| 712 | |
| 713 // If we are using AA, check to see if we are drawing a partial dash at the start. If so | |
| 714 // draw it separately here and adjust our start point accordingly | |
| 715 if (useAA) { | |
| 716 if (info.fPhase > 0 && info.fPhase < info.fIntervals[0]) { | |
| 717 SkPoint startPts[2]; | |
| 718 startPts[0] = ptsRot[0]; | |
| 719 startPts[1].fY = startPts[0].fY; | |
| 720 startPts[1].fX = SkMinScalar(startPts[0].fX + info.fIntervals[0] - i nfo.fPhase, | |
| 721 ptsRot[1].fX); | |
| 722 SkRect startRect; | |
| 723 startRect.set(startPts, 2); | |
| 724 startRect.outset(xStroke, halfStroke); | |
| 725 fContext->drawRect(grPaint, startRect, NULL, &srcRotInv); | |
| 726 | |
| 727 ptsRot[0].fX += info.fIntervals[0] + info.fIntervals[1] - info.fPhas e; | |
| 728 info.fPhase = 0; | |
| 729 } | |
| 730 } | |
| 731 | |
| 732 // adjustments for start and end of bounding rect so we only draw dash inter vals | |
| 733 // contained in the original line segment. | |
| 734 SkScalar startAdj = calc_start_adjustment(info); | |
| 735 SkScalar endingInterval = 0; | |
| 736 SkScalar endAdj = calc_end_adjustment(info, ptsRot, &endingInterval); | |
| 737 if (ptsRot[0].fX + startAdj >= ptsRot[1].fX - endAdj) { | |
| 738 // Nothing left to draw so just return | |
| 739 return true; | |
| 740 } | |
| 741 | |
| 742 // If we are using AA, check to see if we are drawing a partial dash at then end. If so | |
| 743 // draw it separately here and adjust our end point accordingly | |
| 744 if (useAA) { | |
| 745 // If we adjusted the end then we will not be drawing a partial dash at the end. | |
| 746 // If we didn't adjust the end point then we just need to make sure the ending | |
| 747 // dash isn't a full dash | |
| 748 if (0 == endAdj && endingInterval != info.fIntervals[0]) { | |
| 749 | |
| 750 SkPoint endPts[2]; | |
| 751 endPts[1] = ptsRot[1]; | |
| 752 endPts[0].fY = endPts[1].fY; | |
| 753 endPts[0].fX = endPts[1].fX - endingInterval; | |
| 754 | |
| 755 SkRect endRect; | |
| 756 endRect.set(endPts, 2); | |
| 757 endRect.outset(xStroke, halfStroke); | |
| 758 fContext->drawRect(grPaint, endRect, NULL, &srcRotInv); | |
| 759 | |
| 760 ptsRot[1].fX -= endingInterval + info.fIntervals[1]; | |
| 761 if (ptsRot[0].fX >= ptsRot[1].fX) { | |
| 762 // Nothing left to draw so just return | |
| 763 return true; | |
| 764 } | |
| 765 } | |
| 766 } | |
| 767 coordTrans.postConcat(viewMatrix); | |
| 768 | |
| 769 SkPoint devicePts[2]; | |
| 770 viewMatrix.mapPoints(devicePts, ptsRot, 2); | |
| 771 | |
| 772 info.fIntervals[0] *= parallelScale; | |
| 773 info.fIntervals[1] *= parallelScale; | |
| 774 info.fPhase *= parallelScale; | |
| 775 SkScalar strokeWidth = srcStrokeWidth * perpScale; | |
| 776 | |
| 777 if ((strokeWidth < 1.f && !useAA) || 0.f == strokeWidth) { | |
| 778 strokeWidth = 1.f; | |
| 779 } | |
| 780 | |
| 781 // Set up coordTransform for device space transforms | |
| 782 // We rotate the dashed line such that it is horizontal with the start point at smaller x | |
| 783 // then we translate the start point to the origin | |
| 784 if (devicePts[0].fY != devicePts[1].fY || devicePts[0].fX > devicePts[1].fX) { | |
| 785 SkMatrix rot; | |
| 786 align_to_x_axis(devicePts, &rot); | |
| 787 coordTrans.postConcat(rot); | |
| 788 } | |
| 789 coordTrans.postTranslate(-devicePts[0].fX, -devicePts[0].fY); | |
| 790 coordTrans.postTranslate(info.fIntervals[1] * 0.5f + info.fPhase, 0); | |
| 791 | |
| 792 if (SkPaint::kSquare_Cap == cap && 0 != srcStrokeWidth) { | |
| 793 // add cap to on interveal and remove from off interval | |
| 794 info.fIntervals[0] += strokeWidth; | |
| 795 info.fIntervals[1] -= strokeWidth; | |
| 796 } | |
| 797 | |
| 798 if (info.fIntervals[1] > 0.f) { | |
| 799 GrEffectEdgeType edgeType= useAA ? kFillAA_GrEffectEdgeType : | |
| 800 kFillBW_GrEffectEdgeType; | |
| 801 grPaint.addCoverageEffect(GrDashingEffect::Create(edgeType, info, coordT rans, strokeWidth))->unref(); | |
| 802 grPaint.setAntiAlias(false); | |
| 803 } | |
| 804 | |
| 805 SkRect rect; | |
| 806 bool bloat = useAA && info.fIntervals[1] > 0.f; | |
| 807 SkScalar bloatX = bloat ? 0.5f / parallelScale : 0.f; | |
| 808 SkScalar bloatY = bloat ? 0.5f / perpScale : 0.f; | |
| 809 ptsRot[0].fX += startAdj; | |
| 810 ptsRot[1].fX -= endAdj; | |
| 811 if (!hasCap) { | |
| 812 xStroke = 0.f; | |
| 813 } else { | |
| 814 xStroke = halfStroke; | |
| 815 } | |
| 816 rect.set(ptsRot, 2); | |
| 817 rect.outset(bloatX + xStroke, bloatY + halfStroke); | |
| 818 fContext->drawRect(grPaint, rect, NULL, &srcRotInv); | |
| 819 | |
| 820 return true; | |
| 821 } | |
| 822 | |
| 823 /////////////////////////////////////////////////////////////////////////////// | |
| 824 | |
| 562 void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect, | 825 void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect, |
| 563 const SkPaint& paint) { | 826 const SkPaint& paint) { |
| 564 CHECK_FOR_ANNOTATION(paint); | 827 CHECK_FOR_ANNOTATION(paint); |
| 565 CHECK_SHOULD_DRAW(draw, false); | 828 CHECK_SHOULD_DRAW(draw, false); |
| 566 | 829 |
| 567 bool doStroke = paint.getStyle() != SkPaint::kFill_Style; | 830 bool doStroke = paint.getStyle() != SkPaint::kFill_Style; |
| 568 SkScalar width = paint.getStrokeWidth(); | 831 SkScalar width = paint.getStrokeWidth(); |
| 569 | 832 |
| 570 /* | 833 /* |
| 571 We have special code for hairline strokes, miter-strokes, bevel-stroke | 834 We have special code for hairline strokes, miter-strokes, bevel-stroke |
| (...skipping 1548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2120 GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(pict ure, i); | 2383 GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(pict ure, i); |
| 2121 | 2384 |
| 2122 if (NULL != layer->getTexture()) { | 2385 if (NULL != layer->getTexture()) { |
| 2123 fContext->unlockScratchTexture(layer->getTexture()); | 2386 fContext->unlockScratchTexture(layer->getTexture()); |
| 2124 layer->setTexture(NULL); | 2387 layer->setTexture(NULL); |
| 2125 } | 2388 } |
| 2126 } | 2389 } |
| 2127 | 2390 |
| 2128 return true; | 2391 return true; |
| 2129 } | 2392 } |
| OLD | NEW |