| 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 |