aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gyp/core.gyp1
-rw-r--r--gyp/tests.gyp1
-rw-r--r--include/core/SkAnnotation.h87
-rw-r--r--include/core/SkPaint.h21
-rw-r--r--src/core/SkAnnotation.cpp62
-rw-r--r--src/core/SkDevice.cpp7
-rw-r--r--src/core/SkPaint.cpp27
-rw-r--r--src/gpu/SkGpuDevice.cpp8
-rw-r--r--tests/AnnotationTest.cpp34
9 files changed, 244 insertions, 4 deletions
diff --git a/gyp/core.gyp b/gyp/core.gyp
index a109d7b23f..7b5402404f 100644
--- a/gyp/core.gyp
+++ b/gyp/core.gyp
@@ -9,6 +9,7 @@
'../src/core/ARGB32_Clamp_Bilinear_BitmapShader.h',
'../src/core/Sk64.cpp',
'../src/core/SkAAClip.cpp',
+ '../src/core/SkAnnotation.cpp',
'../src/core/SkAdvancedTypefaceMetrics.cpp',
'../src/core/SkAlphaRuns.cpp',
'../src/core/SkAntiRun.h',
diff --git a/gyp/tests.gyp b/gyp/tests.gyp
index cdf755ba5a..c6e2786f05 100644
--- a/gyp/tests.gyp
+++ b/gyp/tests.gyp
@@ -17,6 +17,7 @@
],
'sources': [
'../tests/AAClipTest.cpp',
+ '../tests/AnnotationTest.cpp',
'../tests/BitmapCopyTest.cpp',
'../tests/BitmapGetColorTest.cpp',
'../tests/BitSetTest.cpp',
diff --git a/include/core/SkAnnotation.h b/include/core/SkAnnotation.h
new file mode 100644
index 0000000000..d401588c3c
--- /dev/null
+++ b/include/core/SkAnnotation.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkAnnotation_DEFINED
+#define SkAnnotation_DEFINED
+
+#include "SkFlattenable.h"
+
+class SkData;
+class SkDataSet;
+
+/**
+ * Experimental class for annotating draws. Do not use directly yet.
+ * Use helper functions at the bottom of this file for now.
+ */
+class SkAnnotation : public SkFlattenable {
+public:
+ enum Flags {
+ // If set, the associated drawing primitive should not be drawn
+ kNoDraw_Flag = 1 << 0,
+ };
+
+ SkAnnotation(SkDataSet*, uint32_t flags);
+ virtual ~SkAnnotation();
+
+ uint32_t getFlags() const { return fFlags; }
+ SkDataSet* getDataSet() const { return fDataSet; }
+
+ bool isNoDraw() const { return SkToBool(fFlags & kNoDraw_Flag); }
+
+ /**
+ * Helper for search the annotation's dataset.
+ */
+ SkData* find(const char name[]) const;
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkAnnotation)
+
+protected:
+ SkAnnotation(SkFlattenableReadBuffer&);
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+ SkDataSet* fDataSet;
+ uint32_t fFlags;
+
+ void writeToStream(SkWStream*) const;
+ void readFromStream(SkStream*);
+
+ typedef SkFlattenable INHERITED;
+};
+
+/**
+ * Experimental collection of predefined Keys into the Annotation dictionary
+ */
+class SkAnnotationKeys {
+public:
+ /**
+ * Returns the canonical key whose payload is a URL
+ */
+ static const char* URL_Key();
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Experimental helper functions to use Annotations
+//
+
+struct SkRect;
+class SkCanvas;
+
+/**
+ * Experimental!
+ *
+ * Annotate the canvas by associating the specified URL with the
+ * specified rectangle (in local coordinates, just like drawRect). If the
+ * backend of this canvas does not support annotations, this call is
+ * safely ignored.
+ *
+ * The caller is responsible for managing its ownership of the SkData.
+ */
+SK_API void SkAnnotateRectWithURL(SkCanvas*, const SkRect&, SkData*);
+
+#endif
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h
index 3d585276b4..684bc455b1 100644
--- a/include/core/SkPaint.h
+++ b/include/core/SkPaint.h
@@ -15,6 +15,7 @@
#include "SkDrawLooper.h"
#include "SkXfermode.h"
+class SkAnnotation;
class SkAutoGlyphCache;
class SkColorFilter;
class SkDescriptor;
@@ -581,6 +582,17 @@ public:
SkImageFilter* getImageFilter() const { return fImageFilter; }
SkImageFilter* setImageFilter(SkImageFilter*);
+
+ SkAnnotation* getAnnotation() const { return fAnnotation; }
+ SkAnnotation* setAnnotation(SkAnnotation*);
+
+ /**
+ * Returns true if there is an annotation installed on this paint, and
+ * the annotation specifics no-drawing.
+ */
+ bool isNoDrawAnnotation() const {
+ return SkToBool(fPrivFlags & kNoDrawAnnotation_PrivFlag);
+ }
/**
* Return the paint's SkDrawLooper (if any). Does not affect the looper's
@@ -903,17 +915,24 @@ private:
SkRasterizer* fRasterizer;
SkDrawLooper* fLooper;
SkImageFilter* fImageFilter;
+ SkAnnotation* fAnnotation;
SkColor fColor;
SkScalar fWidth;
SkScalar fMiterLimit;
- unsigned fFlags : 15;
+ // all of these bitfields should add up to 32
+ unsigned fFlags : 16;
unsigned fTextAlign : 2;
unsigned fCapType : 2;
unsigned fJoinType : 2;
unsigned fStyle : 2;
unsigned fTextEncoding : 2; // 3 values
unsigned fHinting : 2;
+ unsigned fPrivFlags : 4; // these are not flattened/unflattened
+
+ enum PrivFlags {
+ kNoDrawAnnotation_PrivFlag = 1 << 0,
+ };
SkDrawCacheProc getDrawCacheProc() const;
SkMeasureCacheProc getMeasureCacheProc(TextBufferDirection dir,
diff --git a/src/core/SkAnnotation.cpp b/src/core/SkAnnotation.cpp
new file mode 100644
index 0000000000..94ce6a0fab
--- /dev/null
+++ b/src/core/SkAnnotation.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkAnnotation.h"
+#include "SkDataSet.h"
+#include "SkStream.h"
+
+SkAnnotation::SkAnnotation(SkDataSet* data, uint32_t flags) {
+ if (NULL == data) {
+ data = SkDataSet::NewEmpty();
+ } else {
+ data->ref();
+ }
+ fDataSet = data;
+ fFlags = flags;
+}
+
+SkAnnotation::~SkAnnotation() {
+ fDataSet->unref();
+}
+
+SkAnnotation::SkAnnotation(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
+ fFlags = buffer.readU32();
+ fDataSet = SkNEW_ARGS(SkDataSet, (buffer));
+}
+
+void SkAnnotation::flatten(SkFlattenableWriteBuffer& buffer) const {
+ buffer.write32(fFlags);
+ fDataSet->flatten(buffer);
+}
+
+SK_DEFINE_FLATTENABLE_REGISTRAR(SkAnnotation)
+
+const char* SkAnnotationKeys::URL_Key() {
+ return "SkAnnotationKey_URL";
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SkCanvas.h"
+
+void SkAnnotateRectWithURL(SkCanvas* canvas, const SkRect& rect, SkData* value) {
+ if (NULL == value) {
+ return;
+ }
+
+ const char* key = SkAnnotationKeys::URL_Key();
+ SkAutoTUnref<SkDataSet> dataset(SkNEW_ARGS(SkDataSet, (key, value)));
+ SkAnnotation* ann = SkNEW_ARGS(SkAnnotation, (dataset,
+ SkAnnotation::kNoDraw_Flag));
+
+ SkPaint paint;
+ paint.setAnnotation(ann)->unref();
+ SkASSERT(paint.isNoDrawAnnotation());
+
+ canvas->drawRect(rect, paint);
+}
+
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index c5dfc66532..95664c88b5 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -15,6 +15,11 @@ SK_DEFINE_INST_COUNT(SkDevice)
///////////////////////////////////////////////////////////////////////////////
+#define CHECK_FOR_NODRAW_ANNOTATION(paint) \
+ do { if (paint.isNoDrawAnnotation()) { return; } } while (0)
+
+///////////////////////////////////////////////////////////////////////////////
+
SkDevice::SkDevice(const SkBitmap& bitmap) : fBitmap(bitmap) {
fOrigin.setZero();
fMetaData = NULL;
@@ -295,12 +300,14 @@ void SkDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t c
void SkDevice::drawRect(const SkDraw& draw, const SkRect& r,
const SkPaint& paint) {
+ CHECK_FOR_NODRAW_ANNOTATION(paint);
draw.drawRect(r, paint);
}
void SkDevice::drawPath(const SkDraw& draw, const SkPath& path,
const SkPaint& paint, const SkMatrix* prePathMatrix,
bool pathIsMutable) {
+ CHECK_FOR_NODRAW_ANNOTATION(paint);
draw.drawPath(path, paint, prePathMatrix, pathIsMutable);
}
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index 08e642cfbf..ea2d1f636e 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -6,8 +6,8 @@
* found in the LICENSE file.
*/
-
#include "SkPaint.h"
+#include "SkAnnotation.h"
#include "SkColorFilter.h"
#include "SkFontHost.h"
#include "SkImageFilter.h"
@@ -55,6 +55,7 @@ SkPaint::SkPaint() {
fRasterizer = NULL;
fLooper = NULL;
fImageFilter = NULL;
+ fAnnotation = NULL;
fWidth = 0;
#endif
@@ -69,6 +70,7 @@ SkPaint::SkPaint() {
fStyle = kFill_Style;
fTextEncoding = kUTF8_TextEncoding;
fHinting = SkPaintDefaults_Hinting;
+ fPrivFlags = 0;
#ifdef SK_BUILD_FOR_ANDROID
fGenerationID = 0;
#endif
@@ -86,6 +88,7 @@ SkPaint::SkPaint(const SkPaint& src) {
SkSafeRef(fRasterizer);
SkSafeRef(fLooper);
SkSafeRef(fImageFilter);
+ SkSafeRef(fAnnotation);
}
SkPaint::~SkPaint() {
@@ -98,6 +101,7 @@ SkPaint::~SkPaint() {
SkSafeUnref(fRasterizer);
SkSafeUnref(fLooper);
SkSafeUnref(fImageFilter);
+ SkSafeUnref(fAnnotation);
}
SkPaint& SkPaint::operator=(const SkPaint& src) {
@@ -112,6 +116,7 @@ SkPaint& SkPaint::operator=(const SkPaint& src) {
SkSafeRef(src.fRasterizer);
SkSafeRef(src.fLooper);
SkSafeRef(src.fImageFilter);
+ SkSafeRef(src.fAnnotation);
SkSafeUnref(fTypeface);
SkSafeUnref(fPathEffect);
@@ -122,6 +127,7 @@ SkPaint& SkPaint::operator=(const SkPaint& src) {
SkSafeUnref(fRasterizer);
SkSafeUnref(fLooper);
SkSafeUnref(fImageFilter);
+ SkSafeUnref(fAnnotation);
#ifdef SK_BUILD_FOR_ANDROID
uint32_t oldGenerationID = fGenerationID;
@@ -371,6 +377,16 @@ SkImageFilter* SkPaint::setImageFilter(SkImageFilter* imageFilter) {
return imageFilter;
}
+SkAnnotation* SkPaint::setAnnotation(SkAnnotation* annotation) {
+ SkRefCnt_SafeAssign(fAnnotation, annotation);
+ GEN_ID_INC;
+
+ bool isNoDraw = annotation && annotation->isNoDraw();
+ fPrivFlags = SkSetClearMask(fPrivFlags, isNoDraw, kNoDrawAnnotation_PrivFlag);
+
+ return annotation;
+}
+
///////////////////////////////////////////////////////////////////////////////
#include "SkGlyphCache.h"
@@ -1809,7 +1825,7 @@ static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
enum FlatFlags {
kHasTypeface_FlatFlag = 0x01,
- kHasEffects_FlatFlag = 0x02
+ kHasEffects_FlatFlag = 0x02,
};
// The size of a flat paint's POD fields
@@ -1833,6 +1849,7 @@ void SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const {
asint(this->getColorFilter()) |
asint(this->getRasterizer()) |
asint(this->getLooper()) |
+ asint(this->getAnnotation()) |
asint(this->getImageFilter())) {
flatFlags |= kHasEffects_FlatFlag;
}
@@ -1870,6 +1887,7 @@ void SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const {
buffer.writeFlattenable(this->getRasterizer());
buffer.writeFlattenable(this->getLooper());
buffer.writeFlattenable(this->getImageFilter());
+ buffer.writeFlattenable(this->getAnnotation());
}
}
@@ -1878,6 +1896,8 @@ void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) {
const void* podData = buffer.skip(kPODPaintSize);
const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
+ fPrivFlags = 0;
+
// the order we read must match the order we wrote in flatten()
this->setTextSize(read_scalar(pod));
this->setTextScaleX(read_scalar(pod));
@@ -1920,6 +1940,7 @@ void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) {
SkSafeUnref(this->setRasterizer((SkRasterizer*) buffer.readFlattenable()));
SkSafeUnref(this->setLooper((SkDrawLooper*) buffer.readFlattenable()));
SkSafeUnref(this->setImageFilter((SkImageFilter*) buffer.readFlattenable()));
+ SkSafeUnref(this->setAnnotation((SkAnnotation*) buffer.readFlattenable()));
} else {
this->setPathEffect(NULL);
this->setShader(NULL);
@@ -2209,7 +2230,7 @@ bool SkImageFilter::asADilate(SkISize* radius) const {
return false;
}
-//////
+////////////////////
SK_DEFINE_INST_COUNT(SkDrawLooper)
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index c731999dba..fc77c47091 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -71,6 +71,12 @@ enum {
///////////////////////////////////////////////////////////////////////////////
+#define CHECK_FOR_NODRAW_ANNOTATION(paint) \
+ do { if (paint.isNoDrawAnnotation()) { return; } } while (0)
+
+///////////////////////////////////////////////////////////////////////////////
+
+
class SkGpuDevice::SkAutoCachedTexture : public ::SkNoncopyable {
public:
SkAutoCachedTexture() { }
@@ -662,6 +668,7 @@ void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect,
const SkPaint& paint) {
+ CHECK_FOR_NODRAW_ANNOTATION(paint);
CHECK_SHOULD_DRAW(draw);
bool doStroke = paint.getStyle() != SkPaint::kFill_Style;
@@ -976,6 +983,7 @@ bool drawWithMaskFilter(GrContext* context, const SkPath& path,
void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
const SkPaint& paint, const SkMatrix* prePathMatrix,
bool pathIsMutable) {
+ CHECK_FOR_NODRAW_ANNOTATION(paint);
CHECK_SHOULD_DRAW(draw);
bool doFill = true;
diff --git a/tests/AnnotationTest.cpp b/tests/AnnotationTest.cpp
new file mode 100644
index 0000000000..fe2cd01900
--- /dev/null
+++ b/tests/AnnotationTest.cpp
@@ -0,0 +1,34 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Test.h"
+#include "SkAnnotation.h"
+#include "SkData.h"
+#include "SkCanvas.h"
+
+static void test_nodraw(skiatest::Reporter* reporter) {
+ SkBitmap bm;
+ bm.setConfig(SkBitmap::kARGB_8888_Config, 10, 10);
+ bm.allocPixels();
+ bm.eraseColor(0);
+
+ SkCanvas canvas(bm);
+ SkRect r = SkRect::MakeWH(SkIntToScalar(10), SkIntToScalar(10));
+
+ SkAutoDataUnref data(SkData::NewWithCString("http://www.gooogle.com"));
+
+ REPORTER_ASSERT(reporter, 0 == *bm.getAddr32(0, 0));
+ SkAnnotateRectWithURL(&canvas, r, data.get());
+ REPORTER_ASSERT(reporter, 0 == *bm.getAddr32(0, 0));
+}
+
+static void TestAnnotation(skiatest::Reporter* reporter) {
+ test_nodraw(reporter);
+}
+
+#include "TestClassDef.h"
+DEFINE_TESTCLASS("Annotation", AnnotationClass, TestAnnotation)