Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / gpu / GrSoftwarePathRenderer.cpp
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
13 ////////////////////////////////////////////////////////////////////////////////
14 bool GrSoftwarePathRenderer::canDrawPath(const SkPath&,
15                                          const SkStrokeRec&,
16                                          const GrDrawTarget*,
17                                          bool antiAlias) const {
18     if (NULL == fContext) {
19         return false;
20     }
21
22     return true;
23 }
24
25 GrPathRenderer::StencilSupport GrSoftwarePathRenderer::onGetStencilSupport(
26     const SkPath&,
27     const SkStrokeRec&,
28     const GrDrawTarget*) const {
29     return GrPathRenderer::kNoSupport_StencilSupport;
30 }
31
32 namespace {
33
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,
39                               const SkPath& path,
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();
45     if (NULL == rt) {
46         return false;
47     }
48     *devPathBounds = SkIRect::MakeWH(rt->width(), rt->height());
49
50     target->getClip()->getConservativeBounds(rt, devClipBounds);
51
52     // TODO: getConservativeBounds already intersects with the
53     // render target's bounding box. Remove this next line
54     if (!devPathBounds->intersect(*devClipBounds)) {
55         return false;
56     }
57
58     if (!path.getBounds().isEmpty()) {
59         SkRect pathSBounds;
60         matrix.mapRect(&pathSBounds, path.getBounds());
61         SkIRect pathIBounds;
62         pathSBounds.roundOut(&pathIBounds);
63         if (!devPathBounds->intersect(pathIBounds)) {
64             // set the correct path bounds, as this would be used later.
65             *devPathBounds = pathIBounds;
66             return false;
67         }
68     } else {
69         *devPathBounds = SkIRect::EmptyIRect();
70         return false;
71     }
72     return true;
73 }
74
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())) {
81         return;
82     }
83     SkRect rect;
84     if (devClipBounds.fTop < devPathBounds.fTop) {
85         rect.iset(devClipBounds.fLeft, devClipBounds.fTop,
86                   devClipBounds.fRight, devPathBounds.fTop);
87         target->drawSimpleRect(rect);
88     }
89     if (devClipBounds.fLeft < devPathBounds.fLeft) {
90         rect.iset(devClipBounds.fLeft, devPathBounds.fTop,
91                   devPathBounds.fLeft, devPathBounds.fBottom);
92         target->drawSimpleRect(rect);
93     }
94     if (devClipBounds.fRight > devPathBounds.fRight) {
95         rect.iset(devPathBounds.fRight, devPathBounds.fTop,
96                   devClipBounds.fRight, devPathBounds.fBottom);
97         target->drawSimpleRect(rect);
98     }
99     if (devClipBounds.fBottom > devPathBounds.fBottom) {
100         rect.iset(devClipBounds.fLeft, devPathBounds.fBottom,
101                   devClipBounds.fRight, devClipBounds.fBottom);
102         target->drawSimpleRect(rect);
103     }
104 }
105
106 }
107
108 ////////////////////////////////////////////////////////////////////////////////
109 // return true on success; false on failure
110 bool GrSoftwarePathRenderer::onDrawPath(const SkPath& path,
111                                         const SkStrokeRec& stroke,
112                                         GrDrawTarget* target,
113                                         bool antiAlias) {
114
115     if (NULL == fContext) {
116         return false;
117     }
118
119     GrDrawState* drawState = target->drawState();
120
121     SkMatrix vm = drawState->getViewMatrix();
122
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);
128         }
129         return true;
130     }
131
132     SkAutoTUnref<GrTexture> texture(
133             GrSWMaskHelper::DrawPathMaskToTexture(fContext, path, stroke,
134                                                   devPathBounds,
135                                                   antiAlias, &vm));
136     if (NULL == texture) {
137         return false;
138     }
139
140     GrSWMaskHelper::DrawToTargetWithPathMask(texture, target, devPathBounds);
141
142     if (path.isInverseFillType()) {
143         draw_around_inv_path(target, devClipBounds, devPathBounds);
144     }
145
146     return true;
147 }