/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrGLPathRange.h"
#include "GrGLPath.h"
#include "GrGLPathRendering.h"
#include "GrGLGpu.h"
GrGLPathRange::GrGLPathRange(GrGLGpu* gpu, PathGenerator* pathGenerator, const GrStrokeInfo& stroke)
: INHERITED(gpu, pathGenerator),
fStroke(stroke),
fBasePathID(gpu->glPathRendering()->genPaths(this->getNumPaths())),
fGpuMemorySize(0) {
this->init();
this->registerWithCache();
}
GrGLPathRange::GrGLPathRange(GrGLGpu* gpu,
GrGLuint basePathID,
int numPaths,
size_t gpuMemorySize,
const GrStrokeInfo& stroke)
: INHERITED(gpu, numPaths),
fStroke(stroke),
fBasePathID(basePathID),
fGpuMemorySize(gpuMemorySize) {
this->init();
this->registerWithCache();
}
void GrGLPathRange::init() {
// Must force fill:
// * dashing: NVPR stroke dashing is different to Skia.
// * end caps: NVPR stroking degenerate contours with end caps is different to Skia.
bool forceFill = fStroke.isDashed() ||
(fStroke.needToApply() && fStroke.getCap() != SkPaint::kButt_Cap);
if (forceFill) {
fShouldStroke = false;
fShouldFill = true;
} else {
fShouldStroke = fStroke.needToApply();
fShouldFill = fStroke.isFillStyle() ||
fStroke.getStyle() == SkStrokeRec::kStrokeAndFill_Style;
}
}
void GrGLPathRange::onInitPath(int index, const SkPath& origSkPath) const {
GrGLGpu* gpu = static_cast<GrGLGpu*>(this->getGpu());
if (nullptr == gpu) {
return;
}
// Make sure the path at this index hasn't been initted already.
SkDEBUGCODE(
GrGLboolean isPath;
GR_GL_CALL_RET(gpu->glInterface(), isPath, IsPath(fBasePathID + index)));
SkASSERT(GR_GL_FALSE == isPath);
if (origSkPath.isEmpty()) {
GrGLPath::InitPathObjectEmptyPath(gpu, fBasePathID + index);
} else if (fShouldStroke) {
GrGLPath::InitPathObjectPathData(gpu, fBasePathID + index, origSkPath);
GrGLPath::InitPathObjectStroke(gpu, fBasePathID + index, fStroke);
} else {
const SkPath* skPath = &origSkPath;
SkTLazy<SkPath> tmpPath;
const GrStrokeInfo* stroke = &fStroke;
GrStrokeInfo tmpStroke(SkStrokeRec::kFill_InitStyle);
// Dashing must be applied to the path. However, if dashing is present,
// we must convert all the paths to fills. The GrStrokeInfo::applyDash leaves
// simple paths as strokes but converts other paths to fills.
// Thus we must stroke the strokes here, so that all paths in the
// path range are using the same style.
if (fStroke.isDashed()) {
if (!stroke->applyDashToPath(tmpPath.init(), &tmpStroke, *skPath)) {
return;
}
skPath = tmpPath.get();
stroke = &tmpStroke;
}
if (stroke->needToApply()) {
if (!tmpPath.isValid()) {
tmpPath.init();
}
if (!stroke->applyToPath(tmpPath.get(), *tmpPath.get())) {
return;
}
}
GrGLPath::InitPathObjectPathData(gpu, fBasePathID + index, *skPath);
}
// TODO: Use a better approximation for the individual path sizes.
fGpuMemorySize += 100;
}
void GrGLPathRange::onRelease() {
SkASSERT(this->getGpu());
if (0 != fBasePathID && this->shouldFreeResources()) {
static_cast<GrGLGpu*>(this->getGpu())->glPathRendering()->deletePaths(fBasePathID,
this->getNumPaths());
fBasePathID = 0;
}
INHERITED::onRelease();
}
void GrGLPathRange::onAbandon() {
fBasePathID = 0;
INHERITED::onAbandon();
}