Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(278)

Unified Diff: src/gpu/GrShape.cpp

Issue 1822723003: Add initial implementation of GrShape and GrStyle classes and tests (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: Fix dumb SkDEBUGCODE mistake Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/gpu/GrShape.h ('k') | src/gpu/GrStyle.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/GrShape.cpp
diff --git a/src/gpu/GrShape.cpp b/src/gpu/GrShape.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5577162ccd8ca4193e66d84c77770a985b846e18
--- /dev/null
+++ b/src/gpu/GrShape.cpp
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrShape.h"
+
+GrShape& GrShape::operator=(const GrShape& that) {
+ bool wasPath = Type::kPath == fType;
+ fStyle = that.fStyle;
+ fType = that.fType;
+ switch (fType) {
+ case Type::kEmpty:
+ if (wasPath) {
+ fPath.reset();
+ }
+ break;
+ case Type::kRRect:
+ if (wasPath) {
+ fPath.reset();
+ }
+ fRRect = that.fRRect;
+ break;
+ case Type::kPath:
+ if (wasPath) {
+ *fPath.get() = *that.fPath.get();
+ } else {
+ fPath.set(*that.fPath.get());
+ }
+ break;
+ }
+ fInheritedKey.reset(that.fInheritedKey.count());
+ memcpy(fInheritedKey.get(), that.fInheritedKey.get(),
+ sizeof(uint32_t) * fInheritedKey.count());
+ return *this;
+}
+
+int GrShape::unstyledKeySize() const {
+ if (fInheritedKey.count()) {
+ return fInheritedKey.count();
+ }
+ switch (fType) {
+ case Type::kEmpty:
+ return 1;
+ case Type::kRRect:
+ SkASSERT(!fInheritedKey.count());
+ SkASSERT(0 == SkRRect::kSizeInMemory % sizeof(uint32_t));
+ return SkRRect::kSizeInMemory / sizeof(uint32_t);
+ case Type::kPath:
+ if (fPath.get()->isVolatile()) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+ SkFAIL("Should never get here.");
+ return 0;
+}
+
+void GrShape::writeUnstyledKey(uint32_t* key) const {
+ SkASSERT(this->unstyledKeySize());
+ SkDEBUGCODE(uint32_t* origKey = key;)
+ if (fInheritedKey.count()) {
+ memcpy(key, fInheritedKey.get(), sizeof(uint32_t) * fInheritedKey.count());
+ SkDEBUGCODE(key += fInheritedKey.count();)
+ } else {
+ switch (fType) {
+ case Type::kEmpty:
+ *key++ = 1;
+ break;
+ case Type::kRRect:
+ fRRect.writeToMemory(key);
+ key += SkRRect::kSizeInMemory / sizeof(uint32_t);
+ break;
+ case Type::kPath:
+ SkASSERT(!fPath.get()->isVolatile());
+ *key++ = fPath.get()->getGenerationID();
+ break;
+ }
+ }
+ SkASSERT(key - origKey == this->unstyledKeySize());
+}
+
+int GrShape::StyleKeySize(const GrStyle& style, bool stopAfterPE) {
+ GR_STATIC_ASSERT(sizeof(uint32_t) == sizeof(SkScalar));
+ int size = 0;
+ if (style.isDashed()) {
+ // One scalar for dash phase and one for each dash value.
+ size += 1 + style.dashIntervalCnt();
+ } else if (style.pathEffect()) {
+ // No key for a generic path effect.
+ return -1;
+ }
+
+ if (stopAfterPE) {
+ return size;
+ }
+
+ if (style.strokeRec().needToApply()) {
+ // One for style/cap/join, 2 for miter and width.
+ size += 3;
+ }
+ return size;
+}
+
+void GrShape::StyleKey(uint32_t* key, const GrStyle& style, bool stopAfterPE) {
+ SkASSERT(key);
+ SkASSERT(StyleKeySize(style, stopAfterPE) >= 0);
+ GR_STATIC_ASSERT(sizeof(uint32_t) == sizeof(SkScalar));
+
+ int i = 0;
+ if (style.isDashed()) {
+ GR_STATIC_ASSERT(sizeof(style.dashPhase()) == sizeof(uint32_t));
+ SkScalar phase = style.dashPhase();
+ memcpy(&key[i++], &phase, sizeof(SkScalar));
+
+ int32_t count = style.dashIntervalCnt();
+ // Dash count should always be even.
+ SkASSERT(0 == (count & 0x1));
+ const SkScalar* intervals = style.dashIntervals();
+ int intervalByteCnt = count * sizeof(SkScalar);
+ memcpy(&key[i], intervals, intervalByteCnt);
+ i += count;
+ } else {
+ SkASSERT(!style.pathEffect());
+ }
+
+ if (!stopAfterPE && style.strokeRec().needToApply()) {
+ enum {
+ kStyleBits = 2,
+ kJoinBits = 2,
+ kCapBits = 32 - kStyleBits - kJoinBits,
+
+ kJoinShift = kStyleBits,
+ kCapShift = kJoinShift + kJoinBits,
+ };
+ GR_STATIC_ASSERT(SkStrokeRec::kStyleCount <= (1 << kStyleBits));
+ GR_STATIC_ASSERT(SkPaint::kJoinCount <= (1 << kJoinBits));
+ GR_STATIC_ASSERT(SkPaint::kCapCount <= (1 << kCapBits));
+ key[i++] = style.strokeRec().getStyle() |
+ style.strokeRec().getJoin() << kJoinShift |
+ style.strokeRec().getCap() << kCapShift;
+
+ SkScalar scalar;
+ // Miter limit only affects miter joins
+ scalar = SkPaint::kMiter_Join == style.strokeRec().getJoin()
+ ? style.strokeRec().getMiter()
+ : -1.f;
+ memcpy(&key[i++], &scalar, sizeof(scalar));
+
+ scalar = style.strokeRec().getWidth();
+ memcpy(&key[i++], &scalar, sizeof(scalar));
+ }
+ SkASSERT(StyleKeySize(style, stopAfterPE) == i);
+}
+
+void GrShape::setInheritedKey(const GrShape &parent, bool stopAfterPE){
+ SkASSERT(!fInheritedKey.count());
+ // If the output shape turns out to be simple, then we will just use its geometric key
+ if (Type::kPath == fType) {
+ // We want ApplyFullStyle(ApplyPathEffect(shape)) to have the same key as
+ // ApplyFullStyle(shape).
+ // The full key is structured as (geo,path_effect,stroke).
+ // If we do ApplyPathEffect we get get,path_effect as the inherited key. If we then
+ // do ApplyFullStyle we'll memcpy geo,path_effect into the new inherited key
+ // and then append the style key (which should now be stroke only) at the end.
+ int parentCnt = parent.fInheritedKey.count();
+ bool useParentGeoKey = !parentCnt;
+ if (useParentGeoKey) {
+ parentCnt = parent.unstyledKeySize();
+ }
+ int styleCnt = StyleKeySize(parent.fStyle, stopAfterPE);
+ if (styleCnt < 0) {
+ // The style doesn't allow a key, set the path to volatile so that we fail when
+ // we try to get a key for the shape.
+ fPath.get()->setIsVolatile(true);
+ } else {
+ fInheritedKey.reset(parentCnt + styleCnt);
+ if (useParentGeoKey) {
+ // This will be the geo key.
+ parent.writeUnstyledKey(fInheritedKey.get());
+ } else {
+ // This should be geo,path_effect
+ memcpy(fInheritedKey.get(), parent.fInheritedKey.get(),
+ parentCnt * sizeof(uint32_t));
+ }
+ // Now turn (geo,path_effect) or (geo) into (geo,path_effect,stroke)
+ StyleKey(fInheritedKey.get() + parentCnt, parent.fStyle, stopAfterPE);
+ }
+ }
+}
+
+GrShape::GrShape(const GrShape& that) : fType(that.fType), fStyle(that.fStyle) {
+ switch (fType) {
+ case Type::kEmpty:
+ return;
+ case Type::kRRect:
+ fRRect = that.fRRect;
+ return;
+ case Type::kPath:
+ fPath.set(*that.fPath.get());
+ return;
+ }
+ fInheritedKey.reset(that.fInheritedKey.count());
+ memcpy(fInheritedKey.get(), that.fInheritedKey.get(),
+ sizeof(uint32_t) * fInheritedKey.count());
+}
+
+GrShape::GrShape(const GrShape& parent, bool stopAfterPE) {
+ fType = Type::kEmpty;
+ SkPathEffect* pe = parent.fStyle.pathEffect();
+ const SkPath* inPath;
+ SkStrokeRec strokeRec = parent.fStyle.strokeRec();
+ if (pe) {
+ fType = Type::kPath;
+ fPath.init();
+ if (parent.fType == Type::kPath) {
+ inPath = parent.fPath.get();
+ } else {
+ inPath = fPath.get();
+ parent.asPath(fPath.get());
+ }
+ // Should we consider bounds? Would have to include in key, but it'd be nice to know
+ // if the bounds actually modified anything before including in key.
+ if (!pe->filterPath(fPath.get(), *inPath, &strokeRec, nullptr)) {
+ // Make an empty unstyled shape if filtering fails.
+ fType = Type::kEmpty;
+ fStyle = GrStyle();
+ fPath.reset();
+ return;
+ }
+ inPath = fPath.get();
+ } else if (stopAfterPE || !strokeRec.needToApply()) {
+ *this = parent;
+ return;
+ } else {
+ fType = Type::kPath;
+ fPath.init();
+ if (parent.fType == Type::kPath) {
+ inPath = parent.fPath.get();
+ } else {
+ inPath = fPath.get();
+ parent.asPath(fPath.get());
+ }
+ }
+ if (!stopAfterPE) {
+ strokeRec.applyToPath(fPath.get(), *inPath);
+ } else {
+ fStyle = GrStyle(strokeRec, nullptr);
+ }
+ this->setInheritedKey(parent, stopAfterPE);
+}
« no previous file with comments | « src/gpu/GrShape.h ('k') | src/gpu/GrStyle.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698