1
2/*
3 * Copyright 2014 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 "GrGLPathRange.h"
10#include "GrGLPath.h"
11#include "GrGLPathRendering.h"
12#include "GrGLGpu.h"
13
14GrGLPathRange::GrGLPathRange(GrGLGpu* gpu, PathGenerator* pathGenerator, const GrStrokeInfo& stroke)
15    : INHERITED(gpu, pathGenerator),
16      fStroke(stroke),
17      fBasePathID(gpu->glPathRendering()->genPaths(this->getNumPaths())),
18      fGpuMemorySize(0) {
19    this->init();
20    this->registerWithCache();
21}
22
23GrGLPathRange::GrGLPathRange(GrGLGpu* gpu,
24                             GrGLuint basePathID,
25                             int numPaths,
26                             size_t gpuMemorySize,
27                             const GrStrokeInfo& stroke)
28    : INHERITED(gpu, numPaths),
29      fStroke(stroke),
30      fBasePathID(basePathID),
31      fGpuMemorySize(gpuMemorySize) {
32    this->init();
33    this->registerWithCache();
34}
35
36void GrGLPathRange::init() {
37    // Must force fill:
38    // * dashing: NVPR stroke dashing is different to Skia.
39    // * end caps: NVPR stroking degenerate contours with end caps is different to Skia.
40    bool forceFill = fStroke.isDashed() ||
41            (fStroke.needToApply() && fStroke.getCap() != SkPaint::kButt_Cap);
42
43    if (forceFill) {
44        fShouldStroke = false;
45        fShouldFill = true;
46    } else {
47        fShouldStroke = fStroke.needToApply();
48        fShouldFill = fStroke.isFillStyle() ||
49                fStroke.getStyle() == SkStrokeRec::kStrokeAndFill_Style;
50    }
51}
52
53void GrGLPathRange::onInitPath(int index, const SkPath& origSkPath) const {
54    GrGLGpu* gpu = static_cast<GrGLGpu*>(this->getGpu());
55    if (nullptr == gpu) {
56        return;
57    }
58
59    // Make sure the path at this index hasn't been initted already.
60    SkDEBUGCODE(
61        GrGLboolean isPath;
62        GR_GL_CALL_RET(gpu->glInterface(), isPath, IsPath(fBasePathID + index)));
63    SkASSERT(GR_GL_FALSE == isPath);
64
65    if (origSkPath.isEmpty()) {
66        GrGLPath::InitPathObjectEmptyPath(gpu, fBasePathID + index);
67    } else if (fShouldStroke) {
68        GrGLPath::InitPathObjectPathData(gpu, fBasePathID + index, origSkPath);
69        GrGLPath::InitPathObjectStroke(gpu, fBasePathID + index, fStroke);
70    } else {
71        const SkPath* skPath = &origSkPath;
72        SkTLazy<SkPath> tmpPath;
73        const GrStrokeInfo* stroke = &fStroke;
74        GrStrokeInfo tmpStroke(SkStrokeRec::kFill_InitStyle);
75
76        // Dashing must be applied to the path. However, if dashing is present,
77        // we must convert all the paths to fills. The GrStrokeInfo::applyDash leaves
78        // simple paths as strokes but converts other paths to fills.
79        // Thus we must stroke the strokes here, so that all paths in the
80        // path range are using the same style.
81        if (fStroke.isDashed()) {
82            if (!stroke->applyDashToPath(tmpPath.init(), &tmpStroke, *skPath)) {
83                return;
84            }
85            skPath = tmpPath.get();
86            stroke = &tmpStroke;
87        }
88        if (stroke->needToApply()) {
89            if (!tmpPath.isValid()) {
90                tmpPath.init();
91            }
92            if (!stroke->applyToPath(tmpPath.get(), *tmpPath.get())) {
93                return;
94            }
95        }
96        GrGLPath::InitPathObjectPathData(gpu, fBasePathID + index, *skPath);
97    }
98    // TODO: Use a better approximation for the individual path sizes.
99    fGpuMemorySize += 100;
100}
101
102void GrGLPathRange::onRelease() {
103    SkASSERT(this->getGpu());
104
105    if (0 != fBasePathID && this->shouldFreeResources()) {
106        static_cast<GrGLGpu*>(this->getGpu())->glPathRendering()->deletePaths(fBasePathID,
107                                                                              this->getNumPaths());
108        fBasePathID = 0;
109    }
110
111    INHERITED::onRelease();
112}
113
114void GrGLPathRange::onAbandon() {
115    fBasePathID = 0;
116
117    INHERITED::onAbandon();
118}
119