1509a5db5e14dd358d2ea7ea950d073513231184drobertphillips@google.com
2509a5db5e14dd358d2ea7ea950d073513231184drobertphillips@google.com/*
3509a5db5e14dd358d2ea7ea950d073513231184drobertphillips@google.com * Copyright 2012 Google Inc.
4509a5db5e14dd358d2ea7ea950d073513231184drobertphillips@google.com *
5509a5db5e14dd358d2ea7ea950d073513231184drobertphillips@google.com * Use of this source code is governed by a BSD-style license that can be
6509a5db5e14dd358d2ea7ea950d073513231184drobertphillips@google.com * found in the LICENSE file.
7509a5db5e14dd358d2ea7ea950d073513231184drobertphillips@google.com */
8509a5db5e14dd358d2ea7ea950d073513231184drobertphillips@google.com
9509a5db5e14dd358d2ea7ea950d073513231184drobertphillips@google.com#include "GrSoftwarePathRenderer.h"
101c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com#include "GrContext.h"
11fe39b2270e725e82f3598adba36d1b5b4cd60186robertphillips@google.com#include "GrSWMaskHelper.h"
12509a5db5e14dd358d2ea7ea950d073513231184drobertphillips@google.com
131c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com////////////////////////////////////////////////////////////////////////////////
145c2ee5c5d8f8593d40a2a9ffd9ca834653ee6af1sugoi@google.combool GrSoftwarePathRenderer::canDrawPath(const SkPath&,
155c2ee5c5d8f8593d40a2a9ffd9ca834653ee6af1sugoi@google.com                                         const SkStrokeRec&,
165c2ee5c5d8f8593d40a2a9ffd9ca834653ee6af1sugoi@google.com                                         const GrDrawTarget*,
17509a5db5e14dd358d2ea7ea950d073513231184drobertphillips@google.com                                         bool antiAlias) const {
181c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com    if (!antiAlias || NULL == fContext) {
191c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com        // TODO: We could allow the SW path to also handle non-AA paths but
201c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com        // this would mean that GrDefaultPathRenderer would never be called
211c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com        // (since it appears after the SW renderer in the path renderer
22dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com        // chain). Some testing would need to be done r.e. performance
231c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com        // and consistency of the resulting images before removing
241c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com        // the "!antiAlias" clause from the above test
25509a5db5e14dd358d2ea7ea950d073513231184drobertphillips@google.com        return false;
26509a5db5e14dd358d2ea7ea950d073513231184drobertphillips@google.com    }
27509a5db5e14dd358d2ea7ea950d073513231184drobertphillips@google.com
281c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com    return true;
291c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com}
301c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com
310afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.comGrPathRenderer::StencilSupport GrSoftwarePathRenderer::onGetStencilSupport(
32a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org    const SkPath&,
33a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org    const SkStrokeRec&,
34a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org    const GrDrawTarget*) const {
350afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com    return GrPathRenderer::kNoSupport_StencilSupport;
360afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com}
370afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com
381c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.comnamespace {
391c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com
401c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com////////////////////////////////////////////////////////////////////////////////
411c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com// gets device coord bounds of path (not considering the fill) and clip. The
42dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com// path bounds will be a subset of the clip bounds. returns false if
431c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com// path bounds would be empty.
441c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.combool get_path_and_clip_bounds(const GrDrawTarget* target,
451c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com                              const SkPath& path,
46a4e2f5beb2d73243c15ab871f013d2ba29e8fea3bsalomon@google.com                              const SkMatrix& matrix,
47a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org                              SkIRect* devPathBounds,
48a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org                              SkIRect* devClipBounds) {
491c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com    // compute bounds as intersection of rt size, clip, and path
501c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com    const GrRenderTarget* rt = target->getDrawState().getRenderTarget();
511c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com    if (NULL == rt) {
521c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com        return false;
531c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com    }
54a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org    *devPathBounds = SkIRect::MakeWH(rt->width(), rt->height());
5515e7ae449c45978bc7ed7aba427369e4f78bc6derobertphillips@google.com
56b6b643945182d1df391fdd11e2e788af8445914frobertphillips@google.com    target->getClip()->getConservativeBounds(rt, devClipBounds);
57b6b643945182d1df391fdd11e2e788af8445914frobertphillips@google.com
58dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com    // TODO: getConservativeBounds already intersects with the
59b6b643945182d1df391fdd11e2e788af8445914frobertphillips@google.com    // render target's bounding box. Remove this next line
60b6b643945182d1df391fdd11e2e788af8445914frobertphillips@google.com    if (!devPathBounds->intersect(*devClipBounds)) {
6115e7ae449c45978bc7ed7aba427369e4f78bc6derobertphillips@google.com        return false;
621c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com    }
6315e7ae449c45978bc7ed7aba427369e4f78bc6derobertphillips@google.com
64eeb064d9572cc6a9859260de155096c43c0a2116robertphillips@google.com    if (!path.getBounds().isEmpty()) {
65a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org        SkRect pathSBounds;
66eeb064d9572cc6a9859260de155096c43c0a2116robertphillips@google.com        matrix.mapRect(&pathSBounds, path.getBounds());
67a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org        SkIRect pathIBounds;
681c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com        pathSBounds.roundOut(&pathIBounds);
69b6b643945182d1df391fdd11e2e788af8445914frobertphillips@google.com        if (!devPathBounds->intersect(pathIBounds)) {
706f14f6e86c3c528f3801e96ae21531e6900d6d16bsalomon@google.com            // set the correct path bounds, as this would be used later.
71b6b643945182d1df391fdd11e2e788af8445914frobertphillips@google.com            *devPathBounds = pathIBounds;
721c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com            return false;
731c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com        }
741c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com    } else {
75a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org        *devPathBounds = SkIRect::EmptyIRect();
761c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com        return false;
771c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com    }
781c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com    return true;
791c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com}
801c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com
811c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com////////////////////////////////////////////////////////////////////////////////
821c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.comvoid draw_around_inv_path(GrDrawTarget* target,
83a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org                          const SkIRect& devClipBounds,
84a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org                          const SkIRect& devPathBounds) {
85fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com    GrDrawState::AutoViewMatrixRestore avmr;
86fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com    if (!avmr.setIdentity(target->drawState())) {
877cb60d6f6638f4f9866af50615b3972fb99f812fbsalomon@google.com        return;
887cb60d6f6638f4f9866af50615b3972fb99f812fbsalomon@google.com    }
89a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org    SkRect rect;
90b6b643945182d1df391fdd11e2e788af8445914frobertphillips@google.com    if (devClipBounds.fTop < devPathBounds.fTop) {
91dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com        rect.iset(devClipBounds.fLeft, devClipBounds.fTop,
92b6b643945182d1df391fdd11e2e788af8445914frobertphillips@google.com                  devClipBounds.fRight, devPathBounds.fTop);
937cb60d6f6638f4f9866af50615b3972fb99f812fbsalomon@google.com        target->drawSimpleRect(rect, NULL);
941c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com    }
95b6b643945182d1df391fdd11e2e788af8445914frobertphillips@google.com    if (devClipBounds.fLeft < devPathBounds.fLeft) {
96dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com        rect.iset(devClipBounds.fLeft, devPathBounds.fTop,
97b6b643945182d1df391fdd11e2e788af8445914frobertphillips@google.com                  devPathBounds.fLeft, devPathBounds.fBottom);
987cb60d6f6638f4f9866af50615b3972fb99f812fbsalomon@google.com        target->drawSimpleRect(rect, NULL);
991c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com    }
100b6b643945182d1df391fdd11e2e788af8445914frobertphillips@google.com    if (devClipBounds.fRight > devPathBounds.fRight) {
101dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com        rect.iset(devPathBounds.fRight, devPathBounds.fTop,
102b6b643945182d1df391fdd11e2e788af8445914frobertphillips@google.com                  devClipBounds.fRight, devPathBounds.fBottom);
1037cb60d6f6638f4f9866af50615b3972fb99f812fbsalomon@google.com        target->drawSimpleRect(rect, NULL);
1041c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com    }
105b6b643945182d1df391fdd11e2e788af8445914frobertphillips@google.com    if (devClipBounds.fBottom > devPathBounds.fBottom) {
106dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com        rect.iset(devClipBounds.fLeft, devPathBounds.fBottom,
107b6b643945182d1df391fdd11e2e788af8445914frobertphillips@google.com                  devClipBounds.fRight, devClipBounds.fBottom);
1087cb60d6f6638f4f9866af50615b3972fb99f812fbsalomon@google.com        target->drawSimpleRect(rect, NULL);
1091c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com    }
110509a5db5e14dd358d2ea7ea950d073513231184drobertphillips@google.com}
111509a5db5e14dd358d2ea7ea950d073513231184drobertphillips@google.com
1121c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com}
1131c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com
1141c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com////////////////////////////////////////////////////////////////////////////////
1151c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com// return true on success; false on failure
116509a5db5e14dd358d2ea7ea950d073513231184drobertphillips@google.combool GrSoftwarePathRenderer::onDrawPath(const SkPath& path,
1175c2ee5c5d8f8593d40a2a9ffd9ca834653ee6af1sugoi@google.com                                        const SkStrokeRec& stroke,
118509a5db5e14dd358d2ea7ea950d073513231184drobertphillips@google.com                                        GrDrawTarget* target,
119509a5db5e14dd358d2ea7ea950d073513231184drobertphillips@google.com                                        bool antiAlias) {
120509a5db5e14dd358d2ea7ea950d073513231184drobertphillips@google.com
1211c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com    if (NULL == fContext) {
1221c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com        return false;
1231c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com    }
1241c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com
125eeb064d9572cc6a9859260de155096c43c0a2116robertphillips@google.com    GrDrawState* drawState = target->drawState();
126eeb064d9572cc6a9859260de155096c43c0a2116robertphillips@google.com
127a4e2f5beb2d73243c15ab871f013d2ba29e8fea3bsalomon@google.com    SkMatrix vm = drawState->getViewMatrix();
128eeb064d9572cc6a9859260de155096c43c0a2116robertphillips@google.com
129a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org    SkIRect devPathBounds, devClipBounds;
130eeb064d9572cc6a9859260de155096c43c0a2116robertphillips@google.com    if (!get_path_and_clip_bounds(target, path, vm,
131b6b643945182d1df391fdd11e2e788af8445914frobertphillips@google.com                                  &devPathBounds, &devClipBounds)) {
132290bf0ae34af76a4350a5df76ce02feb93d68196sugoi@google.com        if (path.isInverseFillType()) {
133b6b643945182d1df391fdd11e2e788af8445914frobertphillips@google.com            draw_around_inv_path(target, devClipBounds, devPathBounds);
1346f14f6e86c3c528f3801e96ae21531e6900d6d16bsalomon@google.com        }
1356f14f6e86c3c528f3801e96ae21531e6900d6d16bsalomon@google.com        return true;
1361c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com    }
137eeb064d9572cc6a9859260de155096c43c0a2116robertphillips@google.com
13885de99c7514564c198712fa1c205b3eba41525a1robertphillips@google.com    SkAutoTUnref<GrTexture> texture(
139290bf0ae34af76a4350a5df76ce02feb93d68196sugoi@google.com            GrSWMaskHelper::DrawPathMaskToTexture(fContext, path, stroke,
140290bf0ae34af76a4350a5df76ce02feb93d68196sugoi@google.com                                                  devPathBounds,
14185de99c7514564c198712fa1c205b3eba41525a1robertphillips@google.com                                                  antiAlias, &vm));
14285de99c7514564c198712fa1c205b3eba41525a1robertphillips@google.com    if (NULL == texture) {
14385de99c7514564c198712fa1c205b3eba41525a1robertphillips@google.com        return false;
1441c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com    }
1451c8b85ec1a7658510e4809d376439cf9fc0a76aarobertphillips@google.com
146b6b643945182d1df391fdd11e2e788af8445914frobertphillips@google.com    GrSWMaskHelper::DrawToTargetWithPathMask(texture, target, devPathBounds);
14785de99c7514564c198712fa1c205b3eba41525a1robertphillips@google.com
148290bf0ae34af76a4350a5df76ce02feb93d68196sugoi@google.com    if (path.isInverseFillType()) {
149b6b643945182d1df391fdd11e2e788af8445914frobertphillips@google.com        draw_around_inv_path(target, devClipBounds, devPathBounds);
15085de99c7514564c198712fa1c205b3eba41525a1robertphillips@google.com    }
15185de99c7514564c198712fa1c205b3eba41525a1robertphillips@google.com
15285de99c7514564c198712fa1c205b3eba41525a1robertphillips@google.com    return true;
153509a5db5e14dd358d2ea7ea950d073513231184drobertphillips@google.com}
154