OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "podofo.h" | 8 #include "podofo.h" |
9 #include "SkPdfHeaders_autogen.h" | 9 #include "SkPdfHeaders_autogen.h" |
10 #include "SkPdfPodofoMapper_autogen.h" | 10 #include "SkPdfPodofoMapper_autogen.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 | 21 |
22 struct PdfToken { | 22 struct PdfToken { |
23 const char* fKeyword; | 23 const char* fKeyword; |
24 SkPdfObject* fObject; | 24 SkPdfObject* fObject; |
25 SkPdfTokenType fType; | 25 SkPdfTokenType fType; |
26 | 26 |
27 PdfToken() : fKeyword(NULL), fObject(NULL) {} | 27 PdfToken() : fKeyword(NULL), fObject(NULL) {} |
28 }; | 28 }; |
29 | 29 |
30 class SkPdfTokenizer { | 30 class SkPdfTokenizer { |
| 31 PdfMemDocument* fDoc; |
31 PdfContentsTokenizer* fTokenizer; | 32 PdfContentsTokenizer* fTokenizer; |
32 PdfMemDocument* fDoc; | |
33 | 33 |
34 char* fUncompressedStream; | 34 char* fUncompressedStream; |
35 pdf_long fUncompressedStreamLength; | 35 pdf_long fUncompressedStreamLength; |
36 | 36 |
37 bool fEmpty; | 37 bool fEmpty; |
38 bool fHasPutBack; | 38 bool fHasPutBack; |
39 PdfToken fPutBack; | 39 PdfToken fPutBack; |
40 | 40 |
41 public: | 41 public: |
42 SkPdfTokenizer(PdfMemDocument* doc = NULL, PdfContentsTokenizer* tokenizer =
NULL) : fDoc(doc), fTokenizer(tokenizer), fEmpty(false), fUncompressedStream(NU
LL), fUncompressedStreamLength(0), fHasPutBack(false) {} | 42 SkPdfTokenizer(PdfMemDocument* doc = NULL, PdfContentsTokenizer* tokenizer =
NULL) : fDoc(doc), fTokenizer(tokenizer), fUncompressedStream(NULL), fUncompres
sedStreamLength(0), fEmpty(false), fHasPutBack(false) {} |
43 SkPdfTokenizer(const SkPdfObject* objWithStream) : fDoc(NULL), fTokenizer(NU
LL), fHasPutBack(false), fEmpty(false) { | 43 SkPdfTokenizer(const SkPdfObject* objWithStream) : fDoc(NULL), fTokenizer(NU
LL), fEmpty(false), fHasPutBack(false) { |
44 fUncompressedStream = NULL; | 44 fUncompressedStream = NULL; |
45 fUncompressedStreamLength = 0; | 45 fUncompressedStreamLength = 0; |
46 | 46 |
47 fDoc = NULL; | 47 fDoc = NULL; |
48 | 48 |
49 | 49 |
50 try { | 50 try { |
51 objWithStream->podofo()->GetStream()->GetFilteredCopy(&fUncompressed
Stream, &fUncompressedStreamLength); | 51 objWithStream->podofo()->GetStream()->GetFilteredCopy(&fUncompressed
Stream, &fUncompressedStreamLength); |
52 if (fUncompressedStream != NULL && fUncompressedStreamLength != 0) { | 52 if (fUncompressedStream != NULL && fUncompressedStreamLength != 0) { |
53 fTokenizer = new PdfContentsTokenizer(fUncompressedStream, fUnco
mpressedStreamLength); | 53 fTokenizer = new PdfContentsTokenizer(fUncompressedStream, fUnco
mpressedStreamLength); |
54 } else { | 54 } else { |
55 fEmpty = true; | 55 fEmpty = true; |
56 } | 56 } |
57 } catch (PdfError& e) { | 57 } catch (PdfError& e) { |
58 fEmpty = true; | 58 fEmpty = true; |
59 } | 59 } |
60 | 60 |
61 } | 61 } |
62 | 62 |
63 SkPdfTokenizer(const char* buffer, int len) : fDoc(NULL), fTokenizer(NULL),
fHasPutBack(false), fUncompressedStream(NULL), fUncompressedStreamLength(0), fEm
pty(false) { | 63 SkPdfTokenizer(const char* buffer, int len) : fDoc(NULL), fTokenizer(NULL),
fUncompressedStream(NULL), fUncompressedStreamLength(0), fEmpty(false), fHasPutB
ack(false) { |
64 try { | 64 try { |
65 fTokenizer = new PdfContentsTokenizer(buffer, len); | 65 fTokenizer = new PdfContentsTokenizer(buffer, len); |
66 } catch (PdfError& e) { | 66 } catch (PdfError& e) { |
67 fEmpty = true; | 67 fEmpty = true; |
68 } | 68 } |
69 } | 69 } |
70 | 70 |
71 ~SkPdfTokenizer() { | 71 ~SkPdfTokenizer() { |
72 free(fUncompressedStream); | 72 free(fUncompressedStream); |
73 } | 73 } |
(...skipping 26 matching lines...) Expand all Loading... |
100 if (!ret) return ret; | 100 if (!ret) return ret; |
101 | 101 |
102 switch (type) { | 102 switch (type) { |
103 case ePdfContentsType_Keyword: | 103 case ePdfContentsType_Keyword: |
104 token->fType = kKeyword_TokenType; | 104 token->fType = kKeyword_TokenType; |
105 break; | 105 break; |
106 | 106 |
107 case ePdfContentsType_Variant: { | 107 case ePdfContentsType_Variant: { |
108 token->fType = kObject_TokenType; | 108 token->fType = kObject_TokenType; |
109 PdfObject* obj = new PdfObject(var); | 109 PdfObject* obj = new PdfObject(var); |
110 PodofoMapper::map(*fDoc, *obj, &token->fObject); | 110 mapObject(*fDoc, *obj, &token->fObject); |
111 } | 111 } |
112 break; | 112 break; |
113 | 113 |
114 case ePdfContentsType_ImageData: | 114 case ePdfContentsType_ImageData: |
115 token->fType = kImageData_TokenType; | 115 token->fType = kImageData_TokenType; |
116 // TODO(edisonn): inline images seem to work without it | 116 // TODO(edisonn): inline images seem to work without it |
117 break; | 117 break; |
118 } | 118 } |
119 #ifdef PDF_TRACE | 119 #ifdef PDF_TRACE |
120 std::string str; | 120 std::string str; |
121 if (token->fObject) { | 121 if (token->fObject) { |
122 token->fObject->podofo()->ToString(str); | 122 token->fObject->podofo()->ToString(str); |
123 } | 123 } |
124 printf("%s %s\n", token->fType == kKeyword_TokenType ? "Keyword" : token
->fType == kObject_TokenType ? "Object" : "ImageData", token->fKeyword ? token->
fKeyword : str.c_str()); | 124 printf("%s %s\n", token->fType == kKeyword_TokenType ? "Keyword" : token
->fType == kObject_TokenType ? "Object" : "ImageData", token->fKeyword ? token->
fKeyword : str.c_str()); |
125 #endif | 125 #endif |
126 return ret; | 126 return ret; |
127 } | 127 } |
128 }; | 128 }; |
129 | 129 |
| 130 extern "C" PdfContext* gPdfContext; |
| 131 extern "C" SkBitmap* gDumpBitmap; |
| 132 extern "C" SkCanvas* gDumpCanvas; |
| 133 |
| 134 // TODO(edisonn): move in trace util. |
| 135 #ifdef PDF_TRACE |
| 136 static void SkTraceMatrix(const SkMatrix& matrix, const char* sz = "") { |
| 137 printf("SkMatrix %s ", sz); |
| 138 for (int i = 0 ; i < 9 ; i++) { |
| 139 printf("%f ", SkScalarToDouble(matrix.get(i))); |
| 140 } |
| 141 printf("\n"); |
| 142 } |
| 143 |
| 144 static void SkTraceRect(const SkRect& rect, const char* sz = "") { |
| 145 printf("SkRect %s ", sz); |
| 146 printf("x = %f ", SkScalarToDouble(rect.x())); |
| 147 printf("y = %f ", SkScalarToDouble(rect.y())); |
| 148 printf("w = %f ", SkScalarToDouble(rect.width())); |
| 149 printf("h = %f ", SkScalarToDouble(rect.height())); |
| 150 printf("\n"); |
| 151 } |
| 152 |
| 153 #else |
| 154 #define SkTraceMatrix(a,b) |
| 155 #define SkTraceRect(a,b) |
| 156 #endif |
| 157 |
| 158 // TODO(edisonn): Document PdfTokenLooper and subclasses. |
| 159 class PdfTokenLooper { |
| 160 protected: |
| 161 PdfTokenLooper* fParent; |
| 162 SkPdfTokenizer* fTokenizer; |
| 163 PdfContext* fPdfContext; |
| 164 SkCanvas* fCanvas; |
| 165 |
| 166 public: |
| 167 PdfTokenLooper(PdfTokenLooper* parent, |
| 168 SkPdfTokenizer* tokenizer, |
| 169 PdfContext* pdfContext, |
| 170 SkCanvas* canvas) |
| 171 : fParent(parent), fTokenizer(tokenizer), fPdfContext(pdfContext), fCanv
as(canvas) {} |
| 172 |
| 173 virtual PdfResult consumeToken(PdfToken& token) = 0; |
| 174 virtual void loop() = 0; |
| 175 |
| 176 void setUp(PdfTokenLooper* parent) { |
| 177 fParent = parent; |
| 178 fTokenizer = parent->fTokenizer; |
| 179 fPdfContext = parent->fPdfContext; |
| 180 fCanvas = parent->fCanvas; |
| 181 } |
| 182 }; |
| 183 |
| 184 class PdfMainLooper : public PdfTokenLooper { |
| 185 public: |
| 186 PdfMainLooper(PdfTokenLooper* parent, |
| 187 SkPdfTokenizer* tokenizer, |
| 188 PdfContext* pdfContext, |
| 189 SkCanvas* canvas) |
| 190 : PdfTokenLooper(parent, tokenizer, pdfContext, canvas) {} |
| 191 |
| 192 virtual PdfResult consumeToken(PdfToken& token); |
| 193 virtual void loop(); |
| 194 }; |
| 195 |
| 196 class PdfInlineImageLooper : public PdfTokenLooper { |
| 197 public: |
| 198 PdfInlineImageLooper() |
| 199 : PdfTokenLooper(NULL, NULL, NULL, NULL) {} |
| 200 |
| 201 virtual PdfResult consumeToken(PdfToken& token); |
| 202 virtual void loop(); |
| 203 PdfResult done(); |
| 204 }; |
| 205 |
| 206 class PdfCompatibilitySectionLooper : public PdfTokenLooper { |
| 207 public: |
| 208 PdfCompatibilitySectionLooper() |
| 209 : PdfTokenLooper(NULL, NULL, NULL, NULL) {} |
| 210 |
| 211 virtual PdfResult consumeToken(PdfToken& token); |
| 212 virtual void loop(); |
| 213 }; |
| 214 |
130 class SkPdfDoc { | 215 class SkPdfDoc { |
131 PdfMemDocument fDoc; | 216 PdfMemDocument fDoc; |
132 public: | 217 public: |
133 | 218 |
134 PdfMemDocument& podofo() {return fDoc;} | 219 PdfMemDocument& podofo() {return fDoc;} |
135 | 220 |
136 SkPdfDoc(const char* path) : fDoc(path) {} | 221 SkPdfDoc(const char* path) : fDoc(path) {} |
137 | 222 |
138 int pages() { | 223 int pages() { |
139 return fDoc.GetPageCount(); | 224 return fDoc.GetPageCount(); |
140 } | 225 } |
141 | 226 |
| 227 double width(int n) { |
| 228 PdfRect rect = fDoc.GetPage(n)->GetMediaBox(); |
| 229 return rect.GetWidth() + rect.GetLeft(); |
| 230 } |
| 231 |
| 232 double height(int n) { |
| 233 PdfRect rect = fDoc.GetPage(n)->GetMediaBox(); |
| 234 return rect.GetHeight() + rect.GetBottom(); |
| 235 } |
| 236 |
142 // Can return NULL | 237 // Can return NULL |
143 SkPdfPageObjectDictionary* page(int n) { | 238 SkPdfPageObjectDictionary* page(int n) { |
144 SkPdfPageObjectDictionary* page = NULL; | 239 SkPdfPageObjectDictionary* page = NULL; |
145 PodofoMapper::map(fDoc, *fDoc.GetPage(n)->GetObject(), &page); | 240 mapPageObjectDictionary(fDoc, *fDoc.GetPage(n)->GetObject(), &page); |
146 return page; | 241 return page; |
147 } | 242 } |
148 | 243 |
149 SkRect MediaBox(int n) { | 244 SkRect MediaBox(int n) { |
150 PdfRect rect = fDoc.GetPage(n)->GetMediaBox(); | 245 PdfRect rect = fDoc.GetPage(n)->GetMediaBox(); |
151 SkRect skrect = SkRect::MakeLTRB(SkDoubleToScalar(rect.GetLeft()), | 246 SkRect skrect = SkRect::MakeLTRB(SkDoubleToScalar(rect.GetLeft()), |
152 SkDoubleToScalar(rect.GetBottom()), | 247 SkDoubleToScalar(rect.GetBottom()), |
153 SkDoubleToScalar(rect.GetLeft() + rect.
GetWidth()), | 248 SkDoubleToScalar(rect.GetLeft() + rect.
GetWidth()), |
154 SkDoubleToScalar(rect.GetBottom() + rec
t.GetHeight())); | 249 SkDoubleToScalar(rect.GetBottom() + rec
t.GetHeight())); |
155 return skrect; | 250 return skrect; |
156 } | 251 } |
157 | 252 |
| 253 void drawPage(int n, SkCanvas* canvas) { |
| 254 SkPdfPageObjectDictionary* pg = page(n); |
| 255 SkPdfTokenizer* tokenizer = tokenizerOfPage(n); |
| 256 |
| 257 PdfContext pdfContext(this); |
| 258 pdfContext.fOriginalMatrix = SkMatrix::I(); |
| 259 pdfContext.fGraphicsState.fResources = NULL; |
| 260 mapResourceDictionary(*pg->Resources(), &pdfContext.fGraphicsState.fReso
urces); |
| 261 |
| 262 gPdfContext = &pdfContext; |
| 263 gDumpCanvas = canvas; |
| 264 |
| 265 // TODO(edisonn): get matrix stuff right. |
| 266 // TODO(edisonn): add DPI/scale/zoom. |
| 267 SkScalar z = SkIntToScalar(0); |
| 268 SkRect rect = MediaBox(n); |
| 269 SkScalar w = rect.width(); |
| 270 SkScalar h = rect.height(); |
| 271 |
| 272 SkPoint pdfSpace[4] = {SkPoint::Make(z, z), SkPoint::Make(w, z), SkPoint
::Make(w, h), SkPoint::Make(z, h)}; |
| 273 // SkPoint skiaSpace[4] = {SkPoint::Make(z, h), SkPoint::Make(w,
h), SkPoint::Make(w, z), SkPoint::Make(z, z)}; |
| 274 |
| 275 // TODO(edisonn): add flag for this app to create sourunding buffer zone |
| 276 // TODO(edisonn): add flagg for no clipping. |
| 277 // Use larger image to make sure we do not draw anything outside of page |
| 278 // could be used in tests. |
| 279 |
| 280 #ifdef PDF_DEBUG_3X |
| 281 SkPoint skiaSpace[4] = {SkPoint::Make(w+z, h+h), SkPoint::Make(w+w, h+h)
, SkPoint::Make(w+w, h+z), SkPoint::Make(w+z, h+z)}; |
| 282 #else |
| 283 SkPoint skiaSpace[4] = {SkPoint::Make(z, h), SkPoint::Make(w, h), SkPoin
t::Make(w, z), SkPoint::Make(z, z)}; |
| 284 #endif |
| 285 //SkPoint pdfSpace[2] = {SkPoint::Make(z, z), SkPoint::Make(w, h)}; |
| 286 //SkPoint skiaSpace[2] = {SkPoint::Make(w, z), SkPoint::Make(z, h)}; |
| 287 |
| 288 //SkPoint pdfSpace[2] = {SkPoint::Make(z, z), SkPoint::Make(z, h)}; |
| 289 //SkPoint skiaSpace[2] = {SkPoint::Make(z, h), SkPoint::Make(z, z)}; |
| 290 |
| 291 //SkPoint pdfSpace[3] = {SkPoint::Make(z, z), SkPoint::Make(z, h), SkPoi
nt::Make(w, h)}; |
| 292 //SkPoint skiaSpace[3] = {SkPoint::Make(z, h), SkPoint::Make(z, z), SkPo
int::Make(w, 0)}; |
| 293 |
| 294 SkAssertResult(pdfContext.fOriginalMatrix.setPolyToPoly(pdfSpace, skiaSp
ace, 4)); |
| 295 SkTraceMatrix(pdfContext.fOriginalMatrix, "Original matrix"); |
| 296 |
| 297 |
| 298 pdfContext.fGraphicsState.fMatrix = pdfContext.fOriginalMatrix; |
| 299 pdfContext.fGraphicsState.fMatrixTm = pdfContext.fGraphicsState.fMatrix; |
| 300 pdfContext.fGraphicsState.fMatrixTlm = pdfContext.fGraphicsState.fMatrix
; |
| 301 |
| 302 canvas->setMatrix(pdfContext.fOriginalMatrix); |
| 303 |
| 304 #ifndef PDF_DEBUG_NO_PAGE_CLIPING |
| 305 canvas->clipRect(SkRect::MakeXYWH(z, z, w, h), SkRegion::kIntersect_Op,
true); |
| 306 #endif |
| 307 |
| 308 // erase with red before? |
| 309 // SkPaint paint; |
| 310 // paint.setColor(SK_ColorRED); |
| 311 // canvas->drawRect(rect, paint); |
| 312 |
| 313 PdfMainLooper looper(NULL, tokenizer, &pdfContext, canvas); |
| 314 looper.loop(); |
| 315 |
| 316 delete tokenizer; |
| 317 |
| 318 |
| 319 canvas->flush(); |
| 320 } |
| 321 |
158 SkPdfTokenizer* tokenizerOfPage(int n) { | 322 SkPdfTokenizer* tokenizerOfPage(int n) { |
159 PdfContentsTokenizer* t = new PdfContentsTokenizer(fDoc.GetPage(n)); | 323 PdfContentsTokenizer* t = new PdfContentsTokenizer(fDoc.GetPage(n)); |
160 return new SkPdfTokenizer(&fDoc, t); | 324 return new SkPdfTokenizer(&fDoc, t); |
161 } | 325 } |
162 }; | 326 }; |
163 | 327 |
| 328 // TODO(edisonn): move in another file |
| 329 class SkPdfViewer : public SkRefCnt { |
| 330 public: |
| 331 |
| 332 bool load(const SkString inputFileName, SkPicture* out); |
| 333 bool write(void*) const { return false; } |
| 334 }; |
| 335 |
| 336 void reportPdfRenderStats(); |
| 337 |
164 #endif // SkPdfParser_DEFINED | 338 #endif // SkPdfParser_DEFINED |
OLD | NEW |