wok-current rev 18440

gambas2: update CPdfDocument.cpp
author Pascal Bellard <pascal.bellard@slitaz.org>
date Wed Sep 23 19:44:57 2015 +0200 (2015-09-23)
parents 243148b143dc
children a3f5bac150c5
files gambas2/receipt gambas2/stuff/CPdfDocument.cpp
line diff
     1.1 --- a/gambas2/receipt	Wed Sep 23 18:02:54 2015 +0200
     1.2 +++ b/gambas2/receipt	Wed Sep 23 19:44:57 2015 +0200
     1.3 @@ -12,11 +12,14 @@
     1.4  TAGS="interpreter basic"
     1.5  
     1.6  DEPENDS="poppler util-linux-uuid"
     1.7 -BUILD_DEPENDS="poppler-dev util-linux-uuid-dev lcms-dev autoconf automake libtool"
     1.8 +BUILD_DEPENDS="poppler-dev util-linux-uuid-dev lcms-dev tiff-dev \
     1.9 +autoconf automake libtool"
    1.10  
    1.11  # Rules to configure and make the package.
    1.12  compile_rules()
    1.13  {
    1.14 +	sed -i '/0.17.0 poppler/{N;p;s/17/20/g}'  gb.pdf/configure.ac
    1.15 +	cp $stuff/CPdfDocument.cpp gb.pdf/src/CPdfDocument.cpp
    1.16  	./reconf-all
    1.17  	./configure \
    1.18  		--prefix=/usr \
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/gambas2/stuff/CPdfDocument.cpp	Wed Sep 23 19:44:57 2015 +0200
     2.3 @@ -0,0 +1,1538 @@
     2.4 +/***************************************************************************
     2.5 +
     2.6 +  CPdfDocument.cpp
     2.7 +
     2.8 +  gb.pdf Component
     2.9 +
    2.10 +  (C) 2005-2007 Daniel Campos Fernández <dcamposf@gmail.com>
    2.11 +
    2.12 +
    2.13 +  This program is free software; you can redistribute it and/or modify
    2.14 +  it under the terms of the GNU General Public License as published by
    2.15 +  the Free Software Foundation; either version 1, or (at your option)
    2.16 +  any later version.
    2.17 +
    2.18 +  This program is free software; you can redistribute it and/or modify
    2.19 +  it under the terms of the GNU General Public License as published by
    2.20 +  the Free Software Foundation; either version 1, or (at your option)
    2.21 +  any later version.
    2.22 +
    2.23 +  This program is distributed in the hope that it will be useful,
    2.24 +  but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.25 +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.26 +  GNU General Public License for more details.
    2.27 +
    2.28 +  You should have received a copy of the GNU General Public License
    2.29 +  along with this program; if not, write to the Free Software
    2.30 +  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    2.31 +
    2.32 +***************************************************************************/
    2.33 +
    2.34 +#define __CPDFDOCUMENT_C
    2.35 +
    2.36 +#include "CPdfDocument.h"
    2.37 +
    2.38 +#include "gambas.h"
    2.39 +#include "main.h"
    2.40 +
    2.41 +#include <stdio.h>
    2.42 +#include <stdint.h>
    2.43 +#include <math.h>
    2.44 +
    2.45 +#include <PDFDoc.h>
    2.46 +#include <Stream.h>
    2.47 +#include <ErrorCodes.h>
    2.48 +#include <Page.h>
    2.49 +#include <Catalog.h>
    2.50 +#include <TextOutputDev.h>
    2.51 +#include <SplashOutputDev.h>
    2.52 +#include <splash/SplashBitmap.h>
    2.53 +#include <goo/GooList.h>
    2.54 +#include <Outline.h>
    2.55 +#include <Link.h>
    2.56 +#include <Gfx.h>
    2.57 +
    2.58 +/*****************************************************************************
    2.59 +
    2.60 + Translations from Poppler universe to Gambas universe
    2.61 +
    2.62 +******************************************************************************/
    2.63 +typedef struct
    2.64 +{
    2.65 +	int32_t x0;
    2.66 +	int32_t y0;
    2.67 +	int32_t x1;
    2.68 +	int32_t y1;
    2.69 +} FoundRect;
    2.70 +
    2.71 +static void aux_return_string_info(void *_object, const char *key)
    2.72 +{
    2.73 +	Object obj;
    2.74 +	Object dst;
    2.75 +	GooString *goo_value;
    2.76 +	Dict *info_dict;
    2.77 +	char *tmpstr;
    2.78 +
    2.79 +	THIS->doc->getDocInfo (&obj);
    2.80 +	if (!obj.isDict()) { GB.ReturnNewZeroString(""); return; }
    2.81 +		
    2.82 +	info_dict=obj.getDict();
    2.83 +	info_dict->lookup ((char *)key, &dst);
    2.84 +	if (!dst.isString ()) { GB.ReturnNewZeroString(""); }
    2.85 +	else {
    2.86 +		goo_value = dst.getString();
    2.87 +
    2.88 +		if (goo_value->hasUnicodeMarker())
    2.89 +		{
    2.90 +			GB.ConvString (&tmpstr,goo_value->getCString()+2,goo_value->getLength()-2,"UTF-16BE","UTF-8");
    2.91 +			GB.ReturnNewZeroString(tmpstr);		
    2.92 +		}		
    2.93 +		else
    2.94 +			GB.ReturnNewString(goo_value->getCString(),goo_value->getLength());		
    2.95 +	}
    2.96 +	dst.free();
    2.97 +	obj.free();		
    2.98 +}
    2.99 +
   2.100 +static void aux_return_date_info(void *_object, const char *key)
   2.101 +{
   2.102 +	// TODO: Y2K effect
   2.103 +	GB_DATE_SERIAL ds;
   2.104 +	GB_DATE ret;
   2.105 +	Object obj;
   2.106 +	Object dst;
   2.107 +	GooString *goo;
   2.108 +	Dict *info_dict;
   2.109 +	char *datestr=NULL,*tofree=NULL;
   2.110 +	int nnum;
   2.111 +
   2.112 +	THIS->doc->getDocInfo (&obj);
   2.113 +	if (!obj.isDict()) { GB.ReturnNull(); return; }
   2.114 +
   2.115 +	info_dict=obj.getDict();
   2.116 +	info_dict->lookup ((char *)key, &dst);
   2.117 +	if (!dst.isString ()) { GB.ReturnNull(); }
   2.118 +	else {
   2.119 +		goo = dst.getString();
   2.120 +		if (goo->hasUnicodeMarker())
   2.121 +			GB.ConvString (&datestr,goo->getCString()+2,goo->getLength()-2,"UTF-16BE","UTF-8");
   2.122 +		else
   2.123 +		{
   2.124 +			GB.NewString(&datestr,goo->getCString(),goo->getLength());
   2.125 +			tofree=datestr;		
   2.126 +		}
   2.127 +
   2.128 +		if (!datestr) { GB.ReturnNull(); }
   2.129 +		else
   2.130 +		{
   2.131 +			if (datestr[0] == 'D' && datestr[1] == ':') datestr += 2;
   2.132 +			nnum=sscanf(datestr, "%4hd%2hd%2hd%2hd%2hd%2hd",&ds.year, &ds.month, \
   2.133 +			                                          &ds.day, &ds.hour, &ds.min, &ds.sec);	
   2.134 +			if (nnum != 6) { GB.ReturnNull(); }
   2.135 +			else
   2.136 +			{
   2.137 +				if (GB.MakeDate(&ds,&ret))
   2.138 +					GB.ReturnNull();
   2.139 +				else
   2.140 +					GB.ReturnDate(&ret);
   2.141 +			}		
   2.142 +		}
   2.143 +		
   2.144 +	}
   2.145 +
   2.146 +	if (tofree) GB.FreeString(&tofree);
   2.147 +	dst.free();
   2.148 +	obj.free();
   2.149 +}
   2.150 +
   2.151 +static void aux_return_unicode_string(Unicode *uni, int32_t  len)
   2.152 +{
   2.153 +	int32_t bc;
   2.154 +	char *ret=NULL;
   2.155 +
   2.156 +	for (bc=0; bc<len; bc++)
   2.157 +		GB.AddString(&ret,(const char*)&uni[bc],0);
   2.158 +
   2.159 +	GB.ReturnNewString(ret,0);
   2.160 +	GB.FreeString(&ret);
   2.161 +}
   2.162 +
   2.163 +static LinkDest *get_dest(LinkAction *act)
   2.164 +{
   2.165 +	switch (act->getKind())
   2.166 +	{
   2.167 +		case actionGoTo: return ((LinkGoTo*)act)->getDest();
   2.168 +		case actionGoToR: return ((LinkGoToR*)act)->getDest();
   2.169 +		default: return 0;
   2.170 +	}
   2.171 +}
   2.172 +
   2.173 +static uint32_t aux_get_page_from_action(void *_object, LinkAction *act)
   2.174 +{
   2.175 +	Ref pref;       
   2.176 +	LinkDest *dest = get_dest(act);
   2.177 +	#if POPPLER_VERSION_0_6
   2.178 +	GooString *name;
   2.179 +	#else
   2.180 +	UGooString *name;
   2.181 +	#endif
   2.182 +
   2.183 +	if (!dest)
   2.184 +	{
   2.185 +		// try to use NamedDest to get dest
   2.186 +		if (!act)
   2.187 +			return 0;
   2.188 +		if (act->getKind () == actionGoTo)
   2.189 +		{
   2.190 +			name = ((LinkGoTo*)act)->getNamedDest();
   2.191 +			if (name)
   2.192 +				dest = THIS->doc->findDest(name);
   2.193 +		}
   2.194 +	}
   2.195 +
   2.196 +	if (!dest)
   2.197 +		return 0;
   2.198 +
   2.199 +	if (dest->isPageRef() )
   2.200 +	{
   2.201 +		pref= dest->getPageRef();
   2.202 +		return THIS->doc->findPage(pref.num, pref.gen);
   2.203 +	}
   2.204 +	else
   2.205 +		return dest->getPageNum();
   2.206 +}
   2.207 +
   2.208 +static void aux_get_dimensions_from_action(LinkAction *act,int *left, int32_t *right, int32_t *top, int32_t *bottom)
   2.209 +{
   2.210 +	LinkDest *dest = get_dest(act);
   2.211 +	if (!dest)
   2.212 +	{
   2.213 +		if (left)   *left=0;
   2.214 +		if (right)  *right=0;
   2.215 +		if (top)    *top=0;
   2.216 +		if (bottom) *bottom=0;
   2.217 +		return;
   2.218 +	}
   2.219 +	
   2.220 +	if (left)   *left=(int32_t)dest->getLeft();
   2.221 +	if (right)  *right=(int32_t)dest->getRight();
   2.222 +	if (top)    *top=(int32_t)dest->getTop();
   2.223 +	if (bottom) *bottom=(int32_t)dest->getBottom();
   2.224 +}
   2.225 +
   2.226 +static double aux_get_zoom_from_action(LinkAction *act)
   2.227 +{
   2.228 +	LinkDest *dest = get_dest(act);
   2.229 +	if (dest)
   2.230 +		return dest->getZoom();
   2.231 +	else
   2.232 +		return 1;
   2.233 +}
   2.234 +
   2.235 +static char* aux_get_target_from_action(LinkAction *act)
   2.236 +{
   2.237 +	char *vl=NULL;
   2.238 +	char *uni=NULL;	
   2.239 +	GooString *tmp=NULL;
   2.240 +
   2.241 +	switch (act->getKind())
   2.242 +	{
   2.243 +		case actionGoToR:
   2.244 +			tmp=((LinkGoToR*)act)->getFileName(); break;
   2.245 +
   2.246 +		case actionLaunch:
   2.247 +			tmp=((LinkLaunch*)act)->getFileName(); break;
   2.248 +
   2.249 +		case actionURI:
   2.250 +			tmp=((LinkURI*)act)->getURI(); break;
   2.251 +			
   2.252 +		case actionNamed:
   2.253 +			tmp=((LinkNamed*)act)->getName(); break;
   2.254 +
   2.255 +		case actionMovie:
   2.256 +			#if POPPLER_VERSION_0_8
   2.257 +			tmp=((LinkMovie*)act)->getAnnotTitle(); break;
   2.258 +			#else
   2.259 +			tmp=((LinkMovie*)act)->getTitle(); break;
   2.260 +			#endif
   2.261 +
   2.262 +		default:
   2.263 +			break;
   2.264 +	}
   2.265 +
   2.266 +	if (!tmp) return NULL;
   2.267 +
   2.268 +	if (tmp->hasUnicodeMarker())
   2.269 +	{
   2.270 +			GB.ConvString (&uni,tmp->getCString()+2,tmp->getLength()-2,"UTF-16BE","UTF-8");
   2.271 +			GB.AddString (&vl,uni,0);	
   2.272 +	}	
   2.273 +	else
   2.274 +			GB.AddString(&vl,tmp->getCString(),tmp->getLength());
   2.275 +	
   2.276 +
   2.277 +	return vl;
   2.278 +
   2.279 +}
   2.280 +
   2.281 +/*****************************************************************************
   2.282 +
   2.283 + PDF document
   2.284 +
   2.285 +******************************************************************************/
   2.286 +
   2.287 +
   2.288 +static void free_all(void *_object)
   2.289 +{
   2.290 +	if (THIS->doc)
   2.291 +	{
   2.292 +		delete THIS->doc;
   2.293 +		THIS->doc=NULL;
   2.294 +	}
   2.295 +
   2.296 +	if (THIS->dev)
   2.297 +	{
   2.298 +		delete THIS->dev;
   2.299 +		THIS->dev=NULL;
   2.300 +	}
   2.301 +
   2.302 +	if (THIS->buf)
   2.303 +	{
   2.304 +		GB.ReleaseFile(&THIS->buf,THIS->len);
   2.305 +		THIS->buf=NULL;
   2.306 +	}
   2.307 +
   2.308 +	if (THIS->Found)
   2.309 +	{		
   2.310 +		GB.FreeArray(POINTER(&THIS->Found));
   2.311 +		THIS->Found=NULL;
   2.312 +	}
   2.313 +
   2.314 +	if (THIS->links)
   2.315 +	{
   2.316 +		delete THIS->links;	
   2.317 +		THIS->links=NULL;
   2.318 +	}
   2.319 +
   2.320 +	if (THIS->pindex)
   2.321 +	{		
   2.322 +		GB.FreeArray(POINTER(&THIS->pindex));
   2.323 +		GB.FreeArray(POINTER(&THIS->oldindex));
   2.324 +		THIS->pindex=NULL;
   2.325 +		THIS->oldindex=NULL;
   2.326 +	}
   2.327 +
   2.328 +	THIS->index=NULL;
   2.329 +	THIS->currpage=-1;
   2.330 +}
   2.331 +
   2.332 +BEGIN_METHOD_VOID (PDFDOCUMENT_free)
   2.333 +
   2.334 +	free_all(_object);
   2.335 +
   2.336 +END_METHOD
   2.337 +
   2.338 +BEGIN_PROPERTY(PDFDOCUMENT_scale)
   2.339 +
   2.340 +	if (READ_PROPERTY){ GB.ReturnFloat(THIS->scale); return; }
   2.341 +	
   2.342 +	if (VPROP(GB_FLOAT)>0) { THIS->scale = VPROP(GB_FLOAT); return; }
   2.343 +
   2.344 +	GB.Error("Zoom must be a positive value");
   2.345 +
   2.346 +END_PROPERTY
   2.347 +
   2.348 +BEGIN_PROPERTY(PDFDOCUMENT_rotation)
   2.349 +
   2.350 +	int32_t rot;
   2.351 +
   2.352 +	if (READ_PROPERTY)
   2.353 +	{
   2.354 +		GB.ReturnInteger(THIS->rotation);
   2.355 +		return;
   2.356 +	}
   2.357 +	
   2.358 +	rot=VPROP(GB_INTEGER);
   2.359 +
   2.360 +	while (rot<0) rot+=360;
   2.361 +	while (rot>=360) rot-=360;
   2.362 +
   2.363 +	switch (rot)
   2.364 +	{
   2.365 +		case 0:
   2.366 +		case 90:
   2.367 +		case 180:
   2.368 +		case 270: 
   2.369 +			THIS->rotation = VPROP(GB_INTEGER);
   2.370 +			break;
   2.371 +	}
   2.372 +
   2.373 +END_PROPERTY
   2.374 +
   2.375 +
   2.376 +int32_t open_document (void *_object, char *sfile, int32_t lfile)
   2.377 +{
   2.378 +	SplashColor white;
   2.379 +	PDFDoc *test;
   2.380 +	MemStream *stream;
   2.381 +	Object obj;
   2.382 +	Outline *outline;
   2.383 +	char *buf=NULL;
   2.384 +	int32_t len=0;
   2.385 +	int32_t ret;
   2.386 +
   2.387 +
   2.388 +	if ( GB.LoadFile(sfile,lfile,&buf,&len) ) return -1;
   2.389 +
   2.390 +	obj.initNull();
   2.391 +	stream=new MemStream(buf,0,(Guint)len,&obj);
   2.392 +	test=new PDFDoc (stream,0,0);
   2.393 +
   2.394 +	if (!test->isOk())
   2.395 +	{
   2.396 +		GB.ReleaseFile(&buf,len);
   2.397 +		ret=test->getErrorCode();
   2.398 +		delete test;
   2.399 +		test=NULL;
   2.400 +		if (ret == errEncrypted) return -2;
   2.401 +		return -3;
   2.402 +	}
   2.403 +
   2.404 +	free_all(_object);
   2.405 +
   2.406 +	THIS->doc=test;
   2.407 +	THIS->buf=buf;
   2.408 +	THIS->len=len;
   2.409 +
   2.410 +	white[0] = 0xFF; white[1] = 0xFF; white[2] = 0xFF;
   2.411 +	THIS->dev=new SplashOutputDev(splashModeRGB8, 3, gFalse, white);
   2.412 +		
   2.413 +	#if POPPLER_VERSION_0_20
   2.414 +	THIS->dev->startDoc(THIS->doc);
   2.415 +	#else
   2.416 +	THIS->dev->startDoc(THIS->doc->getXRef ());
   2.417 +	#endif
   2.418 +
   2.419 +	outline=THIS->doc->getOutline();
   2.420 +	if (outline) THIS->index=outline->getItems();
   2.421 +	
   2.422 +	//if (THIS->index)
   2.423 +	//	if (!THIS->index->getLength()) THIS->index=NULL;
   2.424 +
   2.425 +	THIS->currindex=0;
   2.426 +	THIS->currpage=-1;
   2.427 +
   2.428 +	return 0;
   2.429 +
   2.430 +}
   2.431 +
   2.432 +
   2.433 +BEGIN_METHOD(PDFDOCUMENT_new, GB_STRING File)
   2.434 +
   2.435 +	THIS->scale = 1;
   2.436 +	THIS->rotation = 0;
   2.437 +
   2.438 +	if (!MISSING(File))
   2.439 +	{
   2.440 +		switch (open_document( _object, STRING(File), LENGTH(File)) )
   2.441 +		{
   2.442 +			case -1: GB.Error("File not found"); return;
   2.443 +			case -2: GB.Error("PDF is encrypted"); return;
   2.444 +			case -3: GB.Error("Bad PDF File"); return;
   2.445 +		}
   2.446 +	}
   2.447 +
   2.448 +END_METHOD
   2.449 +
   2.450 +BEGIN_METHOD (PDFDOCUMENT_open, GB_STRING File;)
   2.451 +
   2.452 +	switch (open_document( _object, STRING(File), LENGTH(File)) )
   2.453 +	{
   2.454 +		case -1: GB.Error("File not found"); return;
   2.455 +		case -2: GB.Error("PDF is encrypted"); return;
   2.456 +		case -3: GB.Error("Bad PDF File"); return;
   2.457 +	}
   2.458 +
   2.459 +END_METHOD
   2.460 +
   2.461 +BEGIN_METHOD_VOID(PDFDOCUMENT_close)
   2.462 +
   2.463 +	free_all(_object);
   2.464 +
   2.465 +END_METHOD
   2.466 +
   2.467 +BEGIN_METHOD(PDFDOCUMENT_get,GB_INTEGER index;)
   2.468 +
   2.469 +	if (!THIS->doc || (VARG(index)<1) || ( VARG(index)>THIS->doc->getNumPages() ) )
   2.470 +	{
   2.471 +		GB.Error("Invalid page number");
   2.472 +		GB.ReturnNull();
   2.473 +		return;
   2.474 +	}
   2.475 +
   2.476 +	if (THIS->currpage != (uint32_t)VARG(index) )
   2.477 +	{
   2.478 +		if (THIS->Found)
   2.479 +		{		
   2.480 +			GB.FreeArray(POINTER(&THIS->Found));
   2.481 +			THIS->Found=NULL;
   2.482 +		}
   2.483 +
   2.484 +		if (THIS->links)
   2.485 +		{
   2.486 +			delete THIS->links;	
   2.487 +			THIS->links=NULL;
   2.488 +		}
   2.489 +
   2.490 +		THIS->page=THIS->doc->getCatalog()->getPage(VARG(index));
   2.491 +		THIS->currpage=VARG(index);
   2.492 +	}
   2.493 +		
   2.494 +	RETURN_SELF();
   2.495 +
   2.496 +END_METHOD
   2.497 +
   2.498 +BEGIN_PROPERTY(PDFDOCUMENT_ready)
   2.499 +
   2.500 +	GB.ReturnBoolean( (bool)THIS->doc );
   2.501 +
   2.502 +END_PROPERTY
   2.503 +
   2.504 +BEGIN_PROPERTY(PDFDOCUMENT_count)
   2.505 +
   2.506 +	GB.ReturnInteger( (int32_t) (THIS->doc ? THIS->doc->getNumPages() : 0));
   2.507 +
   2.508 +END_PROPERTY
   2.509 +
   2.510 +BEGIN_PROPERTY(PDFDOCUMENT_info)
   2.511 +
   2.512 +	if (THIS->doc) RETURN_SELF();
   2.513 +	else GB.ReturnNull();
   2.514 +
   2.515 +END_PROPERTY
   2.516 +
   2.517 +/*****************************************************************************
   2.518 +
   2.519 +PDF document information
   2.520 +
   2.521 +******************************************************************************/
   2.522 +
   2.523 +BEGIN_PROPERTY(PDFINFO_title)
   2.524 +
   2.525 +	aux_return_string_info(_object,"Title");
   2.526 +
   2.527 +END_PROPERTY
   2.528 +
   2.529 +BEGIN_PROPERTY(PDFINFO_format)
   2.530 +
   2.531 +	char ctx[16];
   2.532 +	#if POPPLER_VERSION_0_11_3
   2.533 +		snprintf(ctx, sizeof(ctx), "%.2g", THIS->doc->getPDFMajorVersion () + THIS->doc->getPDFMinorVersion() / 10.0);
   2.534 +	#else
   2.535 +		snprintf(ctx, sizeof(ctx), "%.2g", THIS->doc->getPDFVersion());
   2.536 +	#endif
   2.537 +	GB.ReturnNewZeroString(ctx);
   2.538 +
   2.539 +END_PROPERTY
   2.540 +
   2.541 +BEGIN_PROPERTY(PDFINFO_author)
   2.542 +
   2.543 +	aux_return_string_info(_object,"Author");
   2.544 +
   2.545 +END_PROPERTY
   2.546 +
   2.547 +BEGIN_PROPERTY(PDFINFO_subject)
   2.548 +
   2.549 +	aux_return_string_info(_object,"Subject");
   2.550 +
   2.551 +END_PROPERTY
   2.552 +
   2.553 +BEGIN_PROPERTY(PDFINFO_keywords)
   2.554 +
   2.555 +	aux_return_string_info(_object,"Keywords");
   2.556 +
   2.557 +END_PROPERTY
   2.558 +
   2.559 +BEGIN_PROPERTY(PDFINFO_creator)
   2.560 +
   2.561 +	aux_return_string_info(_object,"Creator");
   2.562 +
   2.563 +END_PROPERTY
   2.564 +
   2.565 +BEGIN_PROPERTY(PDFINFO_producer)
   2.566 +
   2.567 +	aux_return_string_info(_object,"Producer");
   2.568 +
   2.569 +END_PROPERTY
   2.570 +
   2.571 +BEGIN_PROPERTY(PDFINFO_linearized)
   2.572 +
   2.573 +	GB.ReturnBoolean(THIS->doc->isLinearized());
   2.574 +
   2.575 +END_PROPERTY
   2.576 +
   2.577 +BEGIN_PROPERTY(PDFINFO_layout)
   2.578 +
   2.579 +	Catalog *catalog;
   2.580 +
   2.581 +	catalog=THIS->doc->getCatalog();
   2.582 +	if (!catalog) { GB.ReturnInteger(Catalog::pageLayoutNone); return; }
   2.583 +	if (!catalog->isOk())  { GB.ReturnInteger(Catalog::pageLayoutNone); return; }
   2.584 +
   2.585 +	GB.ReturnInteger(catalog->getPageLayout());
   2.586 +
   2.587 +END_PROPERTY
   2.588 +
   2.589 +BEGIN_PROPERTY(PDFINFO_mode)
   2.590 +
   2.591 +	Catalog *catalog;
   2.592 +
   2.593 +	catalog=THIS->doc->getCatalog();
   2.594 +	if (!catalog) { GB.ReturnInteger(Catalog::pageModeNone); return; }
   2.595 +	if (!catalog->isOk())  { GB.ReturnInteger(Catalog::pageModeNone); return; }
   2.596 +
   2.597 +	GB.ReturnInteger(catalog->getPageMode());
   2.598 +
   2.599 +
   2.600 +END_PROPERTY
   2.601 +
   2.602 +BEGIN_PROPERTY(PDFINFO_canprint)
   2.603 +	
   2.604 +	GB.ReturnBoolean(THIS->doc->okToPrint());      
   2.605 +
   2.606 +END_PROPERTY
   2.607 +
   2.608 +BEGIN_PROPERTY(PDFINFO_canmodify)
   2.609 +
   2.610 +	GB.ReturnBoolean(THIS->doc->okToChange());
   2.611 +
   2.612 +END_PROPERTY
   2.613 +
   2.614 +BEGIN_PROPERTY(PDFINFO_cancopy)
   2.615 +
   2.616 +	GB.ReturnBoolean(THIS->doc->okToCopy());
   2.617 +
   2.618 +END_PROPERTY
   2.619 +
   2.620 +BEGIN_PROPERTY(PDFINFO_canaddnotes)
   2.621 +
   2.622 +	GB.ReturnBoolean(THIS->doc->okToAddNotes());
   2.623 +
   2.624 +END_PROPERTY
   2.625 +
   2.626 +BEGIN_PROPERTY(PDFINFO_creation)
   2.627 +
   2.628 +	aux_return_date_info(_object,"CreationDate");
   2.629 +
   2.630 +END_PROPERTY
   2.631 +
   2.632 +BEGIN_PROPERTY(PDFINFO_modification)
   2.633 +
   2.634 +	aux_return_date_info(_object,"ModDate");
   2.635 +
   2.636 +END_PROPERTY
   2.637 +
   2.638 +
   2.639 +/*****************************************************************************
   2.640 +
   2.641 +PDF document index
   2.642 +
   2.643 +******************************************************************************/
   2.644 +
   2.645 +
   2.646 +BEGIN_PROPERTY(PDFDOCUMENT_has_index)
   2.647 +
   2.648 +	GB.ReturnBoolean(THIS->index && THIS->index->getLength());
   2.649 +
   2.650 +END_PROPERTY
   2.651 +
   2.652 +BEGIN_PROPERTY(PDFDOCUMENT_index)
   2.653 +
   2.654 +	if (!THIS->index) { GB.ReturnNull(); return; }
   2.655 +	
   2.656 +	THIS->action=((OutlineItem*)THIS->index->get(THIS->currindex))->getAction();
   2.657 +	RETURN_SELF();
   2.658 +
   2.659 +END_PROPERTY
   2.660 +
   2.661 +BEGIN_PROPERTY(PDFINDEX_count)
   2.662 +	
   2.663 +	GB.ReturnInteger(THIS->index->getLength());
   2.664 +
   2.665 +END_PROPERTY
   2.666 +
   2.667 +BEGIN_PROPERTY(PDFINDEX_has_children)
   2.668 +
   2.669 +	OutlineItem *item;
   2.670 +
   2.671 +	item = (OutlineItem *)THIS->index->get (THIS->currindex);
   2.672 +	GB.ReturnBoolean(item->getKids() && item->getKids()->getLength());
   2.673 +
   2.674 +END_PROPERTY
   2.675 +
   2.676 +BEGIN_PROPERTY(PDFINDEX_is_open)
   2.677 +
   2.678 +	OutlineItem *item;
   2.679 +
   2.680 +	item = (OutlineItem *)THIS->index->get (THIS->currindex);
   2.681 +
   2.682 +	if (READ_PROPERTY)
   2.683 +	{	GB.ReturnBoolean(item->isOpen()); return; }
   2.684 +
   2.685 +	if (VPROP(GB_INTEGER)) item->open();
   2.686 +	else item->close();
   2.687 +
   2.688 +END_PROPERTY
   2.689 +
   2.690 +BEGIN_PROPERTY(PDFINDEX_title)
   2.691 +
   2.692 +	OutlineItem *item;
   2.693 +
   2.694 +	item = (OutlineItem *)THIS->index->get (THIS->currindex);
   2.695 +	aux_return_unicode_string(item->getTitle(),item->getTitleLength());
   2.696 +
   2.697 +END_PROPERTY
   2.698 +
   2.699 +
   2.700 +BEGIN_METHOD_VOID(PDFINDEX_root)
   2.701 +
   2.702 +	Outline *outline;
   2.703 +
   2.704 +	outline=THIS->doc->getOutline();
   2.705 +	if (outline) THIS->index=outline->getItems();
   2.706 +	THIS->currindex=0;
   2.707 +	if (THIS->pindex) { GB.FreeArray(POINTER(&THIS->pindex)); THIS->pindex=NULL; }
   2.708 +	if (THIS->oldindex) { GB.FreeArray(POINTER(&THIS->oldindex)); THIS->oldindex=NULL; }
   2.709 +
   2.710 +END_METHOD
   2.711 +
   2.712 +BEGIN_METHOD_VOID(PDFINDEX_prev)
   2.713 +
   2.714 +	if (!THIS->currindex) { GB.ReturnBoolean(true); return; }
   2.715 +
   2.716 +	THIS->currindex--;
   2.717 +	GB.ReturnBoolean(false);
   2.718 +
   2.719 +END_METHOD
   2.720 +
   2.721 +BEGIN_METHOD_VOID(PDFINDEX_next)
   2.722 +
   2.723 +	if ( (THIS->currindex+1) >= (uint32_t)THIS->index->getLength() )
   2.724 +		 { GB.ReturnBoolean(true); return; }
   2.725 +
   2.726 +	THIS->currindex++;
   2.727 +	GB.ReturnBoolean(false);
   2.728 +
   2.729 +END_METHOD
   2.730 +
   2.731 +BEGIN_METHOD_VOID(PDFINDEX_child)
   2.732 +
   2.733 +	OutlineItem *item;
   2.734 +
   2.735 +	item = (OutlineItem *)THIS->index->get (THIS->currindex);
   2.736 +
   2.737 +	if (!item->hasKids() || item->getKids()->getLength() == 0) { GB.ReturnBoolean(true); return; }
   2.738 +
   2.739 +	if (THIS->pindex)
   2.740 +	{
   2.741 +		GB.Add(POINTER(&THIS->pindex));
   2.742 +		GB.Add(POINTER(&THIS->oldindex));
   2.743 +	}
   2.744 +	else
   2.745 +	{
   2.746 +		GB.NewArray(POINTER(&THIS->pindex),sizeof(void*),1);
   2.747 +		GB.NewArray(POINTER(&THIS->oldindex),sizeof(uint32_t),1);
   2.748 +	}	
   2.749 +
   2.750 +	if (!item->isOpen()) item->open(); 
   2.751 +	THIS->pindex[GB.Count(POINTER(THIS->pindex))-1]=(void*)THIS->index;
   2.752 +	THIS->oldindex[GB.Count(POINTER(THIS->pindex))-1]=THIS->currindex;
   2.753 +	THIS->index=item->getKids();	
   2.754 +	THIS->currindex=0;
   2.755 +
   2.756 +	GB.ReturnBoolean(false);
   2.757 +
   2.758 +END_METHOD
   2.759 +
   2.760 +BEGIN_METHOD_VOID(PDFINDEX_parent)
   2.761 +
   2.762 +	if (!THIS->pindex) { GB.ReturnBoolean(true); return; }
   2.763 +
   2.764 +	THIS->index=(GooList*)THIS->pindex[GB.Count(POINTER(THIS->pindex))-1];
   2.765 +	THIS->currindex=THIS->oldindex[GB.Count(POINTER(THIS->pindex))-1];
   2.766 +	if (GB.Count(POINTER(THIS->pindex))==1)
   2.767 +	{
   2.768 +		GB.FreeArray(POINTER(&THIS->pindex));
   2.769 +		GB.FreeArray(POINTER(&THIS->oldindex));
   2.770 +		THIS->oldindex=NULL;
   2.771 +		THIS->pindex=NULL;
   2.772 +	}
   2.773 +	else
   2.774 +	{
   2.775 +		GB.Remove(POINTER(&THIS->pindex),GB.Count(POINTER(THIS->pindex))-1,1);
   2.776 +		GB.Remove(POINTER(&THIS->oldindex),GB.Count(POINTER(THIS->oldindex))-1,1);
   2.777 +	}
   2.778 +
   2.779 +	GB.ReturnBoolean(false);
   2.780 +
   2.781 +END_METHOD
   2.782 +
   2.783 +/*****************************************************************************
   2.784 +
   2.785 + PDF pages
   2.786 +
   2.787 +******************************************************************************/
   2.788 +
   2.789 +BEGIN_PROPERTY (PDFPAGE_width)
   2.790 +
   2.791 +	if ( (THIS->rotation==90) || (THIS->rotation==270) ) 
   2.792 +		GB.ReturnInteger((int32_t)(THIS->page->getMediaHeight()*THIS->scale));
   2.793 +	else
   2.794 +		GB.ReturnInteger((int32_t)(THIS->page->getMediaWidth()*THIS->scale));
   2.795 +
   2.796 +END_PROPERTY
   2.797 +
   2.798 +BEGIN_PROPERTY (PDFPAGE_height)
   2.799 +
   2.800 +	if ( (THIS->rotation==90) || (THIS->rotation==270) )
   2.801 +		GB.ReturnInteger((int32_t)(THIS->page->getMediaWidth()*THIS->scale));
   2.802 +	else	
   2.803 +		GB.ReturnInteger((int32_t)(THIS->page->getMediaHeight()*THIS->scale));
   2.804 +
   2.805 +END_PROPERTY
   2.806 +
   2.807 +static uint32_t *get_page_data(CPDFDOCUMENT *_object, int32_t x, int32_t y, int32_t *width, int32_t *height, double scale, int32_t rotation)
   2.808 +{
   2.809 +	SplashBitmap *map;
   2.810 +	uint32_t *data;
   2.811 +	int32_t w, h;
   2.812 +	int32_t rw;
   2.813 +	int32_t rh;
   2.814 +
   2.815 +	if ( (THIS->rotation==90) || (THIS->rotation==270) )
   2.816 +	{
   2.817 +		rh=(int32_t)(THIS->page->getMediaWidth()*THIS->scale);
   2.818 +		rw=(int32_t)(THIS->page->getMediaHeight()*THIS->scale);
   2.819 +	}
   2.820 +	else
   2.821 +	{
   2.822 +		rw=(int32_t)(THIS->page->getMediaWidth()*THIS->scale);
   2.823 +		rh=(int32_t)(THIS->page->getMediaHeight()*THIS->scale);
   2.824 +	}
   2.825 +
   2.826 +	w = *width;
   2.827 +	h = *height;
   2.828 +
   2.829 +	if (w < 0) w = rw;
   2.830 +	if (h < 0) h = rh;
   2.831 +
   2.832 +	if (x<0) x=0;
   2.833 +	if (y<0) y=0;
   2.834 +	if (w<1) w=1;
   2.835 +	if (h<1) h=1;
   2.836 +
   2.837 +
   2.838 +	if ( (x+w) > rw ) w=rw-x;
   2.839 +	if ( (y+h) > rh ) h=rh-y;
   2.840 +
   2.841 +	if ( (w<0) || (h<0) ) return NULL;
   2.842 +
   2.843 +	#if POPPLER_VERSION_0_20
   2.844 +	THIS->page->displaySlice(THIS->dev,72.0*scale,72.0*scale,
   2.845 +			   rotation,
   2.846 +			   gFalse,
   2.847 +			   gTrue,
   2.848 +			   x,y,w,h,
   2.849 +			   gFalse);
   2.850 +	#else
   2.851 +	THIS->page->displaySlice(THIS->dev,72.0*scale,72.0*scale,
   2.852 +			   rotation,
   2.853 +			   gFalse,
   2.854 +			   gTrue,
   2.855 +			   x,y,w,h,
   2.856 +			   gFalse,
   2.857 +			   THIS->doc->getCatalog ());
   2.858 +	#endif
   2.859 +
   2.860 +	map=THIS->dev->getBitmap();
   2.861 +	
   2.862 +	data=(uint32_t*)map->getDataPtr();
   2.863 +
   2.864 +
   2.865 +	*width = w;
   2.866 +	*height = h;
   2.867 +
   2.868 +	return data;
   2.869 +}
   2.870 +
   2.871 +BEGIN_METHOD(PDFPAGE_image, GB_INTEGER x; GB_INTEGER y; GB_INTEGER w; GB_INTEGER h)
   2.872 +
   2.873 +	GB_IMAGE img = NULL;
   2.874 +	uint32_t *data;
   2.875 +	int32_t x,y, w, h;
   2.876 +
   2.877 +	x = VARGOPT(x, 0);
   2.878 +	y = VARGOPT(y, 0);
   2.879 +	w = VARGOPT(w, -1);
   2.880 +	h = VARGOPT(h, -1);
   2.881 +
   2.882 +	data = get_page_data(THIS, x, y, &w, &h, THIS->scale, THIS->rotation);
   2.883 +	if (!data) { GB.ReturnNull(); return; }
   2.884 +	GB.Image.Create(&img, data, w, h, GB_IMAGE_RGB);
   2.885 +	GB.ReturnObject(img);
   2.886 +
   2.887 +END_METHOD
   2.888 +
   2.889 +BEGIN_PROPERTY (PDFPAGE_property_image)
   2.890 +
   2.891 +	int32_t w=-1;
   2.892 +	int32_t h=-1;
   2.893 +	GB_IMAGE img = NULL;
   2.894 +	uint32_t *data;
   2.895 +
   2.896 +	data = get_page_data(THIS, 0, 0, &w, &h, THIS->scale, THIS->rotation);
   2.897 +	if (!data) { GB.ReturnNull(); return; }
   2.898 +	GB.Image.Create(&img, data, w, h, GB_IMAGE_RGB);
   2.899 +	GB.ReturnObject(img);
   2.900 +
   2.901 +END_PROPERTY
   2.902 +
   2.903 +
   2.904 +BEGIN_METHOD(PDFPAGE_picture, GB_INTEGER x; GB_INTEGER y; GB_INTEGER w; GB_INTEGER h)
   2.905 +
   2.906 +	GB_IMAGE img = NULL;
   2.907 +	uint32_t *data;
   2.908 +	int32_t x,y, w, h;
   2.909 +
   2.910 +	x = VARGOPT(x, 0);
   2.911 +	y = VARGOPT(y, 0);
   2.912 +	w = VARGOPT(w, -1);
   2.913 +	h = VARGOPT(h, -1);
   2.914 +
   2.915 +	data = get_page_data(THIS, x, y, &w, &h, THIS->scale, THIS->rotation);
   2.916 +	if (!data) { GB.ReturnNull(); return; }
   2.917 +	GB.Picture.Create(&img, data, w, h, GB_IMAGE_RGB);
   2.918 +	GB.ReturnObject(img);
   2.919 +
   2.920 +END_METHOD
   2.921 +
   2.922 +BEGIN_PROPERTY (PDFPAGE_property_picture)
   2.923 +
   2.924 +	int32_t w=-1;
   2.925 +	int32_t h=-1;
   2.926 +	GB_IMAGE img = NULL;
   2.927 +	uint32_t *data;
   2.928 +
   2.929 +	data = get_page_data(THIS, 0, 0, &w, &h, THIS->scale, THIS->rotation);
   2.930 +	if (!data) { GB.ReturnNull(); return; }
   2.931 +	GB.Picture.Create(&img, data, w, h, GB_IMAGE_RGB);
   2.932 +	GB.ReturnObject(img);
   2.933 +
   2.934 +END_PROPERTY
   2.935 +
   2.936 +BEGIN_METHOD(PDFPAGE_select, GB_INTEGER X; GB_INTEGER Y; GB_INTEGER W; GB_INTEGER H)
   2.937 +
   2.938 +	TextOutputDev *dev;
   2.939 +	GooString *str;
   2.940 +	Gfx *gfx;
   2.941 +	int32_t x,y,w,h;
   2.942 +
   2.943 +	x = VARGOPT(X, 0);
   2.944 +	y = VARGOPT(Y, 0);
   2.945 +	w = VARGOPT(W, (int32_t)THIS->page->getMediaWidth());
   2.946 +	h = VARGOPT(H, (int32_t)THIS->page->getMediaHeight());
   2.947 +
   2.948 +	#if POPPLER_VERSION_0_20
   2.949 +	dev = new TextOutputDev (NULL, gTrue, 0, gFalse, gFalse);
   2.950 +	gfx = THIS->page->createGfx(dev,72.0,72.0,0,gFalse,gTrue,-1, -1, -1, -1, gFalse, NULL, NULL);
   2.951 +	#else
   2.952 +	dev = new TextOutputDev (NULL, gTrue, gFalse, gFalse);
   2.953 +	gfx = THIS->page->createGfx(dev,72.0,72.0,0,gFalse,gTrue,-1, -1, -1, -1, \
   2.954 +                                gFalse,THIS->doc->getCatalog (),NULL, NULL, NULL, NULL);
   2.955 +	#endif
   2.956 +	
   2.957 +	THIS->page->display(gfx);
   2.958 +	dev->endPage();
   2.959 +
   2.960 +	str=dev->getText((double)x,(double)y,(double)(w+x),(double)(h+y));
   2.961 +
   2.962 +	delete gfx;
   2.963 +	delete dev;
   2.964 +
   2.965 +	if (!str)
   2.966 +	{
   2.967 +		GB.ReturnNewZeroString("");
   2.968 +		return;
   2.969 +	}
   2.970 +	
   2.971 +	GB.ReturnNewString(str->getCString(),str->getLength());	
   2.972 +	delete str;
   2.973 +
   2.974 +END_METHOD
   2.975 +
   2.976 +/*****************************************************************************
   2.977 +
   2.978 + Bookmarks of a PDF page
   2.979 +
   2.980 +******************************************************************************/
   2.981 +
   2.982 +void aux_fill_links(void *_object)
   2.983 +{
   2.984 +	#if POPPLER_VERSION_0_20
   2.985 +	THIS->links = new Links (THIS->page->getAnnots ());
   2.986 +	#elif POPPLER_VERSION_0_17
   2.987 +	THIS->links = new Links (THIS->page->getAnnots (THIS->doc->getCatalog()));
   2.988 +	#else
   2.989 +	Object obj;
   2.990 +	
   2.991 +	THIS->links = new Links (THIS->page->getAnnots (&obj),THIS->doc->getCatalog()->getBaseURI ());
   2.992 +	obj.free();
   2.993 +	#endif
   2.994 +}
   2.995 +
   2.996 +BEGIN_PROPERTY (PDFPAGELINKS_count)
   2.997 +
   2.998 +	if (!THIS->links) aux_fill_links(_object);
   2.999 +	if (!THIS->links) { GB.ReturnInteger(0); return; }
  2.1000 +	GB.ReturnInteger(THIS->links->getNumLinks());
  2.1001 +
  2.1002 +
  2.1003 +END_PROPERTY
  2.1004 +
  2.1005 +BEGIN_METHOD (PDFPAGELINKS_get,GB_INTEGER ind;)
  2.1006 +
  2.1007 +	bool pok=true;
  2.1008 +
  2.1009 +	if (!THIS->links) aux_fill_links(_object);
  2.1010 +	if (!THIS->links) pok=false;
  2.1011 +	else
  2.1012 +	{
  2.1013 +		if (VARG(ind)<0) pok=false;
  2.1014 +		else
  2.1015 +		{
  2.1016 +			if (VARG(ind)>=THIS->links->getNumLinks()) pok=false;
  2.1017 +		}
  2.1018 +	}
  2.1019 +
  2.1020 +	if (!pok) { GB.Error("Out of bounds"); GB.ReturnNull(); return; }
  2.1021 +
  2.1022 +	THIS->lcurrent=VARG(ind);
  2.1023 +	THIS->action=THIS->links->getLink(THIS->lcurrent)->getAction();
  2.1024 +
  2.1025 +	RETURN_SELF();
  2.1026 +
  2.1027 +END_METHOD
  2.1028 +
  2.1029 +BEGIN_PROPERTY (PDFPAGELINKDATA_parameters)
  2.1030 +
  2.1031 +	if (THIS->action->getKind() != actionLaunch )
  2.1032 +	{
  2.1033 +		GB.ReturnNewZeroString("");
  2.1034 +		return;	
  2.1035 +	}
  2.1036 +
  2.1037 +	GB.ReturnNewZeroString(((LinkLaunch*)THIS->action)->getParams()->getCString());
  2.1038 +
  2.1039 +END_PROPERTY
  2.1040 +
  2.1041 +BEGIN_PROPERTY (PDFPAGELINKDATA_uri)
  2.1042 +
  2.1043 +	char *uri;
  2.1044 +
  2.1045 +	uri=aux_get_target_from_action(THIS->action);
  2.1046 +
  2.1047 +	GB.ReturnNewZeroString(uri);
  2.1048 +	if (uri) GB.FreeString(&uri);
  2.1049 +
  2.1050 +END_PROPERTY
  2.1051 +
  2.1052 +BEGIN_PROPERTY(PDFPAGELINKDATA_left)
  2.1053 +
  2.1054 +	int32_t vl;
  2.1055 +
  2.1056 +	aux_get_dimensions_from_action(THIS->action,&vl, NULL, NULL, NULL);
  2.1057 +	GB.ReturnInteger(vl);
  2.1058 +
  2.1059 +END_PROPERTY
  2.1060 +
  2.1061 +BEGIN_PROPERTY(PDFPAGELINKDATA_right)
  2.1062 +
  2.1063 +	int32_t vl;
  2.1064 +
  2.1065 +	aux_get_dimensions_from_action(THIS->action,NULL,&vl, NULL, NULL);
  2.1066 +	GB.ReturnInteger(vl);
  2.1067 +
  2.1068 +END_PROPERTY
  2.1069 +
  2.1070 +BEGIN_PROPERTY(PDFPAGELINKDATA_top)
  2.1071 +
  2.1072 +	int32_t vl;
  2.1073 +
  2.1074 +	aux_get_dimensions_from_action(THIS->action,NULL,NULL,&vl, NULL);
  2.1075 +	GB.ReturnInteger(vl);
  2.1076 +
  2.1077 +END_PROPERTY
  2.1078 +
  2.1079 +BEGIN_PROPERTY(PDFPAGELINKDATA_bottom)
  2.1080 +
  2.1081 +	int32_t vl;
  2.1082 +
  2.1083 +	aux_get_dimensions_from_action(THIS->action,NULL, NULL, NULL,&vl);
  2.1084 +
  2.1085 +	GB.ReturnInteger(vl);
  2.1086 +
  2.1087 +END_PROPERTY
  2.1088 +
  2.1089 +BEGIN_PROPERTY(PDFPAGELINKDATA_zoom)
  2.1090 +
  2.1091 +	GB.ReturnFloat(aux_get_zoom_from_action(THIS->action));
  2.1092 +
  2.1093 +END_PROPERTY
  2.1094 +
  2.1095 +BEGIN_PROPERTY(PDFPAGELINKDATA_page)
  2.1096 +
  2.1097 +	GB.ReturnInteger(aux_get_page_from_action(_object,THIS->action));
  2.1098 +
  2.1099 +END_PROPERTY
  2.1100 +
  2.1101 +BEGIN_PROPERTY (PDFPAGELINKDATA_type)
  2.1102 +
  2.1103 +	GB.ReturnInteger ( (int32_t)THIS->action->getKind() );
  2.1104 +
  2.1105 +END_PROPERTY
  2.1106 +
  2.1107 +BEGIN_PROPERTY(PDFPAGELINKDATA_check)
  2.1108 +
  2.1109 +	if (THIS->action)
  2.1110 +		RETURN_SELF();
  2.1111 +	else
  2.1112 +		GB.ReturnNull();
  2.1113 +
  2.1114 +END_PROPERTY
  2.1115 +
  2.1116 +void aux_get_link_dimensions(void *_object,int32_t *left, int32_t *top, int32_t *width, int32_t *height)
  2.1117 +{
  2.1118 +	double l,t,w,h;
  2.1119 +	double pw,ph;
  2.1120 +
  2.1121 +	pw=THIS->page->getMediaWidth();	
  2.1122 +	ph=THIS->page->getMediaHeight();
  2.1123 +
  2.1124 +	THIS->links->getLink(THIS->lcurrent)->getRect(&l, &t, &w, &h);
  2.1125 +	w=w-l;
  2.1126 +	h=h-t;	
  2.1127 +
  2.1128 +	switch (THIS->rotation)
  2.1129 +	{
  2.1130 +		case 0:
  2.1131 +			if (left) *left=(int32_t)(l*THIS->scale);
  2.1132 +			if (top) *top=(int32_t)((ph-t-h)*THIS->scale);
  2.1133 +			if (width) *width=(int32_t)(w*THIS->scale);
  2.1134 +			if (height) *height=(int32_t)(h*THIS->scale);
  2.1135 +			break;
  2.1136 +	
  2.1137 +		case 90:
  2.1138 +			if (top) *top=(int32_t)(l*THIS->scale);
  2.1139 +			if (left) *left=(int32_t)(t*THIS->scale);
  2.1140 +			if (height) *height=(int32_t)(w*THIS->scale);
  2.1141 +			if (width) *width=(int32_t)(h*THIS->scale);
  2.1142 +			break;
  2.1143 +
  2.1144 +		case 180:
  2.1145 +			if (left) *left=(int32_t)((l-w)*THIS->scale);
  2.1146 +			if (top) *top=(int32_t)(t*THIS->scale);
  2.1147 +			if (width) *width=(int32_t)(w*THIS->scale);
  2.1148 +			if (height) *height=(int32_t)(h*THIS->scale);
  2.1149 +			break;
  2.1150 +
  2.1151 +		case 270:
  2.1152 +			if (top) *top=(int32_t)((pw-l-w)*THIS->scale);
  2.1153 +			if (left) *left=(int32_t)((ph-t-h)*THIS->scale);
  2.1154 +			if (height) *height=(int32_t)(w*THIS->scale);
  2.1155 +			if (width) *width=(int32_t)(h*THIS->scale);
  2.1156 +			break;
  2.1157 +	}
  2.1158 +
  2.1159 +}
  2.1160 +
  2.1161 +BEGIN_PROPERTY (PDFPAGELINK_width)
  2.1162 +
  2.1163 +	int32_t vl;
  2.1164 +	
  2.1165 +	aux_get_link_dimensions(_object,NULL,NULL,&vl,NULL);
  2.1166 +	GB.ReturnInteger(vl);
  2.1167 +
  2.1168 +END_PROPERTY
  2.1169 +
  2.1170 +BEGIN_PROPERTY (PDFPAGELINK_height)
  2.1171 +
  2.1172 +	int32_t vl;
  2.1173 +	
  2.1174 +	aux_get_link_dimensions(_object,NULL,NULL,NULL,&vl);
  2.1175 +	GB.ReturnInteger(vl);
  2.1176 +
  2.1177 +
  2.1178 +END_PROPERTY
  2.1179 +
  2.1180 +BEGIN_PROPERTY (PDFPAGELINK_left)
  2.1181 +
  2.1182 +	int32_t vl;
  2.1183 +	
  2.1184 +	aux_get_link_dimensions(_object,&vl,NULL,NULL,NULL);
  2.1185 +	GB.ReturnInteger(vl);
  2.1186 +	
  2.1187 +
  2.1188 +END_PROPERTY
  2.1189 +
  2.1190 +BEGIN_PROPERTY (PDFPAGELINK_top)
  2.1191 +
  2.1192 +	int32_t vl;
  2.1193 +	
  2.1194 +	aux_get_link_dimensions(_object,NULL,&vl,NULL,NULL);
  2.1195 +	GB.ReturnInteger(vl);
  2.1196 +
  2.1197 +END_PROPERTY
  2.1198 +
  2.1199 +/*****************************************************************************
  2.1200 +
  2.1201 + Finding a text in a PDF page
  2.1202 +
  2.1203 +******************************************************************************/
  2.1204 +
  2.1205 +BEGIN_METHOD (PDFPAGE_find,GB_STRING Text; GB_BOOLEAN Sensitive;)
  2.1206 +
  2.1207 +	TextOutputDev *textdev;
  2.1208 +	double x0=0, y0=0;
  2.1209 +	double x1, y1;
  2.1210 +	FoundRect *el;	
  2.1211 +	Unicode *block=NULL;
  2.1212 +	int32_t nlen=0;
  2.1213 +	bool sensitive=false;
  2.1214 +
  2.1215 +	// TODO: Use UCS-4BE on big endian systems?
  2.1216 +	if (GB.ConvString ((char **)(void *)&block,STRING(Text),LENGTH(Text),"UTF-8","UCS-4LE"))
  2.1217 +	{	
  2.1218 +		GB.Error("Invalid UTF-8 string"); 
  2.1219 +		return;
  2.1220 +	}
  2.1221 +
  2.1222 +	nlen=GB.StringLength((char*)block)/sizeof(Unicode);
  2.1223 +
  2.1224 +	if (!MISSING(Sensitive)) sensitive=VARG(Sensitive);
  2.1225 +
  2.1226 +	#if POPPLER_VERSION_0_20
  2.1227 +	textdev = new TextOutputDev (NULL, true, 0, false, false);
  2.1228 +	THIS->page->display (textdev, 72, 72, 0, false, false, false);
  2.1229 +	#else
  2.1230 +	textdev = new TextOutputDev (NULL, true, false, false);
  2.1231 +	THIS->page->display (textdev, 72, 72, 0, false, false, false, THIS->doc->getCatalog());
  2.1232 +	#endif
  2.1233 +
  2.1234 +	if (THIS->Found) { GB.FreeArray(POINTER(&THIS->Found)); THIS->Found=NULL; }
  2.1235 +
  2.1236 +	#if POPPLER_VERSION_0_20
  2.1237 +	while (textdev->findText (block,nlen,gFalse,gTrue,gTrue,gFalse,sensitive,gFalse,gFalse,&x0,&y0,&x1,&y1))
  2.1238 +	#else
  2.1239 +	while (textdev->findText (block,nlen,gFalse,gTrue,gTrue,gFalse,sensitive,gFalse,&x0,&y0,&x1,&y1))
  2.1240 +	#endif
  2.1241 +	{
  2.1242 +		if (!THIS->Found) {
  2.1243 +			GB.NewArray(POINTER(&THIS->Found),sizeof(FoundRect),1);
  2.1244 +		}		
  2.1245 +		else {
  2.1246 +			GB.Add(POINTER(&THIS->Found));
  2.1247 +		}
  2.1248 +
  2.1249 +		el=(FoundRect*)&((FoundRect*)THIS->Found)[GB.Count(POINTER(THIS->Found))-1];
  2.1250 +		
  2.1251 +		switch (THIS->rotation)
  2.1252 +		{
  2.1253 +			case 0:
  2.1254 +				el->x0=(int32_t)(x0*THIS->scale);
  2.1255 +				el->y0=(int32_t)(y0*THIS->scale);
  2.1256 +				el->x1=(int32_t)((x1-x0)*THIS->scale);
  2.1257 +				el->y1=(int32_t)((y1-y0)*THIS->scale);
  2.1258 +				break;
  2.1259 +
  2.1260 +			case 90:
  2.1261 +				el->y1=(int32_t)((x1-x0)*THIS->scale);
  2.1262 +				el->x1=(int32_t)(y1-y0);
  2.1263 +				el->y0=(int32_t)(x0*THIS->scale);
  2.1264 +				el->x0=(int32_t)((THIS->page->getMediaHeight()-y0-el->x1)*THIS->scale);
  2.1265 +				el->x1=(int32_t)(el->x1*THIS->scale);
  2.1266 +				break;
  2.1267 +
  2.1268 +			case 180:
  2.1269 +				el->x1=(int32_t)(x1-x0);
  2.1270 +				el->y1=(int32_t)(y1-y0);
  2.1271 +				el->x0=(int32_t)((THIS->page->getMediaWidth()-x0-el->x1)*THIS->scale);
  2.1272 +				el->y0=(int32_t)((THIS->page->getMediaHeight()-y0-el->y1)*THIS->scale);
  2.1273 +				el->x1=(int32_t)(el->x1*THIS->scale);
  2.1274 +				el->y1=(int32_t)(el->y1*THIS->scale);
  2.1275 +				break;
  2.1276 +
  2.1277 +			case 270:
  2.1278 +				el->x1=(int32_t)((y1-y0)*THIS->scale);
  2.1279 +				el->y1=(int32_t)(x1-x0);
  2.1280 +				el->x0=(int32_t)(y0*THIS->scale);
  2.1281 +				el->y0=(int32_t)((THIS->page->getMediaWidth()-x0-el->y1)*THIS->scale);
  2.1282 +				el->y1=(int32_t)(el->y1*THIS->scale);
  2.1283 +				break;
  2.1284 +
  2.1285 +		}
  2.1286 +	}
  2.1287 +
  2.1288 +	delete textdev;
  2.1289 +
  2.1290 +
  2.1291 +END_METHOD
  2.1292 +
  2.1293 +
  2.1294 +BEGIN_METHOD (PDFPAGERESULT_get,GB_INTEGER Index;)
  2.1295 +
  2.1296 +	bool bok=true;
  2.1297 +
  2.1298 +	if (!THIS->Found) bok=false;
  2.1299 +	else
  2.1300 +	{
  2.1301 +		if (VARG(Index)<0) bok=false;
  2.1302 +		if (VARG(Index)>= GB.Count(POINTER(THIS->Found)) ) bok=false;
  2.1303 +	}
  2.1304 +	if (!bok) { GB.Error("Out of bounds"); GB.ReturnNull(); return; }
  2.1305 +
  2.1306 +	THIS->fcurrent=VARG(Index);
  2.1307 +	RETURN_SELF();
  2.1308 +
  2.1309 +END_METHOD
  2.1310 +
  2.1311 +BEGIN_PROPERTY (PDFPAGERESULT_count)
  2.1312 +
  2.1313 +	if (!THIS->Found) { GB.ReturnInteger(0); return; } 
  2.1314 +	GB.ReturnInteger( GB.Count(POINTER(THIS->Found)) );
  2.1315 +
  2.1316 +END_PROPERTY
  2.1317 +
  2.1318 +BEGIN_PROPERTY (PDFPAGERESULT_width)
  2.1319 +
  2.1320 +	FoundRect *el=(FoundRect*)&((FoundRect*)THIS->Found)[THIS->fcurrent];
  2.1321 +	GB.ReturnInteger((int32_t)el->x1);
  2.1322 +
  2.1323 +END_PROPERTY
  2.1324 +
  2.1325 +BEGIN_PROPERTY (PDFPAGERESULT_height)
  2.1326 +
  2.1327 +	FoundRect *el=(FoundRect*)&((FoundRect*)THIS->Found)[THIS->fcurrent];
  2.1328 +	GB.ReturnInteger((int32_t)el->y1);
  2.1329 +
  2.1330 +END_PROPERTY
  2.1331 +
  2.1332 +BEGIN_PROPERTY (PDFPAGERESULT_left)
  2.1333 +
  2.1334 +	FoundRect *el=(FoundRect*)&((FoundRect*)THIS->Found)[THIS->fcurrent];
  2.1335 +	GB.ReturnInteger((int32_t)el->x0);
  2.1336 +
  2.1337 +END_PROPERTY
  2.1338 +
  2.1339 +BEGIN_PROPERTY (PDFPAGERESULT_top)
  2.1340 +
  2.1341 +	FoundRect *el=(FoundRect*)&((FoundRect*)THIS->Found)[THIS->fcurrent];
  2.1342 +	GB.ReturnInteger((int32_t)el->y0);
  2.1343 +
  2.1344 +END_PROPERTY
  2.1345 +
  2.1346 +/**********************************************************************
  2.1347 +
  2.1348 +Gambas Interface
  2.1349 +
  2.1350 +***********************************************************************/
  2.1351 +
  2.1352 +
  2.1353 +GB_DESC PdfResultItemDesc[]=
  2.1354 +{
  2.1355 +	GB_DECLARE(".PdfResultItem",0), GB_VIRTUAL_CLASS(),
  2.1356 +
  2.1357 +	GB_PROPERTY_READ("Left","i",PDFPAGERESULT_left),
  2.1358 +	GB_PROPERTY_READ("Top","i",PDFPAGERESULT_top),
  2.1359 +	GB_PROPERTY_READ("Width","i",PDFPAGERESULT_width),
  2.1360 +	GB_PROPERTY_READ("Height","i",PDFPAGERESULT_height),
  2.1361 +
  2.1362 +	GB_END_DECLARE
  2.1363 +};
  2.1364 +
  2.1365 +GB_DESC PdfResultDesc[]=
  2.1366 +{
  2.1367 +	GB_DECLARE(".PdfResult",0), GB_VIRTUAL_CLASS(),
  2.1368 +
  2.1369 +	GB_METHOD("_get",".PdfResultItem",PDFPAGERESULT_get,"(Index)i"),
  2.1370 +	GB_PROPERTY_READ("Count","i",PDFPAGERESULT_count),
  2.1371 +
  2.1372 +	GB_END_DECLARE
  2.1373 +};
  2.1374 +
  2.1375 +
  2.1376 +GB_DESC PdfLinkDataDesc[]=
  2.1377 +{
  2.1378 +	GB_DECLARE(".PdfLinkData",0), GB_VIRTUAL_CLASS(),
  2.1379 +
  2.1380 +	GB_PROPERTY_READ("Type","i",PDFPAGELINKDATA_type),
  2.1381 +	GB_PROPERTY_READ("Target","s",PDFPAGELINKDATA_uri),
  2.1382 +	GB_PROPERTY_READ("Parameters","s",PDFPAGELINKDATA_parameters),
  2.1383 +	GB_PROPERTY_READ("Page","i",PDFPAGELINKDATA_page),
  2.1384 +	GB_PROPERTY_READ("Left","i",PDFPAGELINKDATA_left),
  2.1385 +	GB_PROPERTY_READ("Top","i",PDFPAGELINKDATA_top),
  2.1386 +	GB_PROPERTY_READ("Right","i",PDFPAGELINKDATA_right),
  2.1387 +	GB_PROPERTY_READ("Bottom","i",PDFPAGELINKDATA_bottom),
  2.1388 +	GB_PROPERTY_READ("Zoom","f",PDFPAGELINKDATA_zoom),
  2.1389 +
  2.1390 +	GB_END_DECLARE
  2.1391 +};
  2.1392 +
  2.1393 +GB_DESC PdfLinkDesc[]=
  2.1394 +{
  2.1395 +	GB_DECLARE(".PdfLink",0), GB_VIRTUAL_CLASS(),
  2.1396 +
  2.1397 +	GB_PROPERTY_READ("Left","i",PDFPAGELINK_left),
  2.1398 +	GB_PROPERTY_READ("Top","i",PDFPAGELINK_top),
  2.1399 +	GB_PROPERTY_READ("Width","i",PDFPAGELINK_width),
  2.1400 +	GB_PROPERTY_READ("Height","i",PDFPAGELINK_height),
  2.1401 +	GB_PROPERTY_READ("Data", ".PdfLinkData", PDFPAGELINKDATA_check),
  2.1402 +
  2.1403 +	GB_END_DECLARE
  2.1404 +};
  2.1405 +
  2.1406 +GB_DESC PdfIndexDesc[]=
  2.1407 +{
  2.1408 +	GB_DECLARE(".PdfIndex",0), GB_VIRTUAL_CLASS(),
  2.1409 +
  2.1410 +	GB_PROPERTY("Expanded","b",PDFINDEX_is_open),
  2.1411 +	GB_PROPERTY_READ("Count","i",PDFINDEX_count),
  2.1412 +	GB_PROPERTY_READ("HasChildren","b",PDFINDEX_has_children),
  2.1413 +	GB_PROPERTY_READ("Title","s",PDFINDEX_title),
  2.1414 +
  2.1415 +	GB_PROPERTY_READ("Data", ".PdfLinkData", PDFPAGELINKDATA_check),
  2.1416 +	GB_METHOD("MovePrevious","b",PDFINDEX_prev,0),
  2.1417 +	GB_METHOD("MoveNext","b",PDFINDEX_next,0),
  2.1418 +	GB_METHOD("MoveChild","b",PDFINDEX_child,0),
  2.1419 +	GB_METHOD("MoveParent","b",PDFINDEX_parent,0),
  2.1420 +	GB_METHOD("MoveRoot",0,PDFINDEX_root,0),
  2.1421 +
  2.1422 +	GB_END_DECLARE
  2.1423 +};
  2.1424 +
  2.1425 +
  2.1426 +GB_DESC PdfPageDesc[]=
  2.1427 +{
  2.1428 +	GB_DECLARE(".PdfPage",0), GB_VIRTUAL_CLASS(),
  2.1429 +
  2.1430 +	GB_PROPERTY_READ("W","f",PDFPAGE_width),
  2.1431 +	GB_PROPERTY_READ("H","f",PDFPAGE_height),
  2.1432 +	GB_PROPERTY_READ("Width","f",PDFPAGE_width),
  2.1433 +	GB_PROPERTY_READ("Height","f",PDFPAGE_height),
  2.1434 +	GB_PROPERTY_READ("Picture","Picture",PDFPAGE_property_picture),
  2.1435 +	GB_PROPERTY_READ("Image","Image",PDFPAGE_property_image),
  2.1436 +	GB_PROPERTY_SELF("Result",".PdfResult"),
  2.1437 +
  2.1438 +	GB_METHOD("GetImage","Image",PDFPAGE_image,"[(X)i(Y)i(Width)i(Height)i]"),
  2.1439 +	GB_METHOD("GetPicture","Picture",PDFPAGE_picture,"[(X)i(Y)i(Width)i(Height)i]"),
  2.1440 +	GB_METHOD("Find","b",PDFPAGE_find,"(Text)s[(CaseSensitive)b]"),
  2.1441 +	GB_METHOD("Select","s",PDFPAGE_select,"[(X)i(Y)i(W)i(H)i]"),
  2.1442 +
  2.1443 +	GB_METHOD("_get",".PdfLink",PDFPAGELINKS_get,"(Index)i"),
  2.1444 +	GB_PROPERTY_READ("Count","i",PDFPAGELINKS_count),
  2.1445 +
  2.1446 +	GB_END_DECLARE
  2.1447 +};
  2.1448 +
  2.1449 +GB_DESC PdfDocumentInfo[] =
  2.1450 +{
  2.1451 +	GB_DECLARE(".PdfInfo",0), GB_VIRTUAL_CLASS(),
  2.1452 +
  2.1453 +	GB_PROPERTY_READ("Title","s",PDFINFO_title),
  2.1454 +	GB_PROPERTY_READ("Format","s",PDFINFO_format),
  2.1455 +	GB_PROPERTY_READ("Author","s",PDFINFO_author),
  2.1456 +	GB_PROPERTY_READ("Subject","s",PDFINFO_subject),
  2.1457 +	GB_PROPERTY_READ("Keywords","s",PDFINFO_keywords),
  2.1458 +	GB_PROPERTY_READ("Creator","s",PDFINFO_creator),
  2.1459 +	GB_PROPERTY_READ("Producer","s",PDFINFO_producer),
  2.1460 +	GB_PROPERTY_READ("CreationDate","d",PDFINFO_creation),
  2.1461 +	GB_PROPERTY_READ("ModificationDate","d",PDFINFO_modification),
  2.1462 +	GB_PROPERTY_READ("Linearized","b",PDFINFO_linearized),
  2.1463 +	GB_PROPERTY_READ("Layout","i",PDFINFO_layout),
  2.1464 +	GB_PROPERTY_READ("Mode","i",PDFINFO_mode),
  2.1465 +	GB_PROPERTY_READ("CanCopy","b",PDFINFO_cancopy),
  2.1466 +	GB_PROPERTY_READ("CanModify","b",PDFINFO_canmodify),
  2.1467 +	GB_PROPERTY_READ("CanPrint","b",PDFINFO_canprint),
  2.1468 +	GB_PROPERTY_READ("CanAddNotes","b",PDFINFO_canaddnotes),
  2.1469 +
  2.1470 +	GB_END_DECLARE
  2.1471 +};
  2.1472 +
  2.1473 +GB_DESC PdfLayoutDesc[] =
  2.1474 +{
  2.1475 +
  2.1476 +  GB_DECLARE("PdfLayout", 0), GB_NOT_CREATABLE(),
  2.1477 +
  2.1478 +  GB_CONSTANT("Unset","i",Catalog::pageLayoutNone),
  2.1479 +  GB_CONSTANT("SinglePage","i",Catalog::pageLayoutSinglePage),
  2.1480 +  GB_CONSTANT("OneColumn","i",Catalog::pageLayoutOneColumn),
  2.1481 +  GB_CONSTANT("TwoColumnLeft","i",Catalog::pageLayoutTwoColumnLeft),
  2.1482 +  GB_CONSTANT("TwoColumnRight","i",Catalog::pageLayoutTwoColumnRight),
  2.1483 +  GB_CONSTANT("TwoPageLeft","i",Catalog::pageLayoutTwoPageLeft),
  2.1484 +  GB_CONSTANT("TwoPageRight","i",Catalog::pageLayoutTwoPageRight),
  2.1485 +
  2.1486 +  GB_END_DECLARE
  2.1487 +};
  2.1488 +
  2.1489 +
  2.1490 +GB_DESC PdfModeDesc[] =
  2.1491 +{
  2.1492 +	GB_DECLARE("PdfPageMode",0), GB_NOT_CREATABLE(),
  2.1493 +
  2.1494 +	GB_CONSTANT("Unset","i",Catalog::pageModeNone),
  2.1495 +	GB_CONSTANT("UseOutlines","i",Catalog::pageModeOutlines),
  2.1496 +	GB_CONSTANT("UseThumbs","i",Catalog::pageModeThumbs),
  2.1497 +	GB_CONSTANT("FullScreen","i",Catalog::pageModeFullScreen),
  2.1498 +	GB_CONSTANT("UseOC","i",Catalog::pageModeOC),
  2.1499 +	GB_CONSTANT("UseAttachments","i",Catalog::pageModeAttach),
  2.1500 +
  2.1501 +	GB_END_DECLARE
  2.1502 +};
  2.1503 +
  2.1504 +GB_DESC PdfDocumentDesc[] =
  2.1505 +{
  2.1506 +
  2.1507 +  GB_DECLARE("PdfDocument", sizeof(CPDFDOCUMENT)),
  2.1508 +
  2.1509 +  GB_CONSTANT("Unknown","i",actionUnknown),  /* unknown action */
  2.1510 +  GB_CONSTANT("Goto","i",actionGoTo),        /* go to destination */
  2.1511 +  GB_CONSTANT("GotoRemote","i",actionGoToR), /* go to destination in new file */
  2.1512 +  GB_CONSTANT("Launch","i",actionLaunch),    /* launch app or open doc. */
  2.1513 +  GB_CONSTANT("Uri","i",actionURI),          /* URI */
  2.1514 +  GB_CONSTANT("Named","i",actionNamed),      /* named action*/
  2.1515 +  GB_CONSTANT("Movie","i",actionMovie),      /* movie action */
  2.1516 +
  2.1517 +  GB_CONSTANT("Normal","i",0),
  2.1518 +  GB_CONSTANT("Sideways","i",90),
  2.1519 +  GB_CONSTANT("Inverted","i",180),
  2.1520 +  GB_CONSTANT("SidewaysInverted","i",270),
  2.1521 +
  2.1522 +  GB_METHOD("_new", 0, PDFDOCUMENT_new, "[(File)s]"),
  2.1523 +  GB_METHOD("_free", 0, PDFDOCUMENT_free, 0),
  2.1524 +
  2.1525 +  GB_METHOD("Open",0,PDFDOCUMENT_open,"(File)s"),
  2.1526 +  GB_METHOD("Close",0,PDFDOCUMENT_close,0),
  2.1527 +  GB_METHOD("_get",".PdfPage",PDFDOCUMENT_get,"(Index)i"),
  2.1528 +
  2.1529 +  GB_PROPERTY("Zoom", "f", PDFDOCUMENT_scale),
  2.1530 +  GB_PROPERTY("Orientation", "i", PDFDOCUMENT_rotation),
  2.1531 +
  2.1532 +  GB_PROPERTY_READ("Ready","b",PDFDOCUMENT_ready),
  2.1533 +  GB_PROPERTY_READ("Count","i",PDFDOCUMENT_count),
  2.1534 +  GB_PROPERTY_READ("HasIndex","b",PDFDOCUMENT_has_index),
  2.1535 +  GB_PROPERTY_READ("Index",".PdfIndex",PDFDOCUMENT_index),
  2.1536 +  GB_PROPERTY_READ("Info",".PdfInfo",PDFDOCUMENT_info),
  2.1537 +
  2.1538 +  GB_END_DECLARE
  2.1539 +};
  2.1540 +
  2.1541 +