Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2013 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef SkDocument_DEFINED
      9 #define SkDocument_DEFINED
     10 
     11 #include "SkBitmap.h"
     12 #include "SkPicture.h"
     13 #include "SkRect.h"
     14 #include "SkRefCnt.h"
     15 #include "SkString.h"
     16 #include "SkTime.h"
     17 
     18 class SkCanvas;
     19 class SkPixelSerializer;
     20 class SkWStream;
     21 
     22 /** SK_ScalarDefaultDPI is 72 DPI.
     23 */
     24 #define SK_ScalarDefaultRasterDPI           72.0f
     25 
     26 /**
     27  *  High-level API for creating a document-based canvas. To use..
     28  *
     29  *  1. Create a document, specifying a stream to store the output.
     30  *  2. For each "page" of content:
     31  *      a. canvas = doc->beginPage(...)
     32  *      b. draw_my_content(canvas);
     33  *      c. doc->endPage();
     34  *  3. Close the document with doc->close().
     35  */
     36 class SK_API SkDocument : public SkRefCnt {
     37 public:
     38     /**
     39      *  Create a PDF-backed document, writing the results into a SkWStream.
     40      *
     41      *  PDF pages are sized in point units. 1 pt == 1/72 inch == 127/360 mm.
     42      *
     43      *  @param SkWStream* A PDF document will be written to this
     44      *         stream.  The document may write to the stream at
     45      *         anytime during its lifetime, until either close() is
     46      *         called or the document is deleted.
     47      *  @param dpi The DPI (pixels-per-inch) at which features without
     48      *         native PDF support will be rasterized (e.g. draw image
     49      *         with perspective, draw text with perspective, ...)  A
     50      *         larger DPI would create a PDF that reflects the
     51      *         original intent with better fidelity, but it can make
     52      *         for larger PDF files too, which would use more memory
     53      *         while rendering, and it would be slower to be processed
     54      *         or sent online or to printer.
     55      *  @returns NULL if there is an error, otherwise a newly created
     56      *           PDF-backed SkDocument.
     57      */
     58     static SkDocument* CreatePDF(SkWStream*,
     59                                  SkScalar dpi = SK_ScalarDefaultRasterDPI);
     60 
     61     /**
     62      *  @param jpegEncoder For PDF documents, if a jpegEncoder is set,
     63      *         use it to encode SkImages and SkBitmaps as [JFIF]JPEGs.
     64      *         This feature is deprecated and is only supplied for
     65      *         backwards compatability.
     66      *
     67      *         The prefered method to create PDFs with JPEG images is
     68      *         to use SkImage::NewFromEncoded() and not jpegEncoder.
     69      *         Chromium uses NewFromEncoded.
     70      *
     71      *         If the encoder is unset, or if jpegEncoder->onEncode()
     72      *         returns NULL, fall back on encoding images losslessly
     73      *         with Deflate.
     74      */
     75     static SkDocument* CreatePDF(SkWStream*,
     76                                  SkScalar dpi,
     77                                  SkPixelSerializer* jpegEncoder);
     78 
     79     /**
     80      *  Create a PDF-backed document, writing the results into a file.
     81      */
     82     static SkDocument* CreatePDF(const char outputFilePath[],
     83                                  SkScalar dpi = SK_ScalarDefaultRasterDPI);
     84 
     85     /**
     86      *  Create a XPS-backed document, writing the results into the stream.
     87      *  Returns NULL if XPS is not supported.
     88      */
     89     static SkDocument* CreateXPS(SkWStream* stream,
     90                                  SkScalar dpi = SK_ScalarDefaultRasterDPI);
     91 
     92     /**
     93      *  Create a XPS-backed document, writing the results into a file.
     94      *  Returns NULL if XPS is not supported.
     95      */
     96     static SkDocument* CreateXPS(const char path[],
     97                                  SkScalar dpi = SK_ScalarDefaultRasterDPI);
     98     /**
     99      *  Begin a new page for the document, returning the canvas that will draw
    100      *  into the page. The document owns this canvas, and it will go out of
    101      *  scope when endPage() or close() is called, or the document is deleted.
    102      */
    103     SkCanvas* beginPage(SkScalar width, SkScalar height,
    104                         const SkRect* content = NULL);
    105 
    106     /**
    107      *  Call endPage() when the content for the current page has been drawn
    108      *  (into the canvas returned by beginPage()). After this call the canvas
    109      *  returned by beginPage() will be out-of-scope.
    110      */
    111     void endPage();
    112 
    113     /**
    114      *  Call close() when all pages have been drawn. This will close the file
    115      *  or stream holding the document's contents. After close() the document
    116      *  can no longer add new pages. Deleting the document will automatically
    117      *  call close() if need be.
    118      *  Returns true on success or false on failure.
    119      */
    120     bool close();
    121 
    122     /**
    123      *  Call abort() to stop producing the document immediately.
    124      *  The stream output must be ignored, and should not be trusted.
    125      */
    126     void abort();
    127 
    128     /**
    129      *  Set the document's metadata, if supported by the document
    130      *  type.  The creationDate and modifiedDate parameters can be
    131      *  nullptr.  For example:
    132      *
    133      *  SkDocument* make_doc(SkWStream* output) {
    134      *      std::vector<SkDocument::Attribute> info;
    135      *      info.emplace_back(SkString("Title"), SkString("..."));
    136      *      info.emplace_back(SkString("Author"), SkString("..."));
    137      *      info.emplace_back(SkString("Subject"), SkString("..."));
    138      *      info.emplace_back(SkString("Keywords"), SkString("..."));
    139      *      info.emplace_back(SkString("Creator"), SkString("..."));
    140      *      SkTime::DateTime now;
    141      *      SkTime::GetDateTime(&now);
    142      *      SkDocument* doc = SkDocument::CreatePDF(output);
    143      *      doc->setMetadata(&info[0], (int)info.size(), &now, &now);
    144      *      return doc;
    145      *  }
    146      */
    147     struct Attribute {
    148         SkString fKey, fValue;
    149         Attribute(const SkString& k, const SkString& v) : fKey(k), fValue(v) {}
    150     };
    151     virtual void setMetadata(const SkDocument::Attribute[],
    152                              int /* attributeCount */,
    153                              const SkTime::DateTime* /* creationDate */,
    154                              const SkTime::DateTime* /* modifiedDate */) {}
    155 
    156 protected:
    157     SkDocument(SkWStream*, void (*)(SkWStream*, bool aborted));
    158 
    159     // note: subclasses must call close() in their destructor, as the base class
    160     // cannot do this for them.
    161     virtual ~SkDocument();
    162 
    163     virtual SkCanvas* onBeginPage(SkScalar width, SkScalar height,
    164                                   const SkRect& content) = 0;
    165     virtual void onEndPage() = 0;
    166     virtual bool onClose(SkWStream*) = 0;
    167     virtual void onAbort() = 0;
    168 
    169     // Allows subclasses to write to the stream as pages are written.
    170     SkWStream* getStream() { return fStream; }
    171 
    172     enum State {
    173         kBetweenPages_State,
    174         kInPage_State,
    175         kClosed_State
    176     };
    177     State getState() const { return fState; }
    178 
    179 private:
    180     SkWStream* fStream;
    181     void       (*fDoneProc)(SkWStream*, bool aborted);
    182     State      fState;
    183 
    184     typedef SkRefCnt INHERITED;
    185 };
    186 
    187 #endif
    188