"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "libvips/foreign/pdfiumload.c" between
vips-8.10.6.tar.gz and vips-8.11.0.tar.gz

About: VIPS is a free image processing system (see also the GUI nip2).

pdfiumload.c  (vips-8.10.6):pdfiumload.c  (vips-8.11.0)
/* load PDF with PDFium /* load PDF with PDFium
* *
* 5/4/18 * 5/4/18
* - from pdfload.c * - from pdfload.c
* 8/6/18 * 8/6/18
* - add background param * - add background param
* 16/8/18 * 16/8/18
* - shut down the input file as soon as we can [kleisauke] * - shut down the input file as soon as we can [kleisauke]
* 8/8/19 * 8/8/19
* - add locks, since pdfium is not threadsafe in any way * - add locks, since pdfium is not threadsafe in any way
* 13/10/20
* - have a lock just for pdfium [DarthSim]
* - update for current pdfium
* - add _source input
*/ */
/* /*
This file is part of VIPS. This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
skipping to change at line 42 skipping to change at line 46
*/ */
/* /*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/ */
/* TODO /* TODO
* *
* - needs the reopen-after-minimise system that pdfload has, but we'll need * - what about filename encodings?
* to be able to actually build and test this before we can do that
* - what about filename encodings
* - need to test on Windows * - need to test on Windows
*/ */
/* How to build against PDFium:
*
* Download the prebuilt binary from:
*
* https://github.com/bblanchon/pdfium-binaries
*
* Untar to the libvips install prefix, for example:
*
* cd ~/vips
* tar xf ~/pdfium-linux.tgz
*
* Create a pdfium.pc like this (update the version number):
*
VIPSHOME=/home/john/vips
cat > $VIPSHOME/lib/pkgconfig/pdfium.pc << EOF
prefix=$VIPSHOME
exec_prefix=\${prefix}
libdir=\${exec_prefix}/lib
includedir=\${prefix}/include
Name: pdfium
Description: pdfium
Version: 4290
Requires:
Libs: -L\${libdir} -lpdfium
Cflags: -I\${includedir}
EOF
*
*/
/* /*
#define DEBUG #define DEBUG
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include <config.h> #include <config.h>
#endif /*HAVE_CONFIG_H*/ #endif /*HAVE_CONFIG_H*/
#include <vips/intl.h> #include <vips/intl.h>
#include <stdio.h> #include <stdio.h>
skipping to change at line 76 skipping to change at line 109
#include "pforeign.h" #include "pforeign.h"
#ifdef HAVE_PDFIUM #ifdef HAVE_PDFIUM
#include <fpdfview.h> #include <fpdfview.h>
#include <fpdf_doc.h> #include <fpdf_doc.h>
typedef struct _VipsForeignLoadPdf { typedef struct _VipsForeignLoadPdf {
VipsForeignLoad parent_object; VipsForeignLoad parent_object;
/* Set by subclasses.
*/
VipsSource *source;
/* Load this page. /* Load this page.
*/ */
int page_no; int page_no;
/* Load this many pages. /* Load this many pages.
*/ */
int n; int n;
/* Render at this DPI. /* Render at this DPI.
*/ */
double dpi; double dpi;
/* Calculate this from DPI. At 72 DPI, we render 1:1. /* Calculate this from DPI. At 72 DPI, we render 1:1.
*/ */
double scale; double scale;
/* Background colour. /* Background colour.
*/ */
VipsArrayDouble *background; VipsArrayDouble *background;
FPDF_DOCUMENT *doc; FPDF_FILEACCESS file_access;
FPDF_PAGE *page; FPDF_DOCUMENT doc;
FPDF_PAGE page;
int current_page; int current_page;
/* Doc has this many pages. /* Doc has this many pages.
*/ */
int n_pages; int n_pages;
/* We need to read out the size of each page we will render, and lay /* We need to read out the size of each page we will render, and lay
* them out in the final image. * them out in the final image.
*/ */
VipsRect image; VipsRect image;
skipping to change at line 131 skipping to change at line 169
static char *vips_pdfium_errors[] = { static char *vips_pdfium_errors[] = {
"no error", "no error",
"unknown error", "unknown error",
"file not found or could not be opened", "file not found or could not be opened",
"file not in PDF format or corrupted", "file not in PDF format or corrupted",
"password required or incorrect password", "password required or incorrect password",
"unsupported security scheme", "unsupported security scheme",
"page not found or content error" "page not found or content error"
}; };
static GMutex *vips_pdfium_mutex = NULL;
static void static void
vips_pdfium_error( void ) vips_pdfium_error( void )
{ {
int err = FPDF_GetLastError(); int err = FPDF_GetLastError();
if( err >= 0 && if( err >= 0 &&
err < VIPS_NUMBER( vips_pdfium_errors ) ) err < VIPS_NUMBER( vips_pdfium_errors ) )
vips_error( "pdfload", "%s", _( vips_pdfium_errors[err] ) ); vips_error( "pdfload", "%s", _( vips_pdfium_errors[err] ) );
else else
vips_error( "pdfload", "%s", _( "unknown error" ) ); vips_error( "pdfload", "%s", _( "unknown error" ) );
} }
static void static void
vips_foreign_load_pdf_close( VipsForeignLoadPdf *pdf ) vips_foreign_load_pdf_close( VipsForeignLoadPdf *pdf )
{ {
g_mutex_lock( vips__global_lock ); g_mutex_lock( vips_pdfium_mutex );
VIPS_FREEF( FPDF_ClosePage, pdf->page ); VIPS_FREEF( FPDF_ClosePage, pdf->page );
VIPS_FREEF( FPDF_CloseDocument, pdf->doc ); VIPS_FREEF( FPDF_CloseDocument, pdf->doc );
g_mutex_unlock( vips__global_lock ); g_mutex_unlock( vips_pdfium_mutex );
} }
static void static void
vips_foreign_load_pdf_dispose( GObject *gobject ) vips_foreign_load_pdf_dispose( GObject *gobject )
{ {
VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) gobject; VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) gobject;
vips_foreign_load_pdf_close( pdf ); vips_foreign_load_pdf_close( pdf );
G_OBJECT_CLASS( vips_foreign_load_pdf_parent_class )-> G_OBJECT_CLASS( vips_foreign_load_pdf_parent_class )->
skipping to change at line 180 skipping to change at line 220
config.version = 2; config.version = 2;
config.m_pUserFontPaths = NULL; config.m_pUserFontPaths = NULL;
config.m_pIsolate = NULL; config.m_pIsolate = NULL;
config.m_v8EmbedderSlot = 0; config.m_v8EmbedderSlot = 0;
FPDF_InitLibraryWithConfig( &config ); FPDF_InitLibraryWithConfig( &config );
return( NULL ); return( NULL );
} }
/* This is the m_GetBlock function for FPDF_FILEACCESS.
*/
static gboolean
vips_pdfium_GetBlock( void *param,
unsigned long position, unsigned char *pBuf, unsigned long size )
{
VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) param;
/* PDFium guarantees these.
*/
g_assert( size > 0 );
g_assert( position >= 0 );
g_assert( position + size <= pdf->file_access.m_FileLen );
if( vips_source_seek( pdf->source, position, SEEK_SET ) < 0 )
return( FALSE );
while( size > 0 ) {
size_t n_read;
if( (n_read = vips_source_read( pdf->source, pBuf, size )) < 0 )
return( FALSE );
pBuf += n_read;
size -= n_read;
}
return( TRUE );
}
static int static int
vips_foreign_load_pdf_build( VipsObject *object ) vips_foreign_load_pdf_build( VipsObject *object )
{ {
static GOnce once = G_ONCE_INIT; static GOnce once = G_ONCE_INIT;
VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) object; VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) object;
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( pdf );
gint64 length;
VIPS_ONCE( &once, vips_pdfium_init_cb, NULL ); VIPS_ONCE( &once, vips_pdfium_init_cb, NULL );
if( !vips_object_argument_isset( object, "scale" ) ) if( !vips_object_argument_isset( object, "scale" ) )
pdf->scale = pdf->dpi / 72.0; pdf->scale = pdf->dpi / 72.0;
/* pdfium must know the file length, unfortunately.
*/
if( pdf->source ) {
if( (length = vips_source_length( pdf->source )) <= 0 )
return( -1 );
if( length > 1 << 30 ) {
vips_error( class->nickname,
_( "%s: too large for pdfium" ),
vips_connection_nick(
VIPS_CONNECTION( pdf->source ) ) );
return( -1 );
}
pdf->file_access.m_FileLen = length;
pdf->file_access.m_GetBlock = vips_pdfium_GetBlock;
pdf->file_access.m_Param = pdf;
g_mutex_lock( vips_pdfium_mutex );
if( !(pdf->doc = FPDF_LoadCustomDocument( &pdf->file_access,
NULL )) ) {
g_mutex_unlock( vips_pdfium_mutex );
vips_pdfium_error();
vips_error( "pdfload",
_( "%s: unable to load" ),
vips_connection_nick(
VIPS_CONNECTION( pdf->source ) ) );
return( -1 );
}
g_mutex_unlock( vips_pdfium_mutex );
}
if( VIPS_OBJECT_CLASS( vips_foreign_load_pdf_parent_class )-> if( VIPS_OBJECT_CLASS( vips_foreign_load_pdf_parent_class )->
build( object ) ) build( object ) )
return( -1 ); return( -1 );
return( 0 ); return( 0 );
} }
static VipsForeignFlags static VipsForeignFlags
vips_foreign_load_pdf_get_flags_filename( const char *filename ) vips_foreign_load_pdf_get_flags_filename( const char *filename )
{ {
skipping to change at line 220 skipping to change at line 324
{ {
return( VIPS_FOREIGN_PARTIAL ); return( VIPS_FOREIGN_PARTIAL );
} }
static int static int
vips_foreign_load_pdf_get_page( VipsForeignLoadPdf *pdf, int page_no ) vips_foreign_load_pdf_get_page( VipsForeignLoadPdf *pdf, int page_no )
{ {
if( pdf->current_page != page_no ) { if( pdf->current_page != page_no ) {
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( pdf ); VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( pdf );
g_mutex_lock( vips__global_lock ); g_mutex_lock( vips_pdfium_mutex );
VIPS_FREEF( FPDF_ClosePage, pdf->page ); VIPS_FREEF( FPDF_ClosePage, pdf->page );
pdf->current_page = -1; pdf->current_page = -1;
#ifdef DEBUG #ifdef DEBUG
printf( "vips_foreign_load_pdf_get_page: %d\n", page_no ); printf( "vips_foreign_load_pdf_get_page: %d\n", page_no );
#endif /*DEBUG*/ #endif /*DEBUG*/
if( !(pdf->page = FPDF_LoadPage( pdf->doc, page_no )) ) { if( !(pdf->page = FPDF_LoadPage( pdf->doc, page_no )) ) {
g_mutex_unlock( vips__global_lock ); g_mutex_unlock( vips_pdfium_mutex );
vips_pdfium_error(); vips_pdfium_error();
vips_error( class->nickname, vips_error( class->nickname,
_( "unable to load page %d" ), page_no ); _( "unable to load page %d" ), page_no );
return( -1 ); return( -1 );
} }
pdf->current_page = page_no; pdf->current_page = page_no;
g_mutex_unlock( vips__global_lock ); g_mutex_unlock( vips_pdfium_mutex );
} }
return( 0 ); return( 0 );
} }
/* String-based metadata fields we extract. /* String-based metadata fields we extract.
*/ */
typedef struct _VipsForeignLoadPdfMetadata { typedef struct _VipsForeignLoadPdfMetadata {
char *tag; /* as understood by PDFium */ char *tag; /* as understood by PDFium */
char *field; /* as understood by libvips */ char *field; /* as understood by libvips */
skipping to change at line 281 skipping to change at line 385
/* We render to a linecache, so fat strips work well. /* We render to a linecache, so fat strips work well.
*/ */
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_FATSTRIP, NULL ); vips_image_pipelinev( out, VIPS_DEMAND_STYLE_FATSTRIP, NULL );
/* Extract and attach metadata. Set the old name too for compat. /* Extract and attach metadata. Set the old name too for compat.
*/ */
vips_image_set_int( out, "pdf-n_pages", pdf->n_pages ); vips_image_set_int( out, "pdf-n_pages", pdf->n_pages );
vips_image_set_int( out, VIPS_META_N_PAGES, pdf->n_pages ); vips_image_set_int( out, VIPS_META_N_PAGES, pdf->n_pages );
g_mutex_lock( vips_pdfium_mutex );
for( i = 0; i < n_metadata; i++ ) { for( i = 0; i < n_metadata; i++ ) {
VipsForeignLoadPdfMetadata *metadata = VipsForeignLoadPdfMetadata *metadata =
&vips_foreign_load_pdf_metadata[i]; &vips_foreign_load_pdf_metadata[i];
char text[1024]; char text[1024];
int len; int len;
g_mutex_lock( vips__global_lock );
len = FPDF_GetMetaText( pdf->doc, metadata->tag, text, 1024 ); len = FPDF_GetMetaText( pdf->doc, metadata->tag, text, 1024 );
g_mutex_unlock( vips__global_lock );
if( len > 0 ) { if( len > 0 ) {
char *str; char *str;
/* Silently ignore coding errors. /* Silently ignore coding errors.
*/ */
if( (str = g_utf16_to_utf8( (gunichar2 *) text, len, if( (str = g_utf16_to_utf8( (gunichar2 *) text, len,
NULL, NULL, NULL )) ) { NULL, NULL, NULL )) ) {
vips_image_set_string( out, vips_image_set_string( out,
metadata->field, str ); metadata->field, str );
g_free( str ); g_free( str );
} }
} }
} }
g_mutex_unlock( vips_pdfium_mutex );
/* We need pixels/mm for vips. /* We need pixels/mm for vips.
*/ */
res = pdf->dpi / 25.4; res = pdf->dpi / 25.4;
vips_image_init_fields( out, vips_image_init_fields( out,
pdf->image.width, pdf->image.height, pdf->image.width, pdf->image.height,
4, VIPS_FORMAT_UCHAR, 4, VIPS_FORMAT_UCHAR,
VIPS_CODING_NONE, VIPS_INTERPRETATION_sRGB, res, res ); VIPS_CODING_NONE, VIPS_INTERPRETATION_sRGB, res, res );
return( 0 ); return( 0 );
skipping to change at line 330 skipping to change at line 436
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( load ); VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( load );
VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) load; VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) load;
int top; int top;
int i; int i;
#ifdef DEBUG #ifdef DEBUG
printf( "vips_foreign_load_pdf_header: %p\n", pdf ); printf( "vips_foreign_load_pdf_header: %p\n", pdf );
#endif /*DEBUG*/ #endif /*DEBUG*/
g_mutex_lock( vips__global_lock ); g_mutex_lock( vips_pdfium_mutex );
pdf->n_pages = FPDF_GetPageCount( pdf->doc ); pdf->n_pages = FPDF_GetPageCount( pdf->doc );
g_mutex_unlock( vips__global_lock ); g_mutex_unlock( vips_pdfium_mutex );
/* @n == -1 means until the end of the doc. /* @n == -1 means until the end of the doc.
*/ */
if( pdf->n == -1 ) if( pdf->n == -1 )
pdf->n = pdf->n_pages - pdf->page_no; pdf->n = pdf->n_pages - pdf->page_no;
if( pdf->page_no + pdf->n > pdf->n_pages || if( pdf->page_no + pdf->n > pdf->n_pages ||
pdf->page_no < 0 || pdf->page_no < 0 ||
pdf->n <= 0 ) { pdf->n <= 0 ) {
vips_error( class->nickname, "%s", _( "pages out of range" ) ); vips_error( class->nickname, "%s", _( "pages out of range" ) );
skipping to change at line 403 skipping to change at line 509
VIPS_AREA( pdf->background )->data, NULL, VIPS_AREA( pdf->background )->data, NULL,
VIPS_AREA( pdf->background )->n )) ) VIPS_AREA( pdf->background )->n )) )
return( -1 ); return( -1 );
return( 0 ); return( 0 );
} }
static void static void
vips_foreign_load_pdf_minimise( VipsObject *object, VipsForeignLoadPdf *pdf ) vips_foreign_load_pdf_minimise( VipsObject *object, VipsForeignLoadPdf *pdf )
{ {
/* In seq mode, we can shut down the input at the end of computation. vips_source_minimise( pdf->source );
*/
if( VIPS_FOREIGN_LOAD( pdf )->access == VIPS_ACCESS_SEQUENTIAL )
vips_foreign_load_pdf_close( pdf );
} }
static int static int
vips_foreign_load_pdf_generate( VipsRegion *or, vips_foreign_load_pdf_generate( VipsRegion *or,
void *seq, void *a, void *b, gboolean *stop ) void *seq, void *a, void *b, gboolean *stop )
{ {
VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) a; VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) a;
VipsForeignLoad *load = (VipsForeignLoad *) pdf;
VipsRect *r = &or->valid; VipsRect *r = &or->valid;
int top; int top;
int i; int i;
int y; int y;
/* /*
printf( "vips_foreign_load_pdf_generate: " printf( "vips_foreign_load_pdf_generate: "
"left = %d, top = %d, width = %d, height = %d\n", "left = %d, top = %d, width = %d, height = %d\n",
r->left, r->top, r->width, r->height ); r->left, r->top, r->width, r->height );
skipping to change at line 451 skipping to change at line 553
VipsRect rect; VipsRect rect;
FPDF_BITMAP bitmap; FPDF_BITMAP bitmap;
vips_rect_intersectrect( r, &pdf->pages[i], &rect ); vips_rect_intersectrect( r, &pdf->pages[i], &rect );
if( vips_foreign_load_pdf_get_page( pdf, pdf->page_no + i ) ) if( vips_foreign_load_pdf_get_page( pdf, pdf->page_no + i ) )
return( -1 ); return( -1 );
/* 4 means RGBA. /* 4 means RGBA.
*/ */
g_mutex_lock( vips__global_lock ); g_mutex_lock( vips_pdfium_mutex );
bitmap = FPDFBitmap_CreateEx( rect.width, rect.height, 4, bitmap = FPDFBitmap_CreateEx( rect.width, rect.height, 4,
VIPS_REGION_ADDR( or, rect.left, rect.top ), VIPS_REGION_ADDR( or, rect.left, rect.top ),
VIPS_REGION_LSKIP( or ) ); VIPS_REGION_LSKIP( or ) );
FPDF_RenderPageBitmap( bitmap, pdf->page, FPDF_RenderPageBitmap( bitmap, pdf->page,
0, 0, rect.width, rect.height, 0, 0, rect.width, rect.height,
0, 0 ); 0, 0 );
FPDFBitmap_Destroy( bitmap ); FPDFBitmap_Destroy( bitmap );
g_mutex_unlock( vips__global_lock ); g_mutex_unlock( vips_pdfium_mutex );
top += rect.height; top += rect.height;
i += 1; i += 1;
} }
/* PDFium writes BRGA, we must swap. /* PDFium writes BGRA, we must swap.
* */
* FIXME ... this is a bit slow. for( y = 0; y < r->height; y++ )
*/ vips__bgra2rgba(
for( y = 0; y < r->height; y++ ) { (guint32 *) VIPS_REGION_ADDR( or, r->left, r->top + y ),
VipsPel *p; r->width );
int x;
p = VIPS_REGION_ADDR( or, r->left, r->top + y );
for( x = 0; x < r->width; x++ ) {
VIPS_SWAP( VipsPel, p[0], p[2] );
p += 4;
}
}
return( 0 ); return( 0 );
} }
static int static int
vips_foreign_load_pdf_load( VipsForeignLoad *load ) vips_foreign_load_pdf_load( VipsForeignLoad *load )
{ {
VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) load; VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) load;
VipsImage **t = (VipsImage **) VipsImage **t = (VipsImage **)
vips_object_local_array( (VipsObject *) load, 2 ); vips_object_local_array( (VipsObject *) load, 2 );
skipping to change at line 525 skipping to change at line 619
if( vips_linecache( t[0], &t[1], if( vips_linecache( t[0], &t[1],
"tile_height", pdf->pages[0].height, "tile_height", pdf->pages[0].height,
NULL ) ) NULL ) )
return( -1 ); return( -1 );
if( vips_image_write( t[1], load->real ) ) if( vips_image_write( t[1], load->real ) )
return( -1 ); return( -1 );
return( 0 ); return( 0 );
} }
static void *
vips_foreign_load_pdf_once_init( void *client )
{
/* We must make the mutex on class init (not _build) since we
* can lock ebven if build is not called.
*/
vips_pdfium_mutex = vips_g_mutex_new();
return( NULL );
}
static void static void
vips_foreign_load_pdf_class_init( VipsForeignLoadPdfClass *class ) vips_foreign_load_pdf_class_init( VipsForeignLoadPdfClass *class )
{ {
static GOnce once = G_ONCE_INIT;
GObjectClass *gobject_class = G_OBJECT_CLASS( class ); GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class; VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class; VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
VIPS_ONCE( &once, vips_foreign_load_pdf_once_init, NULL );
gobject_class->dispose = vips_foreign_load_pdf_dispose; gobject_class->dispose = vips_foreign_load_pdf_dispose;
gobject_class->set_property = vips_object_set_property; gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property; gobject_class->get_property = vips_object_get_property;
object_class->nickname = "pdfload_base"; object_class->nickname = "pdfload_base";
object_class->description = _( "load PDF with libpoppler" ); object_class->description = _( "load PDF with PDFium" );
object_class->build = vips_foreign_load_pdf_build; object_class->build = vips_foreign_load_pdf_build;
load_class->get_flags_filename = load_class->get_flags_filename =
vips_foreign_load_pdf_get_flags_filename; vips_foreign_load_pdf_get_flags_filename;
load_class->get_flags = vips_foreign_load_pdf_get_flags; load_class->get_flags = vips_foreign_load_pdf_get_flags;
load_class->header = vips_foreign_load_pdf_header;
load_class->load = vips_foreign_load_pdf_load; load_class->load = vips_foreign_load_pdf_load;
VIPS_ARG_INT( class, "page", 10, VIPS_ARG_INT( class, "page", 10,
_( "Page" ), _( "Page" ),
_( "Load this page from the file" ), _( "Load this page from the file" ),
VIPS_ARGUMENT_OPTIONAL_INPUT, VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadPdf, page_no ), G_STRUCT_OFFSET( VipsForeignLoadPdf, page_no ),
0, 100000, 0 ); 0, 100000, 0 );
VIPS_ARG_INT( class, "n", 11, VIPS_ARG_INT( class, "n", 11,
skipping to change at line 609 skipping to change at line 719
} VipsForeignLoadPdfFile; } VipsForeignLoadPdfFile;
typedef VipsForeignLoadPdfClass VipsForeignLoadPdfFileClass; typedef VipsForeignLoadPdfClass VipsForeignLoadPdfFileClass;
G_DEFINE_TYPE( VipsForeignLoadPdfFile, vips_foreign_load_pdf_file, G_DEFINE_TYPE( VipsForeignLoadPdfFile, vips_foreign_load_pdf_file,
vips_foreign_load_pdf_get_type() ); vips_foreign_load_pdf_get_type() );
static int static int
vips_foreign_load_pdf_file_header( VipsForeignLoad *load ) vips_foreign_load_pdf_file_header( VipsForeignLoad *load )
{ {
VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) load;
VipsForeignLoadPdfFile *file = (VipsForeignLoadPdfFile *) load; VipsForeignLoadPdfFile *file = (VipsForeignLoadPdfFile *) load;
g_mutex_lock( vips__global_lock );
if( !(pdf->doc = FPDF_LoadDocument( file->filename, NULL )) ) {
g_mutex_unlock( vips__global_lock );
vips_pdfium_error();
vips_error( "pdfload",
_( "unable to load \"%s\"" ), file->filename );
return( -1 );
}
g_mutex_unlock( vips__global_lock );
VIPS_SETSTR( load->out->filename, file->filename ); VIPS_SETSTR( load->out->filename, file->filename );
return( vips_foreign_load_pdf_header( load ) ); return( VIPS_FOREIGN_LOAD_CLASS(
vips_foreign_load_pdf_file_parent_class )->header( load ) );
} }
static const char *vips_foreign_pdf_suffs[] = { static const char *vips_foreign_pdf_suffs[] = {
".pdf", ".pdf",
NULL NULL
}; };
static int
vips_foreign_load_pdf_file_build( VipsObject *object )
{
VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) object;
VipsForeignLoadPdfFile *file = (VipsForeignLoadPdfFile *) pdf;
#ifdef DEBUG
printf( "vips_foreign_load_pdf_file_build: %s\n", file->filename );
#endif /*DEBUG*/
if( file->filename &&
!(pdf->source = vips_source_new_from_file( file->filename )) )
return( -1 );
return( VIPS_OBJECT_CLASS( vips_foreign_load_pdf_file_parent_class )->
build( object ) );
}
static gboolean
vips_foreign_load_pdf_is_a_buffer( const void *buf, size_t len )
{
const guchar *str = (const guchar *) buf;
if( len >= 4 &&
str[0] == '%' &&
str[1] == 'P' &&
str[2] == 'D' &&
str[3] == 'F' )
return( 1 );
return( 0 );
}
static gboolean
vips_foreign_load_pdf_is_a( const char *filename )
{
unsigned char buf[4];
if( vips__get_bytes( filename, buf, 4 ) == 4 &&
vips_foreign_load_pdf_is_a_buffer( buf, 4 ) )
return( 1 );
return( 0 );
}
static void static void
vips_foreign_load_pdf_file_class_init( vips_foreign_load_pdf_file_class_init(
VipsForeignLoadPdfFileClass *class ) VipsForeignLoadPdfFileClass *class )
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS( class ); GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class; VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignClass *foreign_class = (VipsForeignClass *) class; VipsForeignClass *foreign_class = (VipsForeignClass *) class;
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class; VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
gobject_class->set_property = vips_object_set_property; gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property; gobject_class->get_property = vips_object_get_property;
object_class->nickname = "pdfload"; object_class->nickname = "pdfload";
object_class->description = _( "load PDF from file" );
object_class->build = vips_foreign_load_pdf_file_build;
foreign_class->suffs = vips_foreign_pdf_suffs; foreign_class->suffs = vips_foreign_pdf_suffs;
load_class->is_a = vips_foreign_load_pdf_is_a; load_class->is_a = vips_foreign_load_pdf_is_a;
load_class->header = vips_foreign_load_pdf_file_header; load_class->header = vips_foreign_load_pdf_file_header;
VIPS_ARG_STRING( class, "filename", 1, VIPS_ARG_STRING( class, "filename", 1,
_( "Filename" ), _( "Filename" ),
_( "Filename to load from" ), _( "Filename to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT, VIPS_ARGUMENT_REQUIRED_INPUT,
skipping to change at line 682 skipping to change at line 827
VipsArea *buf; VipsArea *buf;
} VipsForeignLoadPdfBuffer; } VipsForeignLoadPdfBuffer;
typedef VipsForeignLoadPdfClass VipsForeignLoadPdfBufferClass; typedef VipsForeignLoadPdfClass VipsForeignLoadPdfBufferClass;
G_DEFINE_TYPE( VipsForeignLoadPdfBuffer, vips_foreign_load_pdf_buffer, G_DEFINE_TYPE( VipsForeignLoadPdfBuffer, vips_foreign_load_pdf_buffer,
vips_foreign_load_pdf_get_type() ); vips_foreign_load_pdf_get_type() );
static int static int
vips_foreign_load_pdf_buffer_header( VipsForeignLoad *load ) vips_foreign_load_pdf_buffer_build( VipsObject *object )
{ {
VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) load; VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) object;
VipsForeignLoadPdfBuffer *buffer = VipsForeignLoadPdfBuffer *buffer = (VipsForeignLoadPdfBuffer *) pdf;
(VipsForeignLoadPdfBuffer *) load;
g_mutex_lock( vips__global_lock );
if( !(pdf->doc = FPDF_LoadMemDocument( buffer->buf->data, if( buffer->buf &&
buffer->buf->length, NULL )) ) { !(pdf->source = vips_source_new_from_memory(
g_mutex_unlock( vips__global_lock ); VIPS_AREA( buffer->buf )->data,
vips_pdfium_error(); VIPS_AREA( buffer->buf )->length )) )
vips_error( "pdfload",
"%s", _( "unable to load from buffer" ) );
return( -1 ); return( -1 );
}
g_mutex_unlock( vips__global_lock ); return( VIPS_OBJECT_CLASS( vips_foreign_load_pdf_buffer_parent_class )->
build( object ) );
return( vips_foreign_load_pdf_header( load ) );
} }
static void static void
vips_foreign_load_pdf_buffer_class_init( vips_foreign_load_pdf_buffer_class_init(
VipsForeignLoadPdfBufferClass *class ) VipsForeignLoadPdfBufferClass *class )
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS( class ); GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class; VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class; VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
gobject_class->set_property = vips_object_set_property; gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property; gobject_class->get_property = vips_object_get_property;
object_class->nickname = "pdfload_buffer"; object_class->nickname = "pdfload_buffer";
object_class->description = _( "load PDF from buffer" );
object_class->build = vips_foreign_load_pdf_buffer_build;
load_class->is_a_buffer = vips_foreign_load_pdf_is_a_buffer; load_class->is_a_buffer = vips_foreign_load_pdf_is_a_buffer;
load_class->header = vips_foreign_load_pdf_buffer_header;
VIPS_ARG_BOXED( class, "buffer", 1, VIPS_ARG_BOXED( class, "buffer", 1,
_( "Buffer" ), _( "Buffer" ),
_( "Buffer to load from" ), _( "Buffer to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT, VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadPdfBuffer, buf ), G_STRUCT_OFFSET( VipsForeignLoadPdfBuffer, buf ),
VIPS_TYPE_BLOB ); VIPS_TYPE_BLOB );
} }
static void static void
vips_foreign_load_pdf_buffer_init( VipsForeignLoadPdfBuffer *buffer ) vips_foreign_load_pdf_buffer_init( VipsForeignLoadPdfBuffer *buffer )
{ {
} }
typedef struct _VipsForeignLoadPdfSource {
VipsForeignLoadPdf parent_object;
VipsSource *source;
} VipsForeignLoadPdfSource;
typedef VipsForeignLoadPdfClass VipsForeignLoadPdfSourceClass;
G_DEFINE_TYPE( VipsForeignLoadPdfSource, vips_foreign_load_pdf_source,
vips_foreign_load_pdf_get_type() );
static int
vips_foreign_load_pdf_source_build( VipsObject *object )
{
VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) object;
VipsForeignLoadPdfSource *source = (VipsForeignLoadPdfSource *) pdf;
if( source->source ) {
pdf->source = source->source;
g_object_ref( pdf->source );
}
return( VIPS_OBJECT_CLASS( vips_foreign_load_pdf_source_parent_class )->
build( object ) );
}
static gboolean
vips_foreign_load_pdf_source_is_a_source( VipsSource *source )
{
const unsigned char *p;
return( (p = vips_source_sniff( source, 4 )) &&
p[0] == '%' &&
p[1] == 'P' &&
p[2] == 'D' &&
p[3] == 'F' );
}
static void
vips_foreign_load_pdf_source_class_init(
VipsForeignLoadPdfSourceClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
object_class->nickname = "pdfload_source";
object_class->description = _( "load PDF from source" );
object_class->build = vips_foreign_load_pdf_source_build;
load_class->is_a_source = vips_foreign_load_pdf_source_is_a_source;
VIPS_ARG_OBJECT( class, "source", 1,
_( "Source" ),
_( "Source to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadPdfSource, source ),
VIPS_TYPE_SOURCE );
}
static void
vips_foreign_load_pdf_source_init( VipsForeignLoadPdfSource *source )
{
}
#endif /*HAVE_PDFIUM*/ #endif /*HAVE_PDFIUM*/
 End of changes. 43 change blocks. 
67 lines changed or deleted 276 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)