1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/gpu/GrSoftwarePathRenderer.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,153 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2012 Google Inc. 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 +#include "GrSoftwarePathRenderer.h" 1.13 +#include "GrContext.h" 1.14 +#include "GrSWMaskHelper.h" 1.15 + 1.16 +//////////////////////////////////////////////////////////////////////////////// 1.17 +bool GrSoftwarePathRenderer::canDrawPath(const SkPath&, 1.18 + const SkStrokeRec&, 1.19 + const GrDrawTarget*, 1.20 + bool antiAlias) const { 1.21 + if (!antiAlias || NULL == fContext) { 1.22 + // TODO: We could allow the SW path to also handle non-AA paths but 1.23 + // this would mean that GrDefaultPathRenderer would never be called 1.24 + // (since it appears after the SW renderer in the path renderer 1.25 + // chain). Some testing would need to be done r.e. performance 1.26 + // and consistency of the resulting images before removing 1.27 + // the "!antiAlias" clause from the above test 1.28 + return false; 1.29 + } 1.30 + 1.31 + return true; 1.32 +} 1.33 + 1.34 +GrPathRenderer::StencilSupport GrSoftwarePathRenderer::onGetStencilSupport( 1.35 + const SkPath&, 1.36 + const SkStrokeRec&, 1.37 + const GrDrawTarget*) const { 1.38 + return GrPathRenderer::kNoSupport_StencilSupport; 1.39 +} 1.40 + 1.41 +namespace { 1.42 + 1.43 +//////////////////////////////////////////////////////////////////////////////// 1.44 +// gets device coord bounds of path (not considering the fill) and clip. The 1.45 +// path bounds will be a subset of the clip bounds. returns false if 1.46 +// path bounds would be empty. 1.47 +bool get_path_and_clip_bounds(const GrDrawTarget* target, 1.48 + const SkPath& path, 1.49 + const SkMatrix& matrix, 1.50 + SkIRect* devPathBounds, 1.51 + SkIRect* devClipBounds) { 1.52 + // compute bounds as intersection of rt size, clip, and path 1.53 + const GrRenderTarget* rt = target->getDrawState().getRenderTarget(); 1.54 + if (NULL == rt) { 1.55 + return false; 1.56 + } 1.57 + *devPathBounds = SkIRect::MakeWH(rt->width(), rt->height()); 1.58 + 1.59 + target->getClip()->getConservativeBounds(rt, devClipBounds); 1.60 + 1.61 + // TODO: getConservativeBounds already intersects with the 1.62 + // render target's bounding box. Remove this next line 1.63 + if (!devPathBounds->intersect(*devClipBounds)) { 1.64 + return false; 1.65 + } 1.66 + 1.67 + if (!path.getBounds().isEmpty()) { 1.68 + SkRect pathSBounds; 1.69 + matrix.mapRect(&pathSBounds, path.getBounds()); 1.70 + SkIRect pathIBounds; 1.71 + pathSBounds.roundOut(&pathIBounds); 1.72 + if (!devPathBounds->intersect(pathIBounds)) { 1.73 + // set the correct path bounds, as this would be used later. 1.74 + *devPathBounds = pathIBounds; 1.75 + return false; 1.76 + } 1.77 + } else { 1.78 + *devPathBounds = SkIRect::EmptyIRect(); 1.79 + return false; 1.80 + } 1.81 + return true; 1.82 +} 1.83 + 1.84 +//////////////////////////////////////////////////////////////////////////////// 1.85 +void draw_around_inv_path(GrDrawTarget* target, 1.86 + const SkIRect& devClipBounds, 1.87 + const SkIRect& devPathBounds) { 1.88 + GrDrawState::AutoViewMatrixRestore avmr; 1.89 + if (!avmr.setIdentity(target->drawState())) { 1.90 + return; 1.91 + } 1.92 + SkRect rect; 1.93 + if (devClipBounds.fTop < devPathBounds.fTop) { 1.94 + rect.iset(devClipBounds.fLeft, devClipBounds.fTop, 1.95 + devClipBounds.fRight, devPathBounds.fTop); 1.96 + target->drawSimpleRect(rect, NULL); 1.97 + } 1.98 + if (devClipBounds.fLeft < devPathBounds.fLeft) { 1.99 + rect.iset(devClipBounds.fLeft, devPathBounds.fTop, 1.100 + devPathBounds.fLeft, devPathBounds.fBottom); 1.101 + target->drawSimpleRect(rect, NULL); 1.102 + } 1.103 + if (devClipBounds.fRight > devPathBounds.fRight) { 1.104 + rect.iset(devPathBounds.fRight, devPathBounds.fTop, 1.105 + devClipBounds.fRight, devPathBounds.fBottom); 1.106 + target->drawSimpleRect(rect, NULL); 1.107 + } 1.108 + if (devClipBounds.fBottom > devPathBounds.fBottom) { 1.109 + rect.iset(devClipBounds.fLeft, devPathBounds.fBottom, 1.110 + devClipBounds.fRight, devClipBounds.fBottom); 1.111 + target->drawSimpleRect(rect, NULL); 1.112 + } 1.113 +} 1.114 + 1.115 +} 1.116 + 1.117 +//////////////////////////////////////////////////////////////////////////////// 1.118 +// return true on success; false on failure 1.119 +bool GrSoftwarePathRenderer::onDrawPath(const SkPath& path, 1.120 + const SkStrokeRec& stroke, 1.121 + GrDrawTarget* target, 1.122 + bool antiAlias) { 1.123 + 1.124 + if (NULL == fContext) { 1.125 + return false; 1.126 + } 1.127 + 1.128 + GrDrawState* drawState = target->drawState(); 1.129 + 1.130 + SkMatrix vm = drawState->getViewMatrix(); 1.131 + 1.132 + SkIRect devPathBounds, devClipBounds; 1.133 + if (!get_path_and_clip_bounds(target, path, vm, 1.134 + &devPathBounds, &devClipBounds)) { 1.135 + if (path.isInverseFillType()) { 1.136 + draw_around_inv_path(target, devClipBounds, devPathBounds); 1.137 + } 1.138 + return true; 1.139 + } 1.140 + 1.141 + SkAutoTUnref<GrTexture> texture( 1.142 + GrSWMaskHelper::DrawPathMaskToTexture(fContext, path, stroke, 1.143 + devPathBounds, 1.144 + antiAlias, &vm)); 1.145 + if (NULL == texture) { 1.146 + return false; 1.147 + } 1.148 + 1.149 + GrSWMaskHelper::DrawToTargetWithPathMask(texture, target, devPathBounds); 1.150 + 1.151 + if (path.isInverseFillType()) { 1.152 + draw_around_inv_path(target, devClipBounds, devPathBounds); 1.153 + } 1.154 + 1.155 + return true; 1.156 +}