idea: add annotation to SkPaint

Review URL: https://codereview.appspot.com/6355050

git-svn-id: http://skia.googlecode.com/svn/trunk@4555 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@google.com 2012-07-11 19:57:55 +00:00
Родитель 548a433ec3
Коммит b0a34d80c5
9 изменённых файлов: 244 добавлений и 4 удалений

Просмотреть файл

@ -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',

Просмотреть файл

@ -17,6 +17,7 @@
],
'sources': [
'../tests/AAClipTest.cpp',
'../tests/AnnotationTest.cpp',
'../tests/BitmapCopyTest.cpp',
'../tests/BitmapGetColorTest.cpp',
'../tests/BitSetTest.cpp',

Просмотреть файл

@ -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

Просмотреть файл

@ -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,

62
src/core/SkAnnotation.cpp Normal file
Просмотреть файл

@ -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);
}

Просмотреть файл

@ -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);
}

Просмотреть файл

@ -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)

Просмотреть файл

@ -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;

34
tests/AnnotationTest.cpp Normal file
Просмотреть файл

@ -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)