3 * Copyright 2012 Google Inc.
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
9 #include "GrSoftwarePathRenderer.h"
10 #include "GrContext.h"
11 #include "GrSWMaskHelper.h"
13 ////////////////////////////////////////////////////////////////////////////////
14 bool GrSoftwarePathRenderer::canDrawPath(const SkPath&,
17 bool antiAlias) const {
18 if (NULL == fContext) {
25 GrPathRenderer::StencilSupport GrSoftwarePathRenderer::onGetStencilSupport(
28 const GrDrawTarget*) const {
29 return GrPathRenderer::kNoSupport_StencilSupport;
34 ////////////////////////////////////////////////////////////////////////////////
35 // gets device coord bounds of path (not considering the fill) and clip. The
36 // path bounds will be a subset of the clip bounds. returns false if
37 // path bounds would be empty.
38 bool get_path_and_clip_bounds(const GrDrawTarget* target,
40 const SkMatrix& matrix,
41 SkIRect* devPathBounds,
42 SkIRect* devClipBounds) {
43 // compute bounds as intersection of rt size, clip, and path
44 const GrRenderTarget* rt = target->getDrawState().getRenderTarget();
48 *devPathBounds = SkIRect::MakeWH(rt->width(), rt->height());
50 target->getClip()->getConservativeBounds(rt, devClipBounds);
52 // TODO: getConservativeBounds already intersects with the
53 // render target's bounding box. Remove this next line
54 if (!devPathBounds->intersect(*devClipBounds)) {
58 if (!path.getBounds().isEmpty()) {
60 matrix.mapRect(&pathSBounds, path.getBounds());
62 pathSBounds.roundOut(&pathIBounds);
63 if (!devPathBounds->intersect(pathIBounds)) {
64 // set the correct path bounds, as this would be used later.
65 *devPathBounds = pathIBounds;
69 *devPathBounds = SkIRect::EmptyIRect();
75 ////////////////////////////////////////////////////////////////////////////////
76 void draw_around_inv_path(GrDrawTarget* target,
77 const SkIRect& devClipBounds,
78 const SkIRect& devPathBounds) {
79 GrDrawState::AutoViewMatrixRestore avmr;
80 if (!avmr.setIdentity(target->drawState())) {
84 if (devClipBounds.fTop < devPathBounds.fTop) {
85 rect.iset(devClipBounds.fLeft, devClipBounds.fTop,
86 devClipBounds.fRight, devPathBounds.fTop);
87 target->drawSimpleRect(rect);
89 if (devClipBounds.fLeft < devPathBounds.fLeft) {
90 rect.iset(devClipBounds.fLeft, devPathBounds.fTop,
91 devPathBounds.fLeft, devPathBounds.fBottom);
92 target->drawSimpleRect(rect);
94 if (devClipBounds.fRight > devPathBounds.fRight) {
95 rect.iset(devPathBounds.fRight, devPathBounds.fTop,
96 devClipBounds.fRight, devPathBounds.fBottom);
97 target->drawSimpleRect(rect);
99 if (devClipBounds.fBottom > devPathBounds.fBottom) {
100 rect.iset(devClipBounds.fLeft, devPathBounds.fBottom,
101 devClipBounds.fRight, devClipBounds.fBottom);
102 target->drawSimpleRect(rect);
108 ////////////////////////////////////////////////////////////////////////////////
109 // return true on success; false on failure
110 bool GrSoftwarePathRenderer::onDrawPath(const SkPath& path,
111 const SkStrokeRec& stroke,
112 GrDrawTarget* target,
115 if (NULL == fContext) {
119 GrDrawState* drawState = target->drawState();
121 SkMatrix vm = drawState->getViewMatrix();
123 SkIRect devPathBounds, devClipBounds;
124 if (!get_path_and_clip_bounds(target, path, vm,
125 &devPathBounds, &devClipBounds)) {
126 if (path.isInverseFillType()) {
127 draw_around_inv_path(target, devClipBounds, devPathBounds);
132 SkAutoTUnref<GrTexture> texture(
133 GrSWMaskHelper::DrawPathMaskToTexture(fContext, path, stroke,
136 if (NULL == texture) {
140 GrSWMaskHelper::DrawToTargetWithPathMask(texture, target, devPathBounds);
142 if (path.isInverseFillType()) {
143 draw_around_inv_path(target, devClipBounds, devPathBounds);