1 2/* 3 * Copyright 2012 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9#include "GrSoftwarePathRenderer.h" 10#include "GrContext.h" 11#include "GrSWMaskHelper.h" 12#include "GrVertexBuffer.h" 13#include "batches/GrRectBatchFactory.h" 14 15//////////////////////////////////////////////////////////////////////////////// 16bool GrSoftwarePathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const { 17 if (nullptr == fContext) { 18 return false; 19 } 20 if (args.fStroke->isDashed()) { 21 return false; 22 } 23 return true; 24} 25 26namespace { 27 28//////////////////////////////////////////////////////////////////////////////// 29// gets device coord bounds of path (not considering the fill) and clip. The 30// path bounds will be a subset of the clip bounds. returns false if 31// path bounds would be empty. 32bool get_path_and_clip_bounds(const GrPipelineBuilder* pipelineBuilder, 33 const SkPath& path, 34 const SkMatrix& matrix, 35 SkIRect* devPathBounds, 36 SkIRect* devClipBounds) { 37 // compute bounds as intersection of rt size, clip, and path 38 const GrRenderTarget* rt = pipelineBuilder->getRenderTarget(); 39 if (nullptr == rt) { 40 return false; 41 } 42 43 pipelineBuilder->clip().getConservativeBounds(rt->width(), rt->height(), devClipBounds); 44 45 if (devClipBounds->isEmpty()) { 46 *devPathBounds = SkIRect::MakeWH(rt->width(), rt->height()); 47 return false; 48 } 49 50 if (!path.getBounds().isEmpty()) { 51 SkRect pathSBounds; 52 matrix.mapRect(&pathSBounds, path.getBounds()); 53 SkIRect pathIBounds; 54 pathSBounds.roundOut(&pathIBounds); 55 *devPathBounds = *devClipBounds; 56 if (!devPathBounds->intersect(pathIBounds)) { 57 // set the correct path bounds, as this would be used later. 58 *devPathBounds = pathIBounds; 59 return false; 60 } 61 } else { 62 *devPathBounds = SkIRect::EmptyIRect(); 63 return false; 64 } 65 return true; 66} 67 68//////////////////////////////////////////////////////////////////////////////// 69static void draw_non_aa_rect(GrDrawTarget* drawTarget, 70 const GrPipelineBuilder& pipelineBuilder, 71 GrColor color, 72 const SkMatrix& viewMatrix, 73 const SkRect& rect, 74 const SkMatrix& localMatrix) { 75 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, viewMatrix, rect, 76 nullptr, &localMatrix)); 77 drawTarget->drawBatch(pipelineBuilder, batch); 78} 79 80void draw_around_inv_path(GrDrawTarget* target, 81 GrPipelineBuilder* pipelineBuilder, 82 GrColor color, 83 const SkMatrix& viewMatrix, 84 const SkIRect& devClipBounds, 85 const SkIRect& devPathBounds) { 86 SkMatrix invert; 87 if (!viewMatrix.invert(&invert)) { 88 return; 89 } 90 91 SkRect rect; 92 if (devClipBounds.fTop < devPathBounds.fTop) { 93 rect.iset(devClipBounds.fLeft, devClipBounds.fTop, 94 devClipBounds.fRight, devPathBounds.fTop); 95 draw_non_aa_rect(target, *pipelineBuilder, color, SkMatrix::I(), rect, invert); 96 } 97 if (devClipBounds.fLeft < devPathBounds.fLeft) { 98 rect.iset(devClipBounds.fLeft, devPathBounds.fTop, 99 devPathBounds.fLeft, devPathBounds.fBottom); 100 draw_non_aa_rect(target, *pipelineBuilder, color, SkMatrix::I(), rect, invert); 101 } 102 if (devClipBounds.fRight > devPathBounds.fRight) { 103 rect.iset(devPathBounds.fRight, devPathBounds.fTop, 104 devClipBounds.fRight, devPathBounds.fBottom); 105 draw_non_aa_rect(target, *pipelineBuilder, color, SkMatrix::I(), rect, invert); 106 } 107 if (devClipBounds.fBottom > devPathBounds.fBottom) { 108 rect.iset(devClipBounds.fLeft, devPathBounds.fBottom, 109 devClipBounds.fRight, devClipBounds.fBottom); 110 draw_non_aa_rect(target, *pipelineBuilder, color, SkMatrix::I(), rect, invert); 111 } 112} 113 114} 115 116//////////////////////////////////////////////////////////////////////////////// 117// return true on success; false on failure 118bool GrSoftwarePathRenderer::onDrawPath(const DrawPathArgs& args) { 119 GR_AUDIT_TRAIL_AUTO_FRAME(args.fTarget->getAuditTrail(), "GrSoftwarePathRenderer::onDrawPath"); 120 if (nullptr == fContext) { 121 return false; 122 } 123 124 SkIRect devPathBounds, devClipBounds; 125 if (!get_path_and_clip_bounds(args.fPipelineBuilder, *args.fPath, 126 *args.fViewMatrix, &devPathBounds, &devClipBounds)) { 127 if (args.fPath->isInverseFillType()) { 128 draw_around_inv_path(args.fTarget, args.fPipelineBuilder, args.fColor, 129 *args.fViewMatrix, devClipBounds, devPathBounds); 130 } 131 return true; 132 } 133 134 SkAutoTUnref<GrTexture> texture( 135 GrSWMaskHelper::DrawPathMaskToTexture(fContext, *args.fPath, *args.fStroke, 136 devPathBounds, 137 args.fAntiAlias, args.fViewMatrix)); 138 if (nullptr == texture) { 139 return false; 140 } 141 142 GrSWMaskHelper::DrawToTargetWithPathMask(texture, args.fTarget, args.fPipelineBuilder, 143 args.fColor, *args.fViewMatrix, devPathBounds); 144 145 if (args.fPath->isInverseFillType()) { 146 draw_around_inv_path(args.fTarget, args.fPipelineBuilder, args.fColor, *args.fViewMatrix, 147 devClipBounds, devPathBounds); 148 } 149 150 return true; 151} 152