diff options
34 files changed, 333 insertions, 253 deletions
diff --git a/include/core/SkAnnotation.h b/include/core/SkAnnotation.h index 80503c78d2..2ea66d37ac 100644 --- a/include/core/SkAnnotation.h +++ b/include/core/SkAnnotation.h @@ -1,3 +1,4 @@ + /* * Copyright 2012 Google Inc. * @@ -8,83 +9,21 @@ #ifndef SkAnnotation_DEFINED #define SkAnnotation_DEFINED -#include "SkRefCnt.h" -#include "SkString.h" #include "SkTypes.h" +// for chrome in PrintContextTest.cpp +#define SK_SUPPORT_NEW_ANNOTATION_CANVAS_VIRTUAL + class SkData; -class SkReadBuffer; -class SkWriteBuffer; struct SkPoint; - -/** - * Experimental class for annotating draws. Do not use directly yet. - * Use helper functions at the bottom of this file for now. - */ -class SkAnnotation : public SkRefCnt { -public: - virtual ~SkAnnotation(); - - static SkAnnotation* Create(const char key[], SkData* value) { - return new SkAnnotation(key, value); - } - - static SkAnnotation* Create(SkReadBuffer& buffer) { return new SkAnnotation(buffer); } - - /** - * Return the data for the specified key, or NULL. - */ - SkData* find(const char key[]) const; - - void writeToBuffer(SkWriteBuffer&) const; - -private: - SkAnnotation(const char key[], SkData* value); - SkAnnotation(SkReadBuffer&); - - SkString fKey; - SkData* fData; - - typedef SkRefCnt 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(); - - /** - * Returns the canonical key whose payload is the name of a destination to - * be defined. - */ - static const char* Define_Named_Dest_Key(); - - /** - * Returns the canonical key whose payload is the name of a destination to - * be linked to. - */ - static const char* Link_Named_Dest_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 + * 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. @@ -92,8 +31,6 @@ class SkCanvas; SK_API void SkAnnotateRectWithURL(SkCanvas*, const SkRect&, SkData*); /** - * Experimental! - * * Annotate the canvas by associating a name with the specified point. * * If the backend of this canvas does not support annotations, this call is @@ -104,8 +41,6 @@ SK_API void SkAnnotateRectWithURL(SkCanvas*, const SkRect&, SkData*); SK_API void SkAnnotateNamedDestination(SkCanvas*, const SkPoint&, SkData*); /** - * Experimental! - * * Annotate the canvas by making the specified rectangle link to a named * destination. * @@ -116,5 +51,4 @@ SK_API void SkAnnotateNamedDestination(SkCanvas*, const SkPoint&, SkData*); */ SK_API void SkAnnotateLinkToDestination(SkCanvas*, const SkRect&, SkData*); - #endif diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h index c23d748e78..1b4571a09c 100644 --- a/include/core/SkCanvas.h +++ b/include/core/SkCanvas.h @@ -22,6 +22,7 @@ class GrRenderTarget; class SkBaseDevice; class SkCanvasClipVisitor; class SkClipStack; +class SkData; class SkDraw; class SkDrawable; class SkDrawFilter; @@ -1072,6 +1073,18 @@ public: void drawDrawable(SkDrawable* drawable, const SkMatrix* = NULL); void drawDrawable(SkDrawable*, SkScalar x, SkScalar y); + /** + * Send an "annotation" to the canvas. The annotation is a key/value pair, where the key is + * a null-terminated utf8 string, and the value is a blob of data stored in an SkData + * (which may be null). The annotation is associated with the specified rectangle. + * + * The caller still retains its ownership of the data (if any). + * + * Note: on may canvas types, this information is ignored, but some canvases (e.g. recording + * a picture or drawing to a PDF document) will pass on this information. + */ + void drawAnnotation(const SkRect&, const char key[], SkData* value); + ////////////////////////////////////////////////////////////////////////// #ifdef SK_INTERNAL #ifndef SK_SUPPORT_LEGACY_DRAWFILTER @@ -1221,6 +1234,7 @@ protected: virtual void didConcat(const SkMatrix&) {} virtual void didSetMatrix(const SkMatrix&) {} + virtual void onDrawAnnotation(const SkRect&, const char key[], SkData* value); virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&); virtual void onDrawText(const void* text, size_t byteLength, SkScalar x, diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h index 65ec56f902..cd13d5482e 100644 --- a/include/core/SkDevice.h +++ b/include/core/SkDevice.h @@ -252,6 +252,8 @@ protected: virtual void drawAtlas(const SkDraw&, const SkImage* atlas, const SkRSXform[], const SkRect[], const SkColor[], int count, SkXfermode::Mode, const SkPaint&); + virtual void drawAnnotation(const SkDraw&, const SkRect&, const char[], SkData*) {} + /** The SkDevice passed will be an SkDevice which was returned by a call to onCreateDevice on this device with kNeverTile_TileExpectation. */ diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h index b58a3f3d4f..7090f3e249 100644 --- a/include/core/SkPaint.h +++ b/include/core/SkPaint.h @@ -13,7 +13,6 @@ #include "SkMatrix.h" #include "SkXfermode.h" -class SkAnnotation; class SkAutoDescriptor; class SkAutoGlyphCache; class SkColorFilter; @@ -625,9 +624,6 @@ public: SkImageFilter* getImageFilter() const { return fImageFilter; } SkImageFilter* setImageFilter(SkImageFilter*); - SkAnnotation* getAnnotation() const { return fAnnotation; } - SkAnnotation* setAnnotation(SkAnnotation*); - /** * Return the paint's SkDrawLooper (if any). Does not affect the looper's * reference count. @@ -1039,7 +1035,6 @@ private: SkRasterizer* fRasterizer; SkDrawLooper* fLooper; SkImageFilter* fImageFilter; - SkAnnotation* fAnnotation; SkScalar fTextSize; SkScalar fTextScaleX; diff --git a/include/core/SkPicture.h b/include/core/SkPicture.h index 7c8c187fd8..36f5310230 100644 --- a/include/core/SkPicture.h +++ b/include/core/SkPicture.h @@ -192,10 +192,11 @@ private: // V41: Added serialization of SkBitmapSource's filterQuality parameter // V42: Added a bool to SkPictureShader serialization to indicate did-we-serialize-a-picture? // V43: Added DRAW_IMAGE and DRAW_IMAGE_RECT opt codes to serialized data + // V44: Move annotations from paint to drawAnnotation // Only SKPs within the min/current picture version range (inclusive) can be read. static const uint32_t MIN_PICTURE_VERSION = 35; // Produced by Chrome M39. - static const uint32_t CURRENT_PICTURE_VERSION = 43; + static const uint32_t CURRENT_PICTURE_VERSION = 44; static_assert(MIN_PICTURE_VERSION <= 41, "Remove kFontFileName and related code from SkFontDescriptor.cpp."); @@ -205,7 +206,7 @@ private: static_assert(MIN_PICTURE_VERSION <= 43, "Remove SkBitmapSourceDeserializer."); - + static bool IsValidPictInfo(const SkPictInfo& info); static SkPicture* Forwardport(const SkPictInfo&, const SkPictureData*); diff --git a/include/core/SkWriter32.h b/include/core/SkWriter32.h index 1e7ec6d348..a2c6f5d472 100644 --- a/include/core/SkWriter32.h +++ b/include/core/SkWriter32.h @@ -206,6 +206,18 @@ public: */ static size_t WriteStringSize(const char* str, size_t len = (size_t)-1); + void writeData(const SkData* data) { + uint32_t len = data ? SkToU32(data->size()) : 0; + this->write32(len); + if (data) { + this->writePad(data->data(), len); + } + } + + static size_t WriteDataSize(const SkData* data) { + return 4 + SkAlign4(data ? data->size() : 0); + } + /** * Move the cursor back to offset bytes from the beginning. * offset must be a multiple of 4 no greater than size(). diff --git a/include/private/SkRecords.h b/include/private/SkRecords.h index ecd73a12d9..1e274e9f46 100644 --- a/include/private/SkRecords.h +++ b/include/private/SkRecords.h @@ -8,6 +8,7 @@ #ifndef SkRecords_DEFINED #define SkRecords_DEFINED +#include "SkData.h" #include "SkCanvas.h" #include "SkDrawable.h" #include "SkImageFilter.h" @@ -17,6 +18,7 @@ #include "SkRect.h" #include "SkRRect.h" #include "SkRSXform.h" +#include "SkString.h" #include "SkTextBlob.h" namespace SkRecords { @@ -66,7 +68,8 @@ namespace SkRecords { M(DrawRect) \ M(DrawTextBlob) \ M(DrawAtlas) \ - M(DrawVertices) + M(DrawVertices) \ + M(DrawAnnotation) // Defines SkRecords::Type, an enum of all record types. #define ENUM(T) T##_Type, @@ -358,7 +361,10 @@ RECORD(DrawVertices, kDraw_Tag, RefBox<SkXfermode> xmode; PODArray<uint16_t> indices; int indexCount); - +RECORD(DrawAnnotation, 0, + SkRect rect; + SkString key; + RefBox<SkData> value); #undef RECORD } // namespace SkRecords diff --git a/include/utils/SkDumpCanvas.h b/include/utils/SkDumpCanvas.h index d4c6dbf81b..1c16bf3f03 100644 --- a/include/utils/SkDumpCanvas.h +++ b/include/utils/SkDumpCanvas.h @@ -48,6 +48,7 @@ public: kDrawVertices_Verb, kDrawPatch_Verb, kDrawData_Verb, // obsolete + kDrawAnnotation_Verb, kCull_Verb }; @@ -120,6 +121,7 @@ protected: void onClipRegion(const SkRegion&, SkRegion::Op) override; void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override; + void onDrawAnnotation(const SkRect&, const char key[], SkData* value) override; static const char* EdgeStyleToAAString(ClipEdgeStyle edgeStyle); diff --git a/include/utils/SkNWayCanvas.h b/include/utils/SkNWayCanvas.h index 175701edbe..f2a99db802 100644 --- a/include/utils/SkNWayCanvas.h +++ b/include/utils/SkNWayCanvas.h @@ -79,6 +79,7 @@ protected: void onClipRegion(const SkRegion&, SkRegion::Op) override; void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override; + void onDrawAnnotation(const SkRect&, const char[], SkData*) override; class Iter; diff --git a/samplecode/SampleFilterFuzz.cpp b/samplecode/SampleFilterFuzz.cpp index 687921ae0b..28155f14fd 100644 --- a/samplecode/SampleFilterFuzz.cpp +++ b/samplecode/SampleFilterFuzz.cpp @@ -9,7 +9,6 @@ #include "Sk2DPathEffect.h" #include "SkAlphaThresholdFilter.h" #include "SkArcToPathEffect.h" -#include "SkAnnotation.h" #include "SkBlurImageFilter.h" #include "SkBlurMaskFilter.h" #include "SkCanvas.h" @@ -545,9 +544,6 @@ static SkPaint make_paint() { paint.setRasterizer(rasterizer); paint.setImageFilter(make_image_filter()); SkAutoDataUnref data(make_3Dlut(nullptr, make_bool(), make_bool(), make_bool())); - SkAutoTUnref<SkAnnotation> annotation( - SkAnnotation::Create(make_string().c_str(), data)); - paint.setAnnotation(annotation); paint.setTextAlign(make_paint_align()); paint.setTextSize(make_scalar()); paint.setTextScaleX(make_scalar()); diff --git a/src/core/SkAnnotation.cpp b/src/core/SkAnnotation.cpp index 84d41fc669..09a6296fba 100644 --- a/src/core/SkAnnotation.cpp +++ b/src/core/SkAnnotation.cpp @@ -6,38 +6,10 @@ */ #include "SkAnnotation.h" -#include "SkData.h" -#include "SkPaint.h" +#include "SkAnnotationKeys.h" +#include "SkCanvas.h" #include "SkPoint.h" -#include "SkReadBuffer.h" -#include "SkWriteBuffer.h" - -SkAnnotation::SkAnnotation(const char key[], SkData* value) : fKey(key) { - if (nullptr == value) { - value = SkData::NewEmpty(); - } else { - value->ref(); - } - fData = value; -} - -SkAnnotation::~SkAnnotation() { - fData->unref(); -} - -SkData* SkAnnotation::find(const char key[]) const { - return fKey.equals(key) ? fData : nullptr; -} - -SkAnnotation::SkAnnotation(SkReadBuffer& buffer) { - buffer.readString(&fKey); - fData = buffer.readByteArrayAsData(); -} - -void SkAnnotation::writeToBuffer(SkWriteBuffer& buffer) const { - buffer.writeString(fKey.c_str()); - buffer.writeDataAsByteArray(fData); -} +#include "SkRect.h" const char* SkAnnotationKeys::URL_Key() { return "SkAnnotationKey_URL"; @@ -51,37 +23,26 @@ const char* SkAnnotationKeys::Link_Named_Dest_Key() { return "SkAnnotationKey_Link_Named_Dest"; }; -/////////////////////////////////////////////////////////////////////////////// - -#include "SkCanvas.h" - -static void annotate_paint(SkPaint& paint, const char* key, SkData* value) { - paint.setAnnotation(SkAnnotation::Create(key, value))->unref(); -} +////////////////////////////////////////////////////////////////////////////////////////////////// void SkAnnotateRectWithURL(SkCanvas* canvas, const SkRect& rect, SkData* value) { if (nullptr == value) { return; } - SkPaint paint; - annotate_paint(paint, SkAnnotationKeys::URL_Key(), value); - canvas->drawRect(rect, paint); + canvas->drawAnnotation(rect, SkAnnotationKeys::URL_Key(), value); } void SkAnnotateNamedDestination(SkCanvas* canvas, const SkPoint& point, SkData* name) { if (nullptr == name) { return; } - SkPaint paint; - annotate_paint(paint, SkAnnotationKeys::Define_Named_Dest_Key(), name); - canvas->drawPoint(point.x(), point.y(), paint); + const SkRect rect = SkRect::MakeXYWH(point.x(), point.y(), 0, 0); + canvas->drawAnnotation(rect, SkAnnotationKeys::Define_Named_Dest_Key(), name); } void SkAnnotateLinkToDestination(SkCanvas* canvas, const SkRect& rect, SkData* name) { if (nullptr == name) { return; } - SkPaint paint; - annotate_paint(paint, SkAnnotationKeys::Link_Named_Dest_Key(), name); - canvas->drawRect(rect, paint); + canvas->drawAnnotation(rect, SkAnnotationKeys::Link_Named_Dest_Key(), name); } diff --git a/src/core/SkAnnotationKeys.h b/src/core/SkAnnotationKeys.h new file mode 100644 index 0000000000..dff9338807 --- /dev/null +++ b/src/core/SkAnnotationKeys.h @@ -0,0 +1,33 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkAnnotationKeys_DEFINED +#define SkAnnotationKeys_DEFINED + +#include "SkTypes.h" + +class SkAnnotationKeys { +public: + /** + * Returns the canonical key whose payload is a URL + */ + static const char* URL_Key(); + + /** + * Returns the canonical key whose payload is the name of a destination to + * be defined. + */ + static const char* Define_Named_Dest_Key(); + + /** + * Returns the canonical key whose payload is the name of a destination to + * be linked to. + */ + static const char* Link_Named_Dest_Key(); +}; + +#endif diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp index 8c3c562181..d5dfcc1733 100644 --- a/src/core/SkBitmapDevice.cpp +++ b/src/core/SkBitmapDevice.cpp @@ -20,9 +20,6 @@ class SkColorTable; -#define CHECK_FOR_ANNOTATION(paint) \ - do { if (paint.getAnnotation()) { return; } } while (0) - static bool valid_for_bitmap_device(const SkImageInfo& info, SkAlphaType* newAlphaType) { if (info.width() < 0 || info.height() < 0) { @@ -204,18 +201,14 @@ void SkBitmapDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) { void SkBitmapDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) { - CHECK_FOR_ANNOTATION(paint); draw.drawPoints(mode, count, pts, paint); } void SkBitmapDevice::drawRect(const SkDraw& draw, const SkRect& r, const SkPaint& paint) { - CHECK_FOR_ANNOTATION(paint); draw.drawRect(r, paint); } void SkBitmapDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint& paint) { - CHECK_FOR_ANNOTATION(paint); - SkPath path; path.addOval(oval); // call the VIRTUAL version, so any subclasses who do handle drawPath aren't @@ -224,8 +217,6 @@ void SkBitmapDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPa } void SkBitmapDevice::drawRRect(const SkDraw& draw, const SkRRect& rrect, const SkPaint& paint) { - CHECK_FOR_ANNOTATION(paint); - #ifdef SK_IGNORE_BLURRED_RRECT_OPT SkPath path; @@ -241,7 +232,6 @@ void SkBitmapDevice::drawRRect(const SkDraw& draw, const SkRRect& rrect, const S void SkBitmapDevice::drawPath(const SkDraw& draw, const SkPath& path, const SkPaint& paint, const SkMatrix* prePathMatrix, bool pathIsMutable) { - CHECK_FOR_ANNOTATION(paint); draw.drawPath(path, paint, prePathMatrix, pathIsMutable); } diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index a628105001..f3f38386bd 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -1973,6 +1973,12 @@ void SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const Sk this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint); } +void SkCanvas::drawAnnotation(const SkRect& rect, const char key[], SkData* value) { + if (key) { + this->onDrawAnnotation(rect, key, value); + } +} + void SkCanvas::legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, const SkPaint* paint, SrcRectConstraint constraint) { if (src) { @@ -2725,6 +2731,17 @@ void SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const LOOPER_END } +void SkCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) { + SkASSERT(key); + + SkPaint paint; + LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, nullptr) + while (iter.next()) { + iter.fDevice->drawAnnotation(iter, rect, key, value); + } + LOOPER_END +} + ////////////////////////////////////////////////////////////////////////////// // These methods are NOT virtual, and therefore must call back into virtual // methods, rather than actually drawing themselves. diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp index 017662ff48..cdfb110454 100644 --- a/src/core/SkPaint.cpp +++ b/src/core/SkPaint.cpp @@ -6,7 +6,6 @@ */ #include "SkPaint.h" -#include "SkAnnotation.h" #include "SkAutoKern.h" #include "SkChecksum.h" #include "SkColorFilter.h" @@ -54,7 +53,6 @@ SkPaint::SkPaint() { fRasterizer = nullptr; fLooper = nullptr; fImageFilter = nullptr; - fAnnotation = nullptr; fTextSize = SkPaintDefaults_TextSize; fTextScaleX = SK_Scalar1; @@ -87,7 +85,6 @@ SkPaint::SkPaint(const SkPaint& src) { REF_COPY(fRasterizer); REF_COPY(fLooper); REF_COPY(fImageFilter); - REF_COPY(fAnnotation); COPY(fTextSize); COPY(fTextScaleX); @@ -114,7 +111,6 @@ SkPaint::SkPaint(SkPaint&& src) { REF_MOVE(fRasterizer); REF_MOVE(fLooper); REF_MOVE(fImageFilter); - REF_MOVE(fAnnotation); MOVE(fTextSize); MOVE(fTextScaleX); @@ -138,7 +134,6 @@ SkPaint::~SkPaint() { SkSafeUnref(fRasterizer); SkSafeUnref(fLooper); SkSafeUnref(fImageFilter); - SkSafeUnref(fAnnotation); } SkPaint& SkPaint::operator=(const SkPaint& src) { @@ -158,7 +153,6 @@ SkPaint& SkPaint::operator=(const SkPaint& src) { REF_COPY(fRasterizer); REF_COPY(fLooper); REF_COPY(fImageFilter); - REF_COPY(fAnnotation); COPY(fTextSize); COPY(fTextScaleX); @@ -191,7 +185,6 @@ SkPaint& SkPaint::operator=(SkPaint&& src) { REF_MOVE(fRasterizer); REF_MOVE(fLooper); REF_MOVE(fImageFilter); - REF_MOVE(fAnnotation); MOVE(fTextSize); MOVE(fTextScaleX); @@ -218,7 +211,6 @@ bool operator==(const SkPaint& a, const SkPaint& b) { && EQUAL(fRasterizer) && EQUAL(fLooper) && EQUAL(fImageFilter) - && EQUAL(fAnnotation) && EQUAL(fTextSize) && EQUAL(fTextScaleX) && EQUAL(fTextSkewX) @@ -420,11 +412,6 @@ SkImageFilter* SkPaint::setImageFilter(SkImageFilter* imageFilter) { return imageFilter; } -SkAnnotation* SkPaint::setAnnotation(SkAnnotation* annotation) { - SkRefCnt_SafeAssign(fAnnotation, annotation); - return annotation; -} - /////////////////////////////////////////////////////////////////////////////// static SkScalar mag2(SkScalar x, SkScalar y) { @@ -1897,7 +1884,6 @@ void SkPaint::flatten(SkWriteBuffer& buffer) const { asint(this->getColorFilter()) | asint(this->getRasterizer()) | asint(this->getLooper()) | - asint(this->getAnnotation()) | asint(this->getImageFilter())) { flatFlags |= kHasEffects_FlatFlag; } @@ -1931,13 +1917,6 @@ void SkPaint::flatten(SkWriteBuffer& buffer) const { buffer.writeFlattenable(this->getRasterizer()); buffer.writeFlattenable(this->getLooper()); buffer.writeFlattenable(this->getImageFilter()); - - if (fAnnotation) { - buffer.writeBool(true); - fAnnotation->writeToBuffer(buffer); - } else { - buffer.writeBool(false); - } } } @@ -1981,8 +1960,14 @@ void SkPaint::unflatten(SkReadBuffer& buffer) { SkSafeUnref(this->setLooper(buffer.readDrawLooper())); SkSafeUnref(this->setImageFilter(buffer.readImageFilter())); - if (buffer.readBool()) { - this->setAnnotation(SkAnnotation::Create(buffer))->unref(); + if (buffer.isVersionLT(SkReadBuffer::kAnnotationsMovedToCanvas_Version)) { + // We used to store annotations here (string+skdata) if this bool was true + if (buffer.readBool()) { + // Annotations have moved to drawAnnotation, so we just drop this one on the floor. + SkString key; + buffer.readString(&key); + SkSafeUnref(buffer.readByteArrayAsData()); + } } } else { this->setPathEffect(nullptr); @@ -2205,12 +2190,6 @@ void SkPaint::toString(SkString* str) const { str->append("</dd>"); } - SkAnnotation* annotation = this->getAnnotation(); - if (annotation) { - str->append("<dt>Annotation:</dt><dd>"); - str->append("</dd>"); - } - str->append("<dt>Color:</dt><dd>0x"); SkColor color = this->getColor(); str->appendHex(color); @@ -2437,7 +2416,7 @@ bool SkPaint::nothingToDraw() const { uint32_t SkPaint::getHash() const { // We're going to hash 10 pointers and 7 32-bit values, finishing up with fBitfields, // so fBitfields should be 10 pointers and 6 32-bit values from the start. - static_assert(offsetof(SkPaint, fBitfields) == 10 * sizeof(void*) + 6 * sizeof(uint32_t), + static_assert(offsetof(SkPaint, fBitfields) == 9 * sizeof(void*) + 6 * sizeof(uint32_t), "SkPaint_notPackedTightly"); return SkChecksum::Murmur3(reinterpret_cast<const uint32_t*>(this), offsetof(SkPaint, fBitfields) + sizeof(fBitfields)); diff --git a/src/core/SkPictureFlat.h b/src/core/SkPictureFlat.h index 4eee04fcda..00b7c2bb41 100644 --- a/src/core/SkPictureFlat.h +++ b/src/core/SkPictureFlat.h @@ -78,7 +78,9 @@ enum DrawType { SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016, SAVE_LAYER_SAVELAYERREC, - LAST_DRAWTYPE_ENUM = SAVE_LAYER_SAVELAYERREC, + DRAW_ANNOTATION, + + LAST_DRAWTYPE_ENUM = DRAW_ANNOTATION, }; // In the 'match' method, this constant will match any flavor of DRAW_BITMAP* diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp index a5dd814b82..e8497daca1 100644 --- a/src/core/SkPicturePlayback.cpp +++ b/src/core/SkPicturePlayback.cpp @@ -175,6 +175,12 @@ void SkPicturePlayback::handleOp(SkReader32* reader, canvas->concat(matrix); break; } + case DRAW_ANNOTATION: { + const SkRect& rect = reader->skipT<SkRect>(); + const char* key = reader->readString(); + SkAutoTUnref<SkData> value(reader->readData()); + canvas->drawAnnotation(rect, key, value); + } break; case DRAW_ATLAS: { const SkPaint* paint = fPictureData->getPaint(reader); const SkImage* atlas = fPictureData->getImage(reader); diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp index 2822a1ac16..2718ee999d 100644 --- a/src/core/SkPictureRecord.cpp +++ b/src/core/SkPictureRecord.cpp @@ -777,6 +777,18 @@ void SkPictureRecord::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], this->validate(initialOffset, size); } +void SkPictureRecord::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) { + size_t keyLen = fWriter.WriteStringSize(key); + size_t valueLen = fWriter.WriteDataSize(value); + size_t size = 4 + sizeof(SkRect) + keyLen + valueLen; + + size_t initialOffset = this->addDraw(DRAW_ANNOTATION, &size); + this->addRect(rect); + fWriter.writeString(key); + fWriter.writeData(value); + this->validate(initialOffset, size); +} + /////////////////////////////////////////////////////////////////////////////// SkSurface* SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) { diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h index 2e1e62a021..607f6f10f7 100644 --- a/src/core/SkPictureRecord.h +++ b/src/core/SkPictureRecord.h @@ -204,6 +204,7 @@ protected: void onClipRegion(const SkRegion&, SkRegion::Op) override; void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override; + void onDrawAnnotation(const SkRect&, const char[], SkData*) override; int addPathToHeap(const SkPath& path); // does not write to ops stream diff --git a/src/core/SkReadBuffer.h b/src/core/SkReadBuffer.h index 3d6dd362ac..b9b30944ff 100644 --- a/src/core/SkReadBuffer.h +++ b/src/core/SkReadBuffer.h @@ -60,6 +60,7 @@ public: kBitmapSourceFilterQuality_Version = 41, kPictureShaderHasPictureBool_Version = 42, kHasDrawImageOpCodes_Version = 43, + kAnnotationsMovedToCanvas_Version = 44, }; /** diff --git a/src/core/SkReader32.h b/src/core/SkReader32.h index 68dda23c6e..645d64cc24 100644 --- a/src/core/SkReader32.h +++ b/src/core/SkReader32.h @@ -1,4 +1,3 @@ - /* * Copyright 2008 The Android Open Source Project * @@ -10,6 +9,7 @@ #ifndef SkReader32_DEFINED #define SkReader32_DEFINED +#include "SkData.h" #include "SkMatrix.h" #include "SkPath.h" #include "SkRegion.h" @@ -135,6 +135,14 @@ public: */ size_t readIntoString(SkString* copy); + SkData* readData() { + uint32_t byteLength = this->readU32(); + if (0 == byteLength) { + return SkData::NewEmpty(); + } + return SkData::NewWithCopy(this->skip(byteLength), byteLength); + } + private: template <typename T> bool readObjectFromMemory(T* obj) { size_t size = obj->readFromMemory(this->peek(), this->available()); diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp index 5ca9517d3f..0e4b5af580 100644 --- a/src/core/SkRecordDraw.cpp +++ b/src/core/SkRecordDraw.cpp @@ -117,6 +117,7 @@ DRAW(DrawTextOnPath, drawTextOnPath(r.text, r.byteLength, r.path, &r.matrix, r.p DRAW(DrawAtlas, drawAtlas(r.atlas, r.xforms, r.texs, r.colors, r.count, r.mode, r.cull, r.paint)); DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.colors, r.xmode, r.indices, r.indexCount, r.paint)); +DRAW(DrawAnnotation, drawAnnotation(r.rect, r.key.c_str(), r.value)); #undef DRAW template <> void Draw::draw(const DrawDrawable& r) { @@ -517,6 +518,10 @@ private: return this->adjustAndMap(op.worstCaseBounds, nullptr); } + Bounds bounds(const DrawAnnotation& op) const { + return this->adjustAndMap(op.rect, nullptr); + } + static void AdjustTextForFontMetrics(SkRect* rect, const SkPaint& paint) { #ifdef SK_DEBUG SkRect correct = *rect; diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp index 01c28dfc2b..f9fd8bb374 100644 --- a/src/core/SkRecorder.cpp +++ b/src/core/SkRecorder.cpp @@ -332,6 +332,10 @@ void SkRecorder::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], cons this->copy(cull)); } +void SkRecorder::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) { + APPEND(DrawAnnotation, rect, SkString(key), value); +} + void SkRecorder::willSave() { APPEND(Save); } diff --git a/src/core/SkRecorder.h b/src/core/SkRecorder.h index cd5bc8ad04..7372e540e7 100644 --- a/src/core/SkRecorder.h +++ b/src/core/SkRecorder.h @@ -120,6 +120,7 @@ public: void onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op) override; void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override; + void onDrawAnnotation(const SkRect&, const char[], SkData*) override; SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&) override { return nullptr; } diff --git a/src/core/SkRemote.cpp b/src/core/SkRemote.cpp index 22185cddb0..9b0383d406 100644 --- a/src/core/SkRemote.cpp +++ b/src/core/SkRemote.cpp @@ -5,7 +5,6 @@ * found in the LICENSE file. */ -#include "SkAnnotation.h" #include "SkCanvas.h" #include "SkColorFilter.h" #include "SkDrawLooper.h" @@ -127,7 +126,6 @@ namespace SkRemote { fIDs.rasterizer = fEncoder->define(paint.getRasterizer()); fIDs.looper = fEncoder->define(paint.getLooper()); fIDs.imagefilter = fEncoder->define(paint.getImageFilter()); - fIDs.annotation = fEncoder->define(paint.getAnnotation()); } ~AutoCommonIDs() { if (fEncoder) { @@ -140,7 +138,6 @@ namespace SkRemote { fEncoder->undefine(fIDs.rasterizer); fEncoder->undefine(fIDs.looper); fEncoder->undefine(fIDs.imagefilter); - fEncoder->undefine(fIDs.annotation); } } @@ -461,7 +458,6 @@ namespace SkRemote { ID define(SkRasterizer* v)O{return this->define(Type::kRasterizer, &fRasterizer, v);} ID define(SkDrawLooper* v)O{return this->define(Type::kDrawLooper, &fDrawLooper, v);} ID define(SkImageFilter* v)O{return this->define(Type::kImageFilter, &fImageFilter, v);} - ID define(SkAnnotation* v)O{return this->define(Type::kAnnotation, &fAnnotation, v);} #undef O @@ -480,7 +476,6 @@ namespace SkRemote { case Type::kRasterizer: return fRasterizer .remove(id); case Type::kDrawLooper: return fDrawLooper .remove(id); case Type::kImageFilter: return fImageFilter.remove(id); - case Type::kAnnotation: return fAnnotation .remove(id); }; } @@ -494,7 +489,6 @@ namespace SkRemote { paint->setRasterizer (fRasterizer .find(common.rasterizer)); paint->setLooper (fDrawLooper .find(common.looper)); paint->setImageFilter(fImageFilter.find(common.imagefilter)); - paint->setAnnotation (fAnnotation .find(common.annotation)); } void save() override { fCanvas->save(); } @@ -617,7 +611,6 @@ namespace SkRemote { ReffedIDMap<SkRasterizer , Type::kRasterizer > fRasterizer; ReffedIDMap<SkDrawLooper , Type::kDrawLooper > fDrawLooper; ReffedIDMap<SkImageFilter , Type::kImageFilter> fImageFilter; - ReffedIDMap<SkAnnotation , Type::kAnnotation > fAnnotation; SkCanvas* fCanvas; uint64_t fNextID = 0; @@ -653,7 +646,6 @@ namespace SkRemote { fRasterizer .foreach(undef); fDrawLooper .foreach(undef); fImageFilter.foreach(undef); - fAnnotation .foreach(undef); } template <typename Map, typename T> @@ -679,7 +671,6 @@ namespace SkRemote { ID define(SkRasterizer* v) override { return this->define(&fRasterizer , v); } ID define(SkDrawLooper* v) override { return this->define(&fDrawLooper , v); } ID define(SkImageFilter* v) override { return this->define(&fImageFilter, v); } - ID define(SkAnnotation* v) override { return this->define(&fAnnotation , v); } void undefine(ID) override {} @@ -749,7 +740,6 @@ namespace SkRemote { RefKeyMap<SkRasterizer , Type::kRasterizer > fRasterizer; RefKeyMap<SkDrawLooper , Type::kDrawLooper > fDrawLooper; RefKeyMap<SkImageFilter , Type::kImageFilter> fImageFilter; - RefKeyMap<SkAnnotation , Type::kAnnotation > fAnnotation; Encoder* fWrapped; }; diff --git a/src/core/SkRemote.h b/src/core/SkRemote.h index a1b1405b21..a8126d6c9e 100644 --- a/src/core/SkRemote.h +++ b/src/core/SkRemote.h @@ -79,14 +79,13 @@ namespace SkRemote { virtual ID define(SkRasterizer*) = 0; virtual ID define(SkDrawLooper*) = 0; virtual ID define(SkImageFilter*) = 0; - virtual ID define(SkAnnotation*) = 0; virtual void undefine(ID) = 0; // TODO: do these all belong here in CommonIDs? struct CommonIDs { ID misc, patheffect, shader, xfermode, maskfilter, - colorfilter, rasterizer, looper, imagefilter, annotation; + colorfilter, rasterizer, looper, imagefilter; }; virtual void save() = 0; diff --git a/src/core/SkRemote_protocol.h b/src/core/SkRemote_protocol.h index 19bdc33fdd..825a1c2732 100644 --- a/src/core/SkRemote_protocol.h +++ b/src/core/SkRemote_protocol.h @@ -28,7 +28,6 @@ namespace SkRemote { kRasterizer, kDrawLooper, kImageFilter, - kAnnotation, }; } // namespace SkRemote diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 04bc14e563..a7bf82e6f0 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -68,11 +68,6 @@ enum { kDefaultImageFilterCacheSize = 32 * 1024 * 1024 }; /////////////////////////////////////////////////////////////////////////////// -#define CHECK_FOR_ANNOTATION(paint) \ - do { if (paint.getAnnotation()) { return; } } while (0) - -/////////////////////////////////////////////////////////////////////////////// - // Helper for turning a bitmap into a texture. If the bitmap is GrTexture backed this // just accesses the backing GrTexture. Otherwise, it creates a cached texture // representation and releases it in the destructor. @@ -401,7 +396,6 @@ void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) { ASSERT_SINGLE_OWNER GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawPoints", fContext); - CHECK_FOR_ANNOTATION(paint); CHECK_SHOULD_DRAW(draw); SkScalar width = paint.getStrokeWidth(); @@ -453,7 +447,6 @@ void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect, const SkPaint& paint) { ASSERT_SINGLE_OWNER GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawRect", fContext); - CHECK_FOR_ANNOTATION(paint); CHECK_SHOULD_DRAW(draw); bool doStroke = paint.getStyle() != SkPaint::kFill_Style; @@ -500,7 +493,6 @@ void SkGpuDevice::drawRRect(const SkDraw& draw, const SkRRect& rect, const SkPaint& paint) { ASSERT_SINGLE_OWNER GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawRRect", fContext); - CHECK_FOR_ANNOTATION(paint); CHECK_SHOULD_DRAW(draw); GrPaint grPaint; @@ -565,7 +557,6 @@ void SkGpuDevice::drawDRRect(const SkDraw& draw, const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) { ASSERT_SINGLE_OWNER GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawDRRect", fContext); - CHECK_FOR_ANNOTATION(paint); CHECK_SHOULD_DRAW(draw); if (outer.isEmpty()) { @@ -606,7 +597,6 @@ void SkGpuDevice::drawDRRect(const SkDraw& draw, const SkRRect& outer, void SkGpuDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint& paint) { ASSERT_SINGLE_OWNER GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawOval", fContext); - CHECK_FOR_ANNOTATION(paint); CHECK_SHOULD_DRAW(draw); // Presumably the path effect warps this to something other than an oval @@ -661,7 +651,6 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath, } } - CHECK_FOR_ANNOTATION(paint); CHECK_SHOULD_DRAW(draw); GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawPath", fContext); @@ -1472,7 +1461,6 @@ void SkGpuDevice::drawProducerNine(const SkDraw& draw, GrTextureProducer* produc const SkIRect& center, const SkRect& dst, const SkPaint& paint) { GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawProducerNine", fContext); - CHECK_FOR_ANNOTATION(paint); CHECK_SHOULD_DRAW(draw); bool useFallback = paint.getMaskFilter() || paint.isAntiAlias() || diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index d102f0e977..239b73823b 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -7,7 +7,7 @@ #include "SkPDFDevice.h" -#include "SkAnnotation.h" +#include "SkAnnotationKeys.h" #include "SkColor.h" #include "SkColorFilter.h" #include "SkClipStack.h" @@ -753,6 +753,17 @@ void SkPDFDevice::cleanUp(bool clearFontUsage) { } } +void SkPDFDevice::drawAnnotation(const SkDraw& d, const SkRect& rect, const char key[], + SkData* value) { + if (0 == rect.width() && 0 == rect.height()) { + handlePointAnnotation({ rect.x(), rect.y() }, *d.fMatrix, key, value); + } else { + SkPath path; + path.addRect(rect); + handlePathAnnotation(path, d, key, value); + } +} + void SkPDFDevice::drawPaint(const SkDraw& d, const SkPaint& paint) { SkPaint newPaint = paint; replace_srcmode_on_opaque_paint(&newPaint); @@ -792,12 +803,6 @@ void SkPDFDevice::drawPoints(const SkDraw& d, return; } - if (SkAnnotation* annotation = passedPaint.getAnnotation()) { - if (handlePointAnnotation(points, count, *d.fMatrix, annotation)) { - return; - } - } - // SkDraw::drawPoints converts to multiple calls to fDevice->drawPath. // We only use this when there's a path effect because of the overhead // of multiple calls to setUpContentEntry it causes. @@ -935,14 +940,6 @@ void SkPDFDevice::drawRect(const SkDraw& d, return; } - if (SkAnnotation* annotation = paint.getAnnotation()) { - SkPath path; - path.addRect(rect); - if (handlePathAnnotation(path, d, annotation)) { - return; - } - } - ScopedContentEntry content(this, d, paint); if (!content.entry()) { return; @@ -1021,12 +1018,6 @@ void SkPDFDevice::drawPath(const SkDraw& d, return; } - if (SkAnnotation* annotation = paint.getAnnotation()) { - if (handlePathAnnotation(*pathPtr, d, annotation)) { - return; - } - } - ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint); if (!content.entry()) { return; @@ -1664,26 +1655,26 @@ bool SkPDFDevice::handleInversePath(const SkDraw& d, const SkPath& origPath, return true; } -bool SkPDFDevice::handlePointAnnotation(const SkPoint* points, size_t count, +void SkPDFDevice::handlePointAnnotation(const SkPoint& point, const SkMatrix& matrix, - SkAnnotation* annotationInfo) { - SkData* nameData = annotationInfo->find( - SkAnnotationKeys::Define_Named_Dest_Key()); - if (nameData) { - for (size_t i = 0; i < count; i++) { - SkPoint transformedPoint; - matrix.mapXY(points[i].x(), points[i].y(), &transformedPoint); - fNamedDestinations.emplace_back(nameData, transformedPoint); - } - return true; + const char key[], SkData* value) { + if (!value) { + return; + } + + if (!strcmp(SkAnnotationKeys::Define_Named_Dest_Key(), key)) { + SkPoint transformedPoint; + matrix.mapXY(point.x(), point.y(), &transformedPoint); + fNamedDestinations.emplace_back(value, transformedPoint); } - return false; } -bool SkPDFDevice::handlePathAnnotation(const SkPath& path, +void SkPDFDevice::handlePathAnnotation(const SkPath& path, const SkDraw& d, - SkAnnotation* annotation) { - SkASSERT(annotation); + const char key[], SkData* value) { + if (!value) { + return; + } SkPath transformedPath = path; transformedPath.transform(*d.fMatrix); @@ -1692,24 +1683,15 @@ bool SkPDFDevice::handlePathAnnotation(const SkPath& path, false); SkRect transformedRect = SkRect::Make(clip.getBounds()); - SkData* urlData = annotation->find(SkAnnotationKeys::URL_Key()); - if (urlData) { + if (!strcmp(SkAnnotationKeys::URL_Key(), key)) { if (!transformedRect.isEmpty()) { - fLinkToURLs.emplace_back(transformedRect, urlData); + fLinkToURLs.emplace_back(transformedRect, value); } - return true; - } - - SkData* linkToDestination = - annotation->find(SkAnnotationKeys::Link_Named_Dest_Key()); - if (linkToDestination) { + } else if (!strcmp(SkAnnotationKeys::Link_Named_Dest_Key(), key)) { if (!transformedRect.isEmpty()) { - fLinkToDestinations.emplace_back(transformedRect, linkToDestination); + fLinkToDestinations.emplace_back(transformedRect, value); } - return true; } - - return false; } void SkPDFDevice::appendAnnotations(SkPDFArray* array) const { diff --git a/src/pdf/SkPDFDevice.h b/src/pdf/SkPDFDevice.h index cceb1238f1..d38f282bb0 100644 --- a/src/pdf/SkPDFDevice.h +++ b/src/pdf/SkPDFDevice.h @@ -197,6 +197,8 @@ protected: SkSurface* newSurface(const SkImageInfo&, const SkSurfaceProps&) override; + void drawAnnotation(const SkDraw&, const SkRect&, const char key[], SkData* value) override; + private: struct RectWithData { SkRect rect; @@ -318,10 +320,8 @@ private: bool handleInversePath(const SkDraw& d, const SkPath& origPath, const SkPaint& paint, bool pathIsMutable, const SkMatrix* prePathMatrix = nullptr); - bool handlePointAnnotation(const SkPoint* points, size_t count, - const SkMatrix& matrix, SkAnnotation* annot); - bool handlePathAnnotation(const SkPath& path, const SkDraw& d, - SkAnnotation* annot); + void handlePointAnnotation(const SkPoint&, const SkMatrix&, const char key[], SkData* value); + void handlePathAnnotation(const SkPath&, const SkDraw& d, const char key[], SkData* value); typedef SkBaseDevice INHERITED; diff --git a/src/utils/SkDumpCanvas.cpp b/src/utils/SkDumpCanvas.cpp index 916c32a655..75fa836a6a 100644 --- a/src/utils/SkDumpCanvas.cpp +++ b/src/utils/SkDumpCanvas.cpp @@ -9,6 +9,7 @@ #include "SkDumpCanvas.h" #ifdef SK_DEVELOPER +#include "SkData.h" #include "SkPatchUtils.h" #include "SkPicture.h" #include "SkPixelRef.h" @@ -482,6 +483,13 @@ void SkDumpCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4] texCoords[2].x(), texCoords[2].y(), texCoords[3].x(), texCoords[3].y()); } +void SkDumpCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) { + SkString str; + toString(rect, &str); + this->dump(kDrawAnnotation_Verb, nullptr, "drawAnnotation(%s \"%s\" (%zu))", + str.c_str(), key, value ? value->size() : 0); +} + /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// diff --git a/src/utils/SkNWayCanvas.cpp b/src/utils/SkNWayCanvas.cpp index e3b1e019b6..fd5fa82aa5 100644 --- a/src/utils/SkNWayCanvas.cpp +++ b/src/utils/SkNWayCanvas.cpp @@ -292,6 +292,13 @@ void SkNWayCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4] } } +void SkNWayCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* data) { + Iter iter(fList); + while (iter.next()) { + iter->drawAnnotation(rect, key, data); + } +} + #ifdef SK_SUPPORT_LEGACY_DRAWFILTER SkDrawFilter* SkNWayCanvas::setDrawFilter(SkDrawFilter* filter) { Iter iter(fList); diff --git a/tests/SerializationTest.cpp b/tests/SerializationTest.cpp index a4e40c54ee..eb84b3c957 100644 --- a/tests/SerializationTest.cpp +++ b/tests/SerializationTest.cpp @@ -5,6 +5,7 @@ * found in the LICENSE file. */ +#include "SkAnnotationKeys.h" #include "Resources.h" #include "SkCanvas.h" #include "SkFixed.h" @@ -546,3 +547,85 @@ DEF_TEST(Serialization, reporter) { TestPictureTypefaceSerialization(reporter); } + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#include "SkAnnotation.h" + +static SkPicture* copy_picture_via_serialization(SkPicture* src) { + SkDynamicMemoryWStream wstream; + src->serialize(&wstream); + SkAutoTDelete<SkStreamAsset> rstream(wstream.detachAsStream()); + return SkPicture::CreateFromStream(rstream); +} + +struct AnnotationRec { + const SkRect fRect; + const char* fKey; + SkData* fValue; +}; + +class TestAnnotationCanvas : public SkCanvas { + skiatest::Reporter* fReporter; + const AnnotationRec* fRec; + int fCount; + int fCurrIndex; + +public: + TestAnnotationCanvas(skiatest::Reporter* reporter, const AnnotationRec rec[], int count) + : SkCanvas(100, 100) + , fReporter(reporter) + , fRec(rec) + , fCount(count) + , fCurrIndex(0) + {} + + ~TestAnnotationCanvas() { + REPORTER_ASSERT(fReporter, fCount == fCurrIndex); + } + +protected: + void onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) { + REPORTER_ASSERT(fReporter, fCurrIndex < fCount); + REPORTER_ASSERT(fReporter, rect == fRec[fCurrIndex].fRect); + REPORTER_ASSERT(fReporter, !strcmp(key, fRec[fCurrIndex].fKey)); + REPORTER_ASSERT(fReporter, value->equals(fRec[fCurrIndex].fValue)); + fCurrIndex += 1; + } +}; + +/* + * Test the 3 annotation types by recording them into a picture, serializing, and then playing + * them back into another canvas. + */ +DEF_TEST(Annotations, reporter) { + SkPictureRecorder recorder; + SkCanvas* recordingCanvas = recorder.beginRecording(SkRect::MakeWH(100, 100)); + + const char* str0 = "rect-with-url"; + const SkRect r0 = SkRect::MakeWH(10, 10); + SkAutoTUnref<SkData> d0(SkData::NewWithCString(str0)); + SkAnnotateRectWithURL(recordingCanvas, r0, d0); + + const char* str1 = "named-destination"; + const SkRect r1 = SkRect::MakeXYWH(5, 5, 0, 0); // collapsed to a point + SkAutoTUnref<SkData> d1(SkData::NewWithCString(str1)); + SkAnnotateNamedDestination(recordingCanvas, {r1.x(), r1.y()}, d1); + + const char* str2 = "link-to-destination"; + const SkRect r2 = SkRect::MakeXYWH(20, 20, 5, 6); + SkAutoTUnref<SkData> d2(SkData::NewWithCString(str2)); + SkAnnotateLinkToDestination(recordingCanvas, r2, d2); + + const AnnotationRec recs[] = { + { r0, SkAnnotationKeys::URL_Key(), d0 }, + { r1, SkAnnotationKeys::Define_Named_Dest_Key(), d1 }, + { r2, SkAnnotationKeys::Link_Named_Dest_Key(), d2 }, + }; + + SkAutoTUnref<SkPicture> pict0(recorder.endRecording()); + SkAutoTUnref<SkPicture> pict1(copy_picture_via_serialization(pict0)); + + TestAnnotationCanvas canvas(reporter, recs, SK_ARRAY_COUNT(recs)); + canvas.drawPicture(pict1); +} + diff --git a/tests/Writer32Test.cpp b/tests/Writer32Test.cpp index 39ae79cff6..e03a9163aa 100644 --- a/tests/Writer32Test.cpp +++ b/tests/Writer32Test.cpp @@ -278,3 +278,44 @@ DEF_TEST(Writer32_misc, reporter) { test_rewind(reporter); } +DEF_TEST(Writer32_data, reporter) { + const char* str = "0123456789"; + SkAutoTUnref<SkData> data0(SkData::NewWithCString(str)); + SkAutoTUnref<SkData> data1(SkData::NewEmpty()); + + const size_t sizes[] = { + SkWriter32::WriteDataSize(nullptr), + SkWriter32::WriteDataSize(data0), + SkWriter32::WriteDataSize(data1), + }; + + SkSWriter32<1000> writer; + size_t sizeWritten = 0; + + writer.writeData(nullptr); + sizeWritten += sizes[0]; + REPORTER_ASSERT(reporter, sizeWritten == writer.bytesWritten()); + + writer.writeData(data0); + sizeWritten += sizes[1]; + REPORTER_ASSERT(reporter, sizeWritten == writer.bytesWritten()); + + writer.writeData(data1); + sizeWritten += sizes[2]; + REPORTER_ASSERT(reporter, sizeWritten == writer.bytesWritten()); + + SkAutoTUnref<SkData> result(writer.snapshotAsData()); + + SkReader32 reader(result->data(), result->size()); + SkAutoTUnref<SkData> d0(reader.readData()), + d1(reader.readData()), + d2(reader.readData()); + + REPORTER_ASSERT(reporter, 0 == d0->size()); + REPORTER_ASSERT(reporter, strlen(str)+1 == d1->size()); + REPORTER_ASSERT(reporter, !memcmp(str, d1->data(), strlen(str)+1)); + REPORTER_ASSERT(reporter, 0 == d2->size()); + + REPORTER_ASSERT(reporter, reader.offset() == sizeWritten); + REPORTER_ASSERT(reporter, reader.eof()); +} |