blob: eb342af7301c050b24f911ce970d04e2075010a3 [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
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000011bool SkPdfObject::applyFlateDecodeFilter() {
edisonn@google.com571c70b2013-07-10 17:09:50 +000012 if (!SkFlate::HaveFlate()) {
13 // TODO(edisonn): warn, make callers handle it
14 return false;
15 }
16
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000017 const unsigned char* old = fStr.fBuffer;
18 bool deleteOld = isStreamOwned();
19
20 SkMemoryStream skstream(fStr.fBuffer, fStr.fBytes >> 2, false);
edisonn@google.com571c70b2013-07-10 17:09:50 +000021 SkDynamicMemoryWStream uncompressedData;
22
23 if (SkFlate::Inflate(&skstream, &uncompressedData)) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000024 fStr.fBytes = (uncompressedData.bytesWritten() << 2) + kOwnedStreamBit + kUnfilteredStreamBit;
25 fStr.fBuffer = (const unsigned char*)new unsigned char[uncompressedData.bytesWritten()];
26 uncompressedData.copyTo((void*)fStr.fBuffer);
27
28 if (deleteOld) {
29 delete[] old;
30 }
31
edisonn@google.com571c70b2013-07-10 17:09:50 +000032 return true;
33 } else {
34 // TODO(edisonn): warn, make callers handle it
35 return false;
36 }
37}
38
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000039bool SkPdfObject::applyDCTDecodeFilter() {
edisonn@google.com571c70b2013-07-10 17:09:50 +000040 // this would fail, and it won't allow any more filters.
41 // technically, it would be possible, but not a real world scenario
42 // TODO(edisonn): or get the image here and store it for fast retrieval?
43 return false;
44}
45
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000046bool SkPdfObject::applyFilter(const char* name) {
edisonn@google.com571c70b2013-07-10 17:09:50 +000047 if (strcmp(name, "FlateDecode") == 0) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000048 return applyFlateDecodeFilter();
edisonn@google.com571c70b2013-07-10 17:09:50 +000049 } else if (strcmp(name, "DCTDecode") == 0) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000050 return applyDCTDecodeFilter();
edisonn@google.com571c70b2013-07-10 17:09:50 +000051 }
52 // TODO(edisonn): allert, not supported, but should be implemented asap
53 return false;
54}
55
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000056bool SkPdfObject::filterStream() {
edisonn@google.com571c70b2013-07-10 17:09:50 +000057 if (!hasStream()) {
58 return false;
59 }
60
61 if (isStreamFiltered()) {
62 return true;
63 }
64
65 SkPdfStreamCommonDictionary* stream = (SkPdfStreamCommonDictionary*)this;
66
67 if (!stream->has_Filter()) {
68 fStr.fBytes = ((fStr.fBytes >> 1) << 1) + kFilteredStreamBit;
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000069 } else if (stream->isFilterAName(NULL)) {
edisonn@google.com571c70b2013-07-10 17:09:50 +000070 std::string filterName = stream->getFilterAsName(NULL);
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000071 applyFilter(filterName.c_str());
edisonn@google.com571c70b2013-07-10 17:09:50 +000072 } else if (stream->isFilterAArray(NULL)) {
73 const SkPdfArray* filters = stream->getFilterAsArray(NULL);
74 int cnt = filters->size();
75 for (int i = cnt - 1; i >= 0; i--) {
76 const SkPdfObject* filterName = filters->objAtAIndex(i);
77 if (filterName != NULL && filterName->isName()) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000078 if (!applyFilter(filterName->nameValue())) {
edisonn@google.com571c70b2013-07-10 17:09:50 +000079 break;
80 }
81 } else {
82 // TODO(edisonn): report warning
83 }
84 }
85 }
86
edisonn@google.com571c70b2013-07-10 17:09:50 +000087 return true;
88}