Home | History | Annotate | Download | only in images
      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, 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 
    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", 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