/* * Copyright (C) 2004 Stefan Kleine Stegemann * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "poppler_cairo_img_renderer.h" #include "poppler.h" #include #include #include #include #define PDF_DOC(obj) static_cast(obj) #define PAGE(obj) static_cast(obj) #define CAIRO_DEV_IMG(obj) static_cast(obj) #ifndef MAX #define MAX(a,b) (((a)>(b))?(a):(b)) #endif typedef struct CairoImageDev { CairoOutputDev* device; cairo_surface_t* surface; unsigned char* data; } CairoImageDev; static void my_poppler_cairo_prepare_dev(CairoImageDev* output_dev, Page* page, double scale, int rotation, int transparent) { int width; int height; int rotate = (rotation + page->getRotate()) % 360; if (rotate == 90 || rotate == 270) { #ifdef POPPLER_0_4 width = MAX((int)(page->getHeight() * scale + 0.5), 1); height = MAX((int)(page->getWidth() * scale + 0.5), 1); #endif #ifdef POPPLER_0_5 width = MAX((int)(page->getMediaHeight() * scale + 0.5), 1); height = MAX((int)(page->getMediaWidth() * scale + 0.5), 1); #endif } else { #ifdef POPPLER_0_4 width = MAX((int)(page->getWidth() * scale + 0.5), 1); height = MAX((int)(page->getHeight() * scale + 0.5), 1); #endif #ifdef POPPLER_0_5 width = MAX((int)(page->getMediaWidth() * scale + 0.5), 1); height = MAX((int)(page->getMediaHeight() * scale + 0.5), 1); #endif } int rowstride = width * 4; unsigned char* data = (unsigned char*)malloc(height * rowstride); memset(data, (transparent ? 0x00 : 0xff), height * rowstride); cairo_surface_t* surface = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, width, height, rowstride); #ifdef POPPLER_0_5 output_dev->device->setCairo(cairo_create(surface)); #else output_dev->device->setSurface(surface); #endif output_dev->surface = surface; output_dev->data = data; } void* poppler_cairo_img_device_create(void) { BEGIN_SYNCHRONIZED; CairoOutputDev* cairoDevice = new CairoOutputDev(); CairoImageDev* imageDevice = (CairoImageDev*)malloc(sizeof(CairoImageDev)); imageDevice->device = cairoDevice; imageDevice->surface = NULL; imageDevice->data = NULL; END_SYNCHRONIZED; return imageDevice; } void poppler_cairo_img_device_start_doc(void* output_dev, void* poppler_document) { if (!output_dev || !poppler_document) { return; } SYNCHRONIZED(CAIRO_DEV_IMG(output_dev)->device->startDoc(PDF_DOC(poppler_document)->getXRef())); } void poppler_cairo_img_device_destroy(void* output_dev) { if (!output_dev) { return; } SYNCHRONIZED(delete CAIRO_DEV_IMG(output_dev)->device); free(CAIRO_DEV_IMG(output_dev)); } int poppler_cairo_img_device_display_slice(void* output_dev, void* poppler_page, void* poppler_document, float hDPI, float vDPI, float baseDPI, int rotate, float sliceX, float sliceY, float sliceW, float sliceH) { if (!output_dev || !poppler_page || !poppler_document) { return 0; } double scale = MAX(hDPI / baseDPI, vDPI / baseDPI); my_poppler_cairo_prepare_dev(CAIRO_DEV_IMG(output_dev), PAGE(poppler_page), scale, rotate, 0); SYNCHRONIZED(PAGE(poppler_page)->displaySlice(CAIRO_DEV_IMG(output_dev)->device, (double)hDPI, (double)vDPI, rotate, #ifdef POPPLER_0_5 gTrue, // use MediaBox #endif gTrue, // Crop (int)sliceX, (int)sliceY, (int)sliceW, (int)sliceH, NULL, // Links PDF_DOC(poppler_document)->getCatalog())); return 1; } int poppler_cairo_img_device_get_data(void* output_dev, unsigned char** data, int* width, int* height, int* rowstride) { if (!output_dev || !CAIRO_DEV_IMG(output_dev)->surface || !CAIRO_DEV_IMG(output_dev)->data) { return 0; } *data = CAIRO_DEV_IMG(output_dev)->data; *width = cairo_image_surface_get_width(CAIRO_DEV_IMG(output_dev)->surface); *height = cairo_image_surface_get_height(CAIRO_DEV_IMG(output_dev)->surface); *rowstride = (*width) * 4; cairo_surface_destroy(CAIRO_DEV_IMG(output_dev)->surface); CAIRO_DEV_IMG(output_dev)->surface = NULL; CAIRO_DEV_IMG(output_dev)->data = NULL; // freed after poppler_cairo_img_device_get_rgb return 1; } int poppler_cairo_img_device_get_rgb(unsigned char* cairo_data, unsigned char** rgb_data, int width, int height, int rowstride) { if (!cairo_data) { return 0; } unsigned char* rgb_data_ptr = *rgb_data; for (int row = 0; row < height; row++) { unsigned int *src; src = (unsigned int *) (cairo_data + row * rowstride); for (int col = 0; col < width; col++) { *rgb_data_ptr++ = (*src >> 16) & 0xff; *rgb_data_ptr++ = (*src >> 8) & 0xff; *rgb_data_ptr++ = (*src >> 0) & 0xff; src++; } } free(cairo_data); return 1; }