blob: 57e9abb3680e555d3cbb5fc2926e467d9d0b6302 [file] [log] [blame]
edisonn@google.com571c70b2013-07-10 17:09:50 +00001
2#include "SkPdfObject.h"
3#include "SkPdfStreamCommonDictionary_autogen.h"
4
5#include "SkFlate.h"
6#include "SkStream.h"
7#include "SkPdfNativeTokenizer.h"
8
9SkPdfObject SkPdfObject::kNull = SkPdfObject::makeNull();
10
11bool SkPdfObject::applyFlateDecodeFilter(SkPdfAllocator* allocator) {
12 if (!SkFlate::HaveFlate()) {
13 // TODO(edisonn): warn, make callers handle it
14 return false;
15 }
16
17 SkMemoryStream skstream(fStr.fBuffer, fStr.fBytes >> 1, false);
18 SkDynamicMemoryWStream uncompressedData;
19
20 if (SkFlate::Inflate(&skstream, &uncompressedData)) {
21 fStr.fBytes = (uncompressedData.bytesWritten() << 1) + kUnfilteredStreamBit;
22 fStr.fBuffer = (unsigned char*)allocator->alloc(uncompressedData.bytesWritten());
23 uncompressedData.copyTo(fStr.fBuffer);
24 return true;
25 } else {
26 // TODO(edisonn): warn, make callers handle it
27 return false;
28 }
29}
30
31bool SkPdfObject::applyDCTDecodeFilter(SkPdfAllocator* allocator) {
32 // this would fail, and it won't allow any more filters.
33 // technically, it would be possible, but not a real world scenario
34 // TODO(edisonn): or get the image here and store it for fast retrieval?
35 return false;
36}
37
38bool SkPdfObject::applyFilter(const char* name, SkPdfAllocator* allocator) {
39 if (strcmp(name, "FlateDecode") == 0) {
40 return applyFlateDecodeFilter(allocator);
41 } else if (strcmp(name, "DCTDecode") == 0) {
42 return applyDCTDecodeFilter(allocator);
43 }
44 // TODO(edisonn): allert, not supported, but should be implemented asap
45 return false;
46}
47
48bool SkPdfObject::filterStream(SkPdfAllocator* allocator) {
49 if (!hasStream()) {
50 return false;
51 }
52
53 if (isStreamFiltered()) {
54 return true;
55 }
56
57 SkPdfStreamCommonDictionary* stream = (SkPdfStreamCommonDictionary*)this;
58
59 if (!stream->has_Filter()) {
60 fStr.fBytes = ((fStr.fBytes >> 1) << 1) + kFilteredStreamBit;
61 return true;
62 }
63
64 if (stream->isFilterAName(NULL)) {
65 std::string filterName = stream->getFilterAsName(NULL);
66 applyFilter(filterName.c_str(), allocator);
67 } else if (stream->isFilterAArray(NULL)) {
68 const SkPdfArray* filters = stream->getFilterAsArray(NULL);
69 int cnt = filters->size();
70 for (int i = cnt - 1; i >= 0; i--) {
71 const SkPdfObject* filterName = filters->objAtAIndex(i);
72 if (filterName != NULL && filterName->isName()) {
73 if (!applyFilter(filterName->nameValue(), allocator)) {
74 break;
75 }
76 } else {
77 // TODO(edisonn): report warning
78 }
79 }
80 }
81
82 fStr.fBytes = ((fStr.fBytes >> 1) << 1) + kFilteredStreamBit;
83
84 return true;
85}