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 25class SkFPDFEMBImageDecoder : public SkImageDecoder { 26public: 27 SkFPDFEMBImageDecoder() {} 28 29 virtual Format getFormat() const { 30 return kBMP_Format; 31 } 32 33protected: 34 virtual bool onDecode(SkStream* stream, SkBitmap* bm, 35 SkBitmap::Config pref, Mode mode); 36 37private: 38 bool render(FPDFEMB_PAGE page, const FPDFEMB_RECT& bounds, SkBitmap* bm, 39 SkBitmap::Config prefConfig, SkImageDecoder::Mode mode); 40}; 41 42SkImageDecoder* SkImageDecoder_FPDFEMB_Factory(SkStream*); 43SkImageDecoder* 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 63extern "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 120static inline int PDF2Pixels(int x) { return x / 100; } 121static inline SkScalar PDF2Scalar(int x) { 122 return SkScalarMulDiv(SK_Scalar1, x, 100); 123} 124 125bool 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, NULL); 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 173bool 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", result, 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, document); 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} 237