diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkAnnotation.cpp | 42 | ||||
-rw-r--r-- | src/core/SkDevice.cpp | 1 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 1 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.cpp | 111 | ||||
-rw-r--r-- | src/pdf/SkPDFDocument.cpp | 7 | ||||
-rw-r--r-- | src/pdf/SkPDFPage.cpp | 4 | ||||
-rw-r--r-- | src/pdf/SkPDFPage.h | 5 | ||||
-rw-r--r-- | src/pipe/SkGPipePriv.h | 3 | ||||
-rw-r--r-- | src/pipe/SkGPipeRead.cpp | 3 | ||||
-rw-r--r-- | src/pipe/SkGPipeWrite.cpp | 2 | ||||
-rw-r--r-- | src/ports/SkGlobalInitialization_default.cpp | 6 |
11 files changed, 163 insertions, 22 deletions
diff --git a/src/core/SkAnnotation.cpp b/src/core/SkAnnotation.cpp index 5e4363e728..52fa9b79f2 100644 --- a/src/core/SkAnnotation.cpp +++ b/src/core/SkAnnotation.cpp @@ -8,6 +8,7 @@ #include "SkAnnotation.h" #include "SkDataSet.h" #include "SkFlattenableBuffers.h" +#include "SkPoint.h" #include "SkStream.h" SkAnnotation::SkAnnotation(SkDataSet* data, uint32_t flags) { @@ -42,23 +43,50 @@ const char* SkAnnotationKeys::URL_Key() { return "SkAnnotationKey_URL"; }; +const char* SkAnnotationKeys::Define_Named_Dest_Key() { + return "SkAnnotationKey_Define_Named_Dest"; +}; + +const char* SkAnnotationKeys::Link_Named_Dest_Key() { + return "SkAnnotationKey_Link_Named_Dest"; +}; + /////////////////////////////////////////////////////////////////////////////// #include "SkCanvas.h" -void SkAnnotateRectWithURL(SkCanvas* canvas, const SkRect& rect, SkData* value) { - if (NULL == value) { - return; - } - - const char* key = SkAnnotationKeys::URL_Key(); +static void annotate_paint(SkPaint& paint, const char* key, SkData* value) { 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()); +} +void SkAnnotateRectWithURL(SkCanvas* canvas, const SkRect& rect, SkData* value) { + if (NULL == value) { + return; + } + SkPaint paint; + annotate_paint(paint, SkAnnotationKeys::URL_Key(), value); + canvas->drawRect(rect, paint); +} + +void SkAnnotateNamedDestination(SkCanvas* canvas, const SkPoint& point, SkData* name) { + if (NULL == name) { + return; + } + SkPaint paint; + annotate_paint(paint, SkAnnotationKeys::Define_Named_Dest_Key(), name); + canvas->drawPoint(point.x(), point.y(), paint); +} + +void SkAnnotateLinkToDestination(SkCanvas* canvas, const SkRect& rect, SkData* name) { + if (NULL == name) { + return; + } + SkPaint paint; + annotate_paint(paint, SkAnnotationKeys::Link_Named_Dest_Key(), name); canvas->drawRect(rect, paint); } diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp index 78ce0f635d..90d41862de 100644 --- a/src/core/SkDevice.cpp +++ b/src/core/SkDevice.cpp @@ -348,6 +348,7 @@ void SkDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) { void SkDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) { + CHECK_FOR_NODRAW_ANNOTATION(paint); draw.drawPoints(mode, count, pts, paint); } diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 82c26912a3..77c4bd1115 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -597,6 +597,7 @@ static const GrPrimitiveType gPointMode2PrimtiveType[] = { void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) { + CHECK_FOR_NODRAW_ANNOTATION(paint); CHECK_SHOULD_DRAW(draw, false); SkScalar width = paint.getStrokeWidth(); diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index eae7ab73f0..245299639e 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -645,6 +645,7 @@ void SkPDFDevice::cleanUp(bool clearFontUsage) { fShaderResources.unrefAll(); SkSafeUnref(fAnnotations); SkSafeUnref(fResourceDict); + fNamedDestinations.deleteAll(); if (clearFontUsage) { fFontGlyphUsage->reset(); @@ -703,6 +704,10 @@ void SkPDFDevice::drawPoints(const SkDraw& d, SkCanvas::PointMode mode, return; } + if (handlePointAnnotation(points, count, *d.fMatrix, passedPaint)) { + 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. @@ -791,7 +796,7 @@ void SkPDFDevice::drawRect(const SkDraw& d, const SkRect& r, return; } - if (handleAnnotations(r, *d.fMatrix, paint)) { + if (handleRectAnnotation(r, *d.fMatrix, paint)) { return; } @@ -847,7 +852,7 @@ void SkPDFDevice::drawPath(const SkDraw& d, const SkPath& origPath, return; } - if (handleAnnotations(pathPtr->getBounds(), *d.fMatrix, paint)) { + if (handleRectAnnotation(pathPtr->getBounds(), *d.fMatrix, paint)) { return; } @@ -1286,19 +1291,43 @@ SkData* SkPDFDevice::copyContentToData() const { return data.copyToData(); } -bool SkPDFDevice::handleAnnotations(const SkRect& r, const SkMatrix& matrix, - const SkPaint& p) { +bool SkPDFDevice::handleRectAnnotation(const SkRect& r, const SkMatrix& matrix, + const SkPaint& p) { SkAnnotation* annotationInfo = p.getAnnotation(); if (!annotationInfo) { return false; } SkData* urlData = annotationInfo->find(SkAnnotationKeys::URL_Key()); - if (!urlData) { + if (urlData) { + handleLinkToURL(urlData, r, matrix); + return p.isNoDrawAnnotation(); + } + SkData* linkToName = annotationInfo->find(SkAnnotationKeys::Link_Named_Dest_Key()); + if (linkToName) { + handleLinkToNamedDest(linkToName, r, matrix); + return p.isNoDrawAnnotation(); + } + return false; +} + +bool SkPDFDevice::handlePointAnnotation(const SkPoint* points, size_t count, + const SkMatrix& matrix, + const SkPaint& paint) { + SkAnnotation* annotationInfo = paint.getAnnotation(); + if (!annotationInfo) { return false; } + SkData* nameData = annotationInfo->find(SkAnnotationKeys::Define_Named_Dest_Key()); + if (nameData) { + for (size_t i = 0; i < count; i++) { + defineNamedDestination(nameData, points[i], matrix); + } + return paint.isNoDrawAnnotation(); + } + return false; +} - SkString url(static_cast<const char *>(urlData->data()), - urlData->size() - 1); +SkPDFDict* SkPDFDevice::createLinkAnnotation(const SkRect& r, const SkMatrix& matrix) { SkMatrix transform = matrix; transform.postConcat(fInitialTransform); SkRect translatedRect; @@ -1307,18 +1336,18 @@ bool SkPDFDevice::handleAnnotations(const SkRect& r, const SkMatrix& matrix, if (NULL == fAnnotations) { fAnnotations = SkNEW(SkPDFArray); } - SkAutoTUnref<SkPDFDict> annotation(new SkPDFDict("Annot")); + SkPDFDict* annotation(SkNEW_ARGS(SkPDFDict, ("Annot"))); annotation->insertName("Subtype", "Link"); - fAnnotations->append(annotation.get()); + fAnnotations->append(annotation); - SkAutoTUnref<SkPDFArray> border(new SkPDFArray); + SkAutoTUnref<SkPDFArray> border(SkNEW(SkPDFArray)); border->reserve(3); border->appendInt(0); // Horizontal corner radius. border->appendInt(0); // Vertical corner radius. border->appendInt(0); // Width, 0 = no border. annotation->insert("Border", border.get()); - SkAutoTUnref<SkPDFArray> rect(new SkPDFArray); + SkAutoTUnref<SkPDFArray> rect(SkNEW(SkPDFArray)); rect->reserve(4); rect->appendScalar(translatedRect.fLeft); rect->appendScalar(translatedRect.fTop); @@ -1326,12 +1355,66 @@ bool SkPDFDevice::handleAnnotations(const SkRect& r, const SkMatrix& matrix, rect->appendScalar(translatedRect.fBottom); annotation->insert("Rect", rect.get()); - SkAutoTUnref<SkPDFDict> action(new SkPDFDict("Action")); + return annotation; +} + +void SkPDFDevice::handleLinkToURL(SkData* urlData, const SkRect& r, + const SkMatrix& matrix) { + SkAutoTUnref<SkPDFDict> annotation(createLinkAnnotation(r, matrix)); + + SkString url(static_cast<const char *>(urlData->data()), + urlData->size() - 1); + SkAutoTUnref<SkPDFDict> action(SkNEW_ARGS(SkPDFDict, ("Action"))); action->insertName("S", "URI"); - action->insert("URI", new SkPDFString(url))->unref(); + action->insert("URI", SkNEW_ARGS(SkPDFString, (url)))->unref(); annotation->insert("A", action.get()); +} + +void SkPDFDevice::handleLinkToNamedDest(SkData* nameData, const SkRect& r, + const SkMatrix& matrix) { + SkAutoTUnref<SkPDFDict> annotation(createLinkAnnotation(r, matrix)); + SkString name(static_cast<const char *>(nameData->data()), + nameData->size() - 1); + annotation->insert("Dest", SkNEW_ARGS(SkPDFString, (name)))->unref(); +} + +struct NamedDestination { + const SkData* nameData; + SkPoint point; - return p.isNoDrawAnnotation(); + NamedDestination(const SkData* nameData, const SkPoint& point) + : nameData(nameData), point(point) { + nameData->ref(); + } + + ~NamedDestination() { + nameData->unref(); + } +}; + +void SkPDFDevice::defineNamedDestination(SkData* nameData, const SkPoint& point, + const SkMatrix& matrix) { + SkMatrix transform = matrix; + transform.postConcat(fInitialTransform); + SkPoint translatedPoint; + transform.mapXY(point.x(), point.y(), &translatedPoint); + fNamedDestinations.push( + SkNEW_ARGS(NamedDestination, (nameData, translatedPoint))); +} + +void SkPDFDevice::appendDestinations(SkPDFDict* dict, SkPDFObject* page) { + int nDest = fNamedDestinations.count(); + for (int i = 0; i < nDest; i++) { + NamedDestination* dest = fNamedDestinations[i]; + SkAutoTUnref<SkPDFArray> pdfDest(SkNEW(SkPDFArray)); + pdfDest->reserve(5); + pdfDest->append(SkNEW_ARGS(SkPDFObjRef, (page)))->unref(); + pdfDest->appendName("XYZ"); + pdfDest->appendInt(dest->point.x()); + pdfDest->appendInt(dest->point.y()); + pdfDest->appendInt(0); // Leave zoom unchanged + dict->insert(static_cast<const char *>(dest->nameData->data()), pdfDest); + } } SkPDFFormXObject* SkPDFDevice::createFormXObjectFromDevice() { diff --git a/src/pdf/SkPDFDocument.cpp b/src/pdf/SkPDFDocument.cpp index 4c66c6bb90..7ee2778326 100644 --- a/src/pdf/SkPDFDocument.cpp +++ b/src/pdf/SkPDFDocument.cpp @@ -107,18 +107,25 @@ bool SkPDFDocument::emitPDF(SkWStream* stream) { fDocCatalog->insert("OutputIntent", intentArray.get()); */ + SkPDFDict* dests = SkNEW(SkPDFDict); // fPageResources owns reference + fCatalog->addObject(dests, true /* onFirstPage */); + fPageResources.push(dests); + bool firstPage = true; for (int i = 0; i < fPages.count(); i++) { int resourceCount = fPageResources.count(); fPages[i]->finalizePage(fCatalog.get(), firstPage, &fPageResources); addResourcesToCatalog(resourceCount, firstPage, &fPageResources, fCatalog.get()); + fPages[i]->appendDestinations(dests); if (i == 0) { firstPage = false; fSecondPageFirstResourceIndex = fPageResources.count(); } } + fDocCatalog->insert("Dests", SkNEW_ARGS(SkPDFObjRef, (dests)))->unref(); + // Build font subsetting info before proceeding. perform_font_subsetting(fCatalog.get(), fPages, &fSubstitutes); diff --git a/src/pdf/SkPDFPage.cpp b/src/pdf/SkPDFPage.cpp index f47f8ffd46..4cdc00003b 100644 --- a/src/pdf/SkPDFPage.cpp +++ b/src/pdf/SkPDFPage.cpp @@ -147,3 +147,7 @@ const SkTDArray<SkPDFFont*>& SkPDFPage::getFontResources() const { const SkPDFGlyphSetMap& SkPDFPage::getFontGlyphUsage() const { return fDevice->getFontGlyphUsage(); } + +void SkPDFPage::appendDestinations(SkPDFDict* dict) { + fDevice->appendDestinations(dict, this); +} diff --git a/src/pdf/SkPDFPage.h b/src/pdf/SkPDFPage.h index 72ba335e66..285a2f565e 100644 --- a/src/pdf/SkPDFPage.h +++ b/src/pdf/SkPDFPage.h @@ -48,6 +48,11 @@ public: void finalizePage(SkPDFCatalog* catalog, bool firstPage, SkTDArray<SkPDFObject*>* resourceObjects); + /** Add destinations for this page to the supplied dictionary. + * @param dict Dictionary to add destinations to. + */ + void appendDestinations(SkPDFDict* dict); + /** Determine the size of the page content and store to the catalog * the offsets of all nonresource-indirect objects that make up the page * content. This must be called before emitPage(), but after finalizePage. diff --git a/src/pipe/SkGPipePriv.h b/src/pipe/SkGPipePriv.h index b563652cb9..f5f98f2bdf 100644 --- a/src/pipe/SkGPipePriv.h +++ b/src/pipe/SkGPipePriv.h @@ -25,8 +25,9 @@ enum PaintFlats { kShader_PaintFlat, kImageFilter_PaintFlat, kXfermode_PaintFlat, + kAnnotation_PaintFlat, - kLast_PaintFlat = kXfermode_PaintFlat + kLast_PaintFlat = kAnnotation_PaintFlat }; #define kCount_PaintFlats (kLast_PaintFlat + 1) diff --git a/src/pipe/SkGPipeRead.cpp b/src/pipe/SkGPipeRead.cpp index 6cffb1b343..f47f3bfe65 100644 --- a/src/pipe/SkGPipeRead.cpp +++ b/src/pipe/SkGPipeRead.cpp @@ -53,6 +53,9 @@ static void set_paintflat(SkPaint* paint, SkFlattenable* obj, unsigned paintFlat case kXfermode_PaintFlat: paint->setXfermode((SkXfermode*)obj); break; + case kAnnotation_PaintFlat: + paint->setAnnotation((SkAnnotation*)obj); + break; default: SkDEBUGFAIL("never gets here"); } diff --git a/src/pipe/SkGPipeWrite.cpp b/src/pipe/SkGPipeWrite.cpp index cfd1e7ceef..34020dfe7f 100644 --- a/src/pipe/SkGPipeWrite.cpp +++ b/src/pipe/SkGPipeWrite.cpp @@ -6,6 +6,7 @@ * found in the LICENSE file. */ +#include "SkAnnotation.h" #include "SkBitmapHeap.h" #include "SkCanvas.h" #include "SkColorFilter.h" @@ -47,6 +48,7 @@ static SkFlattenable* get_paintflat(const SkPaint& paint, unsigned paintFlat) { case kShader_PaintFlat: return paint.getShader(); case kImageFilter_PaintFlat: return paint.getImageFilter(); case kXfermode_PaintFlat: return paint.getXfermode(); + case kAnnotation_PaintFlat: return paint.getAnnotation(); } SkDEBUGFAIL("never gets here"); return NULL; diff --git a/src/ports/SkGlobalInitialization_default.cpp b/src/ports/SkGlobalInitialization_default.cpp index 26a61ca394..2d35cefc7d 100644 --- a/src/ports/SkGlobalInitialization_default.cpp +++ b/src/ports/SkGlobalInitialization_default.cpp @@ -15,6 +15,7 @@ #include "Sk1DPathEffect.h" #include "Sk2DPathEffect.h" +#include "SkAnnotation.h" #include "SkAvoidXfermode.h" #include "SkBicubicImageFilter.h" #include "SkBitmapSource.h" @@ -30,6 +31,8 @@ #include "SkComposeShader.h" #include "SkCornerPathEffect.h" #include "SkDashPathEffect.h" +#include "SkData.h" +#include "SkDataSet.h" #include "SkDiscretePathEffect.h" #include "SkDisplacementMapEffect.h" #include "SkEmptyShader.h" @@ -52,6 +55,7 @@ void SkFlattenable::InitializeFlattenables() { + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkAnnotation) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkAvoidXfermode) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBicubicImageFilter) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBitmapProcShader) @@ -66,6 +70,8 @@ void SkFlattenable::InitializeFlattenables() { SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposeShader) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkCornerPathEffect) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDashPathEffect) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkData) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDataSet) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDilateImageFilter) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDiscretePathEffect) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDisplacementMapEffect) |