Line data Source code
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 :
13 0 : GrGLPathRange::GrGLPathRange(GrGLGpu* gpu, PathGenerator* pathGenerator, const GrStyle& style)
14 : : INHERITED(gpu, pathGenerator),
15 : fStyle(style),
16 0 : fBasePathID(gpu->glPathRendering()->genPaths(this->getNumPaths())),
17 0 : fGpuMemorySize(0) {
18 0 : this->init();
19 0 : this->registerWithCache(SkBudgeted::kYes);
20 0 : }
21 :
22 0 : GrGLPathRange::GrGLPathRange(GrGLGpu* gpu,
23 : GrGLuint basePathID,
24 : int numPaths,
25 : size_t gpuMemorySize,
26 0 : const GrStyle& style)
27 : : INHERITED(gpu, numPaths),
28 : fStyle(style),
29 : fBasePathID(basePathID),
30 0 : fGpuMemorySize(gpuMemorySize) {
31 0 : this->init();
32 0 : this->registerWithCache(SkBudgeted::kYes);
33 0 : }
34 :
35 0 : void GrGLPathRange::init() {
36 0 : 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 0 : bool forceFill = fStyle.pathEffect() ||
41 0 : (stroke.needToApply() && stroke.getCap() != SkPaint::kButt_Cap);
42 :
43 0 : if (forceFill) {
44 0 : fShouldStroke = false;
45 0 : fShouldFill = true;
46 : } else {
47 0 : fShouldStroke = stroke.needToApply();
48 0 : fShouldFill = stroke.isFillStyle() ||
49 0 : stroke.getStyle() == SkStrokeRec::kStrokeAndFill_Style;
50 : }
51 0 : }
52 :
53 0 : void GrGLPathRange::onInitPath(int index, const SkPath& origSkPath) const {
54 0 : GrGLGpu* gpu = static_cast<GrGLGpu*>(this->getGpu());
55 0 : if (nullptr == gpu) {
56 0 : return;
57 : }
58 : // Make sure the path at this index hasn't been initted already.
59 0 : SkDEBUGCODE(
60 : GrGLboolean isPath;
61 : GR_GL_CALL_RET(gpu->glInterface(), isPath, IsPath(fBasePathID + index)));
62 0 : SkASSERT(GR_GL_FALSE == isPath);
63 :
64 0 : if (origSkPath.isEmpty()) {
65 0 : GrGLPath::InitPathObjectEmptyPath(gpu, fBasePathID + index);
66 0 : } else if (fShouldStroke) {
67 0 : GrGLPath::InitPathObjectPathData(gpu, fBasePathID + index, origSkPath);
68 0 : GrGLPath::InitPathObjectStroke(gpu, fBasePathID + index, fStyle.strokeRec());
69 : } else {
70 0 : const SkPath* skPath = &origSkPath;
71 0 : SkTLazy<SkPath> tmpPath;
72 0 : 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 0 : if (!fStyle.applyToPath(tmpPath.init(), &fill, *skPath, SK_Scalar1)) {
80 0 : 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 0 : SkASSERT(SkStrokeRec::kFill_InitStyle == fill);
85 0 : skPath = tmpPath.get();
86 :
87 : }
88 0 : GrGLPath::InitPathObjectPathData(gpu, fBasePathID + index, *skPath);
89 : }
90 : // TODO: Use a better approximation for the individual path sizes.
91 0 : fGpuMemorySize += 100;
92 : }
93 :
94 0 : void GrGLPathRange::onRelease() {
95 0 : SkASSERT(this->getGpu());
96 :
97 0 : if (0 != fBasePathID) {
98 0 : static_cast<GrGLGpu*>(this->getGpu())->glPathRendering()->deletePaths(fBasePathID,
99 0 : this->getNumPaths());
100 0 : fBasePathID = 0;
101 : }
102 :
103 0 : INHERITED::onRelease();
104 0 : }
105 :
106 0 : void GrGLPathRange::onAbandon() {
107 0 : fBasePathID = 0;
108 :
109 0 : INHERITED::onAbandon();
110 0 : }
|