Changeset 515


Ignore:
Timestamp:
Sep 7, 2012, 8:38:55 AM (9 years ago)
Author:
Silvan Scherrer
Message:

updated poppler to 0.20.3

Location:
trunk
Files:
2 added
2 deleted
182 edited

Legend:

Unmodified
Added
Removed
  • trunk/Lucide/changelog

    r507 r515  
     11.3.5:
     2  - updated poppler to 0.20.3
     3  - fixed a wpi problem (ticket #244)
     4  - updated cs language file (ticket #243)
     5
     6
    171.3.4:
    28  - WPI: added a check, so also rpm installations work w/o installing the req wpi
  • trunk/Lucide/lng/Lucide.lng

    r509 r515  
    11#
    2 # Lucide language file, EN (1.3.4)
     2# Lucide language file, EN (1.3.5)
    33#
    44
     
    167167AD_ABOUT=About
    168168AD_DESCRIPTION=Plugin-based document viewer with support for various file formats
    169 AD_COPYRIGHTS=(c) Eugene Romanenko, Dmitriy Kuminov, Silvan Scherrer (netlabs.org) in co-operation with Serenity Systems International
     169AD_COPYRIGHTS=(c) Eugene Romanenko, Dmitriy Kuminov, Silvan Scherrer, bww bitwise works GmbH in co-operation with Mensys
    170170AD_OK=~OK
    171171
  • trunk/Lucide/lng/Lucide_da.lng

    r509 r515  
    11#
    2 # Lucide language file, DK (1.3.4)
     2# Lucide language file, DK (1.3.5)
    33#
    44
     
    164164AD_ABOUT=Om
    165165AD_DESCRIPTION=Plugin-baseret dokument fremviser med underst›ttelse for mange forskellige formater
    166 AD_COPYRIGHTS=(c) Eugene Romanenko, Dmitriy Kuminov, Silvan Scherrer (netlabs.org) in co-operation with Serenity Systems International
     166AD_COPYRIGHTS=(c) Eugene Romanenko, Dmitriy Kuminov, Silvan Scherrer, bww bitwise works GmbH in co-operation with Mensys
    167167AD_OK=~OK
    168168
  • trunk/Lucide/lng/Lucide_de.lng

    r509 r515  
    11#
    2 # Lucide language file, DE (1.3.4)
     2# Lucide language file, DE (1.3.5)
    33#
    44
     
    167167AD_ABOUT=šber
    168168AD_DESCRIPTION=Plugin-basierter Dokumentbetrachter fr zahlreiche Dateiformate
    169 AD_COPYRIGHTS=(c) Eugene Romanenko, Dmitriy Kuminov, Silvan Scherrer (netlabs.org) in Zusammenarbeit mit Serenity Systems International
     169AD_COPYRIGHTS=(c) Eugene Romanenko, Dmitriy Kuminov, Silvan Scherrer, bww bitwise works GmbH in Zusammenarbeit mit Mensys
    170170AD_OK=~OK
    171171
  • trunk/Lucide/lng/Lucide_es.lng

    r509 r515  
    11#
    2 # Lucide language file, ES (1.3.4)
     2# Lucide language file, ES (1.3.5)
    33#
    44
     
    167167AD_ABOUT=Acerca de
    168168AD_DESCRIPTION=Visor de documentos con arquitectura de plugins y soporte para varios formatos de archivo
    169 AD_COPYRIGHTS=(c) Eugene Romanenko, Dmitriy Kuminov, Silvan Scherrer (netlabs.org) en colaboraci¢n con Serenity Systems International
     169AD_COPYRIGHTS=(c) Eugene Romanenko, Dmitriy Kuminov, Silvan Scherrer, bww bitwise works GmbH en colaboraci¢n con Mensys
    170170AD_OK=~Bien
    171171
  • trunk/Lucide/lng/Lucide_fr.lng

    r509 r515  
    11#
    2 # Lucide language file, FR (1.3.4)
     2# Lucide language file, FR (1.3.5)
    33# Fichier de langue de Lucide, FR (1.3.3)
    44# 2010-10-??
     
    182182AD_ABOUT=Informations sur le produit
    183183AD_DESCRIPTION=Afficheur de documents bas‚ sur des composants enfichables prenant en charge divers formats de fichiers
    184 AD_COPYRIGHTS=(c) par Eugene Romanenko, Dmitriy Kuminov, Silvan Scherrer (netlabs.org) en coop‚ration avec Serenity Systems International
     184AD_COPYRIGHTS=(c) par Eugene Romanenko, Dmitriy Kuminov, Silvan Scherrer, bww bitwise works GmbH en coop‚ration avec Mensys
    185185AD_OK=~OK
    186186
  • trunk/Lucide/lng/Lucide_it.lng

    r509 r515  
    11#
    2 # Lucide language file, IT (1.3.4)
     2# Lucide language file, IT (1.3.5)
    33#
    44
     
    165165AD_ABOUT=Informazioni sul prodotto
    166166AD_DESCRIPTION=Visualizzatore di documenti basato su plugin, con supporto per molteplici formati di file
    167 AD_COPYRIGHTS=(c) Eugene Romanenko, Dmitriy Kuminov, Silvan Scherrer (netlabs.org) in cooperazione con Serenity Systems International
     167AD_COPYRIGHTS=(c) Eugene Romanenko, Dmitriy Kuminov, Silvan Scherrer, bww bitwise works GmbH in cooperazione con Mensys
    168168AD_OK=~OK
    169169
  • trunk/Lucide/lng/Lucide_nl.lng

    r509 r515  
    11#
    2 # Lucide language file, NL (1.3.4)
     2# Lucide language file, NL (1.3.5)
    33#
    44
     
    167167AD_ABOUT=Info
    168168AD_DESCRIPTION=Op plug-ins gebaseerde document bekijker met ondersteuning voor diverse bestandsindelingen
    169 AD_COPYRIGHTS=(c) Eugene Romanenko, Dmitriy Kuminov, Silvan Scherrer (netlabs.org) in samenwerking met Serenity Systems International
     169AD_COPYRIGHTS=(c) Eugene Romanenko, Dmitriy Kuminov, Silvan Scherrer, bww bitwise works GmbH in samenwerking met Mensys
    170170AD_OK=~OK
    171171
  • trunk/Lucide/lng/Lucide_ru.lng

    r510 r515  
    11#
    2 # Lucide language file, RU (1.3.3)
     2# Lucide language file, RU (1.3.5)
    33#
    44
     
    167167AD_DESCRIPTION=à®á¬®âà險 €®ªã¬¥­â®¢ à §«šç­ëå ä®à¬ â®¢ á ¯®€€¥àŠª®© ¬¥å ­š§¬  ¯« £š­®¢
    168168AD_COPYRIGHTS=(c)
    169 ¢£¥­š© ®¬ ­¥­ª®, „¬šâàš© Šã¬š­®¢, ‘š«ì¢ ­ ˜¥àà¥à (netlabs.org) ¯àš á®âà〭šç¥á⢥ á Serenity Systems International
     169¢£¥­š© ®¬ ­¥­ª®, „¬šâàš© Šã¬š­®¢, ‘š«ì¢ ­ ˜¥àà¥à, bww bitwise works GmbH ¯àš á®âà〭šç¥á⢥ á Mensys
    170170AD_OK=~ŽŠ
    171171
  • trunk/Lucide/lng/Lucide_sv.lng

    r509 r515  
    11#
    2 # Lucide language file, SV (1.3.4)
     2# Lucide language file, SV (1.3.5)
    33#
    44
     
    152152AD_ABOUT=Om
    153153AD_DESCRIPTION=Plugin-baserad dokumentvisare med st”d f”r diverse filformat
    154 AD_COPYRIGHTS=(c) Eugene Romanenko, Dmitriy Kuminov, Silvan Scherrer (netlabs.org) i samarbete med Serenity Systems International
     154AD_COPYRIGHTS=(c) Eugene Romanenko, Dmitriy Kuminov, Silvan Scherrer, bww bitwise works GmbH i samarbete med Mensys
    155155AD_OK=OK
    156156
  • trunk/Lucide/lng/Lucide_zh_TW.lng

    r435 r515  
    134134AD_ABOUT=Ãö©ó
    135135AD_DESCRIPTION=Plugin-based document viewer with support for various file formats
     136AD_COPYRIGHTS=(c) Eugene Romanenko, Dmitriy Kuminov, Silvan Scherrer, bww bitwise works GmbH in co-operation with Mensys
    136137AD_OK=~OK
    137138
  • trunk/Lucide/lng/lucide_cs_cz.lng

    r509 r515  
    11#
    2 # Lucide language file, CS (1.3.4)
     2# Lucide language file, CS (1.3.5)
    33#
    44
     
    178178zn‚ form ty soubor
    179179
    180 AD_COPYRIGHTS=(c) Eugene Romanenko, Dmitriy Kuminov, Silvan Scherrer (netlabs.org) ve spolupr ci se Serenity Systems International
     180AD_COPYRIGHTS=(c) Eugene Romanenko, Dmitriy Kuminov, Silvan Scherrer, bww bitwise works GmbH ve spolupr ci se Mensys
    181181AD_OK=~OK
    182182
  • trunk/Lucide/plugins/lupoppler/lupoppler.cpp

    r497 r515  
    352352                src_x, src_y,
    353353                src_width, src_height,
    354                 gFalse, /* printing (allow links) */
    355                 document->doc->getCatalog() );
     354                gFalse /* printing (allow links) */ );
    356355
    357356    DosReleaseMutexSem( document->mutex );
     
    456455                src_width, src_height,
    457456                NULL, /* links */
    458                 document->doc->getCatalog(),
    459457                abortCheckCbk, &acd );
    460458    DosReleaseMutexSem( document->mutex );
     
    470468    {
    471469        DosRequestMutexSem( document->mutex, SEM_INDEFINITE_WAIT );
    472         page->text_dev = new TextOutputDev( NULL, gTrue, gFalse, gFalse );
     470        page->text_dev = new TextOutputDev( NULL, gTrue, 0, gFalse, gFalse );
    473471
    474472        page->gfx = page->page->createGfx(page->text_dev,
     
    477475                          gTrue, /* Crop */
    478476                          -1, -1, -1, -1,
    479                           NULL, /* links */
    480                           document->doc->getCatalog(),
    481                           NULL, NULL, NULL, NULL);
     477                          NULL, /* printing */
     478                          NULL, NULL);
    482479
    483480        page->page->display( page->gfx );
     
    719716    PopplerPage *page = &( document->pages[ pagenum ] );
    720717
    721     Links *links = new Links( page->page->getAnnots(document->doc->getCatalog()) );
     718    Links *links = new Links( page->page->getAnnots() );
    722719
    723720    if ( links == NULL ) {  // No links, return empty LuLinkMapSequence
     
    805802    PDFDoc *doc = ((PopplerDocument *)somThis->data)->doc;
    806803
    807     PSOutputDev *out = new PSOutputDev( filename, doc, doc->getXRef(), doc->getCatalog(), NULL,
     804    PSOutputDev *out = new PSOutputDev( filename, doc, NULL,
    808805                                (first_page <= last_page) ? (first_page + 1) : (last_page + 1),
    809806                                (first_page <= last_page) ? (last_page + 1) : (first_page + 1),
     
    13421339
    13431340    DosRequestMutexSem( document->mutex, SEM_INDEFINITE_WAIT );
    1344     TextOutputDev *output_dev = new TextOutputDev( NULL, gTrue, gFalse, gFalse );
     1341    TextOutputDev *output_dev = new TextOutputDev( NULL, gTrue, 0, gFalse, gFalse );
    13451342    page->display( output_dev, 72, 72, 0, gFalse,
    1346                    gTrue, NULL, document->doc->getCatalog() );
     1343                   gTrue, NULL );
    13471344    DosReleaseMutexSem( document->mutex );
    13481345
     
    13791376                   gTrue, gFalse, // startAtLast, stopAtLast
    13801377                   caseSensitive, gFalse, // caseSensitive, backwards
     1378                   gFalse, //whole word
    13811379                   &xMin, &yMin, &xMax, &yMax ) )
    13821380    {
     
    14361434    for (int i = 0; i < doc->doc->getNumPages(); ++i) {
    14371435        Page *page = doc->pages[ i ].page;
    1438         FormPageWidgets *widgets = page->getFormWidgets(doc->doc->getCatalog());
     1436        FormPageWidgets *widgets = page->getFormWidgets();
    14391437        if (widgets == NULL || widgets->getNumWidgets() > 0)
    14401438            return TRUE;
     
    14531451    Page *page = doc->pages[ pagenum ].page;
    14541452
    1455     FormPageWidgets *widgets = page->getFormWidgets(doc->doc->getCatalog());
     1453    FormPageWidgets *widgets = page->getFormWidgets();
    14561454
    14571455    LuDocument_LuInputFieldSequence *fields = (LuDocument_LuInputFieldSequence *)
     
    16061604    white[2] = 255;
    16071605    document->output_dev = new SplashOutputDev( splashModeXBGR8, 4, gFalse, white );
    1608     document->output_dev->startDoc( document->doc->getXRef() );
     1606    document->output_dev->startDoc( document->doc );
    16091607
    16101608    long numpages = document->doc->getNumPages();
  • trunk/poppler/mypoppler/Makefile.kmk

    r493 r515  
    3030fofi_TEMPLATE   = PopplerLib
    3131fofi_SOURCES    = $(wildcard $(fofi_DEFPATH)/fofi/*.cc)
     32fofi_INCS       = poppler
    3233
    3334goo_TEMPLATE    = PopplerLib
    34 goo_INCS                = ../../libjpeg
     35goo_INCS                = poppler ../../libjpeg
    3536goo_SOURCES             = $(wildcard $(goo_DEFPATH)/goo/*.cc)
    3637
    3738splash_TEMPLATE = PopplerLib
    38 splash_INCS             = ../freetype2/include ../../libjpeg
     39splash_INCS             = poppler ../freetype2/include ../../libjpeg
    3940splash_SOURCES  = $(wildcard $(splash_DEFPATH)/splash/*.cc)
    4041
     
    4243poppler_INCS            = goo poppler ../fc-emulate-os2 ../../libjpeg
    4344poppler_SOURCES         = $(filter-out \
    44         $(addprefix $(poppler_DEFPATH)/poppler/,                                  \
    45                 ABWOutputDev.cc                                                       \
    46                 ArthurOutputDev.cc                                                    \
    47                 CairoFontEngine.cc                                                    \
    48                 CairoOutputDev.cc                                                     \
    49                 FlateStream.cc                                                        \
    50                 GlobalParamsWin.cc                                                    \
    51                 JPEG2000Stream.cc)                                                    \
     45        $(addprefix $(poppler_DEFPATH)/poppler/, \
     46                ArthurOutputDev.cc \
     47                CairoFontEngine.cc \
     48                CairoOutputDev.cc \
     49                FlateStream.cc \
     50                GlobalParamsWin.cc \
     51                JPEG2000Stream.cc) \
    5252        ,$(wildcard $(poppler_DEFPATH)/poppler/*.cc))
    5353
  • trunk/poppler/mypoppler/_lucide.readme

    r462 r515  
    11please always change this to the newest version
    22
    3 lucide is based on poppler 0.14.2
     3lucide is based on poppler 0.20.3
  • trunk/poppler/mypoppler/config.h

    r497 r515  
    1515
    1616/* Build against libpng. */
    17 /* #undef ENABLE_LIBPNG */
     17// #define ENABLE_LIBPNG 1
    1818
    1919/* Build against libtiff. */
    20 /* #undef ENABLE_LIBTIFF */
     20// #define ENABLE_LIBTIFF 1
    2121
    2222/* Do not hardcode the library location */
     
    6363#define HAVE_INTTYPES_H 1
    6464
    65 /* Define to 1 if you have the `openjpeg' library (-lopenjpeg). */
    66 /* #undef HAVE_LIBOPENJPEG */
    67 
    6865/* Define to 1 if you have the `tiff' library (-ltiff). */
    6966/* #undef HAVE_LIBTIFF */
     
    129126
    130127/* Define to 1 if you have the <tiffio.h> header file. */
    131 /* #undef HAVE_TIFFIO_H */
     128#define HAVE_TIFFIO_H 1
    132129
    133130/* Define to 1 if you have the <unistd.h> header file. */
     
    160157
    161158/* Define to the full name and version of this package. */
    162 #define PACKAGE_STRING "poppler 0.18.1"
     159#define PACKAGE_STRING "poppler 0.20.3"
    163160
    164161/* Define to the one symbol short name of this package. */
     
    169166
    170167/* Define to the version of this package. */
    171 #define PACKAGE_VERSION "0.18.1"
     168#define PACKAGE_VERSION "0.20.3"
    172169
    173170/* Poppler data dir */
    174 #define POPPLER_DATADIR "/@unixroot/usr/local/share/poppler"
     171#define POPPLER_DATADIR "/usr/local/share/poppler"
    175172
    176173/* Support for curl based doc builder is compiled in. */
    177174/* #undef POPPLER_HAS_CURL_SUPPORT */
    178175
     176/* Defines the poppler version */
     177#define POPPLER_VERSION "0.20.3"
     178
    179179/* Define to necessary symbol if this constant uses a non-standard name on
    180180   your system. */
    181 #define PTHREAD_CREATE_JOINABLE unknown
     181/* #undef PTHREAD_CREATE_JOINABLE */
    182182
    183183/* Define to 1 if you have the ANSI C header files. */
     
    188188
    189189/* Defines if use cms */
    190 //#define USE_CMS 1
     190// #define USE_CMS 1
    191191
    192192/* Use fixed point arithmetic in the Splash backend */
     
    196196/* #undef USE_FLOAT */
    197197
     198/* Defines if use lcms1 */
     199// #define USE_LCMS1 1
     200
    198201/* Version number of package */
    199 #define VERSION "0.18.1"
     202#define VERSION "0.20.3"
    200203
    201204/* Use fontconfig font configuration backend */
     
    204207/* Use win32 font configuration backend */
    205208/* #undef WITH_FONTCONFIGURATION_WIN32 */
     209
     210/* OpenJPEG with the OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG flag. */
     211/* #undef WITH_OPENJPEG_IGNORE_PCLR_CMAP_CDEF_FLAG */
    206212
    207213/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
  • trunk/poppler/mypoppler/fofi/FoFiBase.cc

    r497 r515  
    2929
    3030#include <stdio.h>
     31#include <limits.h>
    3132#include "goo/gmem.h"
    3233#include "poppler/Error.h"
     
    5556
    5657  if (!(f = fopen(fileName, "rb"))) {
    57     error(-1, "Cannot open '%s'", fileName);
     58    error(errIO, -1, "Cannot open '{0:s}'", fileName);
    5859    return NULL;
    5960  }
    6061  if (fseek(f, 0, SEEK_END) != 0) {
    61     error(-1, "Cannot seek to end of '%s'", fileName);
     62    error(errIO, -1, "Cannot seek to end of '{0:s}'", fileName);
    6263    fclose(f);
    6364    return NULL;
     
    6566  n = (int)ftell(f);
    6667  if (n < 0) {
    67     error(-1, "Cannot determine length of '%s'", fileName);
     68    error(errIO, -1, "Cannot determine length of '{0:s}'", fileName);
    6869    fclose(f);
    6970    return NULL;
    7071  }
    7172  if (fseek(f, 0, SEEK_SET) != 0) {
    72     error(-1, "Cannot seek to start of '%s'", fileName);
     73    error(errIO, -1, "Cannot seek to start of '{0:s}'", fileName);
    7374    fclose(f);
    7475    return NULL;
     
    110111  int x;
    111112
    112   if (pos < 0 || pos+1 >= len) {
     113  if (pos < 0 || pos+1 >= len || pos > INT_MAX - 1) {
    113114    *ok = gFalse;
    114115    return 0;
     
    125126  int x;
    126127
    127   if (pos < 0 || pos+1 >= len) {
     128  if (pos < 0 || pos+1 >= len || pos > INT_MAX - 1) {
    128129    *ok = gFalse;
    129130    return 0;
     
    137138  int x;
    138139
    139   if (pos < 0 || pos+3 >= len) {
     140  if (pos < 0 || pos+3 >= len || pos > INT_MAX - 3) {
    140141    *ok = gFalse;
    141142    return 0;
     
    154155  Guint x;
    155156
    156   if (pos < 0 || pos+3 >= len) {
     157  if (pos < 0 || pos+3 >= len || pos > INT_MAX - 3) {
    157158    *ok = gFalse;
    158159    return 0;
     
    162163  x = (x << 8) + file[pos+2];
    163164  x = (x << 8) + file[pos+3];
     165  return x;
     166}
     167
     168Guint FoFiBase::getU32LE(int pos, GBool *ok) {
     169  Guint x;
     170
     171  if (pos < 0 || pos+3 >= len || pos > INT_MAX - 3) {
     172    *ok = gFalse;
     173    return 0;
     174  }
     175  x = file[pos+3];
     176  x = (x << 8) + file[pos+2];
     177  x = (x << 8) + file[pos+1];
     178  x = (x << 8) + file[pos];
    164179  return x;
    165180}
     
    169184  int i;
    170185
    171   if (pos < 0 || pos + size > len) {
     186  if (pos < 0 || pos + size > len || pos > INT_MAX - size) {
    172187    *ok = gFalse;
    173188    return 0;
  • trunk/poppler/mypoppler/fofi/FoFiBase.h

    r2 r515  
    1818//------------------------------------------------------------------------
    1919
    20 typedef void (*FoFiOutputFunc)(void *stream, char *data, int len);
     20typedef void (*FoFiOutputFunc)(void *stream, const char *data, int len);
    2121
    2222//------------------------------------------------------------------------
     
    4343  int getS32BE(int pos, GBool *ok);
    4444  Guint getU32BE(int pos, GBool *ok);
     45  Guint getU32LE(int pos, GBool *ok);
    4546  Guint getUVarBE(int pos, int size, GBool *ok);
    4647
  • trunk/poppler/mypoppler/fofi/FoFiEncodings.cc

    r2 r515  
    2020//------------------------------------------------------------------------
    2121
    22 char *fofiType1StandardEncoding[256] = {
     22const char *fofiType1StandardEncoding[256] = {
    2323  NULL,
    2424  NULL,
     
    279279};
    280280
    281 char *fofiType1ExpertEncoding[256] = {
     281const char *fofiType1ExpertEncoding[256] = {
    282282  NULL,
    283283  NULL,
     
    542542//------------------------------------------------------------------------
    543543
    544 char *fofiType1CStdStrings[391] = {
     544const char *fofiType1CStdStrings[391] = {
    545545  ".notdef",
    546546  "space",
  • trunk/poppler/mypoppler/fofi/FoFiEncodings.h

    r2 r515  
    2020//------------------------------------------------------------------------
    2121
    22 extern char *fofiType1StandardEncoding[256];
    23 extern char *fofiType1ExpertEncoding[256];
     22extern const char *fofiType1StandardEncoding[256];
     23extern const char *fofiType1ExpertEncoding[256];
    2424
    2525//------------------------------------------------------------------------
     
    2727//------------------------------------------------------------------------
    2828
    29 extern char *fofiType1CStdStrings[391];
     29extern const char *fofiType1CStdStrings[391];
    3030extern Gushort fofiType1CISOAdobeCharset[229];
    3131extern Gushort fofiType1CExpertCharset[166];
  • trunk/poppler/mypoppler/fofi/FoFiTrueType.cc

    r277 r515  
    1717// Copyright (C) 2007 Koji Otani <sho@bbr.jp>
    1818// Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
    19 // Copyright (C) 2008, 2009 Albert Astals Cid <aacid@kde.org>
     19// Copyright (C) 2008, 2009, 2012 Albert Astals Cid <aacid@kde.org>
    2020// Copyright (C) 2008 Tomas Are Haavet <tomasare@gmail.com>
     21// Copyright (C) 2012 Suzuki Toshiya <mpsuzuki@hiroshima-u.ac.jp>
     22// Copyright (C) 2012 Adrian Johnson <ajohnson@redneon.com>
    2123//
    2224// To see a description of the changes please see the Changelog file that
     
    3335#include <stdlib.h>
    3436#include <string.h>
     37#include <algorithm>
    3538#include "goo/gtypes.h"
    3639#include "goo/gmem.h"
     
    138141#define vertTag 0x76657274
    139142
    140 static int cmpTrueTypeLocaOffset(const void *p1, const void *p2) {
    141   TrueTypeLoca *loca1 = (TrueTypeLoca *)p1;
    142   TrueTypeLoca *loca2 = (TrueTypeLoca *)p2;
    143 
    144   if (loca1->origOffset == loca2->origOffset) {
    145     return loca1->idx - loca2->idx;
    146   }
    147   return loca1->origOffset - loca2->origOffset;
    148 }
    149 
    150 static int cmpTrueTypeLocaIdx(const void *p1, const void *p2) {
    151   TrueTypeLoca *loca1 = (TrueTypeLoca *)p1;
    152   TrueTypeLoca *loca2 = (TrueTypeLoca *)p2;
    153 
    154   return loca1->idx - loca2->idx;
    155 }
    156 
    157 static int cmpTrueTypeTableTag(const void *p1, const void *p2) {
    158   TrueTypeTable *tab1 = (TrueTypeTable *)p1;
    159   TrueTypeTable *tab2 = (TrueTypeTable *)p2;
    160 
    161   return (int)tab1->tag - (int)tab2->tag;
    162 }
     143struct cmpTrueTypeLocaOffsetFunctor {
     144  bool operator()(const TrueTypeLoca &loca1, const TrueTypeLoca &loca2) {
     145    if (loca1.origOffset == loca2.origOffset) {
     146      return loca1.idx < loca2.idx;
     147    }
     148    return loca1.origOffset < loca2.origOffset;
     149  }
     150};
     151
     152struct cmpTrueTypeLocaIdxFunctor {
     153  bool operator()(const TrueTypeLoca &loca1, const TrueTypeLoca &loca2) {
     154    return loca1.idx < loca2.idx;
     155  }
     156};
     157
     158struct cmpTrueTypeTableTagFunctor {
     159  bool operator()(const TrueTypeTable &tab1, const TrueTypeTable &tab2) {
     160    return tab1.tag < tab2.tag;
     161  }
     162};
    163163
    164164//------------------------------------------------------------------------
    165165
    166166struct T42Table {
    167   char *tag;                    // 4-byte tag
     167  const char *tag;              // 4-byte tag
    168168  GBool required;               // required by the TrueType spec?
    169169};
     
    195195// Glyph names in some arbitrary standard order that Apple uses for
    196196// their TrueType fonts.
    197 static char *macGlyphNames[258] = {
     197static const char *macGlyphNames[258] = {
    198198  ".notdef",        "null",           "CR",             "space",
    199199  "exclam",         "quotedbl",       "numbersign",     "dollar",
     
    233233  "trademark",      "acute",          "dieresis",       "notequal",
    234234  "AE",             "Oslash",         "infinity",       "plusminus",
    235   "lessequal",      "greaterequal",   "yen",            "mu1",
     235  "lessequal",      "greaterequal",   "yen",            "mu",
    236236  "partialdiff",    "summation",      "product",        "pi",
    237   "integral",       "ordfeminine",    "ordmasculine",   "Ohm",
     237  "integral",       "ordfeminine",    "ordmasculine",   "Omega",
    238238  "ae",             "oslash",         "questiondown",   "exclamdown",
    239239  "logicalnot",     "radical",        "florin",         "approxequal",
     
    341341}
    342342
    343 Gushort FoFiTrueType::mapCodeToGID(int i, Guint c) {
    344   Gushort gid;
     343int FoFiTrueType::mapCodeToGID(int i, Guint c) {
     344  int gid;
    345345  Guint segCnt, segEnd, segStart, segDelta, segOffset;
    346346  Guint cmapFirst, cmapLen;
     
    445445}
    446446
    447 Gushort *FoFiTrueType::getCIDToGIDMap(int *nCIDs) {
    448   FoFiType1C *ff;
    449   Gushort *map;
     447GBool FoFiTrueType::getCFFBlock(char **start, int *length) {
    450448  int i;
    451449
    452   *nCIDs = 0;
    453450  if (!openTypeCFF) {
    454     return NULL;
     451    return gFalse;
    455452  }
    456453  i = seekTable("CFF ");
    457454  if (!checkRegion(tables[i].offset, tables[i].len)) {
     455    return gFalse;
     456  }
     457  *start = (char *)file + tables[i].offset;
     458  *length = tables[i].len;
     459  return gTrue;
     460}
     461
     462int *FoFiTrueType::getCIDToGIDMap(int *nCIDs) {
     463  char *start;
     464  int length;
     465  FoFiType1C *ff;
     466  int *map;
     467
     468  *nCIDs = 0;
     469  if (!getCFFBlock(&start, &length)) {
    458470    return NULL;
    459471  }
    460   if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
    461                               tables[i].len))) {
     472  if (!(ff = FoFiType1C::make(start, length))) {
    462473    return NULL;
    463474  }
     
    491502}
    492503
     504void FoFiTrueType::getFontMatrix(double *mat) {
     505  char *start;
     506  int length;
     507  FoFiType1C *ff;
     508
     509  if (!getCFFBlock(&start, &length)) {
     510    return;
     511  }
     512  if (!(ff = FoFiType1C::make(start, length))) {
     513    return;
     514  }
     515  ff->getFontMatrix(mat);
     516  delete ff;
     517}
     518
    493519void FoFiTrueType::convertToType42(char *psName, char **encoding,
    494                                    Gushort *codeToGID,
     520                                   int *codeToGID,
    495521                                   FoFiOutputFunc outputFunc,
    496522                                   void *outputStream) {
    497523  GooString *buf;
     524  int maxUsedGlyph;
    498525  GBool ok;
    499526
     
    525552  cvtEncoding(encoding, outputFunc, outputStream);
    526553  cvtCharStrings(encoding, codeToGID, outputFunc, outputStream);
    527   cvtSfnts(outputFunc, outputStream, NULL, gFalse);
     554  cvtSfnts(outputFunc, outputStream, NULL, gFalse, &maxUsedGlyph);
    528555
    529556  // end the dictionary and define the font
     
    531558}
    532559
    533 void FoFiTrueType::convertToType1(char *psName, char **newEncoding,
     560void FoFiTrueType::convertToType1(char *psName, const char **newEncoding,
    534561                                  GBool ascii, FoFiOutputFunc outputFunc,
    535562                                  void *outputStream) {
     563  char *start;
     564  int length;
    536565  FoFiType1C *ff;
    537   int i;
    538 
    539   if (!openTypeCFF) {
     566
     567  if (!getCFFBlock(&start, &length)) {
    540568    return;
    541569  }
    542   i = seekTable("CFF ");
    543   if (!checkRegion(tables[i].offset, tables[i].len)) {
    544     return;
    545   }
    546   if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
    547                               tables[i].len))) {
     570  if (!(ff = FoFiType1C::make(start, length))) {
    548571    return;
    549572  }
     
    553576
    554577void FoFiTrueType::convertToCIDType2(char *psName,
    555                                      Gushort *cidMap, int nCIDs,
     578                                     int *cidMap, int nCIDs,
    556579                                     GBool needVerticalMetrics,
    557580                                     FoFiOutputFunc outputFunc,
    558581                                     void *outputStream) {
    559582  GooString *buf;
    560   Gushort cid;
     583  int cid, maxUsedGlyph;
    561584  GBool ok;
    562585  int i, j, k;
     
    674697
    675698  // write the guts of the dictionary
    676   cvtSfnts(outputFunc, outputStream, NULL, needVerticalMetrics);
     699  cvtSfnts(outputFunc, outputStream, NULL, needVerticalMetrics, &maxUsedGlyph);
    677700
    678701  // end the dictionary and define the font
     
    682705}
    683706
    684 void FoFiTrueType::convertToCIDType0(char *psName,
     707void FoFiTrueType::convertToCIDType0(char *psName, int *cidMap, int nCIDs,
    685708                                     FoFiOutputFunc outputFunc,
    686709                                     void *outputStream) {
     710  char *start;
     711  int length;
    687712  FoFiType1C *ff;
    688   int i;
    689 
    690   if (!openTypeCFF) {
     713
     714  if (!getCFFBlock(&start, &length)) {
    691715    return;
    692716  }
    693   i = seekTable("CFF ");
    694   if (!checkRegion(tables[i].offset, tables[i].len)) {
     717  if (!(ff = FoFiType1C::make(start, length))) {
    695718    return;
    696719  }
    697   if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
    698                               tables[i].len))) {
    699     return;
    700   }
    701   ff->convertToCIDType0(psName, outputFunc, outputStream);
     720  ff->convertToCIDType0(psName, cidMap, nCIDs, outputFunc, outputStream);
    702721  delete ff;
    703722}
    704723
    705 void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs,
     724void FoFiTrueType::convertToType0(char *psName, int *cidMap, int nCIDs,
    706725                                  GBool needVerticalMetrics,
    707726                                  FoFiOutputFunc outputFunc,
     
    709728  GooString *buf;
    710729  GooString *sfntsName;
    711   int n, i, j;
     730  int maxUsedGlyph, n, i, j;
    712731
    713732  if (openTypeCFF) {
     
    717736  // write the Type 42 sfnts array
    718737  sfntsName = (new GooString(psName))->append("_sfnts");
    719   cvtSfnts(outputFunc, outputStream, sfntsName, needVerticalMetrics);
     738  cvtSfnts(outputFunc, outputStream, sfntsName, needVerticalMetrics,
     739           &maxUsedGlyph);
    720740  delete sfntsName;
    721741
    722742  // write the descendant Type 42 fonts
    723   n = cidMap ? nCIDs : nGlyphs;
     743  // (The following is a kludge: nGlyphs is the glyph count from the
     744  // maxp table; maxUsedGlyph is the max glyph number that has a
     745  // non-zero-length description, from the loca table.  The problem is
     746  // that some TrueType font subsets fail to change the glyph count,
     747  // i.e., nGlyphs is much larger than maxUsedGlyph+1, which results
     748  // in an unnecessarily huge Type 0 font.  But some other PDF files
     749  // have fonts with only zero or one used glyph, and a content stream
     750  // that refers to one of the unused glyphs -- this results in PS
     751  // errors if we simply use maxUsedGlyph+1 for the Type 0 font.  So
     752  // we compromise by always defining at least 256 glyphs.)
     753  if (cidMap) {
     754    n = nCIDs;
     755  } else if (nGlyphs > maxUsedGlyph + 256) {
     756    if (maxUsedGlyph <= 255) {
     757      n = 256;
     758    } else {
     759      n = maxUsedGlyph + 1;
     760    }
     761  } else {
     762    n = nGlyphs;
     763  }
    724764  for (i = 0; i < n; i += 256) {
    725765    (*outputFunc)(outputStream, "10 dict begin\n", 14);
     
    786826}
    787827
    788 void FoFiTrueType::convertToType0(char *psName,
     828void FoFiTrueType::convertToType0(char *psName, int *cidMap, int nCIDs,
    789829                                  FoFiOutputFunc outputFunc,
    790830                                  void *outputStream) {
     831  char *start;
     832  int length;
    791833  FoFiType1C *ff;
    792   int i;
    793 
    794   if (!openTypeCFF) {
     834
     835  if (!getCFFBlock(&start, &length)) {
    795836    return;
    796837  }
    797   i = seekTable("CFF ");
    798   if (!checkRegion(tables[i].offset, tables[i].len)) {
     838  if (!(ff = FoFiType1C::make(start, length))) {
    799839    return;
    800840  }
    801   if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
    802                               tables[i].len))) {
    803     return;
    804   }
    805   ff->convertToType0(psName, outputFunc, outputStream);
     841  ff->convertToType0(psName, cidMap, nCIDs, outputFunc, outputStream);
    806842  delete ff;
    807843}
     
    809845void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
    810846                            void *outputStream, char *name,
    811                             Gushort *codeToGID) {
    812   // this substitute cmap table maps char codes 0000-ffff directly to
    813   // glyphs 0000-ffff
    814   static char cmapTab[36] = {
     847                            int *codeToGID) {
     848  // this substitute cmap table maps char code ffff to glyph 0,
     849  // with tables for MacRoman and MS Unicode
     850  static char cmapTab[44] = {
    815851    0, 0,                       // table version number
    816     0, 1,                       // number of encoding tables
     852    0, 2,                       // number of encoding tables
    817853    0, 1,                       // platform ID
    818854    0, 0,                       // encoding ID
    819     0, 0, 0, 12,                // offset of subtable
     855    0, 0, 0, 20,                // offset of subtable
     856    0, 3,                       // platform ID
     857    0, 1,                       // encoding ID
     858    0, 0, 0, 20,                // offset of subtable
    820859    0, 4,                       // subtable format
    821860    0, 24,                      // subtable length
     
    827866    (char)0xff, (char)0xff,     // endCount[0]
    828867    0, 0,                       // reserved
    829     0, 0,                       // startCount[0]
    830     0, 0,                       // idDelta[0]
    831     0, 0                        // pad to a mulitple of four bytes
     868    (char)0xff, (char)0xff,     // startCount[0]
     869    0, 1,                       // idDelta[0]
     870    0, 0                        // idRangeOffset[0]
    832871  };
    833872  static char nameTab[8] = {
     
    851890    0, 1,                       // version
    852891    0, 1,                       // xAvgCharWidth
    853     0, 0,                       // usWeightClass
    854     0, 0,                       // usWidthClass
     892    0x01, (char)0x90,           // usWeightClass
     893    0, 5,                       // usWidthClass
    855894    0, 0,                       // fsType
    856895    0, 0,                       // ySubscriptXSize
     
    878917    0, 0,                       // sTypoDescender
    879918    0, 0,                       // sTypoLineGap
    880     0, 0,                       // usWinAscent
    881     0, 0,                       // usWinDescent
    882     0, 0, 0, 0,                 // ulCodePageRange1
     919    0x20, 0x00,                 // usWinAscent
     920    0x20, 0x00,                 // usWinDescent
     921    0, 0, 0, 1,                 // ulCodePageRange1
    883922    0, 0, 0, 0                  // ulCodePageRange2
    884923  };
    885924  GBool missingCmap, missingName, missingPost, missingOS2;
    886   GBool unsortedLoca, badCmapLen, abbrevHMTX;
    887   int nZeroLengthTables;
     925  GBool unsortedLoca, emptyCmap, badCmapLen, abbrevHMTX;
     926  int nZeroLengthTables, nBogusTables;
    888927  int nHMetrics, advWidth, lsb;
    889928  TrueTypeLoca *locaTable;
     
    949988  }
    950989
    951   // check for zero-length tables
    952   nZeroLengthTables = 0;
     990  // check for zero-length tables and bogus tags
     991  nZeroLengthTables = nBogusTables = 0;
    953992  for (i = 0; i < nTables; ++i) {
    954993    if (tables[i].len == 0) {
    955994      ++nZeroLengthTables;
    956     }
    957   }
    958 
    959   // check for an incorrect cmap table length
    960   badCmapLen = gFalse;
     995      if (tables[i].tag == cmapTag) {
     996        missingCmap = gTrue;
     997      } else if (tables[i].tag == nameTag) {
     998        missingName = gTrue;
     999      } else if (tables[i].tag == postTag) {
     1000        missingPost = gTrue;
     1001      } else if (tables[i].tag == os2Tag) {
     1002        missingOS2 = gTrue;
     1003      }
     1004    } else if (!(tables[i].tag & 0xe0000000) ||
     1005               !(tables[i].tag & 0x00e00000) ||
     1006               !(tables[i].tag & 0x0000e000) ||
     1007               !(tables[i].tag & 0x000000e0)) {
     1008      // tags where any of the bytes are < 0x20 are probably bogus
     1009      // (the TrueType spec uses ASCII sequences for tags) -- this
     1010      // catches problems where the number of tables given in the
     1011      // header is too large, and so gibberish data is read at the end
     1012      // of the table directory
     1013      ++nBogusTables;
     1014    }
     1015  }
     1016
     1017  // check for an empty cmap table or an incorrect cmap table length
     1018  emptyCmap = badCmapLen = gFalse;
    9611019  cmapLen = 0; // make gcc happy
    9621020  if (!missingCmap) {
    963     if (nCmaps > 0) {
     1021    if (nCmaps == 0) {
     1022      emptyCmap = gTrue;
     1023    } else {
    9641024      cmapLen = cmaps[0].offset + cmaps[0].len;
    9651025      for (i = 1; i < nCmaps; ++i) {
    966         if (cmaps[i].offset + cmaps[i].len > cmapLen) {
     1026        if (cmaps[i].offset + cmaps[i].len > cmapLen) {
    9671027          cmapLen = cmaps[i].offset + cmaps[i].len;
    968         }
    969       }
    970     }
    971     cmapLen -= tables[cmapIdx].offset;
    972     if (cmapLen > tables[cmapIdx].len) {
    973       badCmapLen = gTrue;
     1028        }
     1029      }
     1030      cmapLen -= tables[cmapIdx].offset;
     1031      if (cmapLen > tables[cmapIdx].len) {
     1032        badCmapLen = gTrue;
     1033      }
    9741034    }
    9751035  }
     
    9841044  // if nothing is broken, just write the TTF file as is
    9851045  if (!missingCmap && !missingName && !missingPost && !missingOS2 &&
    986       !unsortedLoca && !badCmapLen && !abbrevHMTX && nZeroLengthTables == 0 &&
     1046      !unsortedLoca && !emptyCmap && !badCmapLen && !abbrevHMTX &&
     1047      nZeroLengthTables == 0 && nBogusTables == 0 &&
    9871048      !name && !codeToGID) {
    9881049    (*outputFunc)(outputStream, (char *)file, len);
     
    9981059  glyfLen = 0; // make gcc happy
    9991060  if (unsortedLoca) {
    1000     qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
    1001           &cmpTrueTypeLocaOffset);
     1061    std::sort(locaTable, locaTable + nGlyphs + 1,
     1062              cmpTrueTypeLocaOffsetFunctor());
    10021063    for (i = 0; i < nGlyphs; ++i) {
    10031064      locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset;
    10041065    }
    10051066    locaTable[nGlyphs].len = 0;
    1006     qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
    1007           &cmpTrueTypeLocaIdx);
     1067    std::sort(locaTable, locaTable + nGlyphs + 1, cmpTrueTypeLocaIdxFunctor());
     1068    // if the last entry in the loca is not the max offset (size of
     1069    // the glyf table), something is wrong -- work around the problem
     1070    // by forcing the last sorted entry to have a zero length
     1071    locaTable[nGlyphs].len = 0;
    10081072    pos = 0;
    10091073    for (i = 0; i <= nGlyphs; ++i) {
     
    11351199    newCmapTab[43] = 0;
    11361200    for (i = 0; i < 256; ++i) {
    1137       newCmapTab[44 + 2*i] = codeToGID[i] >> 8;
    1138       newCmapTab[44 + 2*i + 1] = codeToGID[i] & 0xff;
     1201      if (codeToGID[i] < 0) {
     1202        //~ this may not be correct - we want this character to never be
     1203        //~ displayed, but mapping it to the notdef glyph may result in
     1204        //~ little boxes being displayed
     1205        newCmapTab[44 + 2*i] = 0;
     1206        newCmapTab[44 + 2*i + 1] = 0;
     1207      } else {
     1208        newCmapTab[44 + 2*i] = codeToGID[i] >> 8;
     1209        newCmapTab[44 + 2*i + 1] = codeToGID[i] & 0xff;
     1210      }
    11391211    }
    11401212  } else {
     
    11881260  // - compute new table positions, including 4-byte alignment
    11891261  // - (re)compute table checksums
    1190   nNewTables = nTables - nZeroLengthTables +
     1262  nNewTables = nTables - nZeroLengthTables - nBogusTables +
    11911263               (missingCmap ? 1 : 0) + (missingName ? 1 : 0) +
    11921264               (missingPost ? 1 : 0) + (missingOS2 ? 1 : 0);
     
    11941266  j = 0;
    11951267  for (i = 0; i < nTables; ++i) {
    1196     if (tables[i].len > 0) {
     1268    if (tables[i].len > 0 &&
     1269        (tables[i].tag & 0xe0000000) &&
     1270        (tables[i].tag & 0x00e00000) &&
     1271        (tables[i].tag & 0x0000e000) &&
     1272        (tables[i].tag & 0x000000e0)) {
    11971273      newTables[j] = tables[i];
    11981274      newTables[j].origOffset = tables[i].offset;
    1199       if (checkRegion(tables[i].offset, newTables[i].len)) {
     1275      if (checkRegion(tables[i].offset, tables[i].len)) {
    12001276        newTables[j].checksum =
    12011277            computeTableChecksum(file + tables[i].offset, tables[i].len);
     
    12091285        newTables[j].checksum = computeTableChecksum((Guchar *)newCmapTab,
    12101286                                                     newCmapLen);
     1287      } else if (newTables[j].tag == cmapTag && emptyCmap) {
     1288        newTables[j].checksum = computeTableChecksum((Guchar *)cmapTab,
     1289                                                     sizeof(cmapTab));
     1290        newTables[j].len = sizeof(cmapTab);
    12111291      } else if (newTables[j].tag == cmapTag && badCmapLen) {
    12121292        newTables[j].len = cmapLen;
     
    12731353    ++j;
    12741354  }
    1275   qsort(newTables, nNewTables, sizeof(TrueTypeTable),
    1276         &cmpTrueTypeTableTag);
     1355  std::sort(newTables, newTables + nNewTables, cmpTrueTypeTableTagFunctor());
    12771356  pos = 12 + nNewTables * 16;
    12781357  for (i = 0; i < nNewTables; ++i) {
     
    14251504                               FoFiOutputFunc outputFunc,
    14261505                               void *outputStream) {
    1427   char *name;
     1506  const char *name;
    14281507  GooString *buf;
    14291508  int i;
     
    14521531
    14531532void FoFiTrueType::cvtCharStrings(char **encoding,
    1454                                   Gushort *codeToGID,
     1533                                  int *codeToGID,
    14551534                                  FoFiOutputFunc outputFunc,
    14561535                                  void *outputStream) {
     
    15051584void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc,
    15061585                            void *outputStream, GooString *name,
    1507                             GBool needVerticalMetrics) {
     1586                            GBool needVerticalMetrics,
     1587                            int *maxUsedGlyph) {
    15081588  Guchar headData[54];
    15091589  TrueTypeLoca *locaTable;
     
    15141594  Guint checksum;
    15151595  int nNewTables;
    1516   int length, pos, glyfPos, i, j, k;
     1596  int glyfTableLen, length, pos, glyfPos, i, j, k;
    15171597  Guchar vheaTab[36] = {
    15181598    0, 1, 0, 0,                 // table version number
     
    15501630  headData[8] = headData[9] = headData[10] = headData[11] = (Guchar)0;
    15511631
     1632  // check for a bogus loca format field in the 'head' table
     1633  // (I've encountered fonts with loca format set to 0x0100 instead of 0x0001)
     1634  if (locaFmt != 0 && locaFmt != 1) {
     1635    headData[50] = 0;
     1636    headData[51] = 1;
     1637  }
     1638
    15521639  // read the original 'loca' table, pad entries out to 4 bytes, and
    15531640  // sort it into proper order -- some (non-compliant) fonts have
    15541641  // out-of-order loca tables; in order to correctly handle the case
    15551642  // where (compliant) fonts have empty entries in the middle of the
    1556   // table, cmpTrueTypeLocaPos uses offset as its primary sort key,
     1643  // table, cmpTrueTypeLocaOffset uses offset as its primary sort key,
    15571644  // and idx as its secondary key (ensuring that adjacent entries with
    15581645  // the same pos value remain in the same order)
     
    15601647  i = seekTable("loca");
    15611648  pos = tables[i].offset;
     1649  i = seekTable("glyf");
     1650  glyfTableLen = tables[i].len;
    15621651  ok = gTrue;
    15631652  for (i = 0; i <= nGlyphs; ++i) {
     
    15681657      locaTable[i].origOffset = 2 * getU16BE(pos + i*2, &ok);
    15691658    }
    1570   }
    1571   qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
    1572         &cmpTrueTypeLocaOffset);
     1659    if (locaTable[i].origOffset > glyfTableLen) {
     1660      locaTable[i].origOffset = glyfTableLen;
     1661    }
     1662  }
     1663  std::sort(locaTable, locaTable + nGlyphs + 1,
     1664            cmpTrueTypeLocaOffsetFunctor());
    15731665  for (i = 0; i < nGlyphs; ++i) {
    15741666    locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset;
    15751667  }
    15761668  locaTable[nGlyphs].len = 0;
    1577   qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
    1578         &cmpTrueTypeLocaIdx);
     1669  std::sort(locaTable, locaTable + nGlyphs + 1, cmpTrueTypeLocaIdxFunctor());
    15791670  pos = 0;
     1671  *maxUsedGlyph = -1;
    15801672  for (i = 0; i <= nGlyphs; ++i) {
    15811673    locaTable[i].newOffset = pos;
     
    15831675    if (pos & 3) {
    15841676      pos += 4 - (pos & 3);
     1677    }
     1678    if (locaTable[i].len > 0) {
     1679      *maxUsedGlyph = i;
    15851680    }
    15861681  }
     
    16661761        checksum = computeTableChecksum(vheaTab, length);
    16671762      } else if (needVerticalMetrics && i == t42VmtxTable) {
    1668         length = 4 + (nGlyphs - 1) * 4;
     1763        length = 4 + (nGlyphs - 1) * 2;
    16691764        vmtxTab = (Guchar *)gmalloc(length);
    16701765        vmtxTab[0] = advance / 256;
     
    17841879        } else if (needVerticalMetrics && i == t42VmtxTable) {
    17851880          dumpString(vmtxTab, length, outputFunc, outputStream);
    1786           gfree(vmtxTab);
    17871881        }
    17881882      }
     
    17951889  gfree(locaData);
    17961890  gfree(locaTable);
     1891  if (vmtxTab) {
     1892    gfree(vmtxTab);
     1893  }
    17971894}
    17981895
     
    19011998  tables = (TrueTypeTable *)gmallocn(nTables, sizeof(TrueTypeTable));
    19021999  pos += 12;
    1903   int wrongTables = 0;
     2000  j = 0;
    19042001  for (i = 0; i < nTables; ++i) {
    1905     tables[i].tag = getU32BE(pos, &parsedOk);
    1906     tables[i].checksum = getU32BE(pos + 4, &parsedOk);
    1907     tables[i].offset = (int)getU32BE(pos + 8, &parsedOk);
    1908     tables[i].len = (int)getU32BE(pos + 12, &parsedOk);
    1909     if (tables[i].offset + tables[i].len < tables[i].offset ||
    1910         tables[i].offset + tables[i].len > len) {
    1911       i--;
    1912       wrongTables++;
    1913       error(-1, "Found a bad table definition on true type definition, trying to continue...");
     2002    tables[j].tag = getU32BE(pos, &parsedOk);
     2003    tables[j].checksum = getU32BE(pos + 4, &parsedOk);
     2004    tables[j].offset = (int)getU32BE(pos + 8, &parsedOk);
     2005    tables[j].len = (int)getU32BE(pos + 12, &parsedOk);
     2006    if (tables[j].offset + tables[j].len >= tables[j].offset &&
     2007        tables[j].offset + tables[j].len <= len) {
     2008      // ignore any bogus entries in the table directory
     2009      ++j;
    19142010    }
    19152011    pos += 16;
    19162012  }
    1917   nTables -= wrongTables;
    1918   tables = (TrueTypeTable *)greallocn_checkoverflow(tables, nTables, sizeof(TrueTypeTable));
     2013  if (nTables != j) {
     2014    nTables = j;
     2015    tables = (TrueTypeTable *)greallocn_checkoverflow(tables, nTables, sizeof(TrueTypeTable));
     2016  }
    19192017  if (!parsedOk || tables == NULL) {
    19202018    return;
     
    20862184}
    20872185
    2088 int FoFiTrueType::seekTable(char *tag) {
     2186int FoFiTrueType::seekTable(const char *tag) {
    20892187  Guint tagI;
    20902188  int i;
     
    21242222  Only supporting vertical text substitution.
    21252223*/
    2126 int FoFiTrueType::setupGSUB(const char *tagName)
     2224int FoFiTrueType::setupGSUB(const char *scriptName)
     2225{
     2226  return setupGSUB(scriptName, NULL);
     2227}
     2228
     2229/*
     2230  setup GSUB table data
     2231  Only supporting vertical text substitution.
     2232*/
     2233int FoFiTrueType::setupGSUB(const char *scriptName,
     2234                            const char *languageName)
    21272235{
    21282236  Guint gsubTable;
     
    21412249  Guint pos;
    21422250
    2143   if (tagName == 0) {
     2251  if (scriptName == 0) {
    21442252    gsubFeatureTable = 0;
    21452253    return 0;
    21462254  }
    2147   scriptTag = charToTag(tagName);
     2255  scriptTag = charToTag(scriptName);
    21482256  /* read GSUB Header */
    21492257  if ((x = seekTable("GSUB")) < 0) {
     
    21822290  /* use default language system */
    21832291  pos = gsubTable+scriptList+scriptTable;
    2184   langSys = getU16BE(pos,&parsedOk);/* default language system */
     2292  langSys = 0;
     2293  if (languageName) {
     2294    Guint langTag = charToTag(languageName);
     2295    Guint langCount = getU16BE(pos+2,&parsedOk);
     2296    for (i = 0;i < langCount && langSys == 0;i++) {
     2297      tag = getU32BE(pos+4+i*(4+2),&parsedOk);
     2298      if (tag == langTag) {
     2299        langSys = getU16BE(pos+4+i*(4+2)+4,&parsedOk);
     2300      }
     2301    }
     2302  }
     2303  if (langSys == 0) {
     2304    /* default language system */
     2305    langSys = getU16BE(pos,&parsedOk);
     2306  }
    21852307
    21862308  /* read LangSys table */
    21872309  if (langSys == 0) {
    2188     /* no ldefault LangSys */
     2310    /* no default LangSys */
    21892311    return 0;
    21902312  }
     
    23582480    count = getU16BE(pos,&parsedOk);
    23592481    pos += 2;
     2482    // In some poor CJK fonts, key GIDs are not sorted,
     2483    // thus we cannot finish checking even when the range
     2484    // including orgGID seems to have already passed.
    23602485    for (i = 0;i < count;i++) {
    23612486      Guint gid;
     
    23662491        /* found */
    23672492        index = i;
    2368         break;
    2369       } else if (gid > orgGID) {
    2370         /* not found */
    23712493        break;
    23722494      }
     
    23862508      startIndex = getU16BE(pos,&parsedOk);
    23872509      pos += 2;
     2510      // In some poor CJK fonts, key GIDs are not sorted,
     2511      // thus we cannot finish checking even when the range
     2512      // including orgGID seems to have already passed.
    23882513      if (startGID <= orgGID && orgGID <= endGID) {
    23892514        /* found */
    23902515        index = startIndex+orgGID-startGID;
    23912516        break;
    2392       } else if (orgGID <= endGID) {
    2393         /* not found */
    2394         break;
    23952517      }
    23962518    }
  • trunk/poppler/mypoppler/fofi/FoFiTrueType.h

    r497 r515  
    1717// Copyright (C) 2007 Koji Otani <sho@bbr.jp>
    1818// Copyright (C) 2011 Albert Astals Cid <aacid@kde.org>
     19// Copyright (C) 2012 Suzuki Toshiya <mpsuzuki@hiroshima-u.ac.jp>
    1920//
    2021// To see a description of the changes please see the Changelog file that
     
    7273
    7374  // Return the GID corresponding to <c> according to the <i>th cmap.
    74   Gushort mapCodeToGID(int i, Guint c);
     75  int mapCodeToGID(int i, Guint c);
    7576
    7677  // map gid to vertical glyph gid if exist.
     
    8687  // CIDs in *<nCIDs>.  This is only useful for CID fonts.  (Only
    8788  // useful for OpenType CFF fonts.)
    88   Gushort *getCIDToGIDMap(int *nCIDs);
     89  int *getCIDToGIDMap(int *nCIDs);
    8990
    9091  // Returns the least restrictive embedding licensing right (as
     
    9798  int getEmbeddingRights();
    9899
     100  // Return the font matrix as an array of six numbers.  (Only useful
     101  // for OpenType CFF fonts.)
     102  void getFontMatrix(double *mat);
     103
    99104  // Convert to a Type 42 font, suitable for embedding in a PostScript
    100105  // file.  <psName> will be used as the PostScript font name (so we
     
    105110  // (Not useful for OpenType CFF fonts.)
    106111  void convertToType42(char *psName, char **encoding,
    107                        Gushort *codeToGID,
     112                       int *codeToGID,
    108113                       FoFiOutputFunc outputFunc, void *outputStream);
    109114
     
    115120  // non-NULL, it will be used as the PostScript font name.  (Only
    116121  // useful for OpenType CFF fonts.)
    117   void convertToType1(char *psName, char **newEncoding, GBool ascii,
     122  void convertToType1(char *psName, const char **newEncoding, GBool ascii,
    118123                      FoFiOutputFunc outputFunc, void *outputStream);
    119124
     
    123128  // font).  The <cidMap> array maps CIDs to GIDs; it has <nCIDs>
    124129  // entries.  (Not useful for OpenType CFF fonts.)
    125   void convertToCIDType2(char *psName, Gushort *cidMap, int nCIDs,
     130  void convertToCIDType2(char *psName, int *cidMap, int nCIDs,
    126131                         GBool needVerticalMetrics,
    127132                         FoFiOutputFunc outputFunc, void *outputStream);
     
    130135  // PostScript file.  <psName> will be used as the PostScript font
    131136  // name.  (Only useful for OpenType CFF fonts.)
    132   void convertToCIDType0(char *psName,
     137  void convertToCIDType0(char *psName, int *cidMap, int nCIDs,
    133138                         FoFiOutputFunc outputFunc, void *outputStream);
    134139
     
    138143  // table in the font).  The <cidMap> array maps CIDs to GIDs; it has
    139144  // <nCIDs> entries.  (Not useful for OpenType CFF fonts.)
    140   void convertToType0(char *psName, Gushort *cidMap, int nCIDs,
     145  void convertToType0(char *psName, int *cidMap, int nCIDs,
    141146                      GBool needVerticalMetrics,
    142147                      FoFiOutputFunc outputFunc, void *outputStream);
     
    145150  // embedding in a PostScript file.  <psName> will be used as the
    146151  // PostScript font name.  (Only useful for OpenType CFF fonts.)
    147   void convertToType0(char *psName,
     152  void convertToType0(char *psName, int *cidMap, int nCIDs,
    148153                      FoFiOutputFunc outputFunc, void *outputStream);
    149154
     
    155160  // for OpenType CFF fonts.)
    156161  void writeTTF(FoFiOutputFunc outputFunc, void *outputStream,
    157                 char *name = NULL, Gushort *codeToGID = NULL);
    158 
    159   int setupGSUB(const char *tagName);
     162                char *name = NULL, int *codeToGID = NULL);
     163
     164  // Returns a pointer to the CFF font embedded in this OpenType font.
     165  // If successful, sets *<start> and *<length>, and returns true.
     166  // Otherwise returns false.  (Only useful for OpenType CFF fonts).
     167  GBool getCFFBlock(char **start, int *length);
     168
     169  // setup vert/vrt2 GSUB for default lang
     170  int setupGSUB(const char *scriptName);
     171
     172  // setup vert/vrt2 GSUB for specified lang
     173  int setupGSUB(const char *scriptName, const char* languageName);
     174
    160175private:
    161176
     
    165180                   void *outputStream);
    166181  void cvtCharStrings(char **encoding,
    167                       Gushort *codeToGID,
     182                      int *codeToGID,
    168183                      FoFiOutputFunc outputFunc,
    169184                      void *outputStream);
    170185  void cvtSfnts(FoFiOutputFunc outputFunc,
    171186                void *outputStream, GooString *name,
    172                 GBool needVerticalMetrics);
     187                GBool needVerticalMetrics,
     188                int *maxUsedGlyph);
    173189  void dumpString(Guchar *s, int length,
    174190                  FoFiOutputFunc outputFunc,
     
    177193  void parse();
    178194  void readPostTable();
    179   int seekTable(char *tag);
     195  int seekTable(const char *tag);
    180196  Guint charToTag(const char *tagName);
    181197  Guint doMapToVertGID(Guint orgGID);
  • trunk/poppler/mypoppler/fofi/FoFiType1.cc

    r470 r515  
    6060  name = NULL;
    6161  encoding = NULL;
     62  fontMatrix[0] = 0.001;
     63  fontMatrix[1] = 0;
     64  fontMatrix[2] = 0;
     65  fontMatrix[3] = 0.001;
     66  fontMatrix[4] = 0;
     67  fontMatrix[5] = 0;
    6268  parsed = gFalse;
     69  undoPFB();
    6370}
    6471
     
    9198}
    9299
    93 void FoFiType1::writeEncoded(char **newEncoding,
     100void FoFiType1::getFontMatrix(double *mat) {
     101  int i;
     102
     103  if (!parsed) {
     104    parse();
     105  }
     106  for (i = 0; i < 6; ++i) {
     107    mat[i] = fontMatrix[i];
     108  }
     109}
     110
     111void FoFiType1::writeEncoded(const char **newEncoding,
    94112                             FoFiOutputFunc outputFunc, void *outputStream) {
    95113  char buf[512];
     
    194212  char buf[256];
    195213  char c;
    196   int n, code, i, j;
     214  int n, code, base, i, j;
    197215  char *tokptr;
    198 
     216  GBool gotMatrix;
     217
     218  gotMatrix = gFalse;
    199219  for (i = 1, line = (char *)file;
    200220       i <= 100 && line && (!name || !encoding);
     
    214234    } else if (!encoding &&
    215235               !strncmp(line, "/Encoding StandardEncoding def", 30)) {
    216       encoding = fofiType1StandardEncoding;
     236      encoding = (char **)fofiType1StandardEncoding;
    217237    } else if (!encoding &&
    218238               !strncmp(line, "/Encoding 256 array", 19)) {
     
    224244           j < 300 && line && (line1 = getNextLine(line));
    225245           ++j, line = line1) {
    226         if ((n = line1 - line) > 255) {
    227           error(-1, "FoFiType1::parse a line has more than 255 characters, we don't support this");
     246        if ((n = (int)(line1 - line)) > 255) {
     247          error(errSyntaxWarning, -1, "FoFiType1::parse a line has more than 255 characters, we don't support this");
    228248          n = 255;
    229249        }
     
    232252        for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
    233253        if (!strncmp(p, "dup", 3)) {
    234           for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
    235           for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ;
    236           if (*p2) {
    237             c = *p2; // store it so we can recover it after atoi
    238             *p2 = '\0'; // terminate p so atoi works
    239             code = atoi(p);
    240             *p2 = c;
    241             if (code == 8 && *p2 == '#') {
    242               code = 0;
    243               for (++p2; *p2 >= '0' && *p2 <= '7'; ++p2) {
    244                 code = code * 8 + (*p2 - '0');
    245               }
    246             }
    247             if (likely(code < 256 && code >= 0)) {
    248               for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
    249               if (*p == '/') {
    250                 ++p;
    251                 for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
    252                 c = *p2; // store it so we can recover it after copyString
    253                 *p2 = '\0'; // terminate p so copyString works
    254                 encoding[code] = copyString(p);
    255                 *p2 = c;
    256                 p = p2;
    257                 for (; *p == ' ' || *p == '\t'; ++p); // eat spaces between string and put
    258                 if (!strncmp(p, "put", 3)) {
    259                   // eat put and spaces and newlines after put
    260                   for (p += 3; *p == ' ' || *p == '\t' || *p == '\n' || *p == '\r'; ++p);
    261                   if (*p)
    262                   {
    263                     // there is still something after the definition
    264                     // there might be another definition in this line
    265                     // so move line1 to the end of our parsing
    266                     // so we start in the potential next definition in the next loop
    267                     line1 = &line[p - buf];
    268                   }
    269                 } else {
    270                   error(-1, "FoFiType1::parse no put after dup");
    271                 }
    272               }
     254          while (1) {
     255            p += 3;
     256            for (; *p == ' ' || *p == '\t'; ++p) ;
     257            code = 0;
     258            if (*p == '8' && p[1] == '#') {
     259              base = 8;
     260              p += 2;
     261            } else if (*p >= '0' && *p <= '9') {
     262              base = 10;
     263            } else {
     264              break;
     265            }
     266            for (; *p >= '0' && *p < '0' + base; ++p) {
     267              code = code * base + (*p - '0');
     268            }
     269            for (; *p == ' ' || *p == '\t'; ++p) ;
     270            if (*p != '/') {
     271              break;
     272            }
     273            ++p;
     274            for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
     275            if (code >= 0 && code < 256) {
     276              c = *p2;
     277              *p2 = '\0';
     278              encoding[code] = copyString(p);
     279              *p2 = c;
     280            }
     281            for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
     282            if (strncmp(p, "put", 3)) {
     283              break;
     284            }
     285            for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
     286            if (strncmp(p, "dup", 3)) {
     287              break;
    273288            }
    274289          }
     
    282297      //~ check for getinterval/putinterval junk
    283298
     299    } else if (!gotMatrix && !strncmp(line, "/FontMatrix", 11)) {
     300      strncpy(buf, line + 11, 255);
     301      buf[255] = '\0';
     302      if ((p = strchr(buf, '['))) {
     303        ++p;
     304        if ((p2 = strchr(p, ']'))) {
     305          *p2 = '\0';
     306          for (j = 0; j < 6; ++j) {
     307            if ((p = strtok(j == 0 ? p : (char *)NULL, " \t\n\r"))) {
     308              fontMatrix[j] = atof(p);
     309            } else {
     310              break;
     311            }
     312          }
     313        }
     314      }
     315      gotMatrix = gTrue;
     316
    284317    } else {
    285318      line = getNextLine(line);
     
    289322  parsed = gTrue;
    290323}
     324
     325// Undo the PFB encoding, i.e., remove the PFB headers.
     326void FoFiType1::undoPFB() {
     327  GBool ok;
     328  Guchar *file2;
     329  int pos1, pos2, type;
     330  Guint segLen;
     331
     332  ok = gTrue;
     333  if (getU8(0, &ok) != 0x80 || !ok) {
     334    return;
     335  }
     336  file2 = (Guchar *)gmalloc(len);
     337  pos1 = pos2 = 0;
     338  while (getU8(pos1, &ok) == 0x80 && ok) {
     339    type = getU8(pos1 + 1, &ok);
     340    if (type < 1 || type > 2 || !ok) {
     341      break;
     342    }
     343    segLen = getU32LE(pos1 + 2, &ok);
     344    pos1 += 6;
     345    if (!ok || !checkRegion(pos1, segLen)) {
     346      break;
     347    }
     348    memcpy(file2 + pos2, file + pos1, segLen);
     349    pos1 += segLen;
     350    pos2 += segLen;
     351  }
     352  if (freeFileData) {
     353    gfree(fileData);
     354  }
     355  file = fileData = file2;
     356  freeFileData = gTrue;
     357  len = pos2;
     358}
  • trunk/poppler/mypoppler/fofi/FoFiType1.h

    r2 r515  
    3939  char **getEncoding();
    4040
     41  // Return the font matrix as an array of six numbers.
     42  void getFontMatrix(double *mat);
     43
    4144  // Write a version of the Type 1 font file with a new encoding.
    42   void writeEncoded(char **newEncoding,
     45  void writeEncoded(const char **newEncoding,
    4346                    FoFiOutputFunc outputFunc, void *outputStream);
    4447
     
    4952  char *getNextLine(char *line);
    5053  void parse();
     54  void undoPFB();
    5155
    5256  char *name;
    5357  char **encoding;
     58  double fontMatrix[6];
    5459  GBool parsed;
    5560};
  • trunk/poppler/mypoppler/fofi/FoFiType1C.cc

    r461 r515  
    117117}
    118118
    119 Gushort *FoFiType1C::getCIDToGIDMap(int *nCIDs) {
    120   Gushort *map;
     119GooString *FoFiType1C::getGlyphName(int gid) {
     120  char buf[256];
     121  GBool ok;
     122
     123  ok = gTrue;
     124  getString(charset[gid], buf, &ok);
     125  if (!ok) {
     126    return NULL;
     127  }
     128  return new GooString(buf);
     129}
     130
     131int *FoFiType1C::getCIDToGIDMap(int *nCIDs) {
     132  int *map;
    121133  int n, i;
    122134
     
    136148  }
    137149  ++n;
    138   map = (Gushort *)gmallocn(n, sizeof(Gushort));
    139   memset(map, 0, n * sizeof(Gushort));
     150  map = (int *)gmallocn(n, sizeof(int));
     151  memset(map, 0, n * sizeof(int));
    140152  for (i = 0; i < nGlyphs; ++i) {
    141153    map[charset[i]] = i;
     
    145157}
    146158
    147 void FoFiType1C::convertToType1(char *psName, char **newEncoding, GBool ascii,
     159void FoFiType1C::getFontMatrix(double *mat) {
     160  int i;
     161
     162  if (topDict.firstOp == 0x0c1e && privateDicts[0].hasFontMatrix) {
     163    if (topDict.hasFontMatrix) {
     164      mat[0] = topDict.fontMatrix[0] * privateDicts[0].fontMatrix[0] +
     165               topDict.fontMatrix[1] * privateDicts[0].fontMatrix[2];
     166      mat[1] = topDict.fontMatrix[0] * privateDicts[0].fontMatrix[1] +
     167               topDict.fontMatrix[1] * privateDicts[0].fontMatrix[3];
     168      mat[2] = topDict.fontMatrix[2] * privateDicts[0].fontMatrix[0] +
     169               topDict.fontMatrix[3] * privateDicts[0].fontMatrix[2];
     170      mat[3] = topDict.fontMatrix[2] * privateDicts[0].fontMatrix[1] +
     171               topDict.fontMatrix[3] * privateDicts[0].fontMatrix[3];
     172      mat[4] = topDict.fontMatrix[4] * privateDicts[0].fontMatrix[0] +
     173               topDict.fontMatrix[5] * privateDicts[0].fontMatrix[2];
     174      mat[5] = topDict.fontMatrix[4] * privateDicts[0].fontMatrix[1] +
     175               topDict.fontMatrix[5] * privateDicts[0].fontMatrix[3];
     176    } else {
     177      for (i = 0; i < 6; ++i) {
     178        mat[i] = privateDicts[0].fontMatrix[i];
     179      }
     180    }
     181  } else {
     182    for (i = 0; i < 6; ++i) {
     183      mat[i] = topDict.fontMatrix[i];
     184    }
     185  }
     186}
     187
     188void FoFiType1C::convertToType1(char *psName, const char **newEncoding, GBool ascii,
    148189                                FoFiOutputFunc outputFunc,
    149190                                void *outputStream) {
     
    154195  GooString *buf;
    155196  char buf2[256];
    156   char **enc;
     197  const char **enc;
    157198  GBool ok;
    158199  int i;
     
    180221  (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
    181222  if (topDict.versionSID != 0) {
    182     (*outputFunc)(outputStream, "/version (", 10);
    183     (*outputFunc)(outputStream, buf2, strlen(buf2));
    184     (*outputFunc)(outputStream, ") readonly def\n", 15);
     223    (*outputFunc)(outputStream, "/version ", 9);
     224    writePSString(buf2, outputFunc, outputStream);
     225    (*outputFunc)(outputStream, " readonly def\n", 14);
    185226  }
    186227  if (topDict.noticeSID != 0) {
    187228    getString(topDict.noticeSID, buf2, &ok);
    188     (*outputFunc)(outputStream, "/Notice (", 9);
    189     (*outputFunc)(outputStream, buf2, strlen(buf2));
    190     (*outputFunc)(outputStream, ") readonly def\n", 15);
     229    (*outputFunc)(outputStream, "/Notice ", 8);
     230    writePSString(buf2, outputFunc, outputStream);
     231    (*outputFunc)(outputStream, " readonly def\n", 14);
    191232  }
    192233  if (topDict.copyrightSID != 0) {
    193234    getString(topDict.copyrightSID, buf2, &ok);
    194     (*outputFunc)(outputStream, "/Copyright (", 12);
    195     (*outputFunc)(outputStream, buf2, strlen(buf2));
    196     (*outputFunc)(outputStream, ") readonly def\n", 15);
     235    (*outputFunc)(outputStream, "/Copyright ", 11);
     236    writePSString(buf2, outputFunc, outputStream);
     237    (*outputFunc)(outputStream, " readonly def\n", 14);
    197238  }
    198239  if (topDict.fullNameSID != 0) {
    199240    getString(topDict.fullNameSID, buf2, &ok);
    200     (*outputFunc)(outputStream, "/FullName (", 11);
    201     (*outputFunc)(outputStream, buf2, strlen(buf2));
    202     (*outputFunc)(outputStream, ") readonly def\n", 15);
     241    (*outputFunc)(outputStream, "/FullName ", 10);
     242    writePSString(buf2, outputFunc, outputStream);
     243    (*outputFunc)(outputStream, " readonly def\n", 14);
    203244  }
    204245  if (topDict.familyNameSID != 0) {
    205246    getString(topDict.familyNameSID, buf2, &ok);
    206     (*outputFunc)(outputStream, "/FamilyName (", 13);
    207     (*outputFunc)(outputStream, buf2, strlen(buf2));
    208     (*outputFunc)(outputStream, ") readonly def\n", 15);
     247    (*outputFunc)(outputStream, "/FamilyName ", 12);
     248    writePSString(buf2, outputFunc, outputStream);
     249    (*outputFunc)(outputStream, " readonly def\n", 14);
    209250  }
    210251  if (topDict.weightSID != 0) {
    211252    getString(topDict.weightSID, buf2, &ok);
    212     (*outputFunc)(outputStream, "/Weight (", 9);
    213     (*outputFunc)(outputStream, buf2, strlen(buf2));
    214     (*outputFunc)(outputStream, ") readonly def\n", 15);
     253    (*outputFunc)(outputStream, "/Weight ", 8);
     254    writePSString(buf2, outputFunc, outputStream);
     255    (*outputFunc)(outputStream, " readonly def\n", 14);
    215256  }
    216257  if (topDict.isFixedPitch) {
     
    266307    (*outputFunc)(outputStream,
    267308                  "0 1 255 {1 index exch /.notdef put} for\n", 40);
    268     enc = newEncoding ? newEncoding : encoding;
     309    enc = newEncoding ? newEncoding : (const char **)encoding;
    269310    for (i = 0; i < 256; ++i) {
    270311      if (enc[i]) {
     
    445486}
    446487
    447 void FoFiType1C::convertToCIDType0(char *psName,
     488void FoFiType1C::convertToCIDType0(char *psName, int *codeMap, int nCodes,
    448489                                   FoFiOutputFunc outputFunc,
    449490                                   void *outputStream) {
     
    460501
    461502  // compute the CID count and build the CID-to-GID mapping
    462   nCIDs = 0;
    463   for (i = 0; i < nGlyphs; ++i) {
    464     if (charset[i] >= nCIDs) {
    465       nCIDs = charset[i] + 1;
    466     }
    467   }
    468   cidMap = (int *)gmallocn(nCIDs, sizeof(int));
    469   for (i = 0; i < nCIDs; ++i) {
    470     cidMap[i] = -1;
    471   }
    472   for (i = 0; i < nGlyphs; ++i) {
    473     cidMap[charset[i]] = i;
     503  if (codeMap) {
     504    nCIDs = nCodes;
     505    cidMap = (int *)gmallocn(nCIDs, sizeof(int));
     506    for (i = 0; i < nCodes; ++i) {
     507      if (codeMap[i] >= 0 && codeMap[i] < nGlyphs) {
     508        cidMap[i] = codeMap[i];
     509      } else {
     510        cidMap[i] = -1;
     511      }
     512    }
     513  } else if (topDict.firstOp == 0x0c1e) {
     514    nCIDs = 0;
     515    for (i = 0; i < nGlyphs; ++i) {
     516      if (charset[i] >= nCIDs) {
     517        nCIDs = charset[i] + 1;
     518      }
     519    }
     520    cidMap = (int *)gmallocn(nCIDs, sizeof(int));
     521    for (i = 0; i < nCIDs; ++i) {
     522      cidMap[i] = -1;
     523    }
     524    for (i = 0; i < nGlyphs; ++i) {
     525      cidMap[charset[i]] = i;
     526    }
     527  } else {
     528    nCIDs = nGlyphs;
     529    cidMap = (int *)gmallocn(nCIDs, sizeof(int));
     530    for (i = 0; i < nCIDs; ++i) {
     531      cidMap[i] = i;
     532    }
    474533  }
    475534
     
    483542      getIndexVal(&charStringsIdx, gid, &val, &ok);
    484543      if (ok) {
    485         getIndex(privateDicts[fdSelect[gid]].subrsOffset, &subrIdx, &ok);
     544        getIndex(privateDicts[fdSelect ? fdSelect[gid] : 0].subrsOffset,
     545                 &subrIdx, &ok);
    486546        if (!ok) {
    487547          subrIdx.pos = -1;
    488548        }
    489549        cvtGlyph(val.pos, val.len, charStrings,
    490                  &subrIdx, &privateDicts[fdSelect[gid]], gTrue);
     550                 &subrIdx, &privateDicts[fdSelect ? fdSelect[gid] : 0], gTrue);
    491551      }
    492552    }
     
    733793  for (i = 0; i <= nCIDs; i += 6) {
    734794    for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
    735       if (i+j < nCIDs && cidMap[i+j] >= 0) {
     795      if (i+j < nCIDs && cidMap[i+j] >= 0 && fdSelect) {
    736796        buf2[0] = (char)fdSelect[cidMap[i+j]];
    737797      } else {
     
    771831}
    772832
    773 void FoFiType1C::convertToType0(char *psName,
     833void FoFiType1C::convertToType0(char *psName, int *codeMap, int nCodes,
    774834                                FoFiOutputFunc outputFunc,
    775835                                void *outputStream) {
     
    784844
    785845  // compute the CID count and build the CID-to-GID mapping
    786   nCIDs = 0;
    787   for (i = 0; i < nGlyphs; ++i) {
    788     if (charset[i] >= nCIDs) {
    789       nCIDs = charset[i] + 1;
    790     }
    791   }
    792   cidMap = (int *)gmallocn(nCIDs, sizeof(int));
    793   for (i = 0; i < nCIDs; ++i) {
    794     cidMap[i] = -1;
    795   }
    796   for (i = 0; i < nGlyphs; ++i) {
    797     cidMap[charset[i]] = i;
     846  if (codeMap) {
     847    nCIDs = nCodes;
     848    cidMap = (int *)gmallocn(nCIDs, sizeof(int));
     849    for (i = 0; i < nCodes; ++i) {
     850      if (codeMap[i] >= 0 && codeMap[i] < nGlyphs) {
     851        cidMap[i] = codeMap[i];
     852      } else {
     853        cidMap[i] = -1;
     854      }
     855    }
     856  } else if (topDict.firstOp == 0x0c1e) {
     857    nCIDs = 0;
     858    for (i = 0; i < nGlyphs; ++i) {
     859      if (charset[i] >= nCIDs) {
     860        nCIDs = charset[i] + 1;
     861      }
     862    }
     863    cidMap = (int *)gmallocn(nCIDs, sizeof(int));
     864    for (i = 0; i < nCIDs; ++i) {
     865      cidMap[i] = -1;
     866    }
     867    for (i = 0; i < nGlyphs; ++i) {
     868      cidMap[charset[i]] = i;
     869    }
     870  } else {
     871    nCIDs = nGlyphs;
     872    cidMap = (int *)gmallocn(nCIDs, sizeof(int));
     873    for (i = 0; i < nCIDs; ++i) {
     874      cidMap[i] = i;
     875    }
    798876  }
    799877
     
    805883    //~ font up by FD; as a kludge we ignore CID 0, which is .notdef
    806884    fd = 0;
    807     if (fdSelect != NULL) {
     885    // if fdSelect is NULL, we have an 8-bit font, so just leave fd=0
     886    if (fdSelect) {
    808887      for (j = i==0 ? 1 : 0; j < 256 && i+j < nCIDs; ++j) {
    809888        if (cidMap[i+j] >= 0) {
     
    10841163}
    10851164
    1086 void FoFiType1C::eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName,
     1165void FoFiType1C::eexecCvtGlyph(Type1CEexecBuf *eb, const char *glyphName,
    10871166                               int offset, int nBytes,
    10881167                               Type1CIndex *subrIdx,
     
    18101889}
    18111890
    1812 void FoFiType1C::eexecWrite(Type1CEexecBuf *eb, char *s) {
     1891void FoFiType1C::eexecWrite(Type1CEexecBuf *eb, const char *s) {
    18131892  Guchar *p;
    18141893  Guchar x;
     
    18541933}
    18551934
     1935void FoFiType1C::writePSString(char *s, FoFiOutputFunc outputFunc,
     1936                               void *outputStream) {
     1937  char buf[80];
     1938  char *p;
     1939  int i, c;
     1940
     1941  i = 0;
     1942  buf[i++] = '(';
     1943  for (p = s; *p; ++p) {
     1944    c = *p & 0xff;
     1945    if (c == '(' || c == ')' || c == '\\') {
     1946      buf[i++] = '\\';
     1947      buf[i++] = c;
     1948    } else if (c < 0x20 || c >= 0x80) {
     1949      buf[i++] = '\\';
     1950      buf[i++] = '0' + ((c >> 6) & 7);
     1951      buf[i++] = '0' + ((c >> 3) & 7);
     1952      buf[i++] = '0' + (c & 7);
     1953    } else {
     1954      buf[i++] = c;
     1955    }
     1956    if (i >= 64) {
     1957      buf[i++] = '\\';
     1958      buf[i++] = '\n';
     1959      (*outputFunc)(outputStream, buf, i);
     1960      i = 0;
     1961    }
     1962  }
     1963  buf[i++] = ')';
     1964  (*outputFunc)(outputStream, buf, i);
     1965}
     1966
    18561967GBool FoFiType1C::parse() {
    18571968  Type1CIndex fdIdx;
     
    19142025  // for 8-bit fonts: read the private dict
    19152026  } else {
     2027    nFDs = 1;
    19162028    privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
    19172029    readPrivateDict(topDict.privateOffset, topDict.privateSize,
     
    20652177
    20662178  hasFontMatrix = gFalse;
     2179  fontMatrix[0] = fontMatrix[1] = fontMatrix[2] = 0; // make gcc happy
     2180  fontMatrix[3] = fontMatrix[4] = fontMatrix[5] = 0;
    20672181  pSize = pOffset = 0;
    20682182  pos = offset;
     
    22792393
    22802394  if (topDict.encodingOffset == 0) {
    2281     encoding = fofiType1StandardEncoding;
     2395    encoding = (char **)fofiType1StandardEncoding;
    22822396
    22832397  } else if (topDict.encodingOffset == 1) {
    2284     encoding = fofiType1ExpertEncoding;
     2398    encoding = (char **)fofiType1ExpertEncoding;
    22852399
    22862400  } else {
     
    26022716  int n;
    26032717
    2604   if (sid < 391) {
     2718  if (sid < 0) {
     2719    buf[0] = '\0';
     2720  } else if (sid < 391) {
    26052721    strcpy(buf, fofiType1CStdStrings[sid]);
    26062722  } else {
  • trunk/poppler/mypoppler/fofi/FoFiType1C.h

    r257 r515  
    162162  char **getEncoding();
    163163
     164  // Get the glyph names.
     165  int getNumGlyphs() { return nGlyphs; }
     166  GooString *getGlyphName(int gid);
     167
    164168  // Return the mapping from CIDs to GIDs, and return the number of
    165169  // CIDs in *<nCIDs>.  This is only useful for CID fonts.
    166   Gushort *getCIDToGIDMap(int *nCIDs);
     170  int *getCIDToGIDMap(int *nCIDs);
     171
     172  // Return the font matrix as an array of six numbers.
     173  void getFontMatrix(double *mat);
    167174
    168175  // Convert to a Type 1 font, suitable for embedding in a PostScript
     
    172179  // otherwise it will be left as binary data.  If <psName> is non-NULL,
    173180  // it will be used as the PostScript font name.
    174   void convertToType1(char *psName, char **newEncoding, GBool ascii,
     181  void convertToType1(char *psName, const char **newEncoding, GBool ascii,
    175182                      FoFiOutputFunc outputFunc, void *outputStream);
    176183
    177184  // Convert to a Type 0 CIDFont, suitable for embedding in a
    178185  // PostScript file.  <psName> will be used as the PostScript font
    179   // name.
    180   void convertToCIDType0(char *psName,
     186  // name.  There are three cases for the CID-to-GID mapping:
     187  // (1) if <codeMap> is non-NULL, then it is the CID-to-GID mapping
     188  // (2) if <codeMap> is NULL and this is a CID CFF font, then the
     189  //     font's internal CID-to-GID mapping is used
     190  // (3) is <codeMap> is NULL and this is an 8-bit CFF font, then
     191  //     the identity CID-to-GID mapping is used
     192  void convertToCIDType0(char *psName, int *codeMap, int nCodes,
    181193                         FoFiOutputFunc outputFunc, void *outputStream);
    182194
    183195  // Convert to a Type 0 (but non-CID) composite font, suitable for
    184196  // embedding in a PostScript file.  <psName> will be used as the
    185   // PostScript font name.
    186   void convertToType0(char *psName,
     197  // PostScript font name.  There are three cases for the CID-to-GID
     198  // mapping:
     199  // (1) if <codeMap> is non-NULL, then it is the CID-to-GID mapping
     200  // (2) if <codeMap> is NULL and this is a CID CFF font, then the
     201  //     font's internal CID-to-GID mapping is used
     202  // (3) is <codeMap> is NULL and this is an 8-bit CFF font, then
     203  //     the identity CID-to-GID mapping is used
     204  void convertToType0(char *psName, int *codeMap, int nCodes,
    187205                      FoFiOutputFunc outputFunc, void *outputStream);
    188206
     
    190208
    191209  FoFiType1C(char *fileA, int lenA, GBool freeFileDataA);
    192   void eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName,
     210  void eexecCvtGlyph(Type1CEexecBuf *eb, const char *glyphName,
    193211                     int offset, int nBytes,
    194212                     Type1CIndex *subrIdx,
     
    200218                     Type1CPrivateDict *pDict);
    201219  void cvtNum(double x, GBool isFP, GooString *charBuf);
    202   void eexecWrite(Type1CEexecBuf *eb, char *s);
     220  void eexecWrite(Type1CEexecBuf *eb, const char *s);
    203221  void eexecWriteCharstring(Type1CEexecBuf *eb, Guchar *s, int n);
     222  void writePSString(char *s, FoFiOutputFunc outputFunc, void *outputStream);
    204223  GBool parse();
    205224  void readTopDict();
  • trunk/poppler/mypoppler/goo/FixedPoint.cc

    r250 r515  
    8383
    8484int FixedPoint::mul(int x, int y) {
    85 #if 1 //~tmp
    86   return ((FixPtInt64)x * y) >> fixptShift;
    87 #else
    88   int ah0, ah, bh, al, bl;
    89   ah0 = x & fixptMaskH;
    90   ah = x >> fixptShift;
    91   al = x - ah0;
    92   bh = y >> fixptShift;
    93   bl = y - (bh << fixptShift);
    94   return ah0 * bh + ah * bl + al * bh + ((al * bl) >> fixptShift);
    95 #endif
     85  FixPtInt64 z;
     86
     87  z = ((FixPtInt64)x * y) >> fixptShift;
     88  if (z > 0x7fffffffLL) {
     89    return 0x7fffffff;
     90  } else if (z < -0x80000000LL) {
     91    return 0x80000000;
     92  } else {
     93    return (int)z;
     94  }
    9695}
    9796
    9897int FixedPoint::div(int x, int y) {
    99 #if 1 //~tmp
    100   return ((FixPtInt64)x << fixptShift) / y;
    101 #else
    102 #endif
     98  FixPtInt64 z;
     99
     100  z = ((FixPtInt64)x << fixptShift) / y;
     101  if (z > 0x7fffffffLL) {
     102    return 0x7fffffff;
     103  } else if (z < -0x80000000LL) {
     104    return 0x80000000;
     105  } else {
     106    return (int)z;
     107  }
    103108}
    104109
    105110GBool FixedPoint::divCheck(FixedPoint x, FixedPoint y, FixedPoint *result) {
    106 #if 1 //~tmp
    107111  FixPtInt64 z;
    108112
     
    114118  result->val = z;
    115119  return gTrue;
    116 #else
    117 #endif
     120}
     121
     122GBool FixedPoint::checkDet(FixedPoint m11, FixedPoint m12,
     123                          FixedPoint m21, FixedPoint m22,
     124                          FixedPoint epsilon) {
     125  FixPtInt64 det, e;
     126
     127  det = (FixPtInt64)m11.val * (FixPtInt64)m22.val
     128        - (FixPtInt64)m12.val * (FixPtInt64)m21.val;
     129  e = (FixPtInt64)epsilon.val << fixptShift;
     130  // NB: this comparison has to be >= not > because epsilon can be
     131  // truncated to zero as a fixed point value.
     132  return det >= e || det <= -e;
    118133}
    119134
  • trunk/poppler/mypoppler/goo/FixedPoint.h

    r277 r515  
    1212#define FIXEDPOINT_H
    1313
    14 #include "poppler/poppler-config.h"
     14#include "poppler-config.h"
    1515
    1616#if USE_FIXEDPOINT
     
    4646    { return val >> fixptShift; }
    4747
    48   int getRaw() { return val; }
     48  int get16Dot16() { return val; }
    4949
    5050  FixedPoint operator =(FixedPoint x) { val = x.val; return *this; }
     
    133133    { return (x.val + (1 << (fixptShift - 1))) >> fixptShift; }
    134134
     135  // Computes (x+y)/2 avoiding overflow and LSbit accuracy issues.
     136  static FixedPoint avg(FixedPoint x, FixedPoint y)
     137    { return make((x.val >> 1) + (y.val >> 1) + ((x.val | y.val) & 1)); }
     138
     139
    135140  static FixedPoint sqrt(FixedPoint x);
    136141
     
    141146  static GBool divCheck(FixedPoint x, FixedPoint y, FixedPoint *result);
    142147
     148  // Compute abs(m11*m22 - m12*m21) >= epsilon, handling the case
     149  // where the multiplications overflow.
     150  static GBool checkDet(FixedPoint m11, FixedPoint m12,
     151                       FixedPoint m21, FixedPoint m22,
     152                       FixedPoint epsilon);
     153
    143154private:
    144155
     
    148159  static int div(int x, int y);
    149160
    150   int val;                      // 16.16 fixed point
     161  int val;                // fixed point: (n-fixptShift).(fixptShift)
    151162};
    152163
  • trunk/poppler/mypoppler/goo/GooHash.cc

    r2 r515  
    108108  if ((p = find(key, &h))) {
    109109    p->val.p = val;
    110     delete key;
     110    if (deleteKeys) {
     111      delete key;
     112    }
    111113  } else {
    112114    add(key, val);
     
    120122  if ((p = find(key, &h))) {
    121123    p->val.i = val;
    122     delete key;
     124    if (deleteKeys) {
     125      delete key;
     126    }
    123127  } else {
    124128    add(key, val);
     
    146150}
    147151
    148 void *GooHash::lookup(char *key) {
     152void *GooHash::lookup(const char *key) {
    149153  GooHashBucket *p;
    150154  int h;
     
    156160}
    157161
    158 int GooHash::lookupInt(char *key) {
     162int GooHash::lookupInt(const char *key) {
    159163  GooHashBucket *p;
    160164  int h;
     
    212216}
    213217
    214 void *GooHash::remove(char *key) {
     218void *GooHash::remove(const char *key) {
    215219  GooHashBucket *p;
    216220  GooHashBucket **q;
     
    235239}
    236240
    237 int GooHash::removeInt(char *key) {
     241int GooHash::removeInt(const char *key) {
    238242  GooHashBucket *p;
    239243  GooHashBucket **q;
     
    345349}
    346350
    347 GooHashBucket *GooHash::find(char *key, int *h) {
     351GooHashBucket *GooHash::find(const char *key, int *h) {
    348352  GooHashBucket *p;
    349353
     
    358362
    359363int GooHash::hash(GooString *key) {
    360   char *p;
     364  const char *p;
    361365  unsigned int h;
    362366  int i;
     
    369373}
    370374
    371 int GooHash::hash(char *key) {
    372   char *p;
     375int GooHash::hash(const char *key) {
     376  const char *p;
    373377  unsigned int h;
    374378
  • trunk/poppler/mypoppler/goo/GooHash.h

    r2 r515  
    3333  void *lookup(GooString *key);
    3434  int lookupInt(GooString *key);
    35   void *lookup(char *key);
    36   int lookupInt(char *key);
     35  void *lookup(const char *key);
     36  int lookupInt(const char *key);
    3737  void *remove(GooString *key);
    3838  int removeInt(GooString *key);
    39   void *remove(char *key);
    40   int removeInt(char *key);
     39  void *remove(const char *key);
     40  int removeInt(const char *key);
    4141  int getLength() { return len; }
    4242  void startIter(GooHashIter **iter);
     
    4949  void expand();
    5050  GooHashBucket *find(GooString *key, int *h);
    51   GooHashBucket *find(char *key, int *h);
     51  GooHashBucket *find(const char *key, int *h);
    5252  int hash(GooString *key);
    53   int hash(char *key);
     53  int hash(const char *key);
    5454
    5555  GBool deleteKeys;             // set if key strings should be deleted
  • trunk/poppler/mypoppler/goo/GooList.cc

    r2 r515  
    3030
    3131GooList::GooList(int sizeA) {
    32   size = sizeA;
     32  size = sizeA ? sizeA : 8;
    3333  data = (void **)gmallocn(size, sizeof(void*));
    3434  length = 0;
     
    3838GooList::~GooList() {
    3939  gfree(data);
     40}
     41
     42GooList *GooList::copy() {
     43  GooList *ret;
     44
     45  ret = new GooList(length);
     46  ret->length = length;
     47  memcpy(ret->data, data, length * sizeof(void *));
     48  ret->inc = inc;
     49  return ret;
    4050}
    4151
     
    6171  if (length >= size) {
    6272    expand();
     73  }
     74  if (i < 0) {
     75    i = 0;
    6376  }
    6477  if (i < length) {
     
    87100}
    88101
     102void GooList::reverse() {
     103  void *t;
     104  int n, i;
     105
     106  n = length / 2;
     107  for (i = 0; i < n; ++i) {
     108    t = data[i];
     109    data[i] = data[length - 1 - i];
     110    data[length - 1 - i] = t;
     111  }
     112}
     113
    89114void GooList::expand() {
    90115  size += (inc > 0) ? inc : size;
  • trunk/poppler/mypoppler/goo/GooList.h

    r2 r515  
    3737  int getLength() { return length; }
    3838
     39  // Returns a (shallow) copy of this list.
     40  GooList *copy();
     41
    3942  //----- ordered list support
    4043
     
    4245  // Assumes 0 <= i < length.
    4346  void *get(int i) { return data[i]; }
     47
     48  // Replace the <i>th element.
     49  // Assumes 0 <= i < length.
     50  void put(int i, void *p) { data[i] = p; }
    4451
    4552  // Append an element to the end of the list.
     
    6168  // be double-dereferenced.
    6269  void sort(int (*cmp)(const void *ptr1, const void *ptr2));
     70
     71  // Reverse the list.
     72  void reverse();
    6373
    6474  //----- control
  • trunk/poppler/mypoppler/goo/GooString.cc

    r470 r515  
    2020// Copyright (C) 2007 Jeff Muizelaar <jeff@infidigm.net>
    2121// Copyright (C) 2008-2011 Albert Astals Cid <aacid@kde.org>
     22// Copyright (C) 2011 Kenji Uno <ku@digitaldolphins.jp>
    2223//
    2324// To see a description of the changes please see the Changelog file that
     
    5051  long l;
    5152  Gulong ul;
     53#ifdef LLONG_MAX
     54  long long ll;
     55#endif
     56#ifdef ULLONG_MAX
     57  unsigned long long ull;
     58#endif
    5259  double f;
    5360  char c;
     
    7380  fmtULongOctal,
    7481  fmtULongBinary,
     82#ifdef LLONG_MAX
     83  fmtLongLongDecimal,
     84  fmtLongLongHex,
     85  fmtLongLongOctal,
     86  fmtLongLongBinary,
     87#endif
     88#ifdef ULLONG_MAX
     89  fmtULongLongDecimal,
     90  fmtULongLongHex,
     91  fmtULongLongOctal,
     92  fmtULongLongBinary,
     93#endif
    7594  fmtDouble,
    7695  fmtDoubleTrimSmallAware,
     
    82101};
    83102
    84 static char *formatStrings[] = {
     103static const char *formatStrings[] = {
    85104  "d", "x", "o", "b", "ud", "ux", "uo", "ub",
    86105  "ld", "lx", "lo", "lb", "uld", "ulx", "ulo", "ulb",
     106#ifdef LLONG_MAX
     107  "lld", "llx", "llo", "llb",
     108#endif
     109#ifdef ULLONG_MAX
     110  "ulld", "ullx", "ullo", "ullb",
     111#endif
    87112  "f", "gs", "g",
    88113  "c",
     
    130155        memcpy(s1, s, length);
    131156      }
     157      if (s != sStatic)
     158        gfree(s);
    132159    }
    133160
     
    218245}
    219246
    220 GooString *GooString::format(char *fmt, ...) {
     247GooString *GooString::format(const char *fmt, ...) {
    221248  va_list argList;
    222249  GooString *s;
     
    229256}
    230257
    231 GooString *GooString::formatv(char *fmt, va_list argList) {
     258GooString *GooString::formatv(const char *fmt, va_list argList) {
    232259  GooString *s;
    233260
     
    264291}
    265292
    266 GooString *GooString::appendf(char *fmt, ...) {
     293GooString *GooString::appendf(const char *fmt, ...) {
    267294  va_list argList;
    268295
     
    273300}
    274301
    275 GooString *GooString::appendfv(char *fmt, va_list argList) {
     302GooString *GooString::appendfv(const char *fmt, va_list argList) {
    276303  GooStringFormatArg *args;
    277304  int argsLen, argsSize;
     
    282309  char buf[65];
    283310  int len, i;
    284   char *p0, *p1, *str;
     311  const char *p0, *p1;
     312  char *str;
    285313
    286314  argsLen = 0;
     
    319347        for (; *p0 >= '0' && *p0 <= '9'; ++p0) {
    320348          width = 10 * width + (*p0 - '0');
     349        }
     350        if (width < 0) {
     351          width = 0;
    321352        }
    322353        if (*p0 == '.') {
     
    381412            args[argsLen].ul = va_arg(argList, Gulong);
    382413            break;
     414#ifdef LLONG_MAX
     415          case fmtLongLongDecimal:
     416          case fmtLongLongHex:
     417          case fmtLongLongOctal:
     418          case fmtLongLongBinary:
     419            args[argsLen].ll = va_arg(argList, long long);
     420            break;
     421#endif
     422#ifdef ULLONG_MAX
     423          case fmtULongLongDecimal:
     424          case fmtULongLongHex:
     425          case fmtULongLongOctal:
     426          case fmtULongLongBinary:
     427            args[argsLen].ull = va_arg(argList, unsigned long long);
     428            break;
     429#endif
    383430          case fmtDouble:
    384431          case fmtDoubleTrim:
     
    454501          formatUInt(arg.ul, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
    455502          break;
     503#ifdef LLONG_MAX
     504        case fmtLongLongDecimal:
     505          formatInt(arg.ll, buf, sizeof(buf), zeroFill, width, 10, &str, &len);
     506          break;
     507        case fmtLongLongHex:
     508          formatInt(arg.ll, buf, sizeof(buf), zeroFill, width, 16, &str, &len);
     509          break;
     510        case fmtLongLongOctal:
     511          formatInt(arg.ll, buf, sizeof(buf), zeroFill, width, 8, &str, &len);
     512          break;
     513        case fmtLongLongBinary:
     514          formatInt(arg.ll, buf, sizeof(buf), zeroFill, width, 2, &str, &len);
     515          break;
     516#endif
     517#ifdef ULLONG_MAX
     518        case fmtULongLongDecimal:
     519          formatUInt(arg.ull, buf, sizeof(buf), zeroFill, width, 10,
     520                     &str, &len);
     521          break;
     522        case fmtULongLongHex:
     523          formatUInt(arg.ull, buf, sizeof(buf), zeroFill, width, 16,
     524                     &str, &len);
     525          break;
     526        case fmtULongLongOctal:
     527          formatUInt(arg.ull, buf, sizeof(buf), zeroFill, width, 8,
     528                     &str, &len);
     529          break;
     530        case fmtULongLongBinary:
     531          formatUInt(arg.ull, buf, sizeof(buf), zeroFill, width, 2,
     532                     &str, &len);
     533          break;
     534#endif
    456535        case fmtDouble:
    457536          formatDouble(arg.f, buf, sizeof(buf), prec, gFalse, &str, &len);
     
    517596  return this;
    518597}
    519 
     598#ifdef LLONG_MAX
     599void GooString::formatInt(long long x, char *buf, int bufSize,
     600                          GBool zeroFill, int width, int base,
     601                          char **p, int *len) {
     602#else
    520603void GooString::formatInt(long x, char *buf, int bufSize,
    521                         GBool zeroFill, int width, int base,
    522                         char **p, int *len) {
     604                          GBool zeroFill, int width, int base,
     605                          char **p, int *len) {
     606#endif
    523607  static char vals[17] = "0123456789abcdef";
    524608  GBool neg;
     
    550634}
    551635
     636#ifdef ULLONG_MAX
     637void GooString::formatUInt(unsigned long long x, char *buf, int bufSize,
     638                           GBool zeroFill, int width, int base,
     639                           char **p, int *len) {
     640#else
    552641void GooString::formatUInt(Gulong x, char *buf, int bufSize,
    553                          GBool zeroFill, int width, int base,
    554                          char **p, int *len) {
     642                           GBool zeroFill, int width, int base,
     643                           char **p, int *len) {
     644#endif
    555645  static char vals[17] = "0123456789abcdef";
    556646  int i, j;
     
    583673    x = -x;
    584674  }
    585   x = floor(x * pow((double)10, prec) + 0.5);
     675  x = floor(x * pow(10.0, prec) + 0.5);
    586676  i = bufSize;
    587677  started = !trim;
     
    653743  int j;
    654744
    655   if (n > 0) {
     745  if (i >= 0 && n > 0 && i + n > 0) {
    656746    if (i + n > length) {
    657747      n = length - i;
  • trunk/poppler/mypoppler/goo/GooString.h

    r461 r515  
    1818// Copyright (C) 2006 Kristian HÞgsberg <krh@redhat.com>
    1919// Copyright (C) 2006 Krzysztof Kowalczyk <kkowalczyk@gmail.com>
    20 // Copyright (C) 2008-2010 Albert Astals Cid <aacid@kde.org>
     20// Copyright (C) 2008-2010, 2012 Albert Astals Cid <aacid@kde.org>
    2121//
    2222// To see a description of the changes please see the Changelog file that
     
    3232#endif
    3333
     34#include <limits.h> // for LLONG_MAX and ULLONG_MAX
    3435#include <stdarg.h>
    3536#include <stdlib.h> // for NULL
     
    8384  //     ud, ux, uo, ub -- unsigned int
    8485  //     ld, lx, lo, lb, uld, ulx, ulo, ulb -- long, unsigned long
     86  //     lld, llx, llo, llb, ulld, ullx, ullo, ullb
     87  //         -- long long, unsigned long long
    8588  //     f, g -- double
    8689  //     c -- char
     
    8992  //     w -- blank space; arg determines width
    9093  // To get literal curly braces, use {{ or }}.
    91   static GooString *format(char *fmt, ...);
    92   static GooString *formatv(char *fmt, va_list argList);
     94  static GooString *format(const char *fmt, ...);
     95  static GooString *formatv(const char *fmt, va_list argList);
    9396
    9497  // Destructor.
     
    116119
    117120  // Append a formatted string.
    118   GooString *appendf(char *fmt, ...);
    119   GooString *appendfv(char *fmt, va_list argList);
     121  GooString *appendf(const char *fmt, ...);
     122  GooString *appendfv(const char *fmt, va_list argList);
    120123
    121124  // Insert a character or string.
     
    165168
    166169  void resize(int newLength);
     170#ifdef LLONG_MAX
     171  static void formatInt(long long x, char *buf, int bufSize,
     172                        GBool zeroFill, int width, int base,
     173                        char **p, int *len);
     174#else
    167175  static void formatInt(long x, char *buf, int bufSize,
    168176                        GBool zeroFill, int width, int base,
    169177                        char **p, int *len);
     178#endif
     179#ifdef ULLONG_MAX
     180  static void formatUInt(unsigned long long x, char *buf, int bufSize,
     181                         GBool zeroFill, int width, int base,
     182                         char **p, int *len);
     183#else
    170184  static void formatUInt(Gulong x, char *buf, int bufSize,
    171185                         GBool zeroFill, int width, int base,
    172186                         char **p, int *len);
     187#endif
    173188  static void formatDouble(double x, char *buf, int bufSize, int prec,
    174189                           GBool trim, char **p, int *len);
  • trunk/poppler/mypoppler/goo/GooTimer.h

    r497 r515  
    2020#endif
    2121
    22 #include "poppler/poppler-config.h"
     22#include "poppler-config.h"
    2323#include "gtypes.h"
    2424#ifdef HAVE_GETTIMEOFDAY
  • trunk/poppler/mypoppler/goo/JpegWriter.cc

    r497 r515  
    66//
    77// Copyright (C) 2009 Stefan Thomas <thomas@eload24.com>
    8 // Copyright (C) 2010 Adrian Johnson <ajohnson@redneon.com>
     8// Copyright (C) 2010, 2012 Adrian Johnson <ajohnson@redneon.com>
    99// Copyright (C) 2010 Harry Roberts <harry.roberts@midnight-labs.org>
    1010// Copyright (C) 2011 Thomas Freitag <Thomas.Freitag@alfa.de>
     
    2626
    2727        // Send it to poppler's error handler
    28         error(-1, "%s", buffer);
     28        error(errInternal, -1, "{0:s}", buffer);
    2929}
    3030
     
    5454        jpeg_create_compress(&cinfo);
    5555       
     56        // Set colorspace and initialise defaults
     57        cinfo.in_color_space = colorMode; /* colorspace of input image */
     58        jpeg_set_defaults(&cinfo);
     59
    5660        // Set destination file
    5761        jpeg_stdio_dest(&cinfo, f);
     
    6367        cinfo.X_density = hDPI;
    6468        cinfo.Y_density = vDPI;
    65         cinfo.in_color_space = colorMode; /* colorspace of input image */
    6669        /* # of color components per pixel */
    6770        switch (colorMode) {
     
    7881                        return false;
    7982        }
    80         jpeg_set_defaults(&cinfo);
    8183        if (cinfo.in_color_space == JCS_CMYK) {
    8284                jpeg_set_colorspace(&cinfo, JCS_YCCK);
  • trunk/poppler/mypoppler/goo/JpegWriter.h

    r497 r515  
    1818#define JPEGWRITER_H
    1919
    20 #include "poppler/poppler-config.h"
     20#include "poppler-config.h"
    2121
    2222#ifdef ENABLE_LIBJPEG
  • trunk/poppler/mypoppler/goo/PNGWriter.cc

    r497 r515  
    77// Copyright (C) 2009 Warren Toomey <wkt@tuhs.org>
    88// Copyright (C) 2009 Shen Liang <shenzhuxi@gmail.com>
    9 // Copyright (C) 2009 Albert Astals Cid <aacid@kde.org>
     9// Copyright (C) 2009, 2011 Albert Astals Cid <aacid@kde.org>
    1010// Copyright (C) 2009 Stefan Thomas <thomas@eload24.com>
    1111// Copyright (C) 2010, 2011 Adrian Johnson <ajohnson@redneon.com>
     
    2020#include <zlib.h>
    2121#include <stdlib.h>
     22#include <string.h>
    2223
    2324#include "poppler/Error.h"
     
    6768        png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    6869        if (!png_ptr) {
    69                 error(-1, "png_create_write_struct failed");
     70                error(errInternal, -1, "png_create_write_struct failed");
    7071                return false;
    7172        }
     
    7374        info_ptr = png_create_info_struct(png_ptr);
    7475        if (!info_ptr) {
    75                 error(-1, "png_create_info_struct failed");
     76                error(errInternal, -1, "png_create_info_struct failed");
    7677                return false;
    7778        }
    7879
    7980        if (setjmp(png_jmpbuf(png_ptr))) {
    80                 error(-1, "png_jmpbuf failed");
     81                error(errInternal, -1, "png_jmpbuf failed");
    8182                return false;
    8283        }
     
    8586        png_init_io(png_ptr, f);
    8687        if (setjmp(png_jmpbuf(png_ptr))) {
    87                 error(-1, "Error during writing header");
     88                error(errInternal, -1, "Error during writing header");
    8889                return false;
    8990        }
     
    126127        png_write_info(png_ptr, info_ptr);
    127128        if (setjmp(png_jmpbuf(png_ptr))) {
    128                 error(-1, "error during writing png info bytes");
     129                error(errInternal, -1, "error during writing png info bytes");
    129130                return false;
    130131        }
     
    142143        /* write bytes */
    143144        if (setjmp(png_jmpbuf(png_ptr))) {
    144                 error(-1, "Error during writing bytes");
     145                error(errInternal, -1, "Error during writing bytes");
    145146                return false;
    146147        }
     
    154155        png_write_rows(png_ptr, row, 1);
    155156        if (setjmp(png_jmpbuf(png_ptr))) {
    156                 error(-1, "error during png row write");
     157                error(errInternal, -1, "error during png row write");
    157158                return false;
    158159        }
     
    166167        png_write_end(png_ptr, info_ptr);
    167168        if (setjmp(png_jmpbuf(png_ptr))) {
    168                 error(-1, "Error during end of write");
     169                error(errInternal, -1, "Error during end of write");
    169170                return false;
    170171        }
  • trunk/poppler/mypoppler/goo/PNGWriter.h

    r497 r515  
    1616#define PNGWRITER_H
    1717
    18 #include "poppler/poppler-config.h"
     18#include "poppler-config.h"
    1919
    2020#ifdef ENABLE_LIBPNG
  • trunk/poppler/mypoppler/goo/TiffWriter.h

    r497 r515  
    1313#define TIFFWRITER_H
    1414
    15 #include "poppler/poppler-config.h"
     15#include "poppler-config.h"
    1616
    1717#ifdef ENABLE_LIBTIFF
  • trunk/poppler/mypoppler/goo/gfile.cc

    r461 r515  
    4040#    include <fcntl.h>
    4141#  endif
     42#  include <time.h>
    4243#  include <limits.h>
    4344#  include <string.h>
     
    124125}
    125126
    126 GooString *appendToPath(GooString *path, char *fileName) {
     127GooString *appendToPath(GooString *path, const char *fileName) {
    127128#if defined(VMS)
    128129  //---------- VMS ----------
     
    471472}
    472473
    473 GBool openTempFile(GooString **name, FILE **f, char *mode) {
     474GBool openTempFile(GooString **name, FILE **f, const char *mode) {
    474475#if defined(_WIN32)
    475476  //---------- Win32 ----------
     
    489490    s = new GooString();
    490491  }
    491   s->append("x");
     492  s->appendf("x_{0:d}_{1:d}_",
     493             (int)GetCurrentProcessId(), (int)GetCurrentThreadId());
    492494  t = (int)time(NULL);
    493495  for (i = 0; i < 1000; ++i) {
    494     sprintf(buf, "%d", t + i);
    495     s2 = s->copy()->append(buf);
     496    s2 = s->copy()->appendf("{0:d}", t + i);
    496497    if (!(f2 = fopen(s2->getCString(), "r"))) {
    497498      if (!(f2 = fopen(s2->getCString(), mode))) {
     
    525526  if (!(*f = fopen((*name)->getCString(), mode))) {
    526527    delete (*name);
     528    *name = NULL;
    527529    return gFalse;
    528530  }
     
    550552  if (fd < 0 || !(*f = fdopen(fd, mode))) {
    551553    delete *name;
     554    *name = NULL;
    552555    return gFalse;
    553556  }
     
    561564#else
    562565  return system(cmd) ? gFalse : gTrue;
     566#endif
     567}
     568
     569#ifdef WIN32
     570GooString *fileNameToUTF8(char *path) {
     571  GooString *s;
     572  char *p;
     573
     574  s = new GooString();
     575  for (p = path; *p; ++p) {
     576    if (*p & 0x80) {
     577      s->append((char)(0xc0 | ((*p >> 6) & 0x03)));
     578      s->append((char)(0x80 | (*p & 0x3f)));
     579    } else {
     580      s->append(*p);
     581    }
     582  }
     583  return s;
     584}
     585
     586GooString *fileNameToUTF8(wchar_t *path) {
     587  GooString *s;
     588  wchar_t *p;
     589
     590  s = new GooString();
     591  for (p = path; *p; ++p) {
     592    if (*p < 0x80) {
     593      s->append((char)*p);
     594    } else if (*p < 0x800) {
     595      s->append((char)(0xc0 | ((*p >> 6) & 0x1f)));
     596      s->append((char)(0x80 | (*p & 0x3f)));
     597    } else {
     598      s->append((char)(0xe0 | ((*p >> 12) & 0x0f)));
     599      s->append((char)(0x80 | ((*p >> 6) & 0x3f)));
     600      s->append((char)(0x80 | (*p & 0x3f)));
     601    }
     602  }
     603  return s;
     604}
     605#endif
     606
     607FILE *openFile(const char *path, const char *mode) {
     608#ifdef WIN32
     609  OSVERSIONINFO version;
     610  wchar_t wPath[_MAX_PATH + 1];
     611  char nPath[_MAX_PATH + 1];
     612  wchar_t wMode[8];
     613  const char *p;
     614  int i;
     615
     616  // NB: _wfopen is only available in NT
     617  version.dwOSVersionInfoSize = sizeof(version);
     618  GetVersionEx(&version);
     619  if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
     620    for (p = path, i = 0; *p && i < _MAX_PATH; ++i) {
     621      if ((p[0] & 0xe0) == 0xc0 &&
     622          p[1] && (p[1] & 0xc0) == 0x80) {
     623        wPath[i] = (wchar_t)(((p[0] & 0x1f) << 6) |
     624                             (p[1] & 0x3f));
     625        p += 2;
     626      } else if ((p[0] & 0xf0) == 0xe0 &&
     627                 p[1] && (p[1] & 0xc0) == 0x80 &&
     628                 p[2] && (p[2] & 0xc0) == 0x80) {
     629        wPath[i] = (wchar_t)(((p[0] & 0x0f) << 12) |
     630                             ((p[1] & 0x3f) << 6) |
     631                             (p[2] & 0x3f));
     632        p += 3;
     633      } else {
     634        wPath[i] = (wchar_t)(p[0] & 0xff);
     635        p += 1;
     636      }
     637    }
     638    wPath[i] = (wchar_t)0;
     639    for (i = 0; mode[i] && i < sizeof(mode) - 1; ++i) {
     640      wMode[i] = (wchar_t)(mode[i] & 0xff);
     641    }
     642    wMode[i] = (wchar_t)0;
     643    return _wfopen(wPath, wMode);
     644  } else {
     645    for (p = path, i = 0; *p && i < _MAX_PATH; ++i) {
     646      if ((p[0] & 0xe0) == 0xc0 &&
     647          p[1] && (p[1] & 0xc0) == 0x80) {
     648        nPath[i] = (char)(((p[0] & 0x1f) << 6) |
     649                          (p[1] & 0x3f));
     650        p += 2;
     651      } else if ((p[0] & 0xf0) == 0xe0 &&
     652                 p[1] && (p[1] & 0xc0) == 0x80 &&
     653                 p[2] && (p[2] & 0xc0) == 0x80) {
     654        nPath[i] = (char)(((p[1] & 0x3f) << 6) |
     655                          (p[2] & 0x3f));
     656        p += 3;
     657      } else {
     658        nPath[i] = p[0];
     659        p += 1;
     660      }
     661    }
     662    nPath[i] = '\0';
     663    return fopen(nPath, mode);
     664  }
     665#else
     666  return fopen(path, mode);
    563667#endif
    564668}
  • trunk/poppler/mypoppler/goo/gfile.h

    r497 r515  
    2828#define GFILE_H
    2929
    30 #include "poppler/poppler-config.h"
     30#include "poppler-config.h"
    3131#include <stdio.h>
    3232#include <stdlib.h>
     
    8383// Append a file name to a path string.  <path> may be an empty
    8484// string, denoting the current directory).  Returns <path>.
    85 extern GooString *appendToPath(GooString *path, char *fileName);
     85extern GooString *appendToPath(GooString *path, const char *fileName);
    8686
    8787// Grab the path from the front of the file name.  If there is no
     
    106106// reopened later for reading, but not for writing.  The <mode> string
    107107// should be "w" or "wb".  Returns true on success.
    108 extern GBool openTempFile(GooString **name, FILE **f, char *mode);
     108extern GBool openTempFile(GooString **name, FILE **f, const char *mode);
    109109
    110110// Execute <command>.  Returns true on success.
    111111extern GBool executeCommand(char *cmd);
     112
     113#ifdef WIN32
     114// Convert a file name from Latin-1 to UTF-8.
     115extern GooString *fileNameToUTF8(char *path);
     116
     117// Convert a file name from UCS-2 to UTF-8.
     118extern GooString *fileNameToUTF8(wchar_t *path);
     119#endif
     120
     121// Open a file.  On Windows, this converts the path from UTF-8 to
     122// UCS-2 and calls _wfopen (if available).  On other OSes, this simply
     123// calls fopen.
     124extern FILE *openFile(const char *path, const char *mode);
    112125
    113126// Just like fgets, but handles Unix, Mac, and/or DOS end-of-line
  • trunk/poppler/mypoppler/goo/gmem.cc

    r470 r515  
    7272  unsigned long *trl, *p;
    7373
    74   if (size <= 0) {
     74  if (size < 0) {
     75    fprintf(stderr, "Invalid memory allocation size\n");
     76    if (checkoverflow) return NULL;
     77    else exit(1);
     78  }
     79  if (size == 0) {
    7580    return NULL;
    7681  }
     
    105110  void *p;
    106111
    107   if (size <= 0) {
     112  if (size < 0) {
     113    fprintf(stderr, "Invalid memory allocation size\n");
     114    if (checkoverflow) return NULL;
     115    else exit(1);
     116  }
     117  if (size == 0) {
    108118    return NULL;
    109119  }
     
    131141  int oldSize;
    132142
    133   if (size <= 0) {
     143  if (size < 0) {
     144    fprintf(stderr, "Invalid memory allocation size\n");
     145    if (checkoverflow) return NULL;
     146    else exit(1);
     147  }
     148  if (size == 0) {
    134149    if (p) {
    135150      gfree(p);
     
    150165  void *q;
    151166
    152   if (size <= 0) {
     167  if (size < 0) {
     168    fprintf(stderr, "Invalid memory allocation size\n");
     169    if (checkoverflow) return NULL;
     170    else exit(1);
     171  }
     172  if (size == 0) {
    153173    if (p) {
    154174      free(p);
     
    311331#endif
    312332
    313 char *copyString(char *s) {
     333char *copyString(const char *s) {
    314334  char *s1;
    315335
  • trunk/poppler/mypoppler/goo/gmem.h

    r470 r515  
    2727
    2828#include <stdio.h>
    29 #include "poppler/poppler-config.h"
     29#include "poppler-config.h"
    3030
    3131#ifdef __cplusplus
     
    7979 * Allocate memory and copy a string into it.
    8080 */
    81 extern char *copyString(char *s);
     81extern char *copyString(const char *s);
    8282
    8383/*
  • trunk/poppler/mypoppler/goo/gstrtod.cc

    r461 r515  
    11/* This file is part of Libspectre.
    22 *
    3  * Copyright (C) 2007 Albert Astals Cid <aacid@kde.org>
     3 * Copyright (C) 2007, 2012 Albert Astals Cid <aacid@kde.org>
    44 * Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
    55 *
     
    2323#include "gstrtod.h"
    2424
    25 #if !defined(OS2)
    26 #include <clocale>
    27 #include <cerrno>
    28 #include <cstdlib>
    29 #include <cstring>
    30 #else
    3125#include <locale.h>
    3226#include <errno.h>
    3327#include <stdlib.h>
    3428#include <string.h>
    35 #endif
    3629
    3730#define ascii_isspace(c) \
  • trunk/poppler/mypoppler/poppler/Annot.cc

    r497 r515  
    2525// Copyright (C) 2009 Ilya Gorenbein <igorenbein@finjan.com>
    2626// Copyright (C) 2011 José Aliste <jaliste@src.gnome.org>
     27// Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
    2728//
    2829// To see a description of the changes please see the Changelog file that
     
    4849#include "Gfx.h"
    4950#include "Lexer.h"
     51#include "PDFDoc.h"
    5052#include "Page.h"
    5153#include "Annot.h"
     
    9193// = (4 * (sqrt(2) - 1) / 3) * r
    9294#define bezierCircle 0.55228475
    93 
    94 // Ensures that x is between the limits set by low and high.
    95 // If low is greater than high the result is undefined.
    96 #define CLAMP(x, low, high)  (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
    9795
    9896AnnotLineEndingStyle parseAnnotLineEndingStyle(GooString *string) {
     
    124122}
    125123
     124const char* convertAnnotLineEndingStyle(AnnotLineEndingStyle style) {
     125  switch (style) {
     126    case annotLineEndingSquare:
     127      return "Square";
     128    case annotLineEndingCircle:
     129      return "Circle";
     130    case annotLineEndingDiamond:
     131      return "Diamond";
     132    case annotLineEndingOpenArrow:
     133      return "OpenArrow";
     134    case annotLineEndingClosedArrow:
     135      return "ClosedArrow";
     136    case annotLineEndingButt:
     137      return "Butt";
     138    case annotLineEndingROpenArrow:
     139      return "ROpenArrow";
     140    case annotLineEndingRClosedArrow:
     141      return "RClosedArrow";
     142    case annotLineEndingSlash:
     143      return "Slash";
     144    default:
     145      return "None";
     146  }
     147}
     148
    126149static AnnotExternalDataType parseAnnotExternalData(Dict* dict) {
    127150  Object obj1;
     
    252275
    253276  if (array->getLength() % 2) {
    254     error(-1, "Bad Annot Path");
     277    error(errSyntaxError, -1, "Bad Annot Path");
    255278    return;
    256279  }
     
    335358        Object obj;
    336359        if (array->get(i * 8 + j, &obj)->isNum()) {
    337           if (j % 2 == 1)
    338             quadArray[j] = CLAMP (obj.getNum(), rect->y1, rect->y2);
    339           else
    340             quadArray[j] = CLAMP (obj.getNum(), rect->x1, rect->x2);
     360          quadArray[j] = obj.getNum();
    341361        } else {
    342362            correct = gFalse;
    343363            obj.free();
    344             error (-1, "Invalid QuadPoint in annot");
     364            error (errSyntaxError, -1, "Invalid QuadPoint in annot");
    345365            break;
    346366        }
     
    366386    }
    367387  }
     388}
     389
     390AnnotQuadrilaterals::AnnotQuadrilaterals(AnnotQuadrilaterals::AnnotQuadrilateral **quads, int quadsLength) {
     391  quadrilaterals = quads;
     392  quadrilateralsLength = quadsLength;
    368393}
    369394
     
    524549    width = 0;
    525550  }
     551}
     552
     553void AnnotBorderArray::writeToObject(XRef *xref, Object *obj1) const {
     554  Object obj2;
     555
     556  obj1->initArray(xref);
     557  obj1->arrayAdd(obj2.initReal( horizontalCorner ));
     558  obj1->arrayAdd(obj2.initReal( verticalCorner ));
     559  obj1->arrayAdd(obj2.initReal( width ));
     560  // TODO: Dash array
    526561}
    527562
     
    658693}
    659694
     695void AnnotColor::writeToObject(XRef *xref, Object *obj1) const {
     696  Object obj2;
     697  int i;
     698
     699  if (length == 0) {
     700    obj1->initNull(); // Transparent (no color)
     701  } else {
     702    obj1->initArray(xref);
     703    for (i = 0; i < length; ++i)
     704      obj1->arrayAdd( obj2.initReal( values[i] ) );
     705  }
     706}
     707
    660708//------------------------------------------------------------------------
    661709// AnnotIconFit
     
    722770
    723771//------------------------------------------------------------------------
     772// AnnotAppearance
     773//------------------------------------------------------------------------
     774
     775AnnotAppearance::AnnotAppearance(PDFDoc *docA, Object *dict) {
     776  assert(dict->isDict());
     777  doc = docA;
     778  xref = docA->getXRef();
     779  dict->copy(&appearDict);
     780}
     781
     782AnnotAppearance::~AnnotAppearance() {
     783  appearDict.free();
     784}
     785
     786void AnnotAppearance::getAppearanceStream(AnnotAppearance::AnnotAppearanceType type, const char *state, Object *dest) {
     787  Object apData, stream;
     788  apData.initNull();
     789
     790  // Obtain dictionary or stream associated to appearance type
     791  if (type == appearRollover) {
     792    appearDict.dictLookupNF("R", &apData);
     793  } else if (type == appearDown) {
     794    appearDict.dictLookupNF("D", &apData);
     795  }
     796  if (apData.isNull()) { // Normal appearance, also used as fallback
     797    appearDict.dictLookupNF("N", &apData);
     798  }
     799
     800  // Search state if it's a subdictionary
     801  if (apData.isDict() && state) {
     802    Object obj1;
     803    apData.dictLookupNF(state, &obj1);
     804    apData.free();
     805    obj1.copy(&apData);
     806    obj1.free();
     807  }
     808
     809  dest->initNull();
     810  // Sanity check on the value we are about to return: it must be a ref to stream
     811  if (apData.isRef()) {
     812    apData.fetch(xref, &stream);
     813    if (stream.isStream()) {
     814      apData.copy(dest);
     815    } else {
     816      error(errSyntaxWarning, -1, "AP points to a non-stream object");
     817    }
     818    stream.free();
     819  }
     820  apData.free();
     821}
     822
     823GooString * AnnotAppearance::getStateKey(int i) {
     824  Object obj1;
     825  GooString * res = NULL;
     826  appearDict.dictLookupNF("N", &obj1);
     827  if (obj1.isDict()) {
     828    res = new GooString(obj1.dictGetKey(i));
     829  }
     830  obj1.free();
     831  return res;
     832}
     833
     834int AnnotAppearance::getNumStates() {
     835  Object obj1;
     836  int res = 0;
     837  appearDict.dictLookupNF("N", &obj1);
     838  if (obj1.isDict()) {
     839    res = obj1.dictGetLength();
     840  }
     841  obj1.free();
     842  return res;
     843}
     844
     845// Test if stateObj (a Ref or a Dict) points to the specified stream
     846GBool AnnotAppearance::referencesStream(Object *stateObj, Ref refToStream) {
     847  if (stateObj->isRef()) {
     848    Ref r = stateObj->getRef();
     849    if (r.num == refToStream.num && r.gen == refToStream.gen) {
     850      return gTrue;
     851    }
     852  } else if (stateObj->isDict()) { // Test each value
     853    const int size = stateObj->dictGetLength();
     854    for (int i = 0; i < size; ++i) {
     855      Object obj1;
     856      stateObj->dictGetValNF(i, &obj1);
     857      if (obj1.isRef()) {
     858        Ref r = obj1.getRef();
     859        if (r.num == refToStream.num && r.gen == refToStream.gen) {
     860          return gTrue;
     861        }
     862      }
     863      obj1.free();
     864    }
     865  }
     866  return gFalse; // Not found
     867}
     868
     869// Test if this AnnotAppearance references the specified stream
     870GBool AnnotAppearance::referencesStream(Ref refToStream) {
     871  Object obj1;
     872  GBool found;
     873
     874  // Scan each state's ref/subdictionary
     875  appearDict.dictLookupNF("N", &obj1);
     876  found = referencesStream(&obj1, refToStream);
     877  obj1.free();
     878  if (found)
     879    return gTrue;
     880
     881  appearDict.dictLookupNF("R", &obj1);
     882  found = referencesStream(&obj1, refToStream);
     883  obj1.free();
     884  if (found)
     885    return gTrue;
     886
     887  appearDict.dictLookupNF("D", &obj1);
     888  found = referencesStream(&obj1, refToStream);
     889  obj1.free();
     890  return found;
     891}
     892
     893// If this is the only annotation in the document that references the
     894// specified appearance stream, remove the appearance stream
     895void AnnotAppearance::removeStream(Ref refToStream) {
     896  const int lastpage = doc->getNumPages();
     897  for (int pg = 1; pg <= lastpage; ++pg) { // Scan all annotations in the document
     898    Page *page = doc->getPage(pg);
     899    if (!page) {
     900      error(errSyntaxError, -1, "Failed check for shared annotation stream at page {0:d}", pg);
     901      continue;
     902    }
     903    Annots *annots = page->getAnnots();
     904    for (int i = 0; i < annots->getNumAnnots(); ++i) {
     905      AnnotAppearance *annotAp = annots->getAnnot(i)->getAppearStreams();
     906      if (annotAp && annotAp != this && annotAp->referencesStream(refToStream)) {
     907        return; // Another annotation points to the stream -> Don't delete it
     908      }
     909    }
     910  }
     911
     912  // TODO: stream resources (e.g. font), AP name tree
     913  xref->removeIndirectObject(refToStream);
     914}
     915
     916// Removes stream if obj is a Ref, or removes pointed streams if obj is a Dict
     917void AnnotAppearance::removeStateStreams(Object *obj1) {
     918  if (obj1->isRef()) {
     919    removeStream(obj1->getRef());
     920  } else if (obj1->isDict()) {
     921    const int size = obj1->dictGetLength();
     922    for (int i = 0; i < size; ++i) {
     923      Object obj2;
     924      obj1->dictGetValNF(i, &obj2);
     925      if (obj2.isRef()) {
     926        removeStream(obj2.getRef());
     927      }
     928      obj2.free();
     929    }
     930  }
     931}
     932
     933void AnnotAppearance::removeAllStreams() {
     934  Object obj1;
     935  appearDict.dictLookupNF("N", &obj1);
     936  removeStateStreams(&obj1);
     937  obj1.free();
     938  appearDict.dictLookupNF("R", &obj1);
     939  removeStateStreams(&obj1);
     940  obj1.free();
     941  appearDict.dictLookupNF("D", &obj1);
     942  removeStateStreams(&obj1);
     943  obj1.free();
     944}
     945
     946//------------------------------------------------------------------------
    724947// AnnotAppearanceCharacs
    725948//------------------------------------------------------------------------
     
    8061029
    8071030//------------------------------------------------------------------------
     1031// AnnotAppearanceBBox
     1032//------------------------------------------------------------------------
     1033
     1034AnnotAppearanceBBox::AnnotAppearanceBBox(PDFRectangle *rect) {
     1035  origX = rect->x1;
     1036  origY = rect->y1;
     1037  borderWidth = 0;
     1038
     1039  // Initially set the same size as rect
     1040  minX = 0;
     1041  minY = 0;
     1042  maxX = rect->x2 - rect->x1;
     1043  maxY = rect->y2 - rect->y1;
     1044}
     1045
     1046void AnnotAppearanceBBox::extendTo(double x, double y) {
     1047  if (x < minX) {
     1048    minX = x;
     1049  } else if (x > maxX) {
     1050    maxX = x;
     1051  }
     1052  if (y < minY) {
     1053    minY = y;
     1054  } else if (y > maxY) {
     1055    maxY = y;
     1056  }
     1057}
     1058
     1059void AnnotAppearanceBBox::getBBoxRect(double bbox[4]) const {
     1060  Object obj2;
     1061  bbox[0] = minX - borderWidth;
     1062  bbox[1] = minY - borderWidth;
     1063  bbox[2] = maxX + borderWidth;
     1064  bbox[3] = maxY + borderWidth;
     1065}
     1066
     1067double AnnotAppearanceBBox::getPageXMin() const {
     1068  return origX + minX - borderWidth;
     1069}
     1070
     1071double AnnotAppearanceBBox::getPageYMin() const {
     1072  return origY + minY - borderWidth;
     1073}
     1074
     1075double AnnotAppearanceBBox::getPageXMax() const {
     1076  return origX + maxX + borderWidth;
     1077}
     1078
     1079double AnnotAppearanceBBox::getPageYMax() const {
     1080  return origY + maxY + borderWidth;
     1081}
     1082
     1083//------------------------------------------------------------------------
    8081084// Annot
    8091085//------------------------------------------------------------------------
    8101086
    811 Annot::Annot(XRef *xrefA, PDFRectangle *rectA, Catalog *catalog) {
     1087Annot::Annot(PDFDoc *docA, PDFRectangle *rectA) {
    8121088  Object obj1;
    8131089
     
    8161092  type = typeUnknown;
    8171093
    818   obj1.initArray (xrefA);
     1094  obj1.initArray (docA->getXRef());
    8191095  Object obj2;
    8201096  obj1.arrayAdd (obj2.initReal (rectA->x1));
     
    8241100  obj2.free ();
    8251101
    826   annotObj.initDict (xrefA);
     1102  annotObj.initDict (docA->getXRef());
    8271103  annotObj.dictSet ("Type", obj2.initName ("Annot"));
    8281104  annotObj.dictSet ("Rect", &obj1);
    8291105  // obj1 is owned by the dict
    8301106
    831   ref = xrefA->addIndirectObject (&annotObj);
    832 
    833   initialize (xrefA, annotObj.getDict(), catalog);
    834 }
    835 
    836 Annot::Annot(XRef *xrefA, Dict *dict, Catalog* catalog) {
     1107  ref = docA->getXRef()->addIndirectObject (&annotObj);
     1108
     1109  initialize (docA, annotObj.getDict());
     1110}
     1111
     1112Annot::Annot(PDFDoc *docA, Dict *dict) {
    8371113  refCnt = 1;
    8381114  hasRef = false;
     
    8401116  type = typeUnknown;
    8411117  annotObj.initDict (dict);
    842   initialize (xrefA, dict, catalog);
    843 }
    844 
    845 Annot::Annot(XRef *xrefA, Dict *dict, Catalog* catalog, Object *obj) {
     1118  initialize (docA, dict);
     1119}
     1120
     1121Annot::Annot(PDFDoc *docA, Dict *dict, Object *obj) {
    8461122  refCnt = 1;
    8471123  if (obj->isRef()) {
     
    8541130  type = typeUnknown;
    8551131  annotObj.initDict (dict);
    856   initialize (xrefA, dict, catalog);
    857 }
    858 
    859 void Annot::initialize(XRef *xrefA, Dict *dict, Catalog *catalog) {
    860   Object asObj, obj1, obj2, obj3;
    861 
    862   appRef.num = 0;
    863   appRef.gen = 65535;
     1132  initialize (docA, dict);
     1133}
     1134
     1135void Annot::initialize(PDFDoc *docA, Dict *dict) {
     1136  Object apObj, asObj, obj1, obj2;
     1137
    8641138  ok = gTrue;
    865   xref = xrefA;
     1139  doc = docA;
     1140  xref = doc->getXRef();
     1141  appearStreams = NULL;
     1142  appearBBox = NULL;
     1143  appearState = NULL;
    8661144  appearBuf = NULL;
    8671145  fontSize = 0;
     
    8961174    rect->x1 = rect->y1 = 0;
    8971175    rect->x2 = rect->y2 = 1;
    898     error(-1, "Bad bounding box for annotation");
     1176    error(errSyntaxError, -1, "Bad bounding box for annotation");
    8991177    ok = gFalse;
    9001178  }
     
    9111189    Ref ref = obj1.getRef();
    9121190
    913     page = catalog ? catalog->findPage (ref.num, ref.gen) : -1;
     1191    page = doc->getCatalog()->findPage (ref.num, ref.gen);
    9141192  } else {
    9151193    page = 0;
     
    9391217  obj1.free();
    9401218
    941   if (dict->lookup("AP", &obj1)->isDict()) {
    942     Object obj2;
    943 
    944     if (dict->lookup("AS", &obj2)->isName()) {
    945       Object obj3;
    946 
    947       appearState = new GooString(obj2.getName());
    948       if (obj1.dictLookup("N", &obj3)->isDict()) {
    949         Object obj4;
    950 
    951         if (obj3.dictLookupNF(appearState->getCString(), &obj4)->isRef()) {
    952           obj4.copy(&appearance);
    953         } else {
    954           obj4.free();
    955           if (obj3.dictLookupNF("Off", &obj4)->isRef()) {
    956             obj4.copy(&appearance);
    957           }
    958         }
    959         obj4.free();
    960       }
    961       obj3.free();
    962     } else {
    963       obj2.free();
    964 
    965       appearState = NULL;
    966       if (obj1.dictLookupNF("N", &obj2)->isRef()) {
    967         obj2.copy(&appearance);
    968       }
    969     }
    970     obj2.free();
    971   } else {
    972     appearState = NULL;
    973   }
    974   obj1.free();
     1219  //----- get the annotation appearance dictionary
     1220  dict->lookup("AP", &apObj);
     1221  if (apObj.isDict()) {
     1222    appearStreams = new AnnotAppearance(doc, &apObj);
     1223  }
     1224  apObj.free();
     1225
     1226  //----- get the appearance state
     1227  dict->lookup("AS", &asObj);
     1228  if (asObj.isName()) {
     1229    appearState = new GooString(asObj.getName());
     1230  } else if (appearStreams && appearStreams->getNumStates() != 0) {
     1231    error (errSyntaxError, -1, "Invalid or missing AS value in annotation containing one or more appearance subdictionaries");
     1232    // AS value is required in this case, but if the
     1233    // N dictionary contains only one entry
     1234    // take it as default appearance.
     1235    if (appearStreams->getNumStates() == 1) {
     1236      appearState = appearStreams->getStateKey(0);
     1237    }
     1238  }
     1239  if (!appearState) {
     1240    appearState = new GooString("Off");
     1241  }
     1242  asObj.free();
     1243
     1244  //----- get the annotation appearance
     1245  if (appearStreams) {
     1246    appearStreams->getAppearanceStream(AnnotAppearance::appearNormal, appearState->getCString(), &appearance);
     1247  }
    9751248
    9761249  //----- parse the border style
     
    10031276  obj1.free();
    10041277
    1005   optContentConfig = catalog ? catalog->getOptContentConfig() : NULL;
    10061278  dict->lookupNF("OC", &oc);
    1007   if (!oc.isRef() && !oc.isNull()) {
    1008     error (-1, "Annotation OC value not null or dict: %i", oc.getType());
    1009   }
    10101279}
    10111280
     
    10171286}
    10181287
     1288void Annot::setRect(PDFRectangle *rect) {
     1289    setRect(rect->x1, rect->y1, rect->x2, rect->y2);
     1290}
     1291
     1292void Annot::setRect(double x1, double y1, double x2, double y2) {
     1293  Object obj1, obj2;
     1294
     1295  if (x1 < x2) {
     1296    rect->x1 = x1;
     1297    rect->x2 = x2;
     1298  } else {
     1299    rect->x1 = x2;
     1300    rect->x2 = x1;
     1301  }
     1302
     1303  if (y1 < y2) {
     1304    rect->y1 = y1;
     1305    rect->y2 = y2;
     1306  } else {
     1307    rect->y1 = y2;
     1308    rect->y2 = y1;
     1309  }
     1310
     1311  obj1.initArray (xref);
     1312  obj1.arrayAdd (obj2.initReal (rect->x1));
     1313  obj1.arrayAdd (obj2.initReal (rect->y1));
     1314  obj1.arrayAdd (obj2.initReal (rect->x2));
     1315  obj1.arrayAdd (obj2.initReal (rect->y2));
     1316
     1317  update("Rect", &obj1);
     1318}
     1319
    10191320GBool Annot::inRect(double x, double y) const {
    10201321  return rect->contains(x, y);
     
    10221323
    10231324void Annot::update(const char *key, Object *value) {
    1024   /* Set M to current time */
    1025   delete modified;
    1026   modified = timeToDateString(NULL);
    1027 
    1028   Object obj1;
    1029   obj1.initString (modified->copy());
    1030   annotObj.dictSet("M", &obj1);
     1325  /* Set M to current time, unless we are updating M itself */
     1326  if (strcmp(key, "M") != 0) {
     1327    delete modified;
     1328    modified = timeToDateString(NULL);
     1329
     1330    Object obj1;
     1331    obj1.initString (modified->copy());
     1332    annotObj.dictSet("M", &obj1);
     1333  }
    10311334
    10321335  annotObj.dictSet(const_cast<char*>(key), value);
     
    10541357}
    10551358
     1359void Annot::setName(GooString *new_name) {
     1360  delete name;
     1361
     1362  if (new_name) {
     1363    name = new GooString(new_name);
     1364  } else {
     1365    name = new GooString();
     1366  }
     1367
     1368  Object obj1;
     1369  obj1.initString(name->copy());
     1370  update ("NM", &obj1);
     1371}
     1372
     1373void Annot::setModified(GooString *new_modified) {
     1374  delete modified;
     1375
     1376  if (new_modified)
     1377    modified = new GooString(new_modified);
     1378  else
     1379    modified = new GooString();
     1380
     1381  Object obj1;
     1382  obj1.initString(modified->copy());
     1383  update ("M", &obj1);
     1384}
     1385
     1386void Annot::setFlags(Guint new_flags) {
     1387  Object obj1;
     1388  flags = new_flags;
     1389  obj1.initInt(flags);
     1390  update ("F", &obj1);
     1391}
     1392
     1393void Annot::setBorder(AnnotBorderArray *new_border) {
     1394  delete border;
     1395
     1396  if (new_border) {
     1397    Object obj1;
     1398    new_border->writeToObject(xref, &obj1);
     1399    update ("Border", &obj1);
     1400    border = new_border;
     1401  } else {
     1402    border = NULL;
     1403  }
     1404}
     1405
    10561406void Annot::setColor(AnnotColor *new_color) {
    10571407  delete color;
    10581408
    10591409  if (new_color) {
    1060     Object obj1, obj2;
    1061     const double *values = new_color->getValues();
    1062 
    1063     obj1.initArray(xref);
    1064     for (int i = 0; i < (int)new_color->getSpace(); i++)
    1065       obj1.arrayAdd(obj2.initReal (values[i]));
     1410    Object obj1;
     1411    new_color->writeToObject(xref, &obj1);
    10661412    update ("C", &obj1);
    10671413    color = new_color;
     
    10801426}
    10811427
    1082 void Annot::setAppearanceState(char *state) {
     1428void Annot::setAppearanceState(const char *state) {
    10831429  if (!state)
    10841430    return;
    10851431
    1086   if (appearState && appearState->cmp(state) == 0)
    1087     return;
    1088 
    10891432  delete appearState;
    10901433  appearState = new GooString(state);
    10911434
     1435  delete appearBBox;
     1436  appearBBox = NULL;
     1437
    10921438  Object obj1;
    10931439  obj1.initName(state);
     
    10951441
    10961442  // The appearance state determines the current appearance stream
    1097   Object obj2;
    1098   if (annotObj.dictLookup("AP", &obj2)->isDict()) {
    1099     Object obj3;
    1100 
    1101     if (obj2.dictLookup("N", &obj3)->isDict()) {
    1102       Object obj4;
    1103 
    1104       appearance.free();
    1105       if (obj3.dictLookupNF(state, &obj4)->isRef())
    1106         obj4.copy(&appearance);
    1107       else
    1108         appearance.initNull();
    1109       obj4.free();
    1110     }
    1111     obj3.free();
    1112   }
    1113   obj2.free();
     1443  appearance.free();
     1444  if (appearStreams) {
     1445    appearStreams->getAppearanceStream(AnnotAppearance::appearNormal, appearState->getCString(), &appearance);
     1446  } else {
     1447    appearance.initNull();
     1448  }
     1449}
     1450
     1451void Annot::invalidateAppearance() {
     1452  if (appearStreams) { // Remove existing appearance streams
     1453    appearStreams->removeAllStreams();
     1454  }
     1455  delete appearStreams;
     1456  appearStreams = NULL;
     1457
     1458  setAppearanceState("Off"); // Default appearance state
     1459
     1460  Object obj1;
     1461  obj1.initNull();
     1462  update ("AP", &obj1); // Remove AP
     1463  update ("AS", &obj1); // Remove AS
    11141464}
    11151465
     
    11581508    delete modified;
    11591509
     1510  delete appearStreams;
     1511  delete appearBBox;
    11601512  appearance.free();
    11611513
     
    12991651}
    13001652
    1301 void Annot::createResourcesDict(char *formName, Object *formStream,
    1302                                 char *stateName,
    1303                                 double opacity, char *blendMode,
     1653void Annot::createResourcesDict(const char *formName, Object *formStream,
     1654                                const char *stateName,
     1655                                double opacity, const char *blendMode,
    13041656                                Object *resDict) {
    13051657  Object gsDict, stateDict, formDict, obj1;
     
    13221674}
    13231675
     1676Object *Annot::getAppearanceResDict(Object *dest) {
     1677  Object obj1, obj2;
     1678
     1679  dest->initNull(); // Default value
     1680
     1681  // Fetch appearance's resource dict (if any)
     1682  appearance.fetch(xref, &obj1);
     1683  if (obj1.isStream()) {
     1684    obj1.streamGetDict()->lookup("Resources", &obj2);
     1685    if (obj2.isDict()) {
     1686      obj2.copy(dest);
     1687    }
     1688    obj2.free();
     1689  }
     1690  obj1.free();
     1691
     1692  return dest;
     1693}
     1694
    13241695GBool Annot::isVisible(GBool printing) {
    13251696  // check the flags
     
    13311702
    13321703  // check the OC
    1333   if (optContentConfig && oc.isRef()) {
     1704  OCGs *optContentConfig = doc->getCatalog()->getOptContentConfig();
     1705  if (optContentConfig) {
    13341706    if (! optContentConfig->optContentIsVisible(&oc))
    13351707      return gFalse;
     
    13561728//------------------------------------------------------------------------
    13571729
    1358 AnnotPopup::AnnotPopup(XRef *xrefA, PDFRectangle *rect, Catalog *catalog) :
    1359     Annot(xrefA, rect, catalog) {
     1730AnnotPopup::AnnotPopup(PDFDoc *docA, PDFRectangle *rect) :
     1731    Annot(docA, rect) {
    13601732  Object obj1;
    13611733
     
    13631735
    13641736  annotObj.dictSet ("Subtype", obj1.initName ("Popup"));
    1365   initialize (xrefA, annotObj.getDict(), catalog);
    1366 }
    1367 
    1368 AnnotPopup::AnnotPopup(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
    1369     Annot(xrefA, dict, catalog, obj) {
     1737  initialize (docA, annotObj.getDict());
     1738}
     1739
     1740AnnotPopup::AnnotPopup(PDFDoc *docA, Dict *dict, Object *obj) :
     1741    Annot(docA, dict, obj) {
    13701742  type = typePopup;
    1371   initialize(xrefA, dict, catalog);
     1743  initialize(docA, dict);
    13721744}
    13731745
     
    13761748}
    13771749
    1378 void AnnotPopup::initialize(XRef *xrefA, Dict *dict, Catalog *catalog) {
     1750void AnnotPopup::initialize(PDFDoc *docA, Dict *dict) {
    13791751  Object obj1;
    13801752
     
    14131785// AnnotMarkup
    14141786//------------------------------------------------------------------------
    1415 AnnotMarkup::AnnotMarkup(XRef *xrefA, PDFRectangle *rect, Catalog *catalog) :
    1416     Annot(xrefA, rect, catalog) {
    1417   initialize(xrefA, annotObj.getDict(), catalog, &annotObj);
    1418 }
    1419 
    1420 AnnotMarkup::AnnotMarkup(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
    1421     Annot(xrefA, dict, catalog, obj) {
    1422   initialize(xrefA, dict, catalog, obj);
     1787AnnotMarkup::AnnotMarkup(PDFDoc *docA, PDFRectangle *rect) :
     1788    Annot(docA, rect) {
     1789  initialize(docA, annotObj.getDict(), &annotObj);
     1790}
     1791
     1792AnnotMarkup::AnnotMarkup(PDFDoc *docA, Dict *dict, Object *obj) :
     1793    Annot(docA, dict, obj) {
     1794  initialize(docA, dict, obj);
    14231795}
    14241796
     
    14371809}
    14381810
    1439 void AnnotMarkup::initialize(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) {
    1440   Object obj1;
     1811void AnnotMarkup::initialize(PDFDoc *docA, Dict *dict, Object *obj) {
     1812  Object obj1, obj2;
    14411813
    14421814  if (dict->lookup("T", &obj1)->isString()) {
     
    14471819  obj1.free();
    14481820
    1449   if (dict->lookup("Popup", &obj1)->isDict()) {
    1450     popup = new AnnotPopup(xrefA, obj1.getDict(), catalog, obj);
     1821  if (dict->lookup("Popup", &obj1)->isDict() && dict->lookupNF("Popup", &obj2)->isRef()) {
     1822    popup = new AnnotPopup(docA, obj1.getDict(), &obj2);
    14511823  } else {
    14521824    popup = NULL;
     
    15501922}
    15511923
     1924void AnnotMarkup::setDate(GooString *new_date) {
     1925  delete date;
     1926
     1927  if (new_date)
     1928    date = new GooString(new_date);
     1929  else
     1930    date = new GooString();
     1931
     1932  Object obj1;
     1933  obj1.initString(date->copy());
     1934  update ("CreationDate", &obj1);
     1935}
     1936
    15521937//------------------------------------------------------------------------
    15531938// AnnotText
    15541939//------------------------------------------------------------------------
    15551940
    1556 AnnotText::AnnotText(XRef *xrefA, PDFRectangle *rect, Catalog *catalog) :
    1557     AnnotMarkup(xrefA, rect, catalog) {
     1941AnnotText::AnnotText(PDFDoc *docA, PDFRectangle *rect) :
     1942    AnnotMarkup(docA, rect) {
    15581943  Object obj1;
    15591944
     
    15621947
    15631948  annotObj.dictSet ("Subtype", obj1.initName ("Text"));
    1564   initialize (xrefA, catalog, annotObj.getDict());
    1565 }
    1566 
    1567 AnnotText::AnnotText(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
    1568     AnnotMarkup(xrefA, dict, catalog, obj) {
     1949  initialize (docA, annotObj.getDict());
     1950}
     1951
     1952AnnotText::AnnotText(PDFDoc *docA, Dict *dict, Object *obj) :
     1953    AnnotMarkup(docA, dict, obj) {
    15691954
    15701955  type = typeText;
    15711956  flags |= flagNoZoom | flagNoRotate;
    1572   initialize (xrefA, catalog, dict);
     1957  initialize (docA, dict);
    15731958}
    15741959
     
    15771962}
    15781963
    1579 void AnnotText::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
     1964void AnnotText::initialize(PDFDoc *docA, Dict *dict) {
    15801965  Object obj1;
    15811966
     
    19342319    return;
    19352320
    1936   double rectx2 = rect->x2;
    1937   double recty2 = rect->y2;
    19382321  if (appearance.isNull()) {
    19392322    ca = opacity;
     
    19662349    appearBuf->append ("Q\n");
    19672350
     2351    // Force 24x24 rectangle
     2352    PDFRectangle fixedRect(rect->x1, rect->y1, rect->x1 + 24, rect->y1 + 24);
     2353    appearBBox = new AnnotAppearanceBBox(&fixedRect);
    19682354    double bbox[4];
    1969     bbox[0] = bbox[1] = 0;
    1970     bbox[2] = bbox[3] = 24;
     2355    appearBBox->getBBoxRect(bbox);
    19712356    if (ca == 1) {
    19722357      createForm(bbox, gFalse, NULL, &appearance);
     
    19822367    }
    19832368    delete appearBuf;
    1984 
    1985     rectx2 = rect->x1 + 24;
    1986     recty2 = rect->y1 + 24;
    19872369  }
    19882370
    19892371  // draw the appearance stream
    19902372  appearance.fetch(xref, &obj);
    1991   gfx->drawAnnot(&obj, border, color,
    1992                  rect->x1, rect->y1, rectx2, recty2);
     2373  if (appearBBox) {
     2374    gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
     2375                   appearBBox->getPageXMin(), appearBBox->getPageYMin(),
     2376                   appearBBox->getPageXMax(), appearBBox->getPageYMax());
     2377  } else {
     2378    gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
     2379                   rect->x1, rect->y1, rect->x2, rect->y2);
     2380  }
    19932381  obj.free();
    19942382}
     
    19972385// AnnotLink
    19982386//------------------------------------------------------------------------
    1999 AnnotLink::AnnotLink(XRef *xrefA, PDFRectangle *rect, Catalog *catalog) :
    2000     Annot(xrefA, rect, catalog) {
     2387AnnotLink::AnnotLink(PDFDoc *docA, PDFRectangle *rect) :
     2388    Annot(docA, rect) {
    20012389  Object obj1;
    20022390
    20032391  type = typeLink;
    20042392  annotObj.dictSet ("Subtype", obj1.initName ("Link"));
    2005   initialize (xrefA, catalog, annotObj.getDict());
    2006 }
    2007 
    2008 AnnotLink::AnnotLink(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
    2009     Annot(xrefA, dict, catalog, obj) {
     2393  initialize (docA, annotObj.getDict());
     2394}
     2395
     2396AnnotLink::AnnotLink(PDFDoc *docA, Dict *dict, Object *obj) :
     2397    Annot(docA, dict, obj) {
    20102398
    20112399  type = typeLink;
    2012   initialize (xrefA, catalog, dict);
     2400  initialize (docA, dict);
    20132401}
    20142402
     
    20232411}
    20242412
    2025 void AnnotLink::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
     2413void AnnotLink::initialize(PDFDoc *docA, Dict *dict) {
    20262414  Object obj1;
    20272415
     
    20352423    obj1.free();
    20362424    if (dict->lookup("A", &obj1)->isDict()) {
    2037       action = LinkAction::parseAction(&obj1, catalog->getBaseURI());
     2425      action = LinkAction::parseAction(&obj1, doc->getCatalog()->getBaseURI());
    20382426    }
    20392427  }
     
    20902478// AnnotFreeText
    20912479//------------------------------------------------------------------------
    2092 AnnotFreeText::AnnotFreeText(XRef *xrefA, PDFRectangle *rect, GooString *da, Catalog *catalog) :
    2093     AnnotMarkup(xrefA, rect, catalog) {
     2480AnnotFreeText::AnnotFreeText(PDFDoc *docA, PDFRectangle *rect, GooString *da) :
     2481    AnnotMarkup(docA, rect) {
    20942482  Object obj1;
    20952483
     
    21022490  annotObj.dictSet("DA", &obj2);
    21032491
    2104   initialize (xrefA, catalog, annotObj.getDict());
    2105 }
    2106 
    2107 AnnotFreeText::AnnotFreeText(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
    2108     AnnotMarkup(xrefA, dict, catalog, obj) {
     2492  initialize (docA, annotObj.getDict());
     2493}
     2494
     2495AnnotFreeText::AnnotFreeText(PDFDoc *docA, Dict *dict, Object *obj) :
     2496    AnnotMarkup(docA, dict, obj) {
    21092497  type = typeFreeText;
    2110   initialize(xrefA, catalog, dict);
     2498  initialize(docA, dict);
    21112499}
    21122500
     
    21272515}
    21282516
    2129 void AnnotFreeText::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
     2517void AnnotFreeText::initialize(PDFDoc *docA, Dict *dict) {
    21302518  Object obj1;
    21312519
     
    21342522  } else {
    21352523    appearanceString = new GooString();
    2136     error(-1, "Bad appearance for annotation");
     2524    error(errSyntaxError, -1, "Bad appearance for annotation");
    21372525    ok = gFalse;
    21382526  }
     
    22212609}
    22222610
     2611void AnnotFreeText::setAppearanceString(GooString *new_string) {
     2612  delete appearanceString;
     2613
     2614  if (new_string) {
     2615    appearanceString = new GooString(new_string);
     2616  } else {
     2617    appearanceString = new GooString();
     2618  }
     2619
     2620  Object obj1;
     2621  obj1.initString(appearanceString->copy());
     2622  update ("DA", &obj1);
     2623}
     2624
     2625void AnnotFreeText::setQuadding(AnnotFreeTextQuadding new_quadding) {
     2626  Object obj1;
     2627  quadding = new_quadding;
     2628  obj1.initInt((int)quadding);
     2629  update ("Q", &obj1);
     2630}
     2631
     2632void AnnotFreeText::setStyleString(GooString *new_string) {
     2633  delete styleString;
     2634
     2635  if (new_string) {
     2636    styleString = new GooString(new_string);
     2637    //append the unicode marker <FE FF> if needed
     2638    if (!styleString->hasUnicodeMarker()) {
     2639      styleString->insert(0, 0xff);
     2640      styleString->insert(0, 0xfe);
     2641    }
     2642  } else {
     2643    styleString = new GooString();
     2644  }
     2645
     2646  Object obj1;
     2647  obj1.initString(styleString->copy());
     2648  update ("DS", &obj1);
     2649}
     2650
     2651void AnnotFreeText::setCalloutLine(AnnotCalloutLine *line) {
     2652  delete calloutLine;
     2653
     2654  Object obj1;
     2655  if (line == NULL) {
     2656    obj1.initNull();
     2657    calloutLine = NULL;
     2658  } else {
     2659    double x1 = line->getX1(), y1 = line->getY1();
     2660    double x2 = line->getX2(), y2 = line->getY2();
     2661    Object obj2;
     2662    obj1.initArray(xref);
     2663    obj1.arrayAdd( obj2.initReal(x1) );
     2664    obj1.arrayAdd( obj2.initReal(y1) );
     2665    obj1.arrayAdd( obj2.initReal(x2) );
     2666    obj1.arrayAdd( obj2.initReal(y2) );
     2667
     2668    AnnotCalloutMultiLine *mline = dynamic_cast<AnnotCalloutMultiLine*>(line);
     2669    if (mline) {
     2670      double x3 = mline->getX3(), y3 = mline->getY3();
     2671      obj1.arrayAdd( obj2.initReal(x3) );
     2672      obj1.arrayAdd( obj2.initReal(y3) );
     2673      calloutLine = new AnnotCalloutMultiLine(x1, y1, x2, y2, x3, y3);
     2674    } else {
     2675      calloutLine = new AnnotCalloutLine(x1, y1, x2, y2);
     2676    }
     2677  }
     2678
     2679  update("CL", &obj1);
     2680}
     2681
     2682void AnnotFreeText::setIntent(AnnotFreeTextIntent new_intent) {
     2683  Object obj1;
     2684
     2685  intent = new_intent;
     2686  if (new_intent == intentFreeText)
     2687    obj1.initName("FreeText");
     2688  else if (new_intent == intentFreeTextCallout)
     2689    obj1.initName("FreeTextCallout");
     2690  else // intentFreeTextTypeWriter
     2691    obj1.initName("FreeTextTypeWriter");
     2692  update ("IT", &obj1);
     2693}
     2694
     2695static GfxFont * createAnnotDrawFont(XRef * xref, Object *fontResDict)
     2696{
     2697  Ref dummyRef = { -1, -1 };
     2698
     2699  Object baseFontObj, subtypeObj, encodingObj;
     2700  baseFontObj.initName("Helvetica");
     2701  subtypeObj.initName("Type0");
     2702  encodingObj.initName("WinAnsiEncoding");
     2703
     2704  Object fontDictObj;
     2705  Dict *fontDict = new Dict(xref);
     2706  fontDict->decRef();
     2707  fontDict->add(copyString("BaseFont"), &baseFontObj);
     2708  fontDict->add(copyString("Subtype"), &subtypeObj);
     2709  fontDict->add(copyString("Encoding"), &encodingObj);
     2710  fontDictObj.initDict(fontDict);
     2711
     2712  Object fontsDictObj;
     2713  Dict *fontsDict = new Dict(xref);
     2714  fontsDict->decRef();
     2715  fontsDict->add(copyString("AnnotDrawFont"), &fontDictObj);
     2716  fontsDictObj.initDict(fontsDict);
     2717
     2718  Dict *dict = new Dict(xref);
     2719  dict->add(copyString("Font"), &fontsDictObj);
     2720
     2721  fontResDict->initDict(dict);
     2722  return GfxFont::makeFont(xref, "AnnotDrawFont", dummyRef, fontDict);
     2723}
     2724
     2725void AnnotFreeText::parseAppearanceString(GooString *da, double &fontsize, AnnotColor* &fontcolor) {
     2726  fontsize = -1;
     2727  fontcolor = NULL;
     2728  if (da) {
     2729    GooList * daToks = new GooList();
     2730    int j, i = 0;
     2731
     2732    // Tokenize
     2733    while (i < da->getLength()) {
     2734      while (i < da->getLength() && Lexer::isSpace(da->getChar(i))) {
     2735        ++i;
     2736      }
     2737      if (i < da->getLength()) {
     2738        for (j = i + 1; j < da->getLength() && !Lexer::isSpace(da->getChar(j)); ++j) {
     2739        }
     2740        daToks->append(new GooString(da, i, j - i));
     2741        i = j;
     2742      }
     2743    }
     2744
     2745    // Scan backwards: we are looking for the last set value
     2746    for (i = daToks->getLength()-1; i >= 0; --i) {
     2747      if (fontsize == -1) {
     2748        if (!((GooString *)daToks->get(i))->cmp("Tf") && i >= 2) {
     2749            // TODO: Font name
     2750            fontsize = gatof(( (GooString *)daToks->get(i-1) )->getCString());
     2751        }
     2752      }
     2753      if (fontcolor == NULL) {
     2754        if (!((GooString *)daToks->get(i))->cmp("g") && i >= 1) {
     2755          fontcolor = new AnnotColor(gatof(( (GooString *)daToks->get(i-1) )->getCString()));
     2756        } else if (!((GooString *)daToks->get(i))->cmp("rg") && i >= 3) {
     2757          fontcolor = new AnnotColor(gatof(( (GooString *)daToks->get(i-3) )->getCString()),
     2758                                     gatof(( (GooString *)daToks->get(i-2) )->getCString()),
     2759                                     gatof(( (GooString *)daToks->get(i-1) )->getCString()));
     2760        } else if (!((GooString *)daToks->get(i))->cmp("k") && i >= 4) {
     2761          fontcolor = new AnnotColor(gatof(( (GooString *)daToks->get(i-4) )->getCString()),
     2762                                     gatof(( (GooString *)daToks->get(i-3) )->getCString()),
     2763                                     gatof(( (GooString *)daToks->get(i-2) )->getCString()),
     2764                                     gatof(( (GooString *)daToks->get(i-1) )->getCString()));
     2765        }
     2766      }
     2767    }
     2768    deleteGooList(daToks, GooString);
     2769  }
     2770}
     2771
     2772void AnnotFreeText::generateFreeTextAppearance()
     2773{
     2774  double borderWidth, ca = opacity;
     2775
     2776  appearBuf = new GooString ();
     2777  appearBuf->append ("q\n");
     2778 
     2779  if (border) {
     2780    int i, dashLength;
     2781    double *dash;
     2782    borderWidth = border->getWidth();
     2783
     2784    switch (border->getStyle()) {
     2785    case AnnotBorder::borderDashed:
     2786      appearBuf->append("[");
     2787      dashLength = border->getDashLength();
     2788      dash = border->getDash();
     2789      for (i = 0; i < dashLength; ++i)
     2790        appearBuf->appendf(" {0:.2f}", dash[i]);
     2791      appearBuf->append(" ] 0 d\n");
     2792      break;
     2793    default:
     2794      appearBuf->append("[] 0 d\n");
     2795      break;
     2796    }
     2797    appearBuf->appendf("{0:.2f} w\n", borderWidth);
     2798  } else {
     2799    borderWidth = 0; // No border
     2800  }
     2801
     2802  // Box size
     2803  const double width = rect->x2 - rect->x1;
     2804  const double height = rect->y2 - rect->y1;
     2805
     2806  // Parse some properties from the appearance string
     2807  double fontsize;
     2808  AnnotColor *fontcolor;
     2809  parseAppearanceString(appearanceString, fontsize, fontcolor);
     2810  // Default values
     2811  if (fontsize <= 0)
     2812    fontsize = 10;
     2813  if (fontcolor == NULL)
     2814    fontcolor = new AnnotColor(0, 0, 0); // Black
     2815
     2816  // Draw box
     2817  GBool doFill = (color && color->getSpace() != AnnotColor::colorTransparent);
     2818  GBool doStroke = (borderWidth != 0);
     2819  if (doFill || doStroke) {
     2820    if (doStroke) {
     2821      setColor(fontcolor, gFalse); // Border color: same as font color
     2822    }
     2823    appearBuf->appendf ("{0:.2f} {0:.2f} {1:.2f} {2:.2f} re\n", borderWidth/2, width-borderWidth, height-borderWidth);
     2824    if (doFill) {
     2825      setColor(color, gTrue);
     2826      appearBuf->append(doStroke ? "B\n" : "f\n");
     2827    } else {
     2828      appearBuf->append("S\n");
     2829    }
     2830  }
     2831
     2832  // Setup text clipping
     2833  const double textmargin = borderWidth * 2;
     2834  const double textwidth = width - 2*textmargin;
     2835  appearBuf->appendf ("{0:.2f} {0:.2f} {1:.2f} {2:.2f} re W n\n", textmargin, textwidth, height - 2*textmargin);
     2836
     2837  Object fontResDict;
     2838  GfxFont *font = createAnnotDrawFont(xref, &fontResDict);
     2839
     2840  // Set font state
     2841  setColor(fontcolor, gTrue);
     2842  appearBuf->appendf ("BT 1 0 0 1 {0:.2f} {1:.2f} Tm\n", textmargin, height - textmargin - fontsize * font->getDescent());
     2843  appearBuf->appendf ("/AnnotDrawFont {0:.2f} Tf\n", fontsize);
     2844
     2845  int i = 0;
     2846  double xposPrev = 0;
     2847  while (i < contents->getLength()) {
     2848    GooString out;
     2849    double linewidth, xpos;
     2850    layoutText(contents, &out, &i, font, &linewidth, textwidth/fontsize, NULL, gFalse);
     2851    linewidth *= fontsize;
     2852    switch (quadding) {
     2853    case quaddingCentered:
     2854      xpos = (textwidth - linewidth) / 2;
     2855      break;
     2856    case quaddingRightJustified:
     2857      xpos = textwidth - linewidth;
     2858      break;
     2859    default: // quaddingLeftJustified:
     2860      xpos = 0;
     2861      break;
     2862    }
     2863    appearBuf->appendf("{0:.2f} {1:.2f} Td\n", xpos - xposPrev, -fontsize);
     2864    writeString(&out, appearBuf);
     2865    appearBuf->append("Tj\n");
     2866    xposPrev = xpos;
     2867  }
     2868
     2869  font->decRefCnt();
     2870  delete fontcolor;
     2871  appearBuf->append ("ET Q\n");
     2872
     2873  double bbox[4];
     2874  bbox[0] = bbox[1] = 0;
     2875  bbox[2] = rect->x2 - rect->x1;
     2876  bbox[3] = rect->y2 - rect->y1;
     2877
     2878  if (ca == 1) {
     2879    createForm(bbox, gFalse, &fontResDict, &appearance);
     2880  } else {
     2881    Object aStream, resDict;
     2882
     2883    createForm(bbox, gTrue, &fontResDict, &aStream);
     2884    delete appearBuf;
     2885
     2886    appearBuf = new GooString ("/GS0 gs\n/Fm0 Do");
     2887    createResourcesDict("Fm0", &aStream, "GS0", ca, NULL, &resDict);
     2888    createForm(bbox, gFalse, &resDict, &appearance);
     2889  }
     2890  delete appearBuf;
     2891}
     2892
     2893void AnnotFreeText::draw(Gfx *gfx, GBool printing) {
     2894  Object obj;
     2895
     2896  if (!isVisible (printing))
     2897    return;
     2898
     2899  if (appearance.isNull()) {
     2900    generateFreeTextAppearance();
     2901  }
     2902
     2903  // draw the appearance stream
     2904  appearance.fetch(xref, &obj);
     2905  gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
     2906                 rect->x1, rect->y1, rect->x2, rect->y2);
     2907  obj.free();
     2908}
     2909
     2910// Before retrieving the res dict, regenerate the appearance stream if needed,
     2911// because AnnotFreeText::draw needs to store font info in the res dict
     2912Object *AnnotFreeText::getAppearanceResDict(Object *dest) {
     2913  if (appearance.isNull()) {
     2914    generateFreeTextAppearance();
     2915  }
     2916  return Annot::getAppearanceResDict(dest);
     2917}
     2918
    22232919//------------------------------------------------------------------------
    22242920// AnnotLine
    22252921//------------------------------------------------------------------------
    22262922
    2227 AnnotLine::AnnotLine(XRef *xrefA, PDFRectangle *rect, PDFRectangle *lRect, Catalog *catalog) :
    2228     AnnotMarkup(xrefA, rect, catalog) {
     2923AnnotLine::AnnotLine(PDFDoc *docA, PDFRectangle *rect, PDFRectangle *lRect) :
     2924    AnnotMarkup(docA, rect) {
    22292925  Object obj1;
    22302926
     
    22332929
    22342930  Object obj2, obj3;
    2235   obj2.initArray (xrefA);
     2931  obj2.initArray (doc->getXRef());
    22362932  obj2.arrayAdd (obj3.initReal (lRect->x1));
    22372933  obj2.arrayAdd (obj3.initReal (lRect->y1));
     
    22402936  annotObj.dictSet ("L", &obj2);
    22412937
    2242   initialize (xrefA, catalog, annotObj.getDict());
    2243 }
    2244 
    2245 AnnotLine::AnnotLine(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
    2246     AnnotMarkup(xrefA, dict, catalog, obj) {
     2938  initialize (docA, annotObj.getDict());
     2939}
     2940
     2941AnnotLine::AnnotLine(PDFDoc *docA, Dict *dict, Object *obj) :
     2942    AnnotMarkup(docA, dict, obj) {
    22472943  type = typeLine;
    2248   initialize(xrefA, catalog, dict);
     2944  initialize(docA, dict);
    22492945}
    22502946
     
    22602956}
    22612957
    2262 void AnnotLine::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
     2958void AnnotLine::initialize(PDFDoc *docA, Dict *dict) {
    22632959  Object obj1;
    22642960
     
    23973093}
    23983094
     3095void AnnotLine::setVertices(double x1, double y1, double x2, double y2) {
     3096  Object obj1, obj2;
     3097
     3098  delete coord1;
     3099  coord1 = new AnnotCoord(x1, y1);
     3100  delete coord2;
     3101  coord2 = new AnnotCoord(x2, y2);
     3102
     3103  obj1.initArray(xref);
     3104  obj1.arrayAdd( obj2.initReal(x1) );
     3105  obj1.arrayAdd( obj2.initReal(y1) );
     3106  obj1.arrayAdd( obj2.initReal(x2) );
     3107  obj1.arrayAdd( obj2.initReal(y2) );
     3108
     3109  update("L", &obj1);
     3110}
     3111
     3112void AnnotLine::setStartEndStyle(AnnotLineEndingStyle start, AnnotLineEndingStyle end) {
     3113  Object obj1, obj2;
     3114
     3115  startStyle = start;
     3116  endStyle = end;
     3117
     3118  obj1.initArray(xref);
     3119  obj1.arrayAdd( obj2.initName(convertAnnotLineEndingStyle( startStyle )) );
     3120  obj1.arrayAdd( obj2.initName(convertAnnotLineEndingStyle( endStyle )) );
     3121
     3122  update("LE", &obj1);
     3123}
     3124
     3125void AnnotLine::setInteriorColor(AnnotColor *new_color) {
     3126  delete interiorColor;
     3127
     3128  if (new_color) {
     3129    Object obj1;
     3130    new_color->writeToObject(xref, &obj1);
     3131    update ("IC", &obj1);
     3132    interiorColor = new_color;
     3133  } else {
     3134    interiorColor = NULL;
     3135  }
     3136}
     3137
     3138void AnnotLine::setLeaderLineLength(double len) {
     3139  Object obj1;
     3140
     3141  leaderLineLength = len;
     3142  obj1.initReal(len);
     3143  update ("LL", &obj1);
     3144}
     3145
     3146void AnnotLine::setLeaderLineExtension(double len) {
     3147  Object obj1;
     3148
     3149  leaderLineExtension = len;
     3150  obj1.initReal(len);
     3151  update ("LLE", &obj1);
     3152
     3153  // LL is required if LLE is present
     3154  obj1.initReal(leaderLineLength);
     3155  update ("LL", &obj1);
     3156}
     3157
     3158void AnnotLine::setCaption(bool new_cap) {
     3159  Object obj1;
     3160
     3161  caption = new_cap;
     3162  obj1.initBool(new_cap);
     3163  update ("Cap", &obj1);
     3164}
     3165
     3166void AnnotLine::setIntent(AnnotLineIntent new_intent) {
     3167  Object obj1;
     3168
     3169  intent = new_intent;
     3170  if (new_intent == intentLineArrow)
     3171    obj1.initName("LineArrow");
     3172  else // intentLineDimension
     3173    obj1.initName("LineDimension");
     3174  update ("IT", &obj1);
     3175}
     3176
     3177void AnnotLine::generateLineAppearance()
     3178{
     3179  double borderWidth, ca = opacity;
     3180
     3181  appearBBox = new AnnotAppearanceBBox(rect);
     3182  appearBuf = new GooString ();
     3183  appearBuf->append ("q\n");
     3184  if (color) {
     3185    setColor(color, gFalse);
     3186  }
     3187
     3188  if (border) {
     3189    int i, dashLength;
     3190    double *dash;
     3191
     3192    switch (border->getStyle()) {
     3193    case AnnotBorder::borderDashed:
     3194      appearBuf->append("[");
     3195      dashLength = border->getDashLength();
     3196      dash = border->getDash();
     3197      for (i = 0; i < dashLength; ++i)
     3198        appearBuf->appendf(" {0:.2f}", dash[i]);
     3199      appearBuf->append(" ] 0 d\n");
     3200      break;
     3201    default:
     3202      appearBuf->append("[] 0 d\n");
     3203      break;
     3204    }
     3205    borderWidth = border->getWidth();
     3206    appearBuf->appendf("{0:.2f} w\n", borderWidth);
     3207    appearBBox->setBorderWidth(borderWidth);
     3208  } else {
     3209    borderWidth = 0;
     3210  }
     3211
     3212  const double x1 = coord1->getX();
     3213  const double y1 = coord1->getY();
     3214  const double x2 = coord2->getX();
     3215  const double y2 = coord2->getY();
     3216
     3217  // Main segment length
     3218  const double main_len = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
     3219
     3220  // Main segment becomes positive x direction, coord1 becomes (0,0)
     3221  Matrix matr;
     3222  const double angle = atan2(y2 - y1, x2 - x1);
     3223  matr.m[0] = matr.m[3] = cos(angle);
     3224  matr.m[1] = sin(angle);
     3225  matr.m[2] = -matr.m[1];
     3226  matr.m[4] = x1-rect->x1;
     3227  matr.m[5] = y1-rect->y1;
     3228
     3229  double tx, ty, captionwidth = 0, captionheight = 0;
     3230  AnnotLineCaptionPos actualCaptionPos = captionPos;
     3231  const double fontsize = 9;
     3232  const double captionhmargin = 2; // Left and right margin (inline caption only)
     3233  const double captionmaxwidth = main_len - 2 * captionhmargin;
     3234
     3235  Object fontResDict;
     3236  GfxFont *font;
     3237
     3238  // Calculate caption width and height
     3239  if (caption) {
     3240    font = createAnnotDrawFont(xref, &fontResDict);
     3241    int lines = 0;
     3242    int i = 0;
     3243    while (i < contents->getLength()) {
     3244      GooString out;
     3245      double linewidth;
     3246      layoutText(contents, &out, &i, font, &linewidth, 0, NULL, gFalse);
     3247      linewidth *= fontsize;
     3248      if (linewidth > captionwidth) {
     3249        captionwidth = linewidth;
     3250      }
     3251      ++lines;
     3252    }
     3253    captionheight = lines * fontsize;
     3254    // If text is longer than available space, turn into captionPosTop
     3255    if (captionwidth > captionmaxwidth) {
     3256      actualCaptionPos = captionPosTop;
     3257    }
     3258  } else {
     3259    fontResDict.initNull();
     3260    font = NULL;
     3261  }
     3262
     3263  // Draw main segment
     3264  matr.transform (0, leaderLineLength, &tx, &ty);
     3265  appearBuf->appendf ("{0:.2f} {1:.2f} m\n", tx, ty);
     3266  appearBBox->extendTo (tx, ty);
     3267
     3268  if (captionwidth != 0 && actualCaptionPos == captionPosInline) { // Break in the middle
     3269    matr.transform ((main_len-captionwidth)/2 - captionhmargin, leaderLineLength, &tx, &ty);
     3270    appearBuf->appendf ("{0:.2f} {1:.2f} l S\n", tx, ty);
     3271
     3272    matr.transform ((main_len+captionwidth)/2 + captionhmargin, leaderLineLength, &tx, &ty);
     3273    appearBuf->appendf ("{0:.2f} {1:.2f} m\n", tx, ty);
     3274  }
     3275
     3276  matr.transform (main_len, leaderLineLength, &tx, &ty);
     3277  appearBuf->appendf ("{0:.2f} {1:.2f} l S\n", tx, ty);
     3278  appearBBox->extendTo (tx, ty);
     3279
     3280  // TODO: Line endings
     3281
     3282  // Draw caption text
     3283  if (caption) {
     3284    double tlx = (main_len - captionwidth) / 2, tly; // Top-left coords
     3285    if (actualCaptionPos == captionPosInline) {
     3286      tly = leaderLineLength + captionheight / 2;
     3287    } else {
     3288      tly = leaderLineLength + captionheight + 2*borderWidth;
     3289    }
     3290
     3291    tlx += captionTextHorizontal;
     3292    tly += captionTextVertical;
     3293
     3294    // Adjust bounding box
     3295    matr.transform (tlx, tly-captionheight, &tx, &ty);
     3296    appearBBox->extendTo (tx, ty);
     3297    matr.transform (tlx+captionwidth, tly-captionheight, &tx, &ty);
     3298    appearBBox->extendTo (tx, ty);
     3299    matr.transform (tlx+captionwidth, tly, &tx, &ty);
     3300    appearBBox->extendTo (tx, ty);
     3301    matr.transform (tlx, tly, &tx, &ty);
     3302    appearBBox->extendTo (tx, ty);
     3303
     3304    // Setup text state (reusing transformed top-left coord)
     3305    appearBuf->appendf ("0 g BT /AnnotDrawFont {0:.2f} Tf\n", fontsize); // Font color: black
     3306    appearBuf->appendf ("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} Tm\n",
     3307                        matr.m[0], matr.m[1], matr.m[2], matr.m[3], tx, ty);
     3308    appearBuf->appendf ("0 {0:.2f} Td\n",  -fontsize * font->getDescent());
     3309    // Draw text
     3310    int i = 0;
     3311    double xposPrev = 0;
     3312    while (i < contents->getLength()) {
     3313      GooString out;
     3314      double linewidth, xpos;
     3315      layoutText(contents, &out, &i, font, &linewidth, 0, NULL, gFalse);
     3316      linewidth *= fontsize;
     3317      xpos = (captionwidth - linewidth) / 2;
     3318      appearBuf->appendf("{0:.2f} {1:.2f} Td\n", xpos - xposPrev, -fontsize);
     3319      writeString(&out, appearBuf);
     3320      appearBuf->append ("Tj\n");
     3321      xposPrev = xpos;
     3322    }
     3323    appearBuf->append ("ET\n");
     3324    font->decRefCnt();
     3325  }
     3326
     3327  // Draw leader lines
     3328  double ll_len = fabs(leaderLineLength) + leaderLineExtension;
     3329  double sign = leaderLineLength >= 0 ? 1 : -1;
     3330  if (ll_len != 0) {
     3331    matr.transform (0, 0, &tx, &ty);
     3332    appearBuf->appendf ("{0:.2f} {1:.2f} m\n", tx, ty);
     3333    appearBBox->extendTo (tx, ty);
     3334    matr.transform (0, sign*ll_len, &tx, &ty);
     3335    appearBuf->appendf ("{0:.2f} {1:.2f} l S\n", tx, ty);
     3336    appearBBox->extendTo (tx, ty);
     3337
     3338    matr.transform (main_len, 0, &tx, &ty);
     3339    appearBuf->appendf ("{0:.2f} {1:.2f} m\n", tx, ty);
     3340    appearBBox->extendTo (tx, ty);
     3341    matr.transform (main_len, sign*ll_len, &tx, &ty);
     3342    appearBuf->appendf ("{0:.2f} {1:.2f} l S\n", tx, ty);
     3343    appearBBox->extendTo (tx, ty);
     3344  }
     3345
     3346  appearBuf->append ("Q\n");
     3347
     3348  double bbox[4];
     3349  appearBBox->getBBoxRect(bbox);
     3350  if (ca == 1) {
     3351    createForm(bbox, gFalse, &fontResDict, &appearance);
     3352  } else {
     3353    Object aStream, resDict;
     3354
     3355    createForm(bbox, gTrue, &fontResDict, &aStream);
     3356    delete appearBuf;
     3357
     3358    appearBuf = new GooString ("/GS0 gs\n/Fm0 Do");
     3359    createResourcesDict("Fm0", &aStream, "GS0", ca, NULL, &resDict);
     3360    createForm(bbox, gFalse, &resDict, &appearance);
     3361  }
     3362  delete appearBuf;
     3363}
     3364
    23993365void AnnotLine::draw(Gfx *gfx, GBool printing) {
    24003366  Object obj;
    2401   double ca = 1;
    24023367
    24033368  if (!isVisible (printing))
    24043369    return;
    24053370
    2406   /* Some documents like pdf_commenting_new.pdf,
    2407    * have y1 = y2 but line_width > 0, acroread
    2408    * renders the lines in such cases even though
    2409    * the annot bbox is empty. We adjust the bbox here
    2410    * to avoid having an empty bbox so that lines
    2411    * are rendered
    2412    */
    2413   if (rect->y1 == rect->y2)
    2414     rect->y2 += border ? border->getWidth() : 1;
    2415 
    24163371  if (appearance.isNull()) {
    2417     ca = opacity;
    2418 
    2419     appearBuf = new GooString ();
    2420     appearBuf->append ("q\n");
    2421     if (color)
    2422       setColor(color, gFalse);
    2423 
    2424     if (border) {
    2425       int i, dashLength;
    2426       double *dash;
    2427 
    2428       switch (border->getStyle()) {
    2429       case AnnotBorder::borderDashed:
    2430         appearBuf->append("[");
    2431         dashLength = border->getDashLength();
    2432         dash = border->getDash();
    2433         for (i = 0; i < dashLength; ++i)
    2434           appearBuf->appendf(" {0:.2f}", dash[i]);
    2435         appearBuf->append(" ] 0 d\n");
    2436         break;
    2437       default:
    2438         appearBuf->append("[] 0 d\n");
    2439         break;
    2440       }
    2441       appearBuf->appendf("{0:.2f} w\n", border->getWidth());
    2442     }
    2443     appearBuf->appendf ("{0:.2f} {1:.2f} m\n", coord1->getX() - rect->x1, coord1->getY() - rect->y1);
    2444     appearBuf->appendf ("{0:.2f} {1:.2f} l\n", coord2->getX() - rect->x1, coord2->getY() - rect->y1);
    2445     // TODO: Line ending, caption, leader lines
    2446     appearBuf->append ("S\n");
    2447     appearBuf->append ("Q\n");
    2448 
    2449     double bbox[4];
    2450     bbox[0] = bbox[1] = 0;
    2451     bbox[2] = rect->x2 - rect->x1;
    2452     bbox[3] = rect->y2 - rect->y1;
    2453     if (ca == 1) {
    2454       createForm(bbox, gFalse, NULL, &appearance);
    2455     } else {
    2456       Object aStream, resDict;
    2457 
    2458       createForm(bbox, gTrue, NULL, &aStream);
    2459       delete appearBuf;
    2460 
    2461       appearBuf = new GooString ("/GS0 gs\n/Fm0 Do");
    2462       createResourcesDict("Fm0", &aStream, "GS0", ca, NULL, &resDict);
    2463       createForm(bbox, gFalse, &resDict, &appearance);
    2464     }
    2465     delete appearBuf;
     3372    generateLineAppearance();
    24663373  }
    24673374
    24683375  // draw the appearance stream
    24693376  appearance.fetch(xref, &obj);
    2470   gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
    2471                  rect->x1, rect->y1, rect->x2, rect->y2);
     3377  if (appearBBox) {
     3378    gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
     3379                   appearBBox->getPageXMin(), appearBBox->getPageYMin(),
     3380                   appearBBox->getPageXMax(), appearBBox->getPageYMax());
     3381  } else {
     3382    gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
     3383                   rect->x1, rect->y1, rect->x2, rect->y2);
     3384  }
    24723385  obj.free();
     3386}
     3387
     3388// Before retrieving the res dict, regenerate the appearance stream if needed,
     3389// because AnnotLine::draw may need to store font info in the res dict
     3390Object *AnnotLine::getAppearanceResDict(Object *dest) {
     3391  if (appearance.isNull()) {
     3392    generateLineAppearance();
     3393  }
     3394  return Annot::getAppearanceResDict(dest);
    24733395}
    24743396
     
    24763398// AnnotTextMarkup
    24773399//------------------------------------------------------------------------
    2478 AnnotTextMarkup::AnnotTextMarkup(XRef *xrefA, PDFRectangle *rect, AnnotSubtype subType,
    2479                                  AnnotQuadrilaterals *quadPoints, Catalog *catalog) :
    2480     AnnotMarkup(xrefA, rect, catalog) {
     3400AnnotTextMarkup::AnnotTextMarkup(PDFDoc *docA, PDFRectangle *rect, AnnotSubtype subType,
     3401                                 AnnotQuadrilaterals *quadPoints) :
     3402    AnnotMarkup(docA, rect) {
    24813403  Object obj1;
    24823404
     
    24993421
    25003422  Object obj2;
    2501   obj2.initArray (xrefA);
     3423  obj2.initArray (doc->getXRef());
    25023424
    25033425  for (int i = 0; i < quadPoints->getQuadrilateralsLength(); ++i) {
     
    25163438  annotObj.dictSet ("QuadPoints", &obj2);
    25173439
    2518   initialize(xrefA, catalog, annotObj.getDict());
    2519 }
    2520 
    2521 AnnotTextMarkup::AnnotTextMarkup(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
    2522   AnnotMarkup(xrefA, dict, catalog, obj) {
     3440  initialize(docA, annotObj.getDict());
     3441}
     3442
     3443AnnotTextMarkup::AnnotTextMarkup(PDFDoc *docA, Dict *dict, Object *obj) :
     3444  AnnotMarkup(docA, dict, obj) {
    25233445  // the real type will be read in initialize()
    25243446  type = typeHighlight;
    2525   initialize(xrefA, catalog, dict);
    2526 }
    2527 
    2528 void AnnotTextMarkup::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
     3447  initialize(docA, dict);
     3448}
     3449
     3450void AnnotTextMarkup::initialize(PDFDoc *docA, Dict *dict) {
    25293451  Object obj1;
    25303452
     
    25463468    quadrilaterals = new AnnotQuadrilaterals(obj1.getArray(), rect);
    25473469  } else {
    2548     error(-1, "Bad Annot Text Markup QuadPoints");
     3470    error(errSyntaxError, -1, "Bad Annot Text Markup QuadPoints");
    25493471    quadrilaterals = NULL;
    25503472    ok = gFalse;
     
    25593481}
    25603482
    2561 
     3483void AnnotTextMarkup::setType(AnnotSubtype new_type) {
     3484  Object obj1;
     3485
     3486  switch (new_type) {
     3487    case typeHighlight:
     3488      obj1.initName("Highlight");
     3489      break;
     3490    case typeUnderline:
     3491      obj1.initName("Underline");
     3492      break;
     3493    case typeSquiggly:
     3494      obj1.initName("Squiggly");
     3495      break;
     3496    case typeStrikeOut:
     3497      obj1.initName("StrikeOut");
     3498      break;
     3499    default:
     3500      assert(!"Invalid subtype");
     3501  }
     3502
     3503  type = new_type;
     3504  update("Subtype", &obj1);
     3505}
     3506
     3507void AnnotTextMarkup::setQuadrilaterals(AnnotQuadrilaterals *quadPoints) {
     3508  Object obj1, obj2;
     3509  obj1.initArray (xref);
     3510
     3511  for (int i = 0; i < quadPoints->getQuadrilateralsLength(); ++i) {
     3512    obj1.arrayAdd (obj2.initReal (quadPoints->getX1(i)));
     3513    obj1.arrayAdd (obj2.initReal (quadPoints->getY1(i)));
     3514    obj1.arrayAdd (obj2.initReal (quadPoints->getX2(i)));
     3515    obj1.arrayAdd (obj2.initReal (quadPoints->getY2(i)));
     3516    obj1.arrayAdd (obj2.initReal (quadPoints->getX3(i)));
     3517    obj1.arrayAdd (obj2.initReal (quadPoints->getY3(i)));
     3518    obj1.arrayAdd (obj2.initReal (quadPoints->getX4(i)));
     3519    obj1.arrayAdd (obj2.initReal (quadPoints->getY4(i)));
     3520  }
     3521
     3522  quadrilaterals = new AnnotQuadrilaterals(obj1.getArray(), rect);
     3523
     3524  annotObj.dictSet ("QuadPoints", &obj1);
     3525}
    25623526
    25633527void AnnotTextMarkup::draw(Gfx *gfx, GBool printing) {
     
    25713535
    25723536  if (appearance.isNull() || type == typeHighlight) {
     3537    GBool blendMultiply = gTrue;
    25733538    ca = opacity;
    25743539
    25753540    appearBuf = new GooString ();
     3541    appearBuf->append ("q\n");
     3542
     3543    /* Adjust BBox */
     3544    delete appearBBox;
     3545    appearBBox = new AnnotAppearanceBBox(rect);
     3546    for (i = 0; i < quadrilaterals->getQuadrilateralsLength(); ++i) {
     3547      appearBBox->extendTo (quadrilaterals->getX1(i) - rect->x1, quadrilaterals->getY1(i) - rect->y1);
     3548      appearBBox->extendTo (quadrilaterals->getX2(i) - rect->x1, quadrilaterals->getY2(i) - rect->y1);
     3549      appearBBox->extendTo (quadrilaterals->getX3(i) - rect->x1, quadrilaterals->getY3(i) - rect->y1);
     3550      appearBBox->extendTo (quadrilaterals->getX4(i) - rect->x1, quadrilaterals->getY4(i) - rect->y1);
     3551    }
    25763552
    25773553    switch (type) {
     
    25793555      if (color) {
    25803556        setColor(color, gFalse);
    2581         setColor(color, gTrue);
    25823557      }
     3558      appearBuf->append ("[] 0 d 1 w\n");
    25833559
    25843560      for (i = 0; i < quadrilaterals->getQuadrilateralsLength(); ++i) {
    25853561        double x1, x2, y3;
    2586         double x, y;
    25873562
    25883563        x1 = quadrilaterals->getX1(i);
     
    25903565        y3 = quadrilaterals->getY3(i);
    25913566
    2592         x = x1 - rect->x1;
    2593         y = y3 - rect->y1;
    2594         appearBuf->append ("[]0 d 2 w\n");
    2595         appearBuf->appendf ("{0:.2f} {1:.2f} m\n", x, y);
    2596         appearBuf->appendf ("{0:.2f} {1:.2f} l\n", x + (x2 - x1), y);
     3567        appearBuf->appendf ("{0:.2f} {1:.2f} m\n", x1, y3);
     3568        appearBuf->appendf ("{0:.2f} {1:.2f} l\n", x2, y3);
    25973569        appearBuf->append ("S\n");
    25983570      }
     
    26013573      if (color) {
    26023574        setColor(color, gFalse);
    2603         setColor(color, gTrue);
    26043575      }
     3576      blendMultiply = gFalse;
     3577      appearBuf->append ("[] 0 d 1 w\n");
    26053578
    26063579      for (i = 0; i < quadrilaterals->getQuadrilateralsLength(); ++i) {
    26073580        double x1, y1, x2, y3;
    2608         double x, y;
    26093581        double h2;
    26103582
     
    26153587        h2 = (y1 - y3) / 2.0;
    26163588
    2617         x = x1 - rect->x1;
    2618         y = (y3 - rect->y1) + h2;
    2619         appearBuf->append ("[]0 d 2 w\n");
    2620         appearBuf->appendf ("{0:.2f} {1:.2f} m\n", x, y);
    2621         appearBuf->appendf ("{0:.2f} {1:.2f} l\n", x + (x2 - x1), y);
     3589        appearBuf->appendf ("{0:.2f} {1:.2f} m\n", x1, y3+h2);
     3590        appearBuf->appendf ("{0:.2f} {1:.2f} l\n", x2, y3+h2);
    26223591        appearBuf->append ("S\n");
    26233592      }
    26243593      break;
    26253594    case typeSquiggly:
    2626       // TODO
     3595      if (color) {
     3596        setColor(color, gFalse);
     3597      }
     3598      appearBuf->append ("[] 0 d 1 w\n");
     3599
     3600      for (i = 0; i < quadrilaterals->getQuadrilateralsLength(); ++i) {
     3601        double x1, y1, x2, y3;
     3602        double h6;
     3603
     3604        x1 = quadrilaterals->getX1(i);
     3605        y1 = quadrilaterals->getY1(i);
     3606        x2 = quadrilaterals->getX2(i);
     3607        y3 = quadrilaterals->getY3(i);
     3608        h6 = (y1 - y3) / 6.0;
     3609
     3610        appearBuf->appendf ("{0:.2f} {1:.2f} m\n", x1, y3+h6);
     3611        bool down = false;
     3612        do {
     3613          down = !down; // Zigzag line
     3614          x1 += 2;
     3615          appearBuf->appendf ("{0:.2f} {1:.2f} l\n", x1, y3 + (down ? 0 : h6));
     3616        } while (x1 < x2);
     3617        appearBuf->append ("S\n");
     3618      }
     3619      break;
    26273620    default:
    26283621    case typeHighlight:
     
    26323625        setColor(color, gTrue);
    26333626
     3627      double biggestBorder = 0;
    26343628      for (i = 0; i < quadrilaterals->getQuadrilateralsLength(); ++i) {
    26353629        double x1, y1, x2, y2, x3, y3, x4, y4;
     
    26443638        x4 = quadrilaterals->getX4(i);
    26453639        y4 = quadrilaterals->getY4(i);
    2646         h4 = abs(y1 - y3) / 4.0;
     3640        h4 = fabs(y1 - y3) / 4.0;
     3641
     3642        if (h4 > biggestBorder) {
     3643          biggestBorder = h4;
     3644        }
    26473645
    26483646        appearBuf->appendf ("{0:.2f} {1:.2f} m\n", x3, y3);
     
    26543652        appearBuf->append ("f\n");
    26553653      }
    2656 
    2657       Object aStream, resDict;
    2658       double bbox[4];
    2659       bbox[0] = rect->x1;
    2660       bbox[1] = rect->y1;
    2661       bbox[2] = rect->x2;
    2662       bbox[3] = rect->y2;
    2663       createForm(bbox, gTrue, NULL, &aStream);
     3654      appearBBox->setBorderWidth(biggestBorder);
     3655      break;
     3656    }
     3657    appearBuf->append ("Q\n");
     3658
     3659    Object aStream, resDict;
     3660    double bbox[4];
     3661    bbox[0] = appearBBox->getPageXMin();
     3662    bbox[1] = appearBBox->getPageYMin();
     3663    bbox[2] = appearBBox->getPageXMax();
     3664    bbox[3] = appearBBox->getPageYMax();
     3665    createForm(bbox, gTrue, NULL, &aStream);
     3666    delete appearBuf;
     3667
     3668    appearBuf = new GooString ("/GS0 gs\n/Fm0 Do");
     3669    createResourcesDict("Fm0", &aStream, "GS0", 1, blendMultiply ? "Multiply" : NULL, &resDict);
     3670    if (ca == 1) {
     3671      createForm(bbox, gFalse, &resDict, &appearance);
     3672    } else {
     3673      createForm(bbox, gTrue, &resDict, &aStream);
    26643674      delete appearBuf;
    26653675
    26663676      appearBuf = new GooString ("/GS0 gs\n/Fm0 Do");
    2667       createResourcesDict("Fm0", &aStream, "GS0", 1, "Multiply", &resDict);
    2668       if (ca == 1) {
    2669         createForm(bbox, gFalse, &resDict, &appearance);
    2670       } else {
    2671         createForm(bbox, gTrue, &resDict, &aStream);
    2672         delete appearBuf;
    2673 
    2674         appearBuf = new GooString ("/GS0 gs\n/Fm0 Do");
    2675         createResourcesDict("Fm0", &aStream, "GS0", ca, NULL, &resDict);
    2676         createForm(bbox, gFalse, &resDict, &appearance);
    2677       }
    2678       delete appearBuf;
    2679       break;
    2680     }
     3677      createResourcesDict("Fm0", &aStream, "GS0", ca, NULL, &resDict);
     3678      createForm(bbox, gFalse, &resDict, &appearance);
     3679    }
     3680    delete appearBuf;
    26813681  }
    26823682
    26833683  // draw the appearance stream
    26843684  appearance.fetch(xref, &obj);
    2685   gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
    2686                  rect->x1, rect->y1, rect->x2, rect->y2);
     3685  if (appearBBox) {
     3686    gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
     3687                   appearBBox->getPageXMin(), appearBBox->getPageYMin(),
     3688                   appearBBox->getPageXMax(), appearBBox->getPageYMax());
     3689  } else {
     3690    gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
     3691                   rect->x1, rect->y1, rect->x2, rect->y2);
     3692  }
    26873693  obj.free();
    26883694}
     
    26923698//------------------------------------------------------------------------
    26933699
    2694 AnnotWidget::AnnotWidget(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
    2695     Annot(xrefA, dict, catalog, obj) {
     3700AnnotWidget::AnnotWidget(PDFDoc *docA, Dict *dict, Object *obj) :
     3701    Annot(docA, dict, obj) {
    26963702  type = typeWidget;
    26973703  field = NULL;
    2698   initialize(xrefA, catalog, dict);
    2699 }
    2700 
    2701 AnnotWidget::AnnotWidget(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj, FormField *fieldA) :
    2702     Annot(xrefA, dict, catalog, obj) {
     3704  initialize(docA, dict);
     3705}
     3706
     3707AnnotWidget::AnnotWidget(PDFDoc *docA, Dict *dict, Object *obj, FormField *fieldA) :
     3708    Annot(docA, dict, obj) {
    27033709  type = typeWidget;
    27043710  field = fieldA;
    2705   initialize(xrefA, catalog, dict);
     3711  initialize(docA, dict);
    27063712}
    27073713
     
    27203726}
    27213727
    2722 void AnnotWidget::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
    2723   Object obj1;
    2724 
    2725   form = catalog->getForm();
     3728void AnnotWidget::initialize(PDFDoc *docA, Dict *dict) {
     3729  Object obj1;
     3730
     3731  form = doc->getCatalog()->getForm();
    27263732
    27273733  if(dict->lookup("H", &obj1)->isName()) {
     
    27513757  action = NULL;
    27523758  if(dict->lookup("A", &obj1)->isDict()) {
    2753     action = LinkAction::parseAction(&obj1, catalog->getBaseURI());
     3759    action = LinkAction::parseAction(&obj1, doc->getCatalog()->getBaseURI());
    27543760  }
    27553761  obj1.free();
     
    27943800//       Should be able to generate output for any CID-keyed font.
    27953801//       Doesn't handle vertical fonts--should it?
    2796 void AnnotWidget::layoutText(GooString *text, GooString *outBuf, int *i,
     3802void Annot::layoutText(GooString *text, GooString *outBuf, int *i,
    27973803                             GfxFont *font, double *width, double widthLimit,
    27983804                             int *charCount, GBool noReencode)
     
    28163822
    28173823  if (unicode && text->getLength() % 2 != 0) {
    2818     error(-1, "AnnotWidget::layoutText, bad unicode string");
     3824    error(errSyntaxError, -1, "AnnotWidget::layoutText, bad unicode string");
    28193825    return;
    28203826  }
     
    29883994// Copy the given string to appearBuf, adding parentheses around it and
    29893995// escaping characters as appropriate.
    2990 void AnnotWidget::writeString(GooString *str, GooString *appearBuf)
     3996void Annot::writeString(GooString *str, GooString *appearBuf)
    29913997{
    29923998  char c;
     
    30184024  GooString *tok, *convertedText;
    30194025  GfxFont *font;
     4026  double dx, dy;
    30204027  double fontSize, fontSize2, borderWidth, x, xPrev, y, w, wMax;
    30214028  int tfPos, tmPos, i, j;
     4029  int rot;
    30224030  GBool freeText = gFalse;      // true if text should be freed before return
    30234031  GBool freeFont = gFalse;
     
    30764084          // so create a fake one
    30774085          Ref r; // dummy Ref, it's not used at all in this codepath
    3078           r.num = 0;
    3079           r.gen = 0;
     4086          r.num = -1;
     4087          r.gen = -1;
    30804088          Dict *d = new Dict(xref);
    3081           font = new Gfx8BitFont(xref, "ZaDb", r, new GooString("ZapfDingbats"), fontType1, d);
     4089          font = new Gfx8BitFont(xref, "ZaDb", r, new GooString("ZapfDingbats"), fontType1, r, d);
    30824090          delete d;
    30834091          freeFont = gTrue;
    30844092          addDingbatsResource = gTrue;
    30854093        } else {
    3086           error(-1, "Unknown font in field's DA string");
     4094          error(errSyntaxError, -1, "Unknown font in field's DA string");
    30874095        }
    30884096      }
    30894097    } else {
    3090       error(-1, "Invalid font name in 'Tf' operator in field's DA string");
     4098      error(errSyntaxError, -1, "Invalid font name in 'Tf' operator in field's DA string");
    30914099    }
    30924100    tok = (GooString *)daToks->get(tfPos + 1);
    30934101    fontSize = gatof(tok->getCString());
    30944102  } else {
    3095     error(-1, "Missing 'Tf' operator in field's DA string");
     4103    error(errSyntaxError, -1, "Missing 'Tf' operator in field's DA string");
    30964104  }
    30974105  if (!font) {
     
    31264134  }
    31274135  appearBuf->append("q\n");
     4136  rot = appearCharacs ? appearCharacs->getRotation() : 0;
     4137  switch (rot) {
     4138  case 90:
     4139    appearBuf->appendf("0 1 -1 0 {0:.2f} 0 cm\n", rect->x2 - rect->x1);
     4140    dx = rect->y2 - rect->y1;
     4141