Add link annotation support to SkSVGDevice.
This CL implements |SkSVGDevice::drawAnnotation|, overridden from |SKBaseDevice|. |drawAnnotation| supports annotating rectangular areas of a Skia device. Previous to this change, annotations are being used in |SkPDFDevice| to include hyperlinked rectangular areas in .pdf documents. This CL implements the SVG equivalent of this PDF feature. BUG=skia:7581 Docs-Preview: https://skia.org/?cl=104680 Change-Id: I92ae01ceb7ae10cd2010bebab2a58dcfe48ef253 Reviewed-on: https://skia-review.googlesource.com/104680 Commit-Queue: Florin Malita <fmalita@chromium.org> Reviewed-by: Florin Malita <fmalita@chromium.org>
This commit is contained in:
parent
5dd202dc90
commit
fd5a5081d5
1
AUTHORS
1
AUTHORS
@ -12,6 +12,7 @@
|
||||
# Please keep the list sorted alphabetically.
|
||||
|
||||
ACCESS CO., LTD. <*@access-company.com>
|
||||
Amazon, Inc <*@amazon.com>
|
||||
Anthony Catel <paraboul@gmail.com>
|
||||
ARM <*@arm.com>
|
||||
Ehsan Akhgari <ehsan.akhgari@gmail.com>
|
||||
|
@ -16,5 +16,6 @@ Device backends for Skia currently include:
|
||||
* OpenGL
|
||||
* PDF
|
||||
* XPS
|
||||
* SVG
|
||||
* Picture (for recording and then playing back into another Canvas)
|
||||
|
||||
|
@ -7,9 +7,11 @@
|
||||
|
||||
#include "SkSVGDevice.h"
|
||||
|
||||
#include "SkAnnotationKeys.h"
|
||||
#include "SkBase64.h"
|
||||
#include "SkBitmap.h"
|
||||
#include "SkChecksum.h"
|
||||
#include "SkClipOpPriv.h"
|
||||
#include "SkClipStack.h"
|
||||
#include "SkData.h"
|
||||
#include "SkDraw.h"
|
||||
@ -22,7 +24,6 @@
|
||||
#include "SkTypeface.h"
|
||||
#include "SkUtils.h"
|
||||
#include "SkXMLWriter.h"
|
||||
#include "SkClipOpPriv.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@ -621,6 +622,32 @@ void SkSVGDevice::drawPaint(const SkPaint& paint) {
|
||||
SkIntToScalar(this->height())));
|
||||
}
|
||||
|
||||
void SkSVGDevice::drawAnnotation(const SkRect& rect, const char key[], SkData* value) {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(SkAnnotationKeys::URL_Key(), key) ||
|
||||
!strcmp(SkAnnotationKeys::Link_Named_Dest_Key(), key)) {
|
||||
this->cs().save();
|
||||
this->cs().clipRect(rect, this->ctm(), kIntersect_SkClipOp, true);
|
||||
SkRect transformedRect = this->cs().bounds(this->getGlobalBounds());
|
||||
this->cs().restore();
|
||||
if (transformedRect.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SkString url(static_cast<const char*>(value->data()), value->size() - 1);
|
||||
AutoElement a("a", fWriter);
|
||||
a.addAttribute("xlink:href", url.c_str());
|
||||
{
|
||||
AutoElement r("rect", fWriter);
|
||||
r.addAttribute("fill-opacity", "0.0");
|
||||
r.addRectAttributes(transformedRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SkSVGDevice::drawPoints(SkCanvas::PointMode mode, size_t count,
|
||||
const SkPoint pts[], const SkPaint& paint) {
|
||||
SkPath path;
|
||||
|
@ -19,6 +19,7 @@ public:
|
||||
|
||||
protected:
|
||||
void drawPaint(const SkPaint& paint) override;
|
||||
void drawAnnotation(const SkRect& rect, const char key[], SkData* value) override;
|
||||
void drawPoints(SkCanvas::PointMode mode, size_t count,
|
||||
const SkPoint[], const SkPaint& paint) override;
|
||||
void drawRect(const SkRect& r, const SkPaint& paint) override;
|
||||
|
@ -8,7 +8,9 @@
|
||||
#include "SkCanvas.h"
|
||||
#include "SkData.h"
|
||||
#include "SkDocument.h"
|
||||
#include "SkSVGCanvas.h"
|
||||
#include "SkStream.h"
|
||||
#include "SkXMLWriter.h"
|
||||
#include "Test.h"
|
||||
|
||||
/** Returns true if data (may contain null characters) contains needle (null
|
||||
@ -57,8 +59,8 @@ DEF_TEST(Annotation_PdfLink, reporter) {
|
||||
REPORTER_ASSERT(reporter, ContainsString(rawOutput, out->size(), "/Annots "));
|
||||
}
|
||||
|
||||
DEF_TEST(Annotation_NamedDestination, reporter) {
|
||||
REQUIRE_PDF_DOCUMENT(Annotation_NamedDestination, reporter);
|
||||
DEF_TEST(Annotation_PdfDefineNamedDestination, reporter) {
|
||||
REQUIRE_PDF_DOCUMENT(Annotation_PdfNamedDestination, reporter);
|
||||
SkDynamicMemoryWStream outStream;
|
||||
sk_sp<SkDocument> doc(SkDocument::MakePDF(&outStream));
|
||||
SkCanvas* canvas = doc->beginPage(612.0f, 792.0f);
|
||||
@ -75,3 +77,42 @@ DEF_TEST(Annotation_NamedDestination, reporter) {
|
||||
REPORTER_ASSERT(reporter,
|
||||
ContainsString(rawOutput, out->size(), "/example "));
|
||||
}
|
||||
|
||||
DEF_TEST(Annotation_SvgLink, reporter) {
|
||||
SkDynamicMemoryWStream outStream;
|
||||
std::unique_ptr<SkXMLWriter> xmlWriter(new SkXMLStreamWriter(&outStream));
|
||||
SkRect bounds = SkRect::MakeIWH(400, 400);
|
||||
std::unique_ptr<SkCanvas> canvas = SkSVGCanvas::Make(bounds, xmlWriter.get());
|
||||
|
||||
SkRect r = SkRect::MakeXYWH(SkIntToScalar(72), SkIntToScalar(72), SkIntToScalar(288),
|
||||
SkIntToScalar(72));
|
||||
sk_sp<SkData> data(SkData::MakeWithCString("http://www.gooogle.com"));
|
||||
SkAnnotateRectWithURL(canvas.get(), r, data.get());
|
||||
|
||||
canvas->flush();
|
||||
sk_sp<SkData> out = outStream.detachAsData();
|
||||
const char* rawOutput = (const char*)out->data();
|
||||
|
||||
REPORTER_ASSERT(reporter,
|
||||
ContainsString(rawOutput, out->size(), "a xlink:href=\"http://www.gooogle.com\""));
|
||||
}
|
||||
|
||||
DEF_TEST(Annotation_SvgLinkNamedDestination, reporter) {
|
||||
SkDynamicMemoryWStream outStream;
|
||||
std::unique_ptr<SkXMLWriter> xmlWriter(new SkXMLStreamWriter(&outStream));
|
||||
SkRect bounds = SkRect::MakeIWH(400, 400);
|
||||
std::unique_ptr<SkCanvas> canvas = SkSVGCanvas::Make(bounds, xmlWriter.get());
|
||||
|
||||
SkRect r = SkRect::MakeXYWH(SkIntToScalar(72), SkIntToScalar(72), SkIntToScalar(288),
|
||||
SkIntToScalar(72));
|
||||
sk_sp<SkData> data(SkData::MakeWithCString("http://www.gooogle.com/#NamedDestination"));
|
||||
SkAnnotateLinkToDestination(canvas.get(), r, data.get());
|
||||
|
||||
canvas->flush();
|
||||
sk_sp<SkData> out = outStream.detachAsData();
|
||||
const char* rawOutput = (const char*)out->data();
|
||||
|
||||
REPORTER_ASSERT(reporter,
|
||||
ContainsString(rawOutput, out->size(),
|
||||
"a xlink:href=\"http://www.gooogle.com/#NamedDestination\""));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user