OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2007, The Android Open Source Project | |
3 * | |
4 * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 * you may not use this file except in compliance with the License. | |
6 * You may obtain a copy of the License at | |
7 * | |
8 * http://www.apache.org/licenses/LICENSE-2.0 | |
9 * | |
10 * Unless required by applicable law or agreed to in writing, software | |
11 * distributed under the License is distributed on an "AS IS" BASIS, | |
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 * See the License for the specific language governing permissions and | |
14 * limitations under the License. | |
15 */ | |
16 | |
17 #include "SkImageDecoder.h" | |
18 #include "SkScaledBitmapSampler.h" | |
19 #include "SkStream.h" | |
20 #include "SkColorPriv.h" | |
21 #include "SkTDArray.h" | |
22 | |
23 #include "fpdfemb.h" | |
24 | |
25 class SkFPDFEMBImageDecoder : public SkImageDecoder { | |
26 public: | |
27 SkFPDFEMBImageDecoder() {} | |
28 | |
29 virtual Format getFormat() const { | |
30 return kBMP_Format; | |
31 } | |
32 | |
33 protected: | |
34 virtual bool onDecode(SkStream* stream, SkBitmap* bm, | |
35 SkBitmap::Config pref, Mode mode); | |
36 | |
37 private: | |
38 bool render(FPDFEMB_PAGE page, const FPDFEMB_RECT& bounds, SkBitmap* bm, | |
39 SkBitmap::Config prefConfig, SkImageDecoder::Mode mode); | |
40 }; | |
41 | |
42 SkImageDecoder* SkImageDecoder_FPDFEMB_Factory(SkStream*); | |
43 SkImageDecoder* SkImageDecoder_FPDFEMB_Factory(SkStream* stream) { | |
44 static const char kPDFSig[] = { '%', 'P', 'D', 'F' }; | |
45 | |
46 size_t len = stream->getLength(); | |
47 char buffer[sizeof(kPDFSig)]; | |
48 | |
49 SkDebugf("---- SkImageDecoder_FPDFEMB_Factory len=%d\n", len); | |
50 | |
51 if (len != 12683) { return NULL; } | |
52 | |
53 if (len > sizeof(kPDFSig) && | |
54 stream->read(buffer, sizeof(kPDFSig)) == sizeof(kPDFSig) && | |
55 !memcmp(buffer, kPDFSig, sizeof(kPDFSig))) { | |
56 return SkNEW(SkFPDFEMBImageDecoder); | |
57 } | |
58 return NULL; | |
59 } | |
60 | |
61 /////////////////////////////////////////////////////////////////////////////// | |
62 | |
63 extern "C" { | |
64 static void* pdf_alloc(FPDFEMB_MEMMGR* pMgr, unsigned int size) { | |
65 void* addr = sk_malloc_throw(size); | |
66 // SkDebugf("---- pdf_alloc %d %p\n", size, addr); | |
67 return addr; | |
68 } | |
69 | |
70 static void* pdf_alloc_nl(FPDFEMB_MEMMGR* pMgr, unsigned int size) { | |
71 void* addr = sk_malloc_flags(size, 0); | |
72 // SkDebugf("---- pdf_alloc_nl %d %p\n", size, addr); | |
73 return addr; | |
74 } | |
75 | |
76 static void* pdf_realloc(FPDFEMB_MEMMGR*, void* addr, unsigned int size) { | |
77 void* newaddr = sk_realloc_throw(addr, size); | |
78 // SkDebugf("---- pdf_realloc %p %d %p\n", addr, size, newaddr); | |
79 return newaddr; | |
80 } | |
81 | |
82 static void pdf_free(FPDFEMB_MEMMGR* pMgr, void* pointer) { | |
83 // SkDebugf("---- pdf_free %p\n", pointer); | |
84 sk_free(pointer); | |
85 } | |
86 | |
87 void FX_OUTPUT_LOG_FUNC(const char* format, ...) { | |
88 SkDebugf("---- LOG_FUNC %s\n", format); | |
89 } | |
90 | |
91 static unsigned int file_getsize(FPDFEMB_FILE_ACCESS* file) { | |
92 SkStream* stream = (SkStream*)file->user; | |
93 return stream->getLength(); | |
94 } | |
95 | |
96 static FPDFEMB_RESULT file_readblock(FPDFEMB_FILE_ACCESS* file, void* dst, | |
97 unsigned int offset, unsigned int size) { | |
98 SkStream* stream = (SkStream*)file->user; | |
99 // SkDebugf("---- readblock %p %p %d %d\n", stream, dst, offset, size); | |
100 if (!stream->rewind()) { | |
101 SkDebugf("---- rewind failed\n"); | |
102 return FPDFERR_ERROR; | |
103 } | |
104 if (stream->skip(offset) != offset) { | |
105 SkDebugf("---- skip failed\n"); | |
106 return FPDFERR_ERROR; | |
107 } | |
108 if (stream->read(dst, size) != size) { | |
109 SkDebugf("---- read failed\n"); | |
110 return FPDFERR_ERROR; | |
111 } | |
112 return FPDFERR_SUCCESS; | |
113 } | |
114 | |
115 static void pdf_oom_handler(void* memory, int size) { | |
116 SkDebugf("======== pdf OOM %p %d\n", memory, size); | |
117 } | |
118 } | |
119 | |
120 static inline int PDF2Pixels(int x) { return x / 100; } | |
121 static inline SkScalar PDF2Scalar(int x) { | |
122 return SkScalarMulDiv(SK_Scalar1, x, 100); | |
123 } | |
124 | |
125 bool SkFPDFEMBImageDecoder::render(FPDFEMB_PAGE page, const FPDFEMB_RECT& bounds
, SkBitmap* bm, | |
126 SkBitmap::Config prefConfig, SkImageDecoder::Mode mode) { | |
127 int width = PDF2Pixels(bounds.right - bounds.left); | |
128 int height = PDF2Pixels(bounds.top - bounds.bottom); | |
129 | |
130 SkDebugf("----- bitmap size [%d %d], mode=%d\n", width, height, mode); | |
131 bm->setConfig(SkBitmap::kARGB_8888_Config, width, height); | |
132 if (SkImageDecoder::kDecodeBounds_Mode == mode) { | |
133 return true; | |
134 } | |
135 | |
136 // USE THE CODEC TO ALLOCATE THE PIXELS!!!! | |
137 if (!this->allocPixelRef(bm, NULL)) { | |
138 SkDebugf("----- failed to alloc pixels\n"); | |
139 return false; | |
140 } | |
141 | |
142 bm->eraseColor(0); | |
143 | |
144 FPDFEMB_RESULT result; | |
145 FPDFEMB_BITMAP dib; | |
146 | |
147 result = FPDFEMB_CreateDIB(width, height, FPDFDIB_BGRA, bm->getPixels(), | |
148 bm->rowBytes(), &dib); | |
149 SkDebugf("---- createdib %d\n", result); | |
150 | |
151 result = FPDFEMB_StartRender(dib, page, 0, 0, width, height, 0, 0, NULL, NUL
L); | |
152 SkDebugf("---- render %d\n", result); | |
153 | |
154 result = FPDFEMB_DestroyDIB(dib); | |
155 SkDebugf("---- destroydib %d\n", result); | |
156 | |
157 SkPMColor* dst = bm->getAddr32(0, 0); | |
158 const uint8_t* src = (uint8_t*)dst; | |
159 int n = bm->getSize() >> 2; | |
160 for (int i = 0; i < n; i++) { | |
161 int b = *src++; | |
162 int g = *src++; | |
163 int r = *src++; | |
164 int a = *src++; | |
165 *dst++ = SkPackARGB32(a, r, g, b); | |
166 } | |
167 | |
168 return true; | |
169 } | |
170 | |
171 #define USE_FIXED_MEM (4 * 1024 * 1024) | |
172 | |
173 bool SkFPDFEMBImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, | |
174 SkBitmap::Config prefConfig, Mode mode) { | |
175 | |
176 FPDFEMB_RESULT result; | |
177 #ifdef USE_FIXED_MEM | |
178 SkAutoMalloc storage(USE_FIXED_MEM); | |
179 result = FPDFEMB_InitFixedMemory(storage.get(), USE_FIXED_MEM, | |
180 pdf_oom_handler); | |
181 #else | |
182 FPDFEMB_MEMMGR memmgr; | |
183 memmgr.Alloc = pdf_alloc; | |
184 memmgr.AllocNL = pdf_alloc_nl; | |
185 memmgr.Realloc = pdf_realloc; | |
186 memmgr.Free = pdf_free; | |
187 | |
188 result = FPDFEMB_Init(&memmgr); | |
189 #endif | |
190 SkDebugf("----- SkImageDecoder_FPDFEMB_Factory init %d, streamLen = %d\n", r
esult, stream->getLength()); | |
191 | |
192 FPDFEMB_FILE_ACCESS file; | |
193 file.GetSize = file_getsize; | |
194 file.ReadBlock = file_readblock; | |
195 file.user = stream; | |
196 | |
197 FPDFEMB_DOCUMENT document; | |
198 result = FPDFEMB_StartLoadDocument(&file, NULL, &document, NULL); | |
199 SkDebugf("----- SkImageDecoder_FPDFEMB_Factory open %d %p\n", result, docume
nt); | |
200 | |
201 int pageCount = FPDFEMB_GetPageCount(document); | |
202 SkDebugf("----- SkImageDecoder_FPDFEMB_Factory pageCount %d\n", pageCount); | |
203 | |
204 if (pageCount > 0) { | |
205 FPDFEMB_PAGE page; | |
206 result = FPDFEMB_LoadPage(document, 0, &page); | |
207 SkDebugf("----- SkImageDecoder_FPDFEMB_Factory load page %d\n", result); | |
208 | |
209 int width, height; | |
210 result = FPDFEMB_GetPageSize(page, &width, &height); | |
211 SkDebugf("----- SkImageDecoder_FPDFEMB_Factory page size %d [%d %d]\n",
result, width, height); | |
212 | |
213 FPDFEMB_RECT rect; | |
214 result = FPDFEMB_GetPageBBox(page, &rect); | |
215 SkDebugf("----- SkImageDecoder_FPDFEMB_Factory page rect %d [%d %d %d %d
]\n", result, | |
216 rect.left, rect.top, rect.right, rect.bottom); | |
217 | |
218 SkDebugf("----- SkImageDecoder_FPDFEMB_Factory begin page parse...\n"); | |
219 result = FPDFEMB_StartParse(page, false, NULL); | |
220 SkDebugf("----- SkImageDecoder_FPDFEMB_Factory page parse %d\n", result)
; | |
221 | |
222 if (0 == result) { | |
223 this->render(page, rect, bm, prefConfig, mode); | |
224 } | |
225 | |
226 result = FPDFEMB_ClosePage(page); | |
227 SkDebugf("----- SkImageDecoder_FPDFEMB_Factory close page %d\n", result)
; | |
228 } | |
229 | |
230 result = FPDFEMB_CloseDocument(document); | |
231 SkDebugf("----- SkImageDecoder_FPDFEMB_Factory close %d\n", result); | |
232 | |
233 // FPDFEMB_Exit(); | |
234 | |
235 return true; | |
236 } | |
OLD | NEW |