1 /*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "GrGLPathRange.h"
9 #include "GrGLPath.h"
10 #include "GrGLPathRendering.h"
11 #include "GrGLGpu.h"
12
GrGLPathRange(GrGLGpu * gpu,PathGenerator * pathGenerator,const GrStyle & style)13 GrGLPathRange::GrGLPathRange(GrGLGpu* gpu, PathGenerator* pathGenerator, const GrStyle& style)
14 : INHERITED(gpu, pathGenerator),
15 fStyle(style),
16 fBasePathID(gpu->glPathRendering()->genPaths(this->getNumPaths())),
17 fGpuMemorySize(0) {
18 this->init();
19 this->registerWithCache(SkBudgeted::kYes);
20 }
21
GrGLPathRange(GrGLGpu * gpu,GrGLuint basePathID,int numPaths,size_t gpuMemorySize,const GrStyle & style)22 GrGLPathRange::GrGLPathRange(GrGLGpu* gpu,
23 GrGLuint basePathID,
24 int numPaths,
25 size_t gpuMemorySize,
26 const GrStyle& style)
27 : INHERITED(gpu, numPaths),
28 fStyle(style),
29 fBasePathID(basePathID),
30 fGpuMemorySize(gpuMemorySize) {
31 this->init();
32 this->registerWithCache(SkBudgeted::kYes);
33 }
34
init()35 void GrGLPathRange::init() {
36 const SkStrokeRec& stroke = fStyle.strokeRec();
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 = fStyle.pathEffect() ||
41 (stroke.needToApply() && stroke.getCap() != SkPaint::kButt_Cap);
42
43 if (forceFill) {
44 fShouldStroke = false;
45 fShouldFill = true;
46 } else {
47 fShouldStroke = stroke.needToApply();
48 fShouldFill = stroke.isFillStyle() ||
49 stroke.getStyle() == SkStrokeRec::kStrokeAndFill_Style;
50 }
51 }
52
onInitPath(int index,const SkPath & origSkPath) const53 void GrGLPathRange::onInitPath(int index, const SkPath& origSkPath) const {
54 GrGLGpu* gpu = static_cast<GrGLGpu*>(this->getGpu());
55 if (nullptr == gpu) {
56 return;
57 }
58 // Make sure the path at this index hasn't been initted already.
59 SkDEBUGCODE(
60 GrGLboolean isPath;
61 GR_GL_CALL_RET(gpu->glInterface(), isPath, IsPath(fBasePathID + index)));
62 SkASSERT(GR_GL_FALSE == isPath);
63
64 if (origSkPath.isEmpty()) {
65 GrGLPath::InitPathObjectEmptyPath(gpu, fBasePathID + index);
66 } else if (fShouldStroke) {
67 GrGLPath::InitPathObjectPathData(gpu, fBasePathID + index, origSkPath);
68 GrGLPath::InitPathObjectStroke(gpu, fBasePathID + index, fStyle.strokeRec());
69 } else {
70 const SkPath* skPath = &origSkPath;
71 SkTLazy<SkPath> tmpPath;
72 if (!fStyle.isSimpleFill()) {
73 SkStrokeRec::InitStyle fill;
74 // The path effect must be applied to the path. However, if a path effect is present,
75 // we must convert all the paths to fills. The path effect application may leave
76 // simple paths as strokes but converts other paths to fills.
77 // Thus we must stroke the strokes here, so that all paths in the
78 // path range are using the same style.
79 if (!fStyle.applyToPath(tmpPath.init(), &fill, *skPath, SK_Scalar1)) {
80 return;
81 }
82 // We shouldn't have allowed hairlines or arbitrary path effect styles to get here
83 // so after application we better have a filled path.
84 SkASSERT(SkStrokeRec::kFill_InitStyle == fill);
85 skPath = tmpPath.get();
86
87 }
88 GrGLPath::InitPathObjectPathData(gpu, fBasePathID + index, *skPath);
89 }
90 // TODO: Use a better approximation for the individual path sizes.
91 fGpuMemorySize += 100;
92 }
93
onRelease()94 void GrGLPathRange::onRelease() {
95 SkASSERT(this->getGpu());
96
97 if (0 != fBasePathID) {
98 static_cast<GrGLGpu*>(this->getGpu())->glPathRendering()->deletePaths(fBasePathID,
99 this->getNumPaths());
100 fBasePathID = 0;
101 }
102
103 INHERITED::onRelease();
104 }
105
onAbandon()106 void GrGLPathRange::onAbandon() {
107 fBasePathID = 0;
108
109 INHERITED::onAbandon();
110 }
111