blob: bca2c66b37f82614f44660b21fed9d72cb97f00d [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////////////////////////////////////////////////////////////////////////////////
robertphillips@google.come79f3202014-02-11 16:30:21 +000014bool GrSoftwarePathRenderer::canDrawPath(const SkPath&,
15 const SkStrokeRec&,
sugoi@google.com5f74cf82012-12-17 21:16:45 +000016 const GrDrawTarget*,
robertphillips@google.comf4c2c522012-04-27 12:08:47 +000017 bool antiAlias) const {
robertphillips730c0442014-07-25 05:52:38 -070018 if (NULL == fContext) {
robertphillips@google.comf4c2c522012-04-27 12:08:47 +000019 return false;
20 }
21
robertphillips@google.comed4155d2012-05-01 14:30:24 +000022 return true;
robertphillips@google.comf4c2c522012-04-27 12:08:47 +000023}
24
bsalomon@google.com45a15f52012-12-10 19:10:17 +000025GrPathRenderer::StencilSupport GrSoftwarePathRenderer::onGetStencilSupport(
robertphillips@google.come79f3202014-02-11 16:30:21 +000026 const SkPath&,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000027 const SkStrokeRec&,
28 const GrDrawTarget*) const {
bsalomon@google.com45a15f52012-12-10 19:10:17 +000029 return GrPathRenderer::kNoSupport_StencilSupport;
30}
31
robertphillips@google.comed4155d2012-05-01 14:30:24 +000032namespace {
33
34////////////////////////////////////////////////////////////////////////////////
robertphillips@google.comed4155d2012-05-01 14:30:24 +000035// gets device coord bounds of path (not considering the fill) and clip. The
rmistry@google.comd6176b02012-08-23 18:14:13 +000036// path bounds will be a subset of the clip bounds. returns false if
robertphillips@google.comed4155d2012-05-01 14:30:24 +000037// path bounds would be empty.
38bool get_path_and_clip_bounds(const GrDrawTarget* target,
39 const SkPath& path,
bsalomon@google.comb9086a02012-11-01 18:02:54 +000040 const SkMatrix& matrix,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000041 SkIRect* devPathBounds,
42 SkIRect* devClipBounds) {
robertphillips@google.comed4155d2012-05-01 14:30:24 +000043 // compute bounds as intersection of rt size, clip, and path
44 const GrRenderTarget* rt = target->getDrawState().getRenderTarget();
45 if (NULL == rt) {
46 return false;
47 }
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000048 *devPathBounds = SkIRect::MakeWH(rt->width(), rt->height());
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +000049
robertphillips@google.com7b112892012-07-31 15:18:21 +000050 target->getClip()->getConservativeBounds(rt, devClipBounds);
51
rmistry@google.comd6176b02012-08-23 18:14:13 +000052 // TODO: getConservativeBounds already intersects with the
robertphillips@google.com7b112892012-07-31 15:18:21 +000053 // render target's bounding box. Remove this next line
54 if (!devPathBounds->intersect(*devClipBounds)) {
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +000055 return false;
robertphillips@google.comed4155d2012-05-01 14:30:24 +000056 }
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +000057
robertphillips@google.com366f1c62012-06-29 21:38:47 +000058 if (!path.getBounds().isEmpty()) {
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000059 SkRect pathSBounds;
robertphillips@google.com366f1c62012-06-29 21:38:47 +000060 matrix.mapRect(&pathSBounds, path.getBounds());
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000061 SkIRect pathIBounds;
robertphillips@google.comed4155d2012-05-01 14:30:24 +000062 pathSBounds.roundOut(&pathIBounds);
robertphillips@google.com7b112892012-07-31 15:18:21 +000063 if (!devPathBounds->intersect(pathIBounds)) {
bsalomon@google.com276c1fa2012-06-19 13:22:45 +000064 // set the correct path bounds, as this would be used later.
robertphillips@google.com7b112892012-07-31 15:18:21 +000065 *devPathBounds = pathIBounds;
robertphillips@google.comed4155d2012-05-01 14:30:24 +000066 return false;
67 }
68 } else {
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000069 *devPathBounds = SkIRect::EmptyIRect();
robertphillips@google.comed4155d2012-05-01 14:30:24 +000070 return false;
71 }
72 return true;
73}
74
75////////////////////////////////////////////////////////////////////////////////
robertphillips@google.comed4155d2012-05-01 14:30:24 +000076void draw_around_inv_path(GrDrawTarget* target,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000077 const SkIRect& devClipBounds,
78 const SkIRect& devPathBounds) {
bsalomon@google.com137f1342013-05-29 21:27:53 +000079 GrDrawState::AutoViewMatrixRestore avmr;
80 if (!avmr.setIdentity(target->drawState())) {
bsalomon@google.come3d32162012-07-20 13:37:06 +000081 return;
82 }
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +000083 SkRect rect;
robertphillips@google.com7b112892012-07-31 15:18:21 +000084 if (devClipBounds.fTop < devPathBounds.fTop) {
rmistry@google.comd6176b02012-08-23 18:14:13 +000085 rect.iset(devClipBounds.fLeft, devClipBounds.fTop,
robertphillips@google.com7b112892012-07-31 15:18:21 +000086 devClipBounds.fRight, devPathBounds.fTop);
bsalomon@google.come3d32162012-07-20 13:37:06 +000087 target->drawSimpleRect(rect, NULL);
robertphillips@google.comed4155d2012-05-01 14:30:24 +000088 }
robertphillips@google.com7b112892012-07-31 15:18:21 +000089 if (devClipBounds.fLeft < devPathBounds.fLeft) {
rmistry@google.comd6176b02012-08-23 18:14:13 +000090 rect.iset(devClipBounds.fLeft, devPathBounds.fTop,
robertphillips@google.com7b112892012-07-31 15:18:21 +000091 devPathBounds.fLeft, devPathBounds.fBottom);
bsalomon@google.come3d32162012-07-20 13:37:06 +000092 target->drawSimpleRect(rect, NULL);
robertphillips@google.comed4155d2012-05-01 14:30:24 +000093 }
robertphillips@google.com7b112892012-07-31 15:18:21 +000094 if (devClipBounds.fRight > devPathBounds.fRight) {
rmistry@google.comd6176b02012-08-23 18:14:13 +000095 rect.iset(devPathBounds.fRight, devPathBounds.fTop,
robertphillips@google.com7b112892012-07-31 15:18:21 +000096 devClipBounds.fRight, devPathBounds.fBottom);
bsalomon@google.come3d32162012-07-20 13:37:06 +000097 target->drawSimpleRect(rect, NULL);
robertphillips@google.comed4155d2012-05-01 14:30:24 +000098 }
robertphillips@google.com7b112892012-07-31 15:18:21 +000099 if (devClipBounds.fBottom > devPathBounds.fBottom) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000100 rect.iset(devClipBounds.fLeft, devPathBounds.fBottom,
robertphillips@google.com7b112892012-07-31 15:18:21 +0000101 devClipBounds.fRight, devClipBounds.fBottom);
bsalomon@google.come3d32162012-07-20 13:37:06 +0000102 target->drawSimpleRect(rect, NULL);
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000103 }
104}
105
106}
107
108////////////////////////////////////////////////////////////////////////////////
109// return true on success; false on failure
robertphillips@google.come79f3202014-02-11 16:30:21 +0000110bool GrSoftwarePathRenderer::onDrawPath(const SkPath& path,
111 const SkStrokeRec& stroke,
robertphillips@google.comf4c2c522012-04-27 12:08:47 +0000112 GrDrawTarget* target,
robertphillips@google.comf4c2c522012-04-27 12:08:47 +0000113 bool antiAlias) {
114
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000115 if (NULL == fContext) {
116 return false;
117 }
118
robertphillips@google.com366f1c62012-06-29 21:38:47 +0000119 GrDrawState* drawState = target->drawState();
120
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000121 SkMatrix vm = drawState->getViewMatrix();
robertphillips@google.com366f1c62012-06-29 21:38:47 +0000122
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000123 SkIRect devPathBounds, devClipBounds;
robertphillips@google.come79f3202014-02-11 16:30:21 +0000124 if (!get_path_and_clip_bounds(target, path, vm,
robertphillips@google.com7b112892012-07-31 15:18:21 +0000125 &devPathBounds, &devClipBounds)) {
robertphillips@google.come79f3202014-02-11 16:30:21 +0000126 if (path.isInverseFillType()) {
robertphillips@google.com7b112892012-07-31 15:18:21 +0000127 draw_around_inv_path(target, devClipBounds, devPathBounds);
bsalomon@google.com276c1fa2012-06-19 13:22:45 +0000128 }
129 return true;
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000130 }
robertphillips@google.com366f1c62012-06-29 21:38:47 +0000131
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000132 SkAutoTUnref<GrTexture> texture(
robertphillips@google.come79f3202014-02-11 16:30:21 +0000133 GrSWMaskHelper::DrawPathMaskToTexture(fContext, path, stroke,
sugoi@google.com12b4e272012-12-06 20:13:11 +0000134 devPathBounds,
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000135 antiAlias, &vm));
136 if (NULL == texture) {
137 return false;
robertphillips@google.comed4155d2012-05-01 14:30:24 +0000138 }
139
robertphillips@google.com7b112892012-07-31 15:18:21 +0000140 GrSWMaskHelper::DrawToTargetWithPathMask(texture, target, devPathBounds);
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000141
robertphillips@google.come79f3202014-02-11 16:30:21 +0000142 if (path.isInverseFillType()) {
robertphillips@google.com7b112892012-07-31 15:18:21 +0000143 draw_around_inv_path(target, devClipBounds, devPathBounds);
robertphillips@google.com5dfb6722012-07-09 16:32:28 +0000144 }
145
146 return true;
robertphillips@google.comf4c2c522012-04-27 12:08:47 +0000147}