• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "SkPdfNativeObject.h"
9 
10 #include "SkBitmap.h"
11 #include "SkFlate.h"
12 #include "SkPdfFont.h"
13 #include "SkPdfNativeTokenizer.h"
14 #include "SkPdfReporter.h"
15 #include "SkStream.h"
16 
17 // TODO(edisonn): mac builder does not find the header ... but from headers is ok
18 //#include "SkPdfStreamCommonDictionary_autogen.h"
19 #include "SkPdfHeaders_autogen.h"
20 
21 
22 SkPdfNativeObject SkPdfNativeObject::kNull = SkPdfNativeObject::makeNull();
23 
applyFlateDecodeFilter()24 bool SkPdfNativeObject::applyFlateDecodeFilter() {
25     if (!SkFlate::HaveFlate()) {
26         SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kNoFlateLibrary_SkPdfIssue,
27                     "forgot to link with flate library?", NULL, NULL);
28         return false;
29     }
30 
31     const unsigned char* old = fStr.fBuffer;
32     bool deleteOld = isStreamOwned();
33 
34     SkMemoryStream skstream(fStr.fBuffer, fStr.fBytes >> 2, false);
35     SkDynamicMemoryWStream uncompressedData;
36 
37     if (SkFlate::Inflate(&skstream, &uncompressedData)) {
38         fStr.fBytes = (uncompressedData.bytesWritten() << 2) + kOwnedStreamBit +
39                       kUnfilteredStreamBit;
40         fStr.fBuffer = (const unsigned char*)new unsigned char[uncompressedData.bytesWritten()];
41         uncompressedData.copyTo((void*)fStr.fBuffer);
42 
43         if (deleteOld) {
44             delete[] old;
45         }
46 
47         return true;
48     } else {
49         SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kBadStream_SkPdfIssue, "inflate failed", this, NULL);
50         return false;
51     }
52 }
53 
applyDCTDecodeFilter()54 bool SkPdfNativeObject::applyDCTDecodeFilter() {
55     // applyDCTDecodeFilter will fail, and it won't allow any more filters.
56     // technically, it would be possible, but not a real world scenario.
57     // in this way we create the image from the DCT stream directly.
58     return false;
59 }
60 
applyFilter(const char * name)61 bool SkPdfNativeObject::applyFilter(const char* name) {
62     if (strcmp(name, "FlateDecode") == 0) {
63         return applyFlateDecodeFilter();
64     } else if (strcmp(name, "DCTDecode") == 0) {
65         return applyDCTDecodeFilter();
66     }
67     SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, "filter not supported", this,
68                 NULL);
69     return false;
70 }
71 
filterStream()72 bool SkPdfNativeObject::filterStream() {
73     SkPdfMarkObjectUsed();
74 
75     if (!hasStream()) {
76         SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kBadStream_SkPdfIssue, "No Stream", this,
77                     NULL);
78         return false;
79     }
80 
81     if (isStreamFiltered()) {
82         return true;
83     }
84 
85     SkPdfStreamCommonDictionary* stream = (SkPdfStreamCommonDictionary*)this;
86 
87     if (!stream->has_Filter()) {
88         fStr.fBytes = ((fStr.fBytes >> 1) << 1) + kFilteredStreamBit;
89     } else if (stream->isFilterAName(NULL)) {
90         SkString filterName = stream->getFilterAsName(NULL);
91         applyFilter(filterName.c_str());
92     } else if (stream->isFilterAArray(NULL)) {
93         const SkPdfArray* filters = stream->getFilterAsArray(NULL);
94         int cnt = (int) filters->size();
95         for (int i = cnt - 1; i >= 0; i--) {
96             const SkPdfNativeObject* filterName = filters->objAtAIndex(i);
97             if (filterName != NULL && filterName->isName()) {
98                 if (!applyFilter(filterName->nameValue())) {
99                     break;
100                 }
101             } else {
102                 SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kIncositentSyntax_SkPdfIssue,
103                             "filter name should be a Name", this, NULL);
104             }
105         }
106     }
107 
108     return true;
109 }
110 
releaseData()111 void SkPdfNativeObject::releaseData() {
112 #ifdef PDF_TRACK_OBJECT_USAGE
113     SkPdfReportIf(!fUsed, kInfo_SkPdfIssueSeverity, kUnusedObject_SkPdfIssue,
114                   "Unused object in rendering", this, NULL);
115 #endif  // PDF_TRACK_OBJECT_USAGE
116 
117     SkPdfMarkObjectUnused();
118 
119     if (fData) {
120         switch (fDataType) {
121             case kFont_Data:
122                 delete (SkPdfFont*)fData;
123                 break;
124             case kBitmap_Data:
125                 delete (SkBitmap*)fData;
126                 break;
127             default:
128                 SkASSERT(false);
129                 break;
130         }
131     }
132     fData = NULL;
133     fDataType = kEmpty_Data;
134 }
135