blob: 9a9cf328c88d3d286de4734847175da314e2e8e5 [file] [log] [blame]
robertphillips@google.comf4c2c522012-04-27 12:08:47 +00001
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"
robertphillips@google.comed4155d2012-05-01 14:30:24 +000010#include "GrContext.h"
robertphillips@google.com58b20212012-06-27 20:44:52 +000011#include "GrSWMaskHelper.h"
robertphillips@google.comf4c2c522012-04-27 12:08:47 +000012
robertphillips@google.comed4155d2012-05-01 14:30:24 +000013////////////////////////////////////////////////////////////////////////////////
joshualitt9853cce2014-11-17 14:22:48 -080014bool GrSoftwarePathRenderer::canDrawPath(const GrDrawTarget*,
15 const GrDrawState*,
16 const SkPath&,
robertphillips@google.come79f3202014-02-11 16:30:21 +000017 const SkStrokeRec&,
robertphillips@google.comf4c2c522012-04-27 12:08:47 +000018 bool antiAlias) const {
robertphillips730c0442014-07-25 05:52:38 -070019 if (NULL == fContext) {
robertphillips@google.comf4c2c522012-04-27 12:08:47 +000020 return false;
21 }
22
robertphillips@google.comed4155d2012-05-01 14:30:24 +000023 return true;
robertphillips@google.comf4c2c522012-04-27 12:08:47 +000024}
25
joshualitt9853cce2014-11-17 14:22:48 -080026GrPathRenderer::StencilSupport
27GrSoftwarePathRenderer::onGetStencilSupport(const GrDrawTarget*,
28 const GrDrawState*,
29 const SkPath&,
30 const SkStrokeRec&) const {
bsalomon@google.com45a15f52012-12-10 19:10:17 +000031 return GrPathRenderer::kNoSupport_StencilSupport;
32}
33
robertphillips@google.comed4155d2012-05-01 14:30:24 +000034namespace {
35
36////////////////////////////////////////////////////////////////////////////////
robertphillips@google.comed4155d2012-05-01 14:30:24 +000037// gets device coord bounds of path (not considering the fill) and clip. The
rmistry@google.comd6176b02012-08-23 18:14:13 +000038// path bounds will be a subset of the clip bounds. returns false if
robertphillips@google.comed4155d2012-05-01 14:30:24 +000039// path bounds would be empty.
40bool get_path_and_clip_bounds(const GrDrawTarget* target,
joshualitt9853cce2014-11-17 14:22:48 -080041 const GrDrawState* drawState,
robertphillips@google.comed4155d2012-05-01 14:30:24 +000042 const SkPath& path,
bsalomon@google.comb9086a02012-11-01 18:02:54 +000043 const SkMatrix& matrix,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000044 SkIRect* devPathBounds,
45 SkIRect* devClipBounds) {
robertphillips@google.comed4155d2012-05-01 14:30:24 +000046 // compute bounds as intersection of rt size, clip, and path
joshualitt9853cce2014-11-17 14:22:48 -080047 const GrRenderTarget* rt = drawState->getRenderTarget();
robertphillips@google.comed4155d2012-05-01 14:30:24 +000048 if (NULL == rt) {
49 return false;
50 }
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000051 *devPathBounds = SkIRect::MakeWH(rt->width(), rt->height());
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +000052
robertphillips@google.com7b112892012-07-31 15:18:21 +000053 target->getClip()->getConservativeBounds(rt, devClipBounds);
54
rmistry@google.comd6176b02012-08-23 18:14:13 +000055 // TODO: getConservativeBounds already intersects with the
robertphillips@google.com7b112892012-07-31 15:18:21 +000056 // render target's bounding box. Remove this next line
57 if (!devPathBounds->intersect(*devClipBounds)) {
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +000058 return false;
robertphillips@google.comed4155d2012-05-01 14:30:24 +000059 }
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +000060
robertphillips@google.com366f1c62012-06-29 21:38:47 +000061 if (!path.getBounds().isEmpty()) {
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000062 SkRect pathSBounds;
robertphillips@google.com366f1c62012-06-29 21:38:47 +000063 matrix.mapRect(&pathSBounds, path.getBounds());
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000064 SkIRect pathIBounds;
robertphillips@google.comed4155d2012-05-01 14:30:24 +000065 pathSBounds.roundOut(&pathIBounds);
robertphillips@google.com7b112892012-07-31 15:18:21 +000066 if (!devPathBounds->intersect(pathIBounds)) {
bsalomon@google.com276c1fa2012-06-19 13:22:45 +000067 // set the correct path bounds, as this would be used later.
robertphillips@google.com7b112892012-07-31 15:18:21 +000068 *devPathBounds = pathIBounds;
robertphillips@google.comed4155d2012-05-01 14:30:24 +000069 return false;
70 }
71 } else {
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000072 *devPathBounds = SkIRect::EmptyIRect();
robertphillips@google.comed4155d2012-05-01 14:30:24 +000073 return false;
74 }
75 return true;
76}
77
78////////////////////////////////////////////////////////////////////////////////
robertphillips@google.comed4155d2012-05-01 14:30:24 +000079void draw_around_inv_path(GrDrawTarget* target,
joshualitt9853cce2014-11-17 14:22:48 -080080 GrDrawState* drawState,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000081 const SkIRect& devClipBounds,
82 const SkIRect& devPathBounds) {
bsalomon@google.com137f1342013-05-29 21:27:53 +000083 GrDrawState::AutoViewMatrixRestore avmr;
joshualitt9853cce2014-11-17 14:22:48 -080084 if (!avmr.setIdentity(drawState)) {
bsalomon@google.come3d32162012-07-20 13:37:06 +000085 return;
86 }
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000087 SkRect rect;
robertphillips@google.com7b112892012-07-31 15:18:21 +000088 if (devClipBounds.fTop < devPathBounds.fTop) {
rmistry@google.comd6176b02012-08-23 18:14:13 +000089 rect.iset(devClipBounds.fLeft, devClipBounds.fTop,
robertphillips@google.com7b112892012-07-31 15:18:21 +000090 devClipBounds.fRight, devPathBounds.fTop);
joshualitt9853cce2014-11-17 14:22:48 -080091 target->drawSimpleRect(drawState, rect);
robertphillips@google.comed4155d2012-05-01 14:30:24 +000092 }
robertphillips@google.com7b112892012-07-31 15:18:21 +000093 if (devClipBounds.fLeft < devPathBounds.fLeft) {
rmistry@google.comd6176b02012-08-23 18:14:13 +000094 rect.iset(devClipBounds.fLeft, devPathBounds.fTop,
robertphillips@google.com7b112892012-07-31 15:18:21 +000095 devPathBounds.fLeft, devPathBounds.fBottom);
joshualitt9853cce2014-11-17 14:22:48 -080096 target->drawSimpleRect(drawState, rect);
robertphillips@google.comed4155d2012-05-01 14:30:24 +000097 }
robertphillips@google.com7b112892012-07-31 15:18:21 +000098 if (devClipBounds.fRight > devPathBounds.fRight) {
rmistry@google.comd6176b02012-08-23 18:14:13 +000099 rect.iset(devPathBounds.fRight, devPathBounds.fTop,
robertphillips@google.com7b112892012-07-31 15:18:21 +0000100 devClipBounds.fRight, devPathBounds.fBottom);
joshualitt9853cce2014-11-17 14:22:48 -0800101 target->drawSimpleRect(drawState, rect);
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000102 }
robertphillips@google.com7b112892012-07-31 15:18:21 +0000103 if (devClipBounds.fBottom > devPathBounds.fBottom) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000104 rect.iset(devClipBounds.fLeft, devPathBounds.fBottom,
robertphillips@google.com7b112892012-07-31 15:18:21 +0000105 devClipBounds.fRight, devClipBounds.fBottom);
joshualitt9853cce2014-11-17 14:22:48 -0800106 target->drawSimpleRect(drawState, rect);
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000107 }
108}
109
110}
111
112////////////////////////////////////////////////////////////////////////////////
113// return true on success; false on failure
joshualitt9853cce2014-11-17 14:22:48 -0800114bool GrSoftwarePathRenderer::onDrawPath(GrDrawTarget* target,
115 GrDrawState* drawState,
116 const SkPath& path,
robertphillips@google.come79f3202014-02-11 16:30:21 +0000117 const SkStrokeRec& stroke,
robertphillips@google.comf4c2c522012-04-27 12:08:47 +0000118 bool antiAlias) {
119
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000120 if (NULL == fContext) {
121 return false;
122 }
123
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000124 SkMatrix vm = drawState->getViewMatrix();
robertphillips@google.com366f1c62012-06-29 21:38:47 +0000125
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000126 SkIRect devPathBounds, devClipBounds;
joshualitt9853cce2014-11-17 14:22:48 -0800127 if (!get_path_and_clip_bounds(target, drawState, path, vm,
robertphillips@google.com7b112892012-07-31 15:18:21 +0000128 &devPathBounds, &devClipBounds)) {
robertphillips@google.come79f3202014-02-11 16:30:21 +0000129 if (path.isInverseFillType()) {
joshualitt9853cce2014-11-17 14:22:48 -0800130 draw_around_inv_path(target, drawState, devClipBounds, devPathBounds);
bsalomon@google.com276c1fa2012-06-19 13:22:45 +0000131 }
132 return true;
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000133 }
robertphillips@google.com366f1c62012-06-29 21:38:47 +0000134
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000135 SkAutoTUnref<GrTexture> texture(
robertphillips@google.come79f3202014-02-11 16:30:21 +0000136 GrSWMaskHelper::DrawPathMaskToTexture(fContext, path, stroke,
sugoi@google.com12b4e272012-12-06 20:13:11 +0000137 devPathBounds,
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000138 antiAlias, &vm));
139 if (NULL == texture) {
140 return false;
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000141 }
142
joshualitt9853cce2014-11-17 14:22:48 -0800143 GrDrawState copy = *drawState;
144 GrSWMaskHelper::DrawToTargetWithPathMask(texture, target, &copy, devPathBounds);
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000145
robertphillips@google.come79f3202014-02-11 16:30:21 +0000146 if (path.isInverseFillType()) {
joshualitt9853cce2014-11-17 14:22:48 -0800147 draw_around_inv_path(target, drawState, devClipBounds, devPathBounds);
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000148 }
149
150 return true;
robertphillips@google.comf4c2c522012-04-27 12:08:47 +0000151}