blob: 4b5f59e401036f865d35b2c141cdc7e0e688cfd0 [file] [log] [blame]
edisonn@google.com571c70b2013-07-10 17:09:50 +00001
edisonn@google.com3aa35552013-08-14 18:26:20 +00002#include "SkPdfNativeObject.h"
edisonn@google.com33f11b62013-08-14 21:35:27 +00003
4// TODO(edisonn): mac builder does not find the header ... but from headers is ok
5//#include "SkPdfStreamCommonDictionary_autogen.h"
6#include "SkPdfHeaders_autogen.h"
edisonn@google.com571c70b2013-07-10 17:09:50 +00007
8#include "SkFlate.h"
9#include "SkStream.h"
10#include "SkPdfNativeTokenizer.h"
11
edisonn@google.comb0145ce2013-08-05 16:23:23 +000012#include "SkBitmap.h"
13#include "SkPdfFont.h"
14
edisonn@google.com3aa35552013-08-14 18:26:20 +000015SkPdfNativeObject SkPdfNativeObject::kNull = SkPdfNativeObject::makeNull();
edisonn@google.com571c70b2013-07-10 17:09:50 +000016
edisonn@google.com3aa35552013-08-14 18:26:20 +000017bool SkPdfNativeObject::applyFlateDecodeFilter() {
edisonn@google.com571c70b2013-07-10 17:09:50 +000018 if (!SkFlate::HaveFlate()) {
19 // TODO(edisonn): warn, make callers handle it
20 return false;
21 }
22
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000023 const unsigned char* old = fStr.fBuffer;
24 bool deleteOld = isStreamOwned();
25
26 SkMemoryStream skstream(fStr.fBuffer, fStr.fBytes >> 2, false);
edisonn@google.com571c70b2013-07-10 17:09:50 +000027 SkDynamicMemoryWStream uncompressedData;
28
29 if (SkFlate::Inflate(&skstream, &uncompressedData)) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000030 fStr.fBytes = (uncompressedData.bytesWritten() << 2) + kOwnedStreamBit + kUnfilteredStreamBit;
31 fStr.fBuffer = (const unsigned char*)new unsigned char[uncompressedData.bytesWritten()];
32 uncompressedData.copyTo((void*)fStr.fBuffer);
33
34 if (deleteOld) {
35 delete[] old;
36 }
37
edisonn@google.com571c70b2013-07-10 17:09:50 +000038 return true;
39 } else {
40 // TODO(edisonn): warn, make callers handle it
41 return false;
42 }
43}
44
edisonn@google.com3aa35552013-08-14 18:26:20 +000045bool SkPdfNativeObject::applyDCTDecodeFilter() {
edisonn@google.com571c70b2013-07-10 17:09:50 +000046 // this would fail, and it won't allow any more filters.
47 // technically, it would be possible, but not a real world scenario
48 // TODO(edisonn): or get the image here and store it for fast retrieval?
49 return false;
50}
51
edisonn@google.com3aa35552013-08-14 18:26:20 +000052bool SkPdfNativeObject::applyFilter(const char* name) {
edisonn@google.com571c70b2013-07-10 17:09:50 +000053 if (strcmp(name, "FlateDecode") == 0) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000054 return applyFlateDecodeFilter();
edisonn@google.com571c70b2013-07-10 17:09:50 +000055 } else if (strcmp(name, "DCTDecode") == 0) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000056 return applyDCTDecodeFilter();
edisonn@google.com571c70b2013-07-10 17:09:50 +000057 }
58 // TODO(edisonn): allert, not supported, but should be implemented asap
59 return false;
60}
61
edisonn@google.com3aa35552013-08-14 18:26:20 +000062bool SkPdfNativeObject::filterStream() {
edisonn@google.com571c70b2013-07-10 17:09:50 +000063 if (!hasStream()) {
64 return false;
65 }
66
67 if (isStreamFiltered()) {
68 return true;
69 }
70
71 SkPdfStreamCommonDictionary* stream = (SkPdfStreamCommonDictionary*)this;
72
73 if (!stream->has_Filter()) {
74 fStr.fBytes = ((fStr.fBytes >> 1) << 1) + kFilteredStreamBit;
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000075 } else if (stream->isFilterAName(NULL)) {
edisonn@google.com571c70b2013-07-10 17:09:50 +000076 std::string filterName = stream->getFilterAsName(NULL);
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000077 applyFilter(filterName.c_str());
edisonn@google.com571c70b2013-07-10 17:09:50 +000078 } else if (stream->isFilterAArray(NULL)) {
79 const SkPdfArray* filters = stream->getFilterAsArray(NULL);
80 int cnt = filters->size();
81 for (int i = cnt - 1; i >= 0; i--) {
edisonn@google.com3aa35552013-08-14 18:26:20 +000082 const SkPdfNativeObject* filterName = filters->objAtAIndex(i);
edisonn@google.com571c70b2013-07-10 17:09:50 +000083 if (filterName != NULL && filterName->isName()) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000084 if (!applyFilter(filterName->nameValue())) {
edisonn@google.com571c70b2013-07-10 17:09:50 +000085 break;
86 }
87 } else {
88 // TODO(edisonn): report warning
89 }
90 }
91 }
92
edisonn@google.com571c70b2013-07-10 17:09:50 +000093 return true;
94}
edisonn@google.comb0145ce2013-08-05 16:23:23 +000095
edisonn@google.com3aa35552013-08-14 18:26:20 +000096void SkPdfNativeObject::releaseData() {
edisonn@google.comb0145ce2013-08-05 16:23:23 +000097 if (fData) {
98 switch (fDataType) {
99 case kFont_Data:
100 delete (SkPdfFont*)fData;
101 break;
102 case kBitmap_Data:
103 delete (SkBitmap*)fData;
104 break;
105 default:
106 SkASSERT(false);
107 break;
108 }
109 }
110 fData = NULL;
111 fDataType = kEmpty_Data;
112}