Changeset 277


Ignore:
Timestamp:
Dec 30, 2009, 7:13:45 PM (12 years ago)
Author:
rbri
Message:

PDF plugin: Poppler library updated to version 0.12.3

Location:
trunk/poppler/mypoppler
Files:
7 added
2 deleted
97 edited

Legend:

Unmodified
Added
Removed
  • trunk/poppler/mypoppler/fofi/FoFiTrueType.cc

    r257 r277  
    1717// Copyright (C) 2007 Koji Otani <sho@bbr.jp>
    1818// Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
    19 // Copyright (C) 2008 Albert Astals Cid <aacid@kde.org>
     19// Copyright (C) 2008, 2009 Albert Astals Cid <aacid@kde.org>
    2020// Copyright (C) 2008 Tomas Are Haavet <tomasare@gmail.com>
    2121//
     
    15401540  // construct the 'head' table, zero out the font checksum
    15411541  i = seekTable("head");
     1542  if (i < 0 || i >= nTables) {
     1543    return;
     1544  }
    15421545  pos = tables[i].offset;
    15431546  if (!checkRegion(pos, 54)) {
  • trunk/poppler/mypoppler/fofi/FoFiType1C.cc

    r250 r277  
    77//========================================================================
    88
     9//========================================================================
     10//
     11// Modified under the Poppler project - http://poppler.freedesktop.org
     12//
     13// All changes made under the Poppler project to this file are licensed
     14// under GPL version 2 or later
     15//
     16// Copyright (C) 2009 Albert Astals Cid <aacid@kde.org>
     17//
     18// To see a description of the changes please see the Changelog file that
     19// came with your tarball or type make ChangeLog if you are building from git
     20//
     21//========================================================================
     22
    923#include <config.h>
    1024
     
    1731#include <math.h>
    1832#include "goo/gmem.h"
     33#include "goo/gstrtod.h"
    1934#include "goo/GooString.h"
    2035#include "FoFiEncodings.h"
     
    24652480    } while (i < 64);
    24662481    buf[i] = '\0';
    2467     op.num = atof(buf);
     2482    op.num = gatof(buf);
    24682483    op.isFP = gTrue;
    24692484
  • trunk/poppler/mypoppler/goo/FixedPoint.h

    r250 r277  
    1212#define FIXEDPOINT_H
    1313
    14 #include <poppler/poppler-config.h>
     14#include "poppler/poppler-config.h"
    1515
    1616#if USE_FIXEDPOINT
  • trunk/poppler/mypoppler/goo/GooMutex.h

    r250 r277  
    66//
    77// Copyright 2002-2003 Glyph & Cog, LLC
     8//
     9//========================================================================
     10
     11//========================================================================
     12//
     13// Modified under the Poppler project - http://poppler.freedesktop.org
     14//
     15// All changes made under the Poppler project to this file are licensed
     16// under GPL version 2 or later
     17//
     18// Copyright (C) 2009 Kovid Goyal <kovid@kovidgoyal.net>
     19//
     20// To see a description of the changes please see the Changelog file that
     21// came with your tarball or type make ChangeLog if you are building from git
    822//
    923//========================================================================
     
    2337// gDestroyMutex(&m);
    2438
    25 #ifdef WIN32
     39#ifdef _WIN32
    2640
    2741#include <windows.h>
  • trunk/poppler/mypoppler/goo/GooString.cc

    r263 r277  
    1919// Copyright (C) 2006 Krzysztof Kowalczyk <kkowalczyk@gmail.com>
    2020// Copyright (C) 2007 Jeff Muizelaar <jeff@infidigm.net>
    21 // Copyright (C) 2008 Albert Astals Cid <aacid@kde.org>
     21// Copyright (C) 2008, 2009 Albert Astals Cid <aacid@kde.org>
    2222//
    2323// To see a description of the changes please see the Changelog file that
     
    4040#include "gmem.h"
    4141#include "GooString.h"
     42
     43static const int MAXIMUM_DOUBLE_PREC = 16;
    4244
    4345//------------------------------------------------------------------------
     
    7274  fmtULongBinary,
    7375  fmtDouble,
     76  fmtDoubleTrimSmallAware,
    7477  fmtDoubleTrim,
    7578  fmtChar,
     
    8285  "d", "x", "o", "b", "ud", "ux", "uo", "ub",
    8386  "ld", "lx", "lo", "lb", "uld", "ulx", "ulo", "ulb",
    84   "f", "g",
     87  "f", "gs", "g",
    8588  "c",
    8689  "s",
     
    380383          case fmtDouble:
    381384          case fmtDoubleTrim:
     385          case fmtDoubleTrimSmallAware:
    382386            args[argsLen].f = va_arg(argList, double);
    383387            break;
     
    456460          formatDouble(arg.f, buf, sizeof(buf), prec, gTrue, &str, &len);
    457461          break;
     462        case fmtDoubleTrimSmallAware:
     463          formatDoubleSmallAware(arg.f, buf, sizeof(buf), prec, gTrue, &str, &len);
     464          break;
    458465        case fmtChar:
    459466          buf[0] = arg.c;
     
    606613}
    607614
     615void GooString::formatDoubleSmallAware(double x, char *buf, int bufSize, int prec,
     616                                      GBool trim, char **p, int *len)
     617{
     618  double absX = fabs(x);
     619  if (absX >= 0.1) {
     620    formatDouble(x, buf, bufSize, prec, trim, p, len);
     621  } else {
     622    while (absX < 0.1 && prec < MAXIMUM_DOUBLE_PREC)
     623    {
     624      absX = absX * 10;
     625      prec++;
     626    }
     627    formatDouble(x, buf, bufSize, prec, trim, p, len);
     628  }
     629}
     630
    608631GooString *GooString::insert(int i, char c) {
    609632  return insert(i, (const char*)&c, 1);
     
    767790  for (i = 0; i < getLength(); ++i) {
    768791    c = getChar(i);
    769     if ((psmode && (c <= (char)0x20 || c >= (char)0x7f)) ||
     792    if (c <= (char)0x20 || c >= (char)0x7f ||
    770793        c == ' ' ||
    771794        c == '(' || c == ')' || c == '<' || c == '>' ||
    772795        c == '[' || c == ']' || c == '{' || c == '}' ||
    773         c == '/' || c == '%') {
     796        c == '/' || c == '%' || c == '#') {
    774797      sprintf(buf, "#%02x", c & 0xff);
    775798      name->append(buf);
  • trunk/poppler/mypoppler/goo/GooString.h

    r263 r277  
    1818// Copyright (C) 2006 Kristian HÞgsberg <krh@redhat.com>
    1919// Copyright (C) 2006 Krzysztof Kowalczyk <kkowalczyk@gmail.com>
    20 // Copyright (C) 2008 Albert Astals Cid <aacid@kde.org>
     20// Copyright (C) 2008, 2009 Albert Astals Cid <aacid@kde.org>
    2121//
    2222// To see a description of the changes please see the Changelog file that
     
    170170  static void formatDouble(double x, char *buf, int bufSize, int prec,
    171171                           GBool trim, char **p, int *len);
     172  static void formatDoubleSmallAware(double x, char *buf, int bufSize, int prec,
     173                                     GBool trim, char **p, int *len);
    172174};
    173175
  • trunk/poppler/mypoppler/goo/Makefile

    r236 r277  
    77
    88OBJS = FixedPoint.obj gfile.obj gmempp.obj GooHash.obj GooList.obj \
    9        GooString.obj GooTimer.obj gmem.obj
     9       GooString.obj GooTimer.obj gmem.obj PNGWriter.obj gstrtod.obj
    1010       
    11        
     11
    1212all: $(LIBS)
    1313
    1414$(LIBS): $(OBJS)
    15         rm -f $(LIBS)
    16         wlib $@ + $(OBJS)
     15        rm -f $(LIBS)
     16        wlib $@ + $(OBJS)
    1717
    1818.c.obj:
    19         $(CC) $(CFLAGS_C) -c $<
     19        $(CC) $(CFLAGS_C) -c $<
    2020
    2121.cc.obj:
    22         $(CC) $(CFLAGS) -c $<
     22        $(CC) $(CFLAGS) -c $<
  • trunk/poppler/mypoppler/goo/gfile.cc

    r257 r277  
    1919// Copyright (C) 2006 Kristian HÞgsberg <krh@redhat.com>
    2020// Copyright (C) 2008 Adam Batkin <adam@batkin.net>
     21// Copyright (C) 2008 Hib Eris <hib@hiberis.nl>
     22// Copyright (C) 2009 Albert Astals Cid <aacid@kde.org>
     23// Copyright (C) 2009 Kovid Goyal <kovid@kovidgoyal.net>
    2124//
    2225// To see a description of the changes please see the Changelog file that
     
    2730#include <config.h>
    2831
    29 #ifdef WIN32
     32#ifdef _WIN32
    3033#  include <time.h>
    3134#else
     
    4548#    include <unixlib.h>
    4649#  endif
    47 #endif // WIN32
     50#endif // _WIN32
    4851#include "GooString.h"
    4952#include "gfile.h"
     
    6265  return new GooString("SYS$LOGIN:");
    6366
    64 #elif defined(__EMX__) || defined(WIN32) || defined(OS2)
     67#elif defined(__EMX__) || defined(_WIN32) || defined(OS2)
    6568  //---------- OS/2+EMX and Win32 ----------
    6669  char *s;
     
    108111#if defined(__EMX__)
    109112  if (_getcwd2(buf, sizeof(buf)))
    110 #elif defined(WIN32)
     113#elif defined(_WIN32)
    111114  if (GetCurrentDirectory(sizeof(buf), buf))
    112115#elif defined(ACORN)
     
    135138      for (p2 = p1; p2 > p0 && *p2 != '.' && *p2 != '['; --p2) ;
    136139      if (*p2 == '[')
    137         ++p2;
     140        ++p2;
    138141      path->del(p2 - p0, p1 - p2);
    139142    } else if (*p1 == ':') {
     
    162165  return path;
    163166
    164 #elif defined(WIN32)
     167#elif defined(_WIN32)
    165168  //---------- Win32 ----------
    166169  GooString *tmp;
     
    223226    for (i = path->getLength() - 2; i >= 0; --i) {
    224227      if (path->getChar(i) == '/' || path->getChar(i) == '\\' ||
    225           path->getChar(i) == ':')
    226         break;
     228          path->getChar(i) == ':')
     229        break;
    227230    }
    228231    if (i <= 0) {
    229232      if (path->getChar(0) == '/' || path->getChar(0) == '\\') {
    230         path->del(1, path->getLength() - 1);
     233        path->del(1, path->getLength() - 1);
    231234      } else if (path->getLength() >= 2 && path->getChar(1) == ':') {
    232         path->del(2, path->getLength() - 2);
     235        path->del(2, path->getLength() - 2);
    233236      } else {
    234         path->clear();
    235         path->append("..");
     237        path->clear();
     238        path->append("..");
    236239      }
    237240    } else {
    238241      if (path->getChar(i-1) == ':')
    239         ++i;
     242        ++i;
    240243      path->del(i, path->getLength() - i);
    241244    }
     
    263266    for (i = path->getLength() - 2; i >= 0; --i) {
    264267      if (path->getChar(i) == '/')
    265         break;
     268        break;
    266269    }
    267270    if (i <= 0) {
    268271      if (path->getChar(0) == '/') {
    269         path->del(1, path->getLength() - 1);
     272        path->del(1, path->getLength() - 1);
    270273      } else {
    271         path->clear();
    272         path->append("..");
     274        path->clear();
     275        path->append("..");
    273276      }
    274277    } else {
     
    298301  return new GooString();
    299302
    300 #elif defined(__EMX__) || defined(WIN32) || defined(OS2)
     303#elif defined(__EMX__) || defined(_WIN32) || defined(OS2)
    301304  //---------- OS/2+EMX and Win32 ----------
    302305  char *p;
     
    340343  //---------- VMS ----------
    341344  return strchr(path, ':') ||
    342         (path[0] == '[' && path[1] != '.' && path[1] != '-');
    343 
    344 #elif defined(__EMX__) || defined(WIN32) || defined(OS2)
     345        (path[0] == '[' && path[1] != '.' && path[1] != '-');
     346
     347#elif defined(__EMX__) || defined(_WIN32) || defined(OS2)
    345348  //---------- OS/2+EMX and Win32 ----------
    346349  return path[0] == '/' || path[0] == '\\' || path[1] == ':';
     
    372375  return path;
    373376
    374 #elif defined(WIN32)
     377#elif defined(_WIN32)
    375378  //---------- Win32 ----------
    376379  char buf[_MAX_PATH];
     
    407410  path->append(buf);
    408411  return path;
    409  
     412
    410413#else
    411414  //---------- Unix and OS/2+EMX ----------
     
    419422    if (path->getChar(1) == '/' ||
    420423#ifdef __EMX__
    421         path->getChar(1) == '\\' ||
    422 #endif
    423         path->getLength() == 1) {
     424        path->getChar(1) == '\\' ||
     425#endif
     426        path->getLength() == 1) {
    424427      path->del(0, 1);
    425428      s = getHomeDir();
     
    434437#endif
    435438      if ((n = p2 - p1) > PATH_MAX)
    436         n = PATH_MAX;
     439        n = PATH_MAX;
    437440      strncpy(buf, p1, n);
    438441      buf[n] = '\0';
    439442      if ((pw = getpwnam(buf))) {
    440         path->del(0, p2 - p1 + 1);
    441         path->insert(0, pw->pw_dir);
     443        path->del(0, p2 - p1 + 1);
     444        path->insert(0, pw->pw_dir);
    442445      }
    443446    }
     
    455458
    456459time_t getModTime(char *fileName) {
    457 #ifdef WIN32
     460#ifdef _WIN32
    458461  //~ should implement this, but it's (currently) only used in xpdf
    459462  return 0;
     
    468471}
    469472
    470 GBool openTempFile(GooString **name, FILE **f, char *mode, char *ext) {
    471 #if defined(WIN32)
     473GBool openTempFile(GooString **name, FILE **f, char *mode) {
     474#if defined(_WIN32)
    472475  //---------- Win32 ----------
    473476  char *tempDir;
     
    491494    sprintf(buf, "%d", t + i);
    492495    s2 = s->copy()->append(buf);
    493     if (ext) {
    494       s2->append(ext);
    495     }
    496496    if (!(f2 = fopen(s2->getCString(), "r"))) {
    497497      if (!(f2 = fopen(s2->getCString(), mode))) {
    498         delete s2;
    499         delete s;
     498        delete s2;
     499        delete s;
    500500        return gFalse;
    501501      }
     
    522522  }
    523523  *name = new GooString(s);
    524   if (ext) {
    525     (*name)->append(ext);
    526   }
    527524  if (!(*f = fopen((*name)->getCString(), mode))) {
    528525    delete (*name);
     
    535532  int fd;
    536533
    537   if (ext) {
    538 #if HAVE_MKSTEMPS
    539     if ((s = getenv("TMPDIR"))) {
    540       *name = new GooString(s);
    541     } else {
    542       *name = new GooString("/tmp");
    543     }
    544     (*name)->append("/XXXXXX")->append(ext);
    545     fd = mkstemps((*name)->getCString(), strlen(ext));
    546 #elif defined(HAVE_MKSTEMP)
    547     if ((s = getenv("TMPDIR"))) {
    548       *name = new GooString(s);
    549     } else {
    550       *name = new GooString("/tmp");
    551     }
    552     (*name)->append("/XXXXXX")->append(ext);
    553     fd = mkstemp((*name)->getCString());
    554 #else
    555     if (!(s = tmpnam(NULL))) {
    556       return gFalse;
    557     }
     534#if HAVE_MKSTEMP
     535  if ((s = getenv("TMPDIR"))) {
    558536    *name = new GooString(s);
    559     (*name)->append(ext);
    560     fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600);
    561 #endif
    562537  } else {
    563 #if HAVE_MKSTEMP
    564     if ((s = getenv("TMPDIR"))) {
    565       *name = new GooString(s);
    566     } else {
    567       *name = new GooString("/tmp");
    568     }
    569     (*name)->append("/XXXXXX");
    570     fd = mkstemp((*name)->getCString());
     538    *name = new GooString("/tmp");
     539  }
     540  (*name)->append("/XXXXXX");
     541  fd = mkstemp((*name)->getCString());
    571542#else // HAVE_MKSTEMP
    572     if (!(s = tmpnam(NULL))) {
    573       return gFalse;
    574     }
    575     *name = new GooString(s);
    576     fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600);
     543  if (!(s = tmpnam(NULL))) {
     544    return gFalse;
     545  }
     546  *name = new GooString(s);
     547  fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600);
    577548#endif // HAVE_MKSTEMP
    578   }
    579549  if (fd < 0 || !(*f = fdopen(fd, mode))) {
    580550    delete *name;
     
    608578      c = fgetc(f);
    609579      if (c == '\x0a' && i < size - 1) {
    610         buf[i++] = (char)c;
     580        buf[i++] = (char)c;
    611581      } else if (c != EOF) {
    612         ungetc(c, f);
     582        ungetc(c, f);
    613583      }
    614584      break;
     
    629599#ifdef VMS
    630600  char *p;
    631 #elif defined(WIN32)
    632   int fa;
     601#elif defined(_WIN32)
     602  DWORD fa;
    633603#elif defined(ACORN)
    634604#else
     
    643613#ifdef VMS
    644614    if (!strcmp(nameA, "-") ||
    645         ((p = strrchr(nameA, '.')) && !strncmp(p, ".DIR;", 5)))
     615        ((p = strrchr(nameA, '.')) && !strncmp(p, ".DIR;", 5)))
    646616      dir = gTrue;
    647617#elif defined(ACORN)
    648618#else
    649 #ifdef WIN32
     619#ifdef _WIN32
    650620    fa = GetFileAttributes(fullPath->getCString());
    651621    dir = (fa != 0xFFFFFFFF && (fa & FILE_ATTRIBUTE_DIRECTORY));
     
    666636  path = new GooString(name);
    667637  doStat = doStatA;
    668 #if defined(WIN32)
     638#if defined(_WIN32)
    669639  GooString *tmp;
    670640
     
    685655GDir::~GDir() {
    686656  delete path;
    687 #if defined(WIN32)
     657#if defined(_WIN32)
    688658  if (hnd != INVALID_HANDLE_VALUE) {
    689659    FindClose(hnd);
     
    701671  GDirEntry *e;
    702672
    703 #if defined(WIN32)
     673#if defined(_WIN32)
    704674  if (hnd != INVALID_HANDLE_VALUE) {
    705675    e = new GDirEntry(path->getCString(), ffd.cFileName, doStat);
     
    745715
    746716void GDir::rewind() {
    747 #ifdef WIN32
     717#ifdef _WIN32
    748718  GooString *tmp;
    749719
  • trunk/poppler/mypoppler/goo/gfile.h

    r257 r277  
    1717//
    1818// Copyright (C) 2006 Kristian HÞgsberg <krh@redhat.com>
     19// Copyright (C) 2009 Albert Astals Cid <aacid@kde.org>
     20// Copyright (C) 2009 Kovid Goyal <kovid@kovidgoyal.net>
    1921//
    2022// To see a description of the changes please see the Changelog file that
     
    3032#include <stddef.h>
    3133extern "C" {
    32 #if defined(WIN32)
     34#if defined(_WIN32)
    3335#  include <sys/stat.h>
    3436#  ifdef FPTEX
     
    103105// reopened later for reading, but not for writing.  The <mode> string
    104106// should be "w" or "wb".  Returns true on success.
    105 extern GBool openTempFile(GooString **name, FILE **f, char *mode, char *ext);
     107extern GBool openTempFile(GooString **name, FILE **f, char *mode);
    106108
    107109// Execute <command>.  Returns true on success.
     
    127129private:
    128130
    129   GooString *name;              // dir/file name
     131  GooString *name;              // dir/file name
    130132  GooString *fullPath;
    131   GBool dir;                    // is it a directory?
     133  GBool dir;                    // is it a directory?
    132134};
    133135
     
    142144private:
    143145
    144   GooString *path;              // directory path
    145   GBool doStat;                 // call stat() for each entry?
    146 #if defined(WIN32)
     146  GooString *path;              // directory path
     147  GBool doStat;                 // call stat() for each entry?
     148#if defined(_WIN32)
    147149  WIN32_FIND_DATA ffd;
    148150  HANDLE hnd;
     
    150152#elif defined(MACOS)
    151153#else
    152   DIR *dir;                     // the DIR structure from opendir()
     154  DIR *dir;                     // the DIR structure from opendir()
    153155#ifdef VMS
    154   GBool needParent;             // need to return an entry for [-]
     156  GBool needParent;             // need to return an entry for [-]
    155157#endif
    156158#endif
  • trunk/poppler/mypoppler/goo/gmem.cc

    r257 r277  
    1515//
    1616// Copyright (C) 2005 Takashi Iwai <tiwai@suse.de>
    17 // Copyright (C) 2007, 2008 Albert Astals Cid <aacid@kde.org>
     17// Copyright (C) 2007-2009 Albert Astals Cid <aacid@kde.org>
    1818// Copyright (C) 2008 Jonathan Kew <jonathan_kew@sil.org>
    1919//
     
    6464#endif /* DEBUG_MEM */
    6565
    66 void *gmalloc(size_t size) GMEM_EXCEP {
     66inline static void *gmalloc(size_t size, bool checkoverflow) GMEM_EXCEP {
    6767#ifdef DEBUG_MEM
    6868  int size1;
     
    8181#else
    8282    fprintf(stderr, "Out of memory\n");
    83     exit(1);
     83    if (checkoverflow) return NULL;
     84    else exit(1);
    8485#endif
    8586  }
     
    116117#else
    117118    fprintf(stderr, "Out of memory\n");
    118     exit(1);
     119    if (checkoverflow) return NULL;
     120    else exit(1);
    119121#endif
    120122  }
     
    123125}
    124126
    125 void *grealloc(void *p, size_t size) GMEM_EXCEP {
     127void *gmalloc(size_t size) GMEM_EXCEP {
     128  return gmalloc(size, false);
     129}
     130
     131void *gmalloc_checkoverflow(size_t size) GMEM_EXCEP {
     132  return gmalloc(size, true);
     133}
     134
     135inline static void *grealloc(void *p, size_t size, bool checkoverflow) GMEM_EXCEP {
    126136#ifdef DEBUG_MEM
    127137  GMemHdr *hdr;
     
    138148    hdr = (GMemHdr *)((char *)p - gMemHdrSize);
    139149    oldSize = hdr->size;
    140     q = gmalloc(size);
     150    q = gmalloc(size, checkoverflow);
    141151    memcpy(q, p, size < oldSize ? size : oldSize);
    142152    gfree(p);
    143153  } else {
    144     q = gmalloc(size);
     154    q = gmalloc(size, checkoverflow);
    145155  }
    146156  return q;
     
    164174#else
    165175    fprintf(stderr, "Out of memory\n");
    166     exit(1);
     176    if (checkoverflow) return NULL;
     177    else exit(1);
    167178#endif
    168179  }
     
    171182}
    172183
    173 void *gmallocn(int nObjs, int objSize) GMEM_EXCEP {
     184void *grealloc(void *p, size_t size) GMEM_EXCEP {
     185  return grealloc(p, size, false);
     186}
     187
     188void *grealloc_checkoverflow(void *p, size_t size) GMEM_EXCEP {
     189  return grealloc(p, size, true);
     190}
     191
     192inline static void *gmallocn(int nObjs, int objSize, bool checkoverflow) GMEM_EXCEP {
    174193  int n;
    175194
     
    183202#else
    184203    fprintf(stderr, "Bogus memory allocation size\n");
    185     exit(1);
    186 #endif
    187   }
    188   return gmalloc(n);
     204    if (checkoverflow) return NULL;
     205    else exit(1);
     206#endif
     207  }
     208  return gmalloc(n, checkoverflow);
     209}
     210
     211void *gmallocn(int nObjs, int objSize) GMEM_EXCEP {
     212  return gmallocn(nObjs, objSize, false);
    189213}
    190214
    191215void *gmallocn_checkoverflow(int nObjs, int objSize) GMEM_EXCEP {
    192   int n;
    193 
    194   if (nObjs == 0) {
    195     return NULL;
    196   }
    197   n = nObjs * objSize;
    198   if (objSize <= 0 || nObjs < 0 || nObjs >= INT_MAX / objSize) {
     216  return gmallocn(nObjs, objSize, true);
     217}
     218
     219inline static void *gmallocn3(int a, int b, int c, bool checkoverflow) GMEM_EXCEP {
     220  int n = a * b;
     221  if (b <= 0 || a < 0 || a >= INT_MAX / b) {
    199222#if USE_EXCEPTIONS
    200223    throw GMemException();
    201224#else
    202225    fprintf(stderr, "Bogus memory allocation size\n");
    203     return NULL;
    204 #endif
    205   }
    206   return gmalloc(n);
    207 }
    208 
    209 void *greallocn(void *p, int nObjs, int objSize) GMEM_EXCEP {
     226    if (checkoverflow) return NULL;
     227    else exit(1);
     228#endif
     229  }
     230  return gmallocn(n, c, checkoverflow);
     231}
     232
     233void *gmallocn3(int a, int b, int c) GMEM_EXCEP {
     234  return gmallocn3(a, b, c, false);
     235}
     236
     237void *gmallocn3_checkoverflow(int a, int b, int c) GMEM_EXCEP {
     238  return gmallocn3(a, b, c, true);
     239}
     240
     241inline static void *greallocn(void *p, int nObjs, int objSize, bool checkoverflow) GMEM_EXCEP {
    210242  int n;
    211243
     
    222254#else
    223255    fprintf(stderr, "Bogus memory allocation size\n");
    224     exit(1);
    225 #endif
    226   }
    227   return grealloc(p, n);
     256    if (checkoverflow) return NULL;
     257    else exit(1);
     258#endif
     259  }
     260  return grealloc(p, n, checkoverflow);
     261}
     262
     263void *greallocn(void *p, int nObjs, int objSize) GMEM_EXCEP {
     264  return greallocn(p, nObjs, objSize, false);
    228265}
    229266
    230267void *greallocn_checkoverflow(void *p, int nObjs, int objSize) GMEM_EXCEP {
    231   int n;
    232 
    233   if (nObjs == 0) {
    234     if (p) {
    235       gfree(p);
    236     }
    237     return NULL;
    238   }
    239   n = nObjs * objSize;
    240   if (objSize <= 0 || nObjs < 0 || nObjs >= INT_MAX / objSize) {
    241 #if USE_EXCEPTIONS
    242     throw GMemException();
    243 #else
    244     fprintf(stderr, "Bogus memory allocation size\n");
    245     return NULL;
    246 #endif
    247   }
    248   return grealloc(p, n);
     268  return greallocn(p, nObjs, objSize, true);
    249269}
    250270
  • trunk/poppler/mypoppler/goo/gmem.h

    r257 r277  
    1515//
    1616// Copyright (C) 2005 Takashi Iwai <tiwai@suse.de>
    17 // Copyright (C) 2007, 2008 Albert Astals Cid <aacid@kde.org>
     17// Copyright (C) 2007-2009 Albert Astals Cid <aacid@kde.org>
    1818// Copyright (C) 2008 Jonathan Kew <jonathan_kew@sil.org>
    1919//
     
    2727
    2828#include <stdio.h>
    29 #include <poppler/poppler-config.h>
     29#include "poppler/poppler-config.h"
    3030
    3131#if USE_EXCEPTIONS
     
    5454 */
    5555extern void *gmalloc(size_t size) GMEM_EXCEP;
     56extern void *gmalloc_checkoverflow(size_t size) GMEM_EXCEP;
    5657
    5758/*
     
    6061 */
    6162extern void *grealloc(void *p, size_t size) GMEM_EXCEP;
     63extern void *grealloc_checkoverflow(size_t size) GMEM_EXCEP;
    6264
    6365/*
     
    7173extern void *gmallocn(int nObjs, int objSize) GMEM_EXCEP;
    7274extern void *gmallocn_checkoverflow(int nObjs, int objSize) GMEM_EXCEP;
     75extern void *gmallocn3(int a, int b, int c) GMEM_EXCEP;
     76extern void *gmallocn3_checkoverflow(int a, int b, int c) GMEM_EXCEP;
    7377extern void *greallocn(void *p, int nObjs, int objSize) GMEM_EXCEP;
    7478extern void *greallocn_checkoverflow(void *p, int nObjs, int objSize) GMEM_EXCEP;
  • trunk/poppler/mypoppler/poppler/ABWOutputDev.cc

    r257 r277  
    55// Copyright 2006-2007 Jauco Noordzij <jauco@jauco.nl>
    66// Copyright 2007 Dominic Lachowicz <cinamod@hotmail.com>
     7// Copyright 2008 Hib Eris <hib@hiberis.nl>
    78//
    89// Based somewhat on HtmlOutputDev.cc
     
    456457
    457458void ABWOutputDev::ATP_recursive(xmlNodePtr N_parent){
    458   xmlNodePtr N_first, N_second, N_line, N_tempCol, N_tempColset;
     459  xmlNodePtr N_first, N_second, N_line, N_tempCol, N_tempColset = NULL;
    459460
    460461  N_first  = N_parent->children;
  • trunk/poppler/mypoppler/poppler/ABWOutputDev.h

    r257 r277  
    44//
    55// Copyright 2006-2007 Jauco Noordzij <jauco@jauco.nl>
     6// Copyright (C) 2009 Kovid Goyal <kovid@kovidgoyal.net>
    67//
    78//========================================================================
     
    2829#include <libxml/xpathInternals.h>
    2930
    30 #ifdef WIN32
     31#ifdef _WIN32
    3132#  define SLASH '\\'
    3233#else
  • trunk/poppler/mypoppler/poppler/Annot.cc

    r263 r277  
    1717// Copyright (C) 2007, 2008 Julien Rebetez <julienr@svn.gnome.org>
    1818// Copyright (C) 2007-2009 Albert Astals Cid <aacid@kde.org>
    19 // Copyright (C) 2007, 2008 Carlos Garcia Campos <carlosgc@gnome.org>
     19// Copyright (C) 2007-2009 Carlos Garcia Campos <carlosgc@gnome.org>
    2020// Copyright (C) 2007, 2008 Iñigo Martínez <inigomartinez@gmail.com>
    2121// Copyright (C) 2007 Jeff Muizelaar <jeff@infidigm.net>
     
    3838#include <stdlib.h>
    3939#include <math.h>
     40#include <assert.h>
    4041#include "goo/gmem.h"
     42#include "goo/gstrtod.h"
    4143#include "GooList.h"
    4244#include "Error.h"
     
    5759#include "Sound.h"
    5860#include "FileSpec.h"
     61#include "DateInfo.h"
    5962#include <string.h>
    6063
     
    457460  int arrayLength = array->getLength();
    458461
    459   if (arrayLength >= 3) {
     462  GBool correct = gTrue;
     463  if (arrayLength == 3 || arrayLength == 4) {
    460464    // implementation note 81 in Appendix H.
    461465
    462466    if (array->get(0, &obj1)->isNum())
    463467      horizontalCorner = obj1.getNum();
     468    else
     469      correct = gFalse;
    464470    obj1.free();
    465471
    466472    if (array->get(1, &obj1)->isNum())
    467473      verticalCorner = obj1.getNum();
     474    else
     475      correct = gFalse;
    468476    obj1.free();
    469477
    470478    if (array->get(2, &obj1)->isNum())
    471479      width = obj1.getNum();
     480    else
     481      correct = gFalse;
    472482    obj1.free();
    473483
    474484    // TODO: check not all zero ? (Line Dash Pattern Page 217 PDF 8.1)
    475     if (arrayLength > 3) {
    476       GBool correct = gTrue;
    477       int tempLength = array->getLength() - 3;
    478       double *tempDash = (double *) gmallocn (tempLength, sizeof (double));
    479 
    480       for(int i = 0; i < tempLength && i < DASH_LIMIT && correct; i++) {
    481 
    482         if (array->get((i + 3), &obj1)->isNum()) {
    483           tempDash[i] = obj1.getNum();
    484 
    485           if (tempDash[i] < 0)
     485    if (arrayLength == 4) {
     486      if (array->get(3, &obj1)->isArray()) {
     487        Array *dashPattern = obj1.getArray();
     488        int tempLength = dashPattern->getLength();
     489        double *tempDash = (double *) gmallocn (tempLength, sizeof (double));
     490
     491        for(int i = 0; i < tempLength && i < DASH_LIMIT && correct; i++) {
     492
     493          if (dashPattern->get(i, &obj1)->isNum()) {
     494            tempDash[i] = obj1.getNum();
     495
     496            if (tempDash[i] < 0)
     497              correct = gFalse;
     498
     499          } else {
    486500            correct = gFalse;
    487 
     501          }
     502          obj1.free();
     503        }
     504
     505        if (correct) {
     506          dashLength = tempLength;
     507          dash = tempDash;
     508          style = borderDashed;
    488509        } else {
    489           correct = gFalse;
     510          gfree (tempDash);
    490511        }
    491         obj1.free();
    492       }
    493 
    494       if (correct) {
    495         dashLength = tempLength;
    496         dash = tempDash;
    497         style = borderDashed;
    498512      } else {
    499         gfree (tempDash);
    500       }
    501     }
     513        correct = gFalse;
     514      }
     515      obj1.free();
     516    }
     517  } else {
     518    correct = gFalse;
     519  }
     520 
     521  if (!correct) {
     522    width = 0;
    502523  }
    503524}
     
    594615}
    595616
     617AnnotColor::AnnotColor(double gray) {
     618  length = 1;
     619  values = (double *) gmallocn (length, sizeof(double));
     620
     621  values[0] = gray;
     622}
     623
     624AnnotColor::AnnotColor(double r, double g, double b) {
     625  length = 3;
     626  values = (double *) gmallocn (length, sizeof(double));
     627
     628  values[0] = r;
     629  values[1] = g;
     630  values[2] = b;
     631}
     632
     633AnnotColor::AnnotColor(double c, double m, double y, double k) {
     634  length = 4;
     635  values = (double *) gmallocn (length, sizeof(double));
     636
     637  values[0] = c;
     638  values[1] = m;
     639  values[2] = y;
     640  values[3] = k;
     641}
     642
    596643AnnotColor::AnnotColor(Array *array) {
    597644  // TODO: check what Acrobat does in the case of having more than 5 numbers.
     
    613660      obj1.free();
    614661    }
     662  } else {
     663    values = NULL;
     664    length = 0;
    615665  }
    616666}
     
    796846//------------------------------------------------------------------------
    797847
     848Annot::Annot(XRef *xrefA, PDFRectangle *rectA, Catalog *catalog) {
     849  Object obj1;
     850
     851  flags = flagUnknown;
     852  type = typeUnknown;
     853
     854  obj1.initArray (xrefA);
     855  Object obj2;
     856  obj1.arrayAdd (obj2.initReal (rectA->x1));
     857  obj1.arrayAdd (obj2.initReal (rectA->y1));
     858  obj1.arrayAdd (obj2.initReal (rectA->x2));
     859  obj1.arrayAdd (obj2.initReal (rectA->y2));
     860  obj2.free ();
     861
     862  annotObj.initDict (xrefA);
     863  annotObj.dictSet ("Type", obj2.initName ("Annot"));
     864  annotObj.dictSet ("Rect", &obj1);
     865  // obj1 is owned by the dict
     866
     867  ref = xrefA->addIndirectObject (&annotObj);
     868
     869  initialize (xrefA, annotObj.getDict(), catalog);
     870}
     871
    798872Annot::Annot(XRef *xrefA, Dict *dict, Catalog* catalog) {
    799873  hasRef = false;
    800874  flags = flagUnknown;
    801875  type = typeUnknown;
     876  annotObj.initDict (dict);
    802877  initialize (xrefA, dict, catalog);
    803878}
     
    812887  flags = flagUnknown;
    813888  type = typeUnknown;
     889  annotObj.initDict (dict);
    814890  initialize (xrefA, dict, catalog);
    815891}
     
    9671043}
    9681044
     1045void Annot::update(const char *key, Object *value) {
     1046  /* Set M to current time */
     1047  delete modified;
     1048  modified = timeToDateString(NULL);
     1049
     1050  Object obj1;
     1051  obj1.initString (modified->copy());
     1052  annotObj.dictSet("M", &obj1);
     1053
     1054  annotObj.dictSet(const_cast<char*>(key), value);
     1055 
     1056  xref->setModifiedObject(&annotObj, ref);
     1057}
     1058
     1059void Annot::setContents(GooString *new_content) {
     1060  delete contents;
     1061
     1062  if (new_content) {
     1063    contents = new GooString(new_content);
     1064    //append the unicode marker <FE FF> if needed       
     1065    if (!contents->hasUnicodeMarker()) {
     1066      contents->insert(0, 0xff);
     1067      contents->insert(0, 0xfe);
     1068    }
     1069  } else {
     1070    contents = new GooString();
     1071  }
     1072 
     1073  Object obj1;
     1074  obj1.initString(contents->copy());
     1075  update ("Contents", &obj1);
     1076}
     1077
     1078void Annot::setColor(AnnotColor *new_color) {
     1079  delete color;
     1080
     1081  if (new_color) {
     1082    Object obj1, obj2;
     1083    double *values = new_color->getValues();
     1084
     1085    obj1.initArray(xref);
     1086    for (int i = 0; i < (int)new_color->getSpace(); i++)
     1087      obj1.arrayAdd(obj2.initReal (values[i]));
     1088    update ("C", &obj1);
     1089    color = new_color;
     1090  } else {
     1091    color = NULL;
     1092  }
     1093}
     1094
    9691095double Annot::getXMin() {
    9701096  return rect->x1;
     
    9891115
    9901116Annot::~Annot() {
     1117  annotObj.free();
     1118 
    9911119  delete rect;
    992 
     1120 
    9931121  if (contents)
    9941122    delete contents;
     
    11661294//------------------------------------------------------------------------
    11671295
     1296AnnotPopup::AnnotPopup(XRef *xrefA, PDFRectangle *rect, Catalog *catalog) :
     1297    Annot(xrefA, rect, catalog) {
     1298  Object obj1;
     1299
     1300  type = typePopup;
     1301
     1302  annotObj.dictSet ("Subtype", obj1.initName ("Popup"));
     1303  initialize (xrefA, annotObj.getDict(), catalog);
     1304}
     1305
    11681306AnnotPopup::AnnotPopup(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
    11691307    Annot(xrefA, dict, catalog, obj) {
     
    11731311
    11741312AnnotPopup::~AnnotPopup() {
    1175   /*
    1176   if (parent)
    1177     delete parent;
    1178   */
     1313  parent.free();
    11791314}
    11801315
    11811316void AnnotPopup::initialize(XRef *xrefA, Dict *dict, Catalog *catalog) {
    11821317  Object obj1;
    1183   /*
    1184   if (dict->lookup("Parent", &obj1)->isDict()) {
    1185     parent = NULL;
    1186   } else {
    1187     parent = NULL;
    1188   }
    1189   obj1.free();
    1190   */
     1318
     1319  if (!dict->lookupNF("Parent", &parent)->isRef()) {
     1320    parent.initNull();
     1321  }
     1322
    11911323  if (dict->lookup("Open", &obj1)->isBool()) {
    11921324    open = obj1.getBool();
     
    11971329}
    11981330
     1331void AnnotPopup::setParent(Object *parentA) {
     1332  parentA->copy(&parent);
     1333  update ("Parent", &parent);
     1334}
     1335
     1336void AnnotPopup::setParent(Annot *parentA) {
     1337  Ref parentRef = parentA->getRef();
     1338  parent.initRef(parentRef.num, parentRef.gen);
     1339  update ("Parent", &parent);
     1340}
     1341
     1342void AnnotPopup::setOpen(GBool openA) {
     1343  Object obj1;
     1344
     1345  open = openA;
     1346  obj1.initBool(open);
     1347  update ("Open", &obj1);
     1348}
     1349
    11991350//------------------------------------------------------------------------
    12001351// AnnotMarkup
    12011352//------------------------------------------------------------------------
    1202  
     1353AnnotMarkup::AnnotMarkup(XRef *xrefA, PDFRectangle *rect, Catalog *catalog) :
     1354    Annot(xrefA, rect, catalog) {
     1355  initialize(xrefA, annotObj.getDict(), catalog, &annotObj);
     1356}
     1357
    12031358AnnotMarkup::AnnotMarkup(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
    12041359    Annot(xrefA, dict, catalog, obj) {
     
    12901445}
    12911446
     1447void AnnotMarkup::setLabel(GooString *new_label) {
     1448  delete label;
     1449
     1450  if (new_label) {
     1451    label = new GooString(new_label);
     1452    //append the unicode marker <FE FF> if needed
     1453    if (!label->hasUnicodeMarker()) {
     1454      label->insert(0, 0xff);
     1455      label->insert(0, 0xfe);
     1456    }
     1457  } else {
     1458    label = new GooString();
     1459  }
     1460
     1461  Object obj1;
     1462  obj1.initString(label->copy());
     1463  update ("T", &obj1);
     1464}
     1465
     1466void AnnotMarkup::setPopup(AnnotPopup *new_popup) {
     1467  delete popup;
     1468
     1469  if (new_popup) {
     1470    Object obj1;
     1471    Ref popupRef = new_popup->getRef();
     1472
     1473    obj1.initRef (popupRef.num, popupRef.gen);
     1474    update ("Popup", &obj1);
     1475
     1476    new_popup->setParent(this);
     1477    popup = new_popup;
     1478  } else {
     1479    popup = NULL;
     1480  }
     1481}
     1482
    12921483//------------------------------------------------------------------------
    12931484// AnnotText
    12941485//------------------------------------------------------------------------
     1486
     1487AnnotText::AnnotText(XRef *xrefA, PDFRectangle *rect, Catalog *catalog) :
     1488    AnnotMarkup(xrefA, rect, catalog) {
     1489  Object obj1;
     1490
     1491  type = typeText;
     1492  flags |= flagNoZoom | flagNoRotate;
     1493
     1494  annotObj.dictSet ("Subtype", obj1.initName ("Text"));
     1495  initialize (xrefA, catalog, annotObj.getDict());
     1496}
    12951497
    12961498AnnotText::AnnotText(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
     
    13041506AnnotText::~AnnotText() {
    13051507  delete icon;
    1306 }
    1307 
    1308 void AnnotText::setModified(GooString *date) {
    1309   if (date) {
    1310     delete modified;
    1311     modified = new GooString(date);
    1312   }
    13131508}
    13141509
     
    13941589}
    13951590
     1591void AnnotText::setOpen(GBool openA) {
     1592  Object obj1;
     1593
     1594  open = openA;
     1595  obj1.initBool(open);
     1596  update ("Open", &obj1);
     1597}
     1598
     1599void AnnotText::setIcon(GooString *new_icon) {
     1600  if (new_icon && icon->cmp(new_icon) == 0)
     1601    return;
     1602
     1603  delete icon;
     1604
     1605  if (new_icon) {
     1606    icon = new GooString (new_icon);
     1607  } else {
     1608    icon = new GooString("Note");
     1609  }
     1610
     1611  Object obj1;
     1612  obj1.initName (icon->getCString());
     1613  update("Name", &obj1);
     1614}
     1615
    13961616//------------------------------------------------------------------------
    13971617// AnnotLink
    13981618//------------------------------------------------------------------------
     1619AnnotLink::AnnotLink(XRef *xrefA, PDFRectangle *rect, Catalog *catalog) :
     1620    Annot(xrefA, rect, catalog) {
     1621  Object obj1;
     1622
     1623  type = typeLink;
     1624  annotObj.dictSet ("Subtype", obj1.initName ("Link"));
     1625  initialize (xrefA, catalog, annotObj.getDict());
     1626}
    13991627
    14001628AnnotLink::AnnotLink(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
     
    14851713// AnnotFreeText
    14861714//------------------------------------------------------------------------
     1715AnnotFreeText::AnnotFreeText(XRef *xrefA, PDFRectangle *rect, GooString *da, Catalog *catalog) :
     1716    AnnotMarkup(xrefA, rect, catalog) {
     1717  Object obj1;
     1718
     1719  type = typeFreeText;
     1720
     1721  annotObj.dictSet ("Subtype", obj1.initName ("FreeText"));
     1722
     1723  Object obj2;
     1724  obj2.initString (da->copy());
     1725  annotObj.dictSet("DA", &obj2);
     1726
     1727  initialize (xrefA, catalog, annotObj.getDict());
     1728}
    14871729
    14881730AnnotFreeText::AnnotFreeText(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
     
    16081850//------------------------------------------------------------------------
    16091851
     1852AnnotLine::AnnotLine(XRef *xrefA, PDFRectangle *rect, PDFRectangle *lRect, Catalog *catalog) :
     1853    AnnotMarkup(xrefA, rect, catalog) {
     1854  Object obj1;
     1855
     1856  type = typeLine;
     1857  annotObj.dictSet ("Subtype", obj1.initName ("Line"));
     1858
     1859  Object obj2, obj3;
     1860  obj2.initArray (xrefA);
     1861  obj2.arrayAdd (obj3.initReal (lRect->x1));
     1862  obj2.arrayAdd (obj3.initReal (lRect->y1));
     1863  obj2.arrayAdd (obj3.initReal (lRect->x2));
     1864  obj2.arrayAdd (obj3.initReal (lRect->y2));
     1865  annotObj.dictSet ("L", &obj2);
     1866
     1867  initialize (xrefA, catalog, annotObj.getDict());
     1868}
     1869
    16101870AnnotLine::AnnotLine(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
    16111871    AnnotMarkup(xrefA, dict, catalog, obj) {
     
    17672027// AnnotTextMarkup
    17682028//------------------------------------------------------------------------
     2029AnnotTextMarkup::AnnotTextMarkup(XRef *xrefA, PDFRectangle *rect, AnnotSubtype subType,
     2030                                 AnnotQuadrilaterals *quadPoints, Catalog *catalog) :
     2031    AnnotMarkup(xrefA, rect, catalog) {
     2032  Object obj1;
     2033
     2034  switch (subType) {
     2035    case typeHighlight:
     2036      annotObj.dictSet ("Subtype", obj1.initName ("Highlight"));
     2037      break;
     2038    case typeUnderline:
     2039      annotObj.dictSet ("Subtype", obj1.initName ("Underline"));
     2040      break;
     2041    case typeSquiggly:
     2042      annotObj.dictSet ("Subtype", obj1.initName ("Squiggly"));
     2043      break;
     2044    case typeStrikeOut:
     2045      annotObj.dictSet ("Subtype", obj1.initName ("StrikeOut"));
     2046      break;
     2047    default:
     2048      assert (0 && "Invalid subtype for AnnotTextMarkup\n");
     2049  }
     2050
     2051  Object obj2;
     2052  obj2.initArray (xrefA);
     2053
     2054  for (int i = 0; i < quadPoints->getQuadrilateralsLength(); ++i) {
     2055    Object obj3;
     2056
     2057    obj2.arrayAdd (obj3.initReal (quadPoints->getX1(i)));
     2058    obj2.arrayAdd (obj3.initReal (quadPoints->getY1(i)));
     2059    obj2.arrayAdd (obj3.initReal (quadPoints->getX2(i)));
     2060    obj2.arrayAdd (obj3.initReal (quadPoints->getY2(i)));
     2061    obj2.arrayAdd (obj3.initReal (quadPoints->getX3(i)));
     2062    obj2.arrayAdd (obj3.initReal (quadPoints->getY3(i)));
     2063    obj2.arrayAdd (obj3.initReal (quadPoints->getX4(i)));
     2064    obj2.arrayAdd (obj3.initReal (quadPoints->getY4(i)));
     2065  }
     2066
     2067  annotObj.dictSet ("QuadPoints", &obj2);
     2068
     2069  initialize(xrefA, catalog, annotObj.getDict());
     2070}
    17692071
    17702072AnnotTextMarkup::AnnotTextMarkup(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
     
    19312233  double dx, dy, ox, oy;
    19322234  GBool unicode = text->hasUnicodeMarker();
    1933   CharCodeToUnicode *ccToUnicode = font->getToUnicode();
    1934   ccToUnicode->decRefCnt();
    19352235  GBool spacePrev;              // previous character was a space
    19362236
     
    19962296    if (noReencode) {
    19972297      outBuf->append(uChar);
    1998     } else if (ccToUnicode->mapToCharCode(&uChar, &c, 1)) {
    1999       if (font->isCIDFont()) {
    2000         // TODO: This assumes an identity CMap.  It should be extended to
    2001         // handle the general case.
    2002         outBuf->append((c >> 8) & 0xff);
    2003         outBuf->append(c & 0xff);
     2298    } else {
     2299      CharCodeToUnicode *ccToUnicode = font->getToUnicode();
     2300      if (!ccToUnicode) {
     2301        // This assumes an identity CMap.
     2302        outBuf->append((uChar >> 8) & 0xff);
     2303        outBuf->append(uChar & 0xff);
     2304      } else if (ccToUnicode->mapToCharCode(&uChar, &c, 1)) {
     2305        ccToUnicode->decRefCnt();
     2306        if (font->isCIDFont()) {
     2307          // TODO: This assumes an identity CMap.  It should be extended to
     2308          // handle the general case.
     2309          outBuf->append((c >> 8) & 0xff);
     2310          outBuf->append(c & 0xff);
     2311        } else {
     2312          // 8-bit font
     2313          outBuf->append(c);
     2314        }
    20042315      } else {
    2005         // 8-bit font
    2006         outBuf->append(c);
    2007       }
    2008     } else {
    2009       fprintf(stderr,
    2010               "warning: layoutText: cannot convert U+%04X\n", uChar);
     2316        ccToUnicode->decRefCnt();
     2317        fprintf(stderr,
     2318                "warning: layoutText: cannot convert U+%04X\n", uChar);
     2319      }
    20112320    }
    20122321
     
    22112520    }
    22122521    tok = (GooString *)daToks->get(tfPos + 1);
    2213     fontSize = atof(tok->getCString());
     2522    fontSize = gatof(tok->getCString());
    22142523  } else {
    22152524    error(-1, "Missing 'Tf' operator in field's DA string");
     
    25702879    }
    25712880    tok = (GooString *)daToks->get(tfPos + 1);
    2572     fontSize = atof(tok->getCString());
     2881    fontSize = gatof(tok->getCString());
    25732882  } else {
    25742883    error(-1, "Missing 'Tf' operator in field's DA string");
     
    31613470// AnnotMovie
    31623471//------------------------------------------------------------------------
    3163  
     3472AnnotMovie::AnnotMovie(XRef *xrefA, PDFRectangle *rect, Movie *movieA, Catalog *catalog) :
     3473    Annot(xrefA, rect, catalog) {
     3474  Object obj1;
     3475
     3476  type = typeMovie;
     3477  annotObj.dictSet ("Subtype", obj1.initName ("Movie"));
     3478
     3479  movie = movieA->copy();
     3480  // TODO: create movie dict from movieA
     3481
     3482  initialize(xrefA, catalog, annotObj.getDict());
     3483}
     3484
    31643485AnnotMovie::AnnotMovie(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
    31653486  Annot(xrefA, dict, catalog, obj) {
     
    32163537  if (dict->lookup("Movie", &movieDict)->isDict()) {
    32173538    Object obj2;
    3218     getFileSpecNameForPlatform(movieDict.dictLookup("F", &obj1), &obj2);
    3219     fileName = obj2.getString()->copy();
    3220     obj2.free();
     3539    if (getFileSpecNameForPlatform(movieDict.dictLookup("F", &obj1), &obj2)) {
     3540      fileName = obj2.getString()->copy();
     3541      obj2.free();
     3542    }
    32213543    obj1.free();
    32223544
     
    32253547      if (aspect->getLength() >= 2) {
    32263548        Object tmp;
    3227         width = aspect->get(0, &tmp)->getInt();
     3549        if( aspect->get(0, &tmp)->isNum() ) {
     3550          width = (int)floor( aspect->get(0, &tmp)->getNum() + 0.5 );
     3551        }
    32283552        tmp.free();
    3229         height = aspect->get(1, &tmp)->getInt();
     3553        if( aspect->get(1, &tmp)->isNum() ) {
     3554          height = (int)floor( aspect->get(1, &tmp)->getNum() + 0.5 );
     3555        }
    32303556        tmp.free();
    32313557      }
     
    34263752// AnnotScreen
    34273753//------------------------------------------------------------------------
    3428  
     3754AnnotScreen::AnnotScreen(XRef *xrefA, PDFRectangle *rect, Catalog *catalog) :
     3755    Annot(xrefA, rect, catalog) {
     3756  Object obj1;
     3757
     3758  type = typeScreen;
     3759
     3760  annotObj.dictSet ("Subtype", obj1.initName ("Screen"));
     3761  initialize(xrefA, catalog, annotObj.getDict());
     3762}
     3763
    34293764AnnotScreen::AnnotScreen(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
    34303765  Annot(xrefA, dict, catalog, obj) {
     
    34673802// AnnotStamp
    34683803//------------------------------------------------------------------------
    3469  
     3804AnnotStamp::AnnotStamp(XRef *xrefA, PDFRectangle *rect, Catalog *catalog) :
     3805  AnnotMarkup(xrefA, rect, catalog) {
     3806  Object obj1;
     3807
     3808  type = typeStamp;
     3809  annotObj.dictSet ("Subtype", obj1.initName ("Stamp"));
     3810  initialize(xrefA, catalog, annotObj.getDict());
     3811}
     3812
    34703813AnnotStamp::AnnotStamp(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
    34713814  AnnotMarkup(xrefA, dict, catalog, obj) {
     
    34933836// AnnotGeometry
    34943837//------------------------------------------------------------------------
     3838AnnotGeometry::AnnotGeometry(XRef *xrefA, PDFRectangle *rect, AnnotSubtype subType, Catalog *catalog) :
     3839    AnnotMarkup(xrefA, rect, catalog) {
     3840  Object obj1;
     3841
     3842  switch (subType) {
     3843    case typeSquare:
     3844      annotObj.dictSet ("Subtype", obj1.initName ("Square"));
     3845      break;
     3846    case typeCircle:
     3847      annotObj.dictSet ("Subtype", obj1.initName ("Circle"));
     3848      break;
     3849    default:
     3850      assert (0 && "Invalid subtype for AnnotGeometry\n");
     3851  }
     3852
     3853  initialize(xrefA, catalog, annotObj.getDict());
     3854}
    34953855
    34963856AnnotGeometry::AnnotGeometry(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
     
    35453905// AnnotPolygon
    35463906//------------------------------------------------------------------------
     3907AnnotPolygon::AnnotPolygon(XRef *xrefA, PDFRectangle *rect, AnnotSubtype subType,
     3908                           AnnotPath *path, Catalog *catalog) :
     3909    AnnotMarkup(xrefA, rect, catalog) {
     3910  Object obj1;
     3911
     3912  switch (subType) {
     3913    case typePolygon:
     3914      annotObj.dictSet ("Subtype", obj1.initName ("Polygon"));
     3915      break;
     3916    case typePolyLine:
     3917      annotObj.dictSet ("Subtype", obj1.initName ("PolyLine"));
     3918      break;
     3919    default:
     3920      assert (0 && "Invalid subtype for AnnotGeometry\n");
     3921  }
     3922
     3923  Object obj2;
     3924  obj2.initArray (xrefA);
     3925
     3926  for (int i = 0; i < path->getCoordsLength(); ++i) {
     3927    Object obj3;
     3928
     3929    obj2.arrayAdd (obj3.initReal (path->getX(i)));
     3930    obj2.arrayAdd (obj3.initReal (path->getY(i)));
     3931  }
     3932
     3933  annotObj.dictSet ("Vertices", &obj2);
     3934
     3935  initialize(xrefA, catalog, annotObj.getDict());
     3936}
    35473937
    35483938AnnotPolygon::AnnotPolygon(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
     
    36394029// AnnotCaret
    36404030//------------------------------------------------------------------------
     4031AnnotCaret::AnnotCaret(XRef *xrefA, PDFRectangle *rect, Catalog *catalog) :
     4032    AnnotMarkup(xrefA, rect, catalog) {
     4033  Object obj1;
     4034
     4035  type = typeCaret;
     4036
     4037  annotObj.dictSet ("Subtype", obj1.initName ("Caret"));
     4038  initialize(xrefA, catalog, annotObj.getDict());
     4039}
    36414040
    36424041AnnotCaret::AnnotCaret(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
     
    36764075// AnnotInk
    36774076//------------------------------------------------------------------------
     4077AnnotInk::AnnotInk(XRef *xrefA, PDFRectangle *rect, AnnotPath **paths, int n_paths, Catalog *catalog) :
     4078    AnnotMarkup(xrefA, rect, catalog) {
     4079  Object obj1;
     4080
     4081  type = typeInk;
     4082
     4083  annotObj.dictSet ("Subtype", obj1.initName ("Ink"));
     4084
     4085  Object obj2;
     4086  obj2.initArray (xrefA);
     4087
     4088  for (int i = 0; i < n_paths; ++i) {
     4089    AnnotPath *path = paths[i];
     4090    Object obj3;
     4091    obj3.initArray (xrefA);
     4092
     4093    for (int j = 0; j < path->getCoordsLength(); ++j) {
     4094      Object obj4;
     4095
     4096      obj3.arrayAdd (obj4.initReal (path->getX(j)));
     4097      obj3.arrayAdd (obj4.initReal (path->getY(j)));
     4098    }
     4099
     4100    obj2.arrayAdd (&obj3);
     4101  }
     4102
     4103  annotObj.dictSet ("InkList", &obj2);
     4104
     4105  initialize(xrefA, catalog, annotObj.getDict());
     4106}
    36784107
    36794108AnnotInk::AnnotInk(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
     
    37174146// AnnotFileAttachment
    37184147//------------------------------------------------------------------------
     4148AnnotFileAttachment::AnnotFileAttachment(XRef *xrefA, PDFRectangle *rect, GooString *filename, Catalog *catalog) :
     4149    AnnotMarkup(xrefA, rect, catalog) {
     4150  Object obj1;
     4151
     4152  type = typeFileAttachment;
     4153
     4154  annotObj.dictSet ("Subtype", obj1.initName ("FileAttachment"));
     4155
     4156  Object obj2;
     4157  obj2.initString(filename->copy());
     4158  annotObj.dictSet ("FS", &obj2);
     4159
     4160  initialize(xrefA, catalog, annotObj.getDict());
     4161}
    37194162
    37204163AnnotFileAttachment::AnnotFileAttachment(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
     
    37344177  Object obj1;
    37354178
    3736   if (dict->lookup("FS", &obj1)->isDict()) {
     4179  if (dict->lookup("FS", &obj1)->isDict() || dict->lookup("FS", &obj1)->isString()) {
    37374180    obj1.copy(&file);
    37384181  } else {
     
    37534196// AnnotSound
    37544197//------------------------------------------------------------------------
     4198AnnotSound::AnnotSound(XRef *xrefA, PDFRectangle *rect, Sound *soundA, Catalog *catalog) :
     4199    AnnotMarkup(xrefA, rect, catalog) {
     4200  Object obj1;
     4201
     4202  type = typeSound;
     4203
     4204  annotObj.dictSet ("Subtype", obj1.initName ("Sound"));
     4205
     4206  Object obj2;
     4207  Stream *str = soundA->getStream();
     4208  obj2.initStream (str);
     4209  str->incRef(); //FIXME: initStream should do this?
     4210  annotObj.dictSet ("Sound", &obj2);
     4211
     4212  initialize(xrefA, catalog, annotObj.getDict());
     4213}
    37554214
    37564215AnnotSound::AnnotSound(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
     
    37874246// Annot3D
    37884247//------------------------------------------------------------------------
     4248Annot3D::Annot3D(XRef *xrefA, PDFRectangle *rect, Catalog *catalog) :
     4249    Annot(xrefA, rect, catalog) {
     4250  Object obj1;
     4251
     4252  type = type3D;
     4253
     4254  annotObj.dictSet ("Subtype", obj1.initName ("3D"));
     4255
     4256  initialize(xrefA, catalog, annotObj.getDict());
     4257}
    37894258
    37904259Annot3D::Annot3D(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
     
    39924461    } else if (!typeName->cmp("3D")) {
    39934462      annot = new Annot3D(xref, dict, catalog, obj);
     4463    } else if (!typeName->cmp("Popup")) {
     4464      /* Popup annots are already handled by markup annots
     4465       * Here we only care about popup annots without a
     4466       * markup annotation associated
     4467       */
     4468      Object obj2;
     4469
     4470      if (dict->lookup("Parent", &obj2)->isNull())
     4471        annot = new AnnotPopup(xref, dict, catalog, obj);
     4472      else
     4473        annot = NULL;
     4474     
     4475      obj2.free();
    39944476    } else {
    39954477      annot = new Annot(xref, dict, catalog, obj);
  • trunk/poppler/mypoppler/poppler/Annot.h

    r263 r277  
    1616// Copyright (C) 2006 Scott Turner <scotty1024@mac.com>
    1717// Copyright (C) 2007, 2008 Julien Rebetez <julienr@svn.gnome.org>
    18 // Copyright (C) 2007, 2008 Carlos Garcia Campos <carlosgc@gnome.org>
     18// Copyright (C) 2007-2009 Carlos Garcia Campos <carlosgc@gnome.org>
    1919// Copyright (C) 2007, 2008 Iñigo Martínez <inigomartinez@gmail.com>
    2020// Copyright (C) 2008 Michael Vrable <mvrable@cs.ucsd.edu>
     
    288288
    289289  AnnotColor();
     290  AnnotColor(double gray);
     291  AnnotColor(double r, double g, double b);
     292  AnnotColor(double c, double m, double y, double k);
    290293  AnnotColor(Array *array);
    291294  ~AnnotColor();
     
    481484  };
    482485
    483   Annot(XRef *xrefA, Dict *dict, Catalog* catalog);
     486  Annot(XRef *xrefA, PDFRectangle *rectA, Catalog *catalog);
     487  Annot(XRef *xrefA, Dict *dict, Catalog *catalog);
    484488  Annot(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj);
    485489  virtual ~Annot();
     
    498502  double getFontSize() { return fontSize; }
    499503
     504  // Sets the annot contents to new_content
     505  // new_content should never be NULL
     506  void setContents(GooString *new_content);
     507
     508  // The annotation takes the ownership of
     509  // new_color.
     510  void setColor(AnnotColor *new_color);
     511
    500512  // getters
     513  Ref getRef() const { return ref; }
    501514  AnnotSubtype getType() const { return type; }
    502515  PDFRectangle *getRect() const { return rect; }
     
    526539  void drawCircleTopLeft(double cx, double cy, double r);
    527540  void drawCircleBottomRight(double cx, double cy, double r);
     541
     542  // Updates the field key of the annotation dictionary
     543  // and sets M to the current time
     544  void update(const char *key, Object *value);
     545
     546  Object annotObj;
    528547 
    529548  // required data
     
    563582class AnnotPopup: public Annot {
    564583public:
     584  AnnotPopup(XRef *xrefA, PDFRectangle *rect, Catalog *catalog);
    565585  AnnotPopup(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj);
    566586  ~AnnotPopup();
    567587
    568   Dict *getParent() const { return parent; }
     588  Object *getParent(Object *obj) { return parent.fetch (xref, obj); }
     589  Object *getParentNF(Object *obj) { return &parent; }
     590  void setParent(Object *parentA);
     591  void setParent(Annot *parentA);
    569592  GBool getOpen() const { return open; }
     593  void setOpen(GBool openA);
    570594
    571595protected:
    572596  void initialize(XRef *xrefA, Dict *dict, Catalog *catalog);
    573597
    574   Dict *parent; // Parent
     598  Object parent; // Parent
    575599  GBool open;   // Open
    576600};
     
    587611  };
    588612
     613  AnnotMarkup(XRef *xrefA, PDFRectangle *rect, Catalog *catalog);
    589614  AnnotMarkup(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj);
    590615  virtual ~AnnotMarkup();
     
    600625  AnnotMarkupReplyType getReplyTo() const { return replyTo; }
    601626  AnnotExternalDataType getExData() const { return exData; }
     627
     628  // The annotation takes the ownership of new_popup
     629  void setPopup(AnnotPopup *new_popup);
     630  void setLabel(GooString *new_label);
    602631
    603632protected:
     
    638667  };
    639668
     669  AnnotText(XRef *xrefA, PDFRectangle *rect, Catalog *catalog);
    640670  AnnotText(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj);
    641671  ~AnnotText();
     
    646676  AnnotTextState getState() const { return state; }
    647677
    648   // setters
    649   void setModified(GooString *date);
     678  void setOpen(GBool openA);
     679  void setIcon(GooString *new_icon);
    650680
    651681private:
     
    687717  };
    688718
     719  AnnotMovie(XRef *xrefA, PDFRectangle *rect, Movie *movieA, Catalog *catalog);
    689720  AnnotMovie(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj);
    690721  ~AnnotMovie();
     
    760791 public:
    761792
     793  AnnotScreen(XRef *xrefA, PDFRectangle *rect, Catalog *catalog);
    762794  AnnotScreen(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj);
    763795  ~AnnotScreen();
     
    795827  };
    796828
     829  AnnotLink(XRef *xrefA, PDFRectangle *rect, Catalog *catalog);
    797830  AnnotLink(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj);
    798831  virtual ~AnnotLink();
     
    838871  };
    839872
     873  AnnotFreeText(XRef *xrefA, PDFRectangle *rect, GooString *da, Catalog *catalog);
    840874  AnnotFreeText(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj);
    841875  ~AnnotFreeText();
     
    889923  };
    890924
     925  AnnotLine(XRef *xrefA, PDFRectangle *rect, PDFRectangle *lRect, Catalog *catalog);
    891926  AnnotLine(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj);
    892927  ~AnnotLine();
     
    941976public:
    942977
     978  AnnotTextMarkup(XRef *xrefA, PDFRectangle *rect, AnnotSubtype subType,
     979                  AnnotQuadrilaterals *quadPoints, Catalog *catalog);
    943980  AnnotTextMarkup(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj);
    944981  virtual ~AnnotTextMarkup();
     
    960997public:
    961998
     999  AnnotStamp(XRef *xrefA, PDFRectangle *rect, Catalog *catalog);
    9621000  AnnotStamp(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj);
    9631001  ~AnnotStamp();
     
    9801018public:
    9811019
     1020  AnnotGeometry(XRef *xrefA, PDFRectangle *rect, AnnotSubtype subType, Catalog *catalog);
    9821021  AnnotGeometry(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj);
    9831022  ~AnnotGeometry();
     
    10101049  };
    10111050
     1051  AnnotPolygon(XRef *xrefA, PDFRectangle *rect, AnnotSubtype subType,
     1052               AnnotPath *path, Catalog *catalog);
    10121053  AnnotPolygon(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj);
    10131054  ~AnnotPolygon();
     
    10511092  };
    10521093
     1094  AnnotCaret(XRef *xrefA, PDFRectangle *rect, Catalog *catalog);
    10531095  AnnotCaret(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj);
    10541096  ~AnnotCaret();
     
    10731115public:
    10741116
     1117  AnnotInk(XRef *xrefA, PDFRectangle *rect, AnnotPath **paths, int n_paths, Catalog *catalog);
    10751118  AnnotInk(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj);
    10761119  ~AnnotInk();
     
    11001143public:
    11011144
     1145  AnnotFileAttachment(XRef *xrefA, PDFRectangle *rect, GooString *filename, Catalog *catalog);
    11021146  AnnotFileAttachment(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj);
    11031147  ~AnnotFileAttachment();
     
    11251169public:
    11261170
     1171  AnnotSound(XRef *xrefA, PDFRectangle *rect, Sound *soundA, Catalog *catalog);
    11271172  AnnotSound(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj);
    11281173  ~AnnotSound();
     
    12451290public:
    12461291
     1292  Annot3D(XRef *xrefA, PDFRectangle *rect, Catalog *catalog);
    12471293  Annot3D(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj);
    12481294  ~Annot3D();
  • trunk/poppler/mypoppler/poppler/ArthurOutputDev.cc

    r257 r277  
    1515//
    1616// Copyright (C) 2005 Brad Hards <bradh@frogmouth.net>
    17 // Copyright (C) 2005-2008 Albert Astals Cid <aacid@kde.org>
     17// Copyright (C) 2005-2009 Albert Astals Cid <aacid@kde.org>
    1818// Copyright (C) 2008 Pino Toscano <pino@kde.org>
     19// Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
     20// Copyright (C) 2009 Petr Gajdos <pgajdos@novell.com>
    1921//
    2022// To see a description of the changes please see the Changelog file that
     
    105107#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
    106108  globalParams->getEnableFreeType(),
     109  gFalse,
    107110#endif
    108111  m_painter->testRenderHint(QPainter::TextAntialiasing));
     
    265268  int substIdx, n;
    266269  int faceIndex = 0;
     270  SplashCoord matrix[6];
    267271
    268272  m_needFontUpdate = false;
     
    450454  m22 = textMat[3] * fontSize;
    451455
    452   SplashCoord matrix[6];
    453456  {
    454457  QMatrix painterMatrix = m_painter->worldMatrix();
     
    663666void ArthurOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
    664667                                    int width, int height, GBool invert,
    665                                     GBool inlineImg)
     668                                    GBool interpolate, GBool inlineImg)
    666669{
    667670  qDebug() << "drawImageMask";
     
    732735  cairo_surface_destroy (image);
    733736  free (buffer);
     737  imgStr->close ();
    734738  delete imgStr;
    735739#endif
     
    740744                                int width, int height,
    741745                                GfxImageColorMap *colorMap,
    742                                 int *maskColors, GBool inlineImg)
     746                                GBool interpolate, int *maskColors, GBool inlineImg)
    743747{
    744748  unsigned char *buffer;
     
    752756  int is_identity_transform;
    753757 
    754   buffer = (unsigned char *)gmalloc (width * height * 4);
     758  buffer = (unsigned char *)gmallocn3(width, height, 4);
    755759
    756760  /* TODO: Do we want to cache these? */
     
    763767   * so check its underlying color space as well */
    764768  is_identity_transform = colorMap->getColorSpace()->getMode() == csDeviceRGB ||
    765                   colorMap->getColorSpace()->getMode() == csICCBased &&
    766                   ((GfxICCBasedColorSpace*)colorMap->getColorSpace())->getAlt()->getMode() == csDeviceRGB;
     769                  (colorMap->getColorSpace()->getMode() == csICCBased &&
     770                  ((GfxICCBasedColorSpace*)colorMap->getColorSpace())->getAlt()->getMode() == csDeviceRGB);
    767771
    768772  if (maskColors) {
  • trunk/poppler/mypoppler/poppler/ArthurOutputDev.h

    r257 r277  
    1616// Copyright (C) 2005 Brad Hards <bradh@frogmouth.net>
    1717// Copyright (C) 2005 Albert Astals Cid <aacid@kde.org>
     18// Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
    1819//
    1920// To see a description of the changes please see the Changelog file that
     
    127128  virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
    128129                             int width, int height, GBool invert,
    129                              GBool inlineImg);
     130                             GBool interpolate, GBool inlineImg);
    130131  virtual void drawImage(GfxState *state, Object *ref, Stream *str,
    131132                         int width, int height, GfxImageColorMap *colorMap,
    132                          int *maskColors, GBool inlineImg);
     133                         GBool interpolate, int *maskColors, GBool inlineImg);
    133134
    134135  //----- Type 3 font operators
  • trunk/poppler/mypoppler/poppler/CMap.cc

    r257 r277  
    1515//
    1616// Copyright (C) 2008 Koji Otani <sho@bbr.jp>
    17 // Copyright (C) 2008 Albert Astals Cid <aacid@kde.org>
     17// Copyright (C) 2008, 2009 Albert Astals Cid <aacid@kde.org>
    1818//
    1919// To see a description of the changes please see the Changelog file that
     
    3939#include "PSTokenizer.h"
    4040#include "CMap.h"
     41#include "Object.h"
    4142
    4243//------------------------------------------------------------------------
     
    5657}
    5758
     59static int getCharFromStream(void *data) {
     60  return ((Stream *)data)->getChar();
     61}
     62
    5863//------------------------------------------------------------------------
    5964
    6065CMap *CMap::parse(CMapCache *cache, GooString *collectionA,
    61                   GooString *cMapNameA) {
    62   FILE *f;
     66                  GooString *cMapNameA, Stream *stream) {
     67  FILE *f = NULL;
    6368  CMap *cmap;
    6469  PSTokenizer *pst;
     
    6772  Guint start, end, code;
    6873
    69   if (!(f = globalParams->findCMapFile(collectionA, cMapNameA))) {
    70 
    71     // Check for an identity CMap.
    72     if (!cMapNameA->cmp("Identity") || !cMapNameA->cmp("Identity-H")) {
    73       return new CMap(collectionA->copy(), cMapNameA->copy(), 0);
    74     }
    75     if (!cMapNameA->cmp("Identity-V")) {
    76       return new CMap(collectionA->copy(), cMapNameA->copy(), 1);
    77     }
    78 
    79     error(-1, "Couldn't find '%s' CMap file for '%s' collection",
    80           cMapNameA->getCString(), collectionA->getCString());
    81     return NULL;
     74  if (stream) {
     75    stream->reset();
     76    pst = new PSTokenizer(&getCharFromStream, stream);
     77  } else {
     78    if (!(f = globalParams->findCMapFile(collectionA, cMapNameA))) {
     79
     80      // Check for an identity CMap.
     81      if (!cMapNameA->cmp("Identity") || !cMapNameA->cmp("Identity-H")) {
     82        return new CMap(collectionA->copy(), cMapNameA->copy(), 0);
     83      }
     84      if (!cMapNameA->cmp("Identity-V")) {
     85        return new CMap(collectionA->copy(), cMapNameA->copy(), 1);
     86      }
     87
     88      error(-1, "Couldn't find '%s' CMap file for '%s' collection",
     89            cMapNameA->getCString(), collectionA->getCString());
     90      return NULL;
     91    }
     92    pst = new PSTokenizer(&getCharFromFile, f);
    8293  }
    8394
    8495  cmap = new CMap(collectionA->copy(), cMapNameA->copy());
    8596
    86   pst = new PSTokenizer(&getCharFromFile, f);
    8797  pst->getToken(tok1, sizeof(tok1), &n1);
    8898  while (pst->getToken(tok2, sizeof(tok2), &n2)) {
     
    167177  delete pst;
    168178
    169   fclose(f);
     179  if (f) {
     180    fclose(f);
     181  }
    170182
    171183  return cmap;
     
    205217
    206218  useNameStr = new GooString(useName);
    207   subCMap = cache->getCMap(collection, useNameStr);
     219  subCMap = cache->getCMap(collection, useNameStr, NULL);
    208220  delete useNameStr;
    209221  if (!subCMap) {
     
    424436}
    425437
    426 CMap *CMapCache::getCMap(GooString *collection, GooString *cMapName) {
     438CMap *CMapCache::getCMap(GooString *collection, GooString *cMapName, Stream *stream) {
    427439  CMap *cmap;
    428440  int i, j;
     
    443455    }
    444456  }
    445   if ((cmap = CMap::parse(this, collection, cMapName))) {
     457  if ((cmap = CMap::parse(this, collection, cMapName, stream))) {
    446458    if (cache[cMapCacheSize - 1]) {
    447459      cache[cMapCacheSize - 1]->decRefCnt();
  • trunk/poppler/mypoppler/poppler/CMap.h

    r257 r277  
    1515//
    1616// Copyright (C) 2008 Koji Otani <sho@bbr.jp>
     17// Copyright (C) 2009 Albert Astals Cid <aacid@kde.org>
    1718//
    1819// To see a description of the changes please see the Changelog file that
     
    3940struct CMapVectorEntry;
    4041class CMapCache;
     42class Stream;
    4143
    4244//------------------------------------------------------------------------
     
    4648
    4749  // Create the CMap specified by <collection> and <cMapName>.  Sets
    48   // the initial reference count to 1.  Returns NULL on failure.
     50  // the initial reference count to 1.
     51  // Stream is a stream containing the CMap, can be NULL and
     52  // this means the CMap will be searched in the CMap files
     53  // Returns NULL on failure.
    4954  static CMap *parse(CMapCache *cache, GooString *collectionA,
    50                      GooString *cMapNameA);
     55                     GooString *cMapNameA, Stream *stream);
    5156
    5257  ~CMap();
     
    108113  // Get the <cMapName> CMap for the specified character collection.
    109114  // Increments its reference count; there will be one reference for
    110   // the cache plus one for the caller of this function.  Returns NULL
    111   // on failure.
    112   CMap *getCMap(GooString *collection, GooString *cMapName);
     115  // the cache plus one for the caller of this function.
     116  // Stream is a stream containing the CMap, can be NULL and
     117  // this means the CMap will be searched in the CMap files
     118  // Returns NULL on failure.
     119  CMap *getCMap(GooString *collection, GooString *cMapName, Stream *stream);
    113120
    114121private:
  • trunk/poppler/mypoppler/poppler/CairoFontEngine.cc

    r257 r277  
    1818// Copyright (C) 2005, 2006 Kristian HÞgsberg <krh@redhat.com>
    1919// Copyright (C) 2005 Martin Kretzschmar <martink@gnome.org>
    20 // Copyright (C) 2005 Albert Astals Cid <aacid@kde.org>
     20// Copyright (C) 2005, 2009 Albert Astals Cid <aacid@kde.org>
    2121// Copyright (C) 2006, 2007 Carlos Garcia Campos <carlosgc@gnome.org>
    2222// Copyright (C) 2007 Koji Otani <sho@bbr.jp>
    23 // Copyright (C) 2008 Chris Wilson <chris@chris-wilson.co.uk>
     23// Copyright (C) 2008, 2009 Chris Wilson <chris@chris-wilson.co.uk>
     24// Copyright (C) 2008 Adrian Johnson <ajohnson@redneon.com>
     25// Copyright (C) 2009 Darren Kenny <darren.kenny@sun.com>
    2426//
    2527// To see a description of the changes please see the Changelog file that
     
    3335#include <string.h>
    3436#include "CairoFontEngine.h"
     37#include "CairoOutputDev.h"
    3538#include "CharCodeToUnicode.h"
    3639#include "GlobalParams.h"
     
    3942#include "goo/gfile.h"
    4043#include "Error.h"
     44#include "XRef.h"
     45#include "Gfx.h"
     46#include "Page.h"
    4147
    4248#if HAVE_FCNTL_H && HAVE_SYS_MMAN_H && HAVE_SYS_STAT_H
     
    5157#endif
    5258
    53 static void fileWrite(void *stream, char *data, int len) {
    54   fwrite(data, 1, len, (FILE *)stream);
    55 }
    5659
    5760//------------------------------------------------------------------------
    5861// CairoFont
     62//------------------------------------------------------------------------
     63
     64CairoFont::CairoFont(Ref ref,
     65                     cairo_font_face_t *cairo_font_face,
     66                     Gushort *codeToGID,
     67                     int codeToGIDLen,
     68                     GBool substitute,
     69                     GBool printing) : ref(ref),
     70                                       cairo_font_face(cairo_font_face),
     71                                       codeToGID(codeToGID),
     72                                       codeToGIDLen(codeToGIDLen),
     73                                       substitute(substitute),
     74                                       printing(printing)      { }
     75
     76CairoFont::~CairoFont() {
     77  cairo_font_face_destroy (cairo_font_face);
     78  gfree(codeToGID);
     79}
     80
     81GBool
     82CairoFont::matches(Ref &other, GBool printingA) {
     83  return (other.num == ref.num && other.gen == ref.gen);
     84}
     85
     86cairo_font_face_t *
     87CairoFont::getFontFace(void) {
     88  return cairo_font_face;
     89}
     90
     91unsigned long
     92CairoFont::getGlyph(CharCode code,
     93                    Unicode *u, int uLen) {
     94  FT_UInt gid;
     95
     96  if (codeToGID && code < codeToGIDLen) {
     97    gid = (FT_UInt)codeToGID[code];
     98  } else {
     99    gid = (FT_UInt)code;
     100  }
     101  return gid;
     102}
     103
     104double
     105CairoFont::getSubstitutionCorrection(GfxFont *gfxFont)
     106{
     107  double w1, w2,w3;
     108  CharCode code;
     109  char *name;
     110
     111  // for substituted fonts: adjust the font matrix -- compare the
     112  // width of 'm' in the original font and the substituted font
     113  if (isSubstitute() && !gfxFont->isCIDFont()) {
     114    for (code = 0; code < 256; ++code) {
     115      if ((name = ((Gfx8BitFont *)gfxFont)->getCharName(code)) &&
     116          name[0] == 'm' && name[1] == '\0') {
     117        break;
     118      }
     119    }
     120    if (code < 256) {
     121      w1 = ((Gfx8BitFont *)gfxFont)->getWidth(code);
     122      {
     123        cairo_matrix_t m;
     124        cairo_matrix_init_identity(&m);
     125        cairo_font_options_t *options = cairo_font_options_create();
     126        cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_NONE);
     127        cairo_font_options_set_hint_metrics(options, CAIRO_HINT_METRICS_OFF);
     128        cairo_scaled_font_t *scaled_font = cairo_scaled_font_create(cairo_font_face, &m, &m, options);
     129
     130        cairo_text_extents_t extents;
     131        cairo_scaled_font_text_extents(scaled_font, "m", &extents);
     132
     133        cairo_scaled_font_destroy(scaled_font);
     134        cairo_font_options_destroy(options);
     135        w3 = extents.width;
     136        w2 = extents.x_advance;
     137      }
     138      if (!gfxFont->isSymbolic()) {
     139        // if real font is substantially narrower than substituted
     140        // font, reduce the font size accordingly
     141        if (w1 > 0.01 && w1 < 0.9 * w2) {
     142          w1 /= w2;
     143          return w1;
     144        }
     145      }
     146    }
     147  }
     148  return 1.0;
     149}
     150
     151//------------------------------------------------------------------------
     152// CairoFreeTypeFont
    59153//------------------------------------------------------------------------
    60154
     
    149243    _ft_open_faces = data->next;
    150244
     245#if defined(__SUNPRO_CC) && defined(__sun) && defined(__SVR4)
     246  munmap ((char*)data->bytes, data->size);
     247#else
    151248  munmap (data->bytes, data->size);
     249#endif
    152250  close (data->fd);
    153251
     
    191289  for (l = _ft_open_faces; l; l = l->next) {
    192290    if (_ft_face_data_equal (l, &tmpl)) {
     291#if defined(__SUNPRO_CC) && defined(__sun) && defined(__SVR4)
     292      munmap ((char*)tmpl.bytes, tmpl.size);
     293#else
    193294      munmap (tmpl.bytes, tmpl.size);
     295#endif
    194296      close (tmpl.fd);
    195297      *face_out = l->face;
     
    200302
    201303  /* not a dup, open and insert into list */
    202   if (FT_New_Face (lib, filename, 0, &tmpl.face)) {
     304  if (FT_New_Memory_Face (lib,
     305                          (FT_Byte *) tmpl.bytes, tmpl.size,
     306                          0, &tmpl.face))
     307  {
     308#if defined(__SUNPRO_CC) && defined(__sun) && defined(__SVR4)
     309    munmap ((char*)tmpl.bytes, tmpl.size);
     310#else
    203311    munmap (tmpl.bytes, tmpl.size);
     312#endif
     313
    204314    close (tmpl.fd);
    205315    return gFalse;
     
    224334    cairo_font_face_destroy (l->font_face);
    225335    _ft_done_face (l);
    226     return NULL;
     336    return gFalse;
    227337  }
    228338
     
    235345#endif
    236346
    237 CairoFont *CairoFont::create(GfxFont *gfxFont, XRef *xref, FT_Library lib, GBool useCIDs) {
     347CairoFreeTypeFont::CairoFreeTypeFont(Ref ref,
     348                                     cairo_font_face_t *cairo_font_face,
     349                                     FT_Face face,
     350                                     Gushort *codeToGID,
     351                                     int codeToGIDLen,
     352                                     GBool substitute) : CairoFont(ref,
     353                                                                   cairo_font_face,
     354                                                                   codeToGID,
     355                                                                   codeToGIDLen,
     356                                                                   substitute,
     357                                                                   gTrue),
     358                                                         face(face) { }
     359
     360CairoFreeTypeFont::~CairoFreeTypeFont() { }
     361
     362CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref,
     363                                             FT_Library lib, GBool useCIDs) {
    238364  Ref embRef;
    239365  Object refObj, strObj;
    240   GooString *tmpFileName, *fileName,*tmpFileName2;
     366  GooString *tmpFileName, *fileName;
    241367  DisplayFontParam *dfp;
    242368  FILE *tmpFile;
     
    266392
    267393  if (gfxFont->getEmbeddedFontID(&embRef)) {
    268     if (!openTempFile(&tmpFileName, &tmpFile, "wb", NULL)) {
     394    if (!openTempFile(&tmpFileName, &tmpFile, "wb")) {
    269395      error(-1, "Couldn't create temporary font file");
    270396      goto err2;
     
    317443  case fontType1:
    318444  case fontType1C:
     445  case fontType1COT:
    319446    if (! _ft_new_face (lib, fileName->getCString(), &face, &font_face)) {
    320447      error(-1, "could not create type1 face");
     
    363490      codeToGIDLen = 256;
    364491    }
    365     if (!openTempFile(&tmpFileName2, &tmpFile, "wb", NULL)) {
    366       delete ff;
    367       error(-1, "failed to open truetype tempfile\n");
    368       goto err2;
    369     }
    370     ff->writeTTF(&fileWrite, tmpFile);
    371     fclose(tmpFile);
    372     delete ff;
    373 
    374     if (! _ft_new_face (lib, tmpFileName2->getCString(), &face, &font_face)) {
     492    if (! _ft_new_face (lib, fileName->getCString(), &face, &font_face)) {
    375493      error(-1, "could not create truetype face\n");
    376494      goto err2;
    377495    }
    378     unlink (tmpFileName2->getCString());
    379     delete tmpFileName2;
    380496    break;
    381497   
     
    403519   
    404520  default:
    405     printf ("font type not handled\n");
     521    printf ("font type %d not handled\n", (int)fontType);
    406522    goto err2;
    407523    break;
     
    416532  }
    417533
    418   return new CairoFont(ref,
     534  return new CairoFreeTypeFont(ref,
    419535                       font_face, face,
    420536                       codeToGID, codeToGIDLen,
     
    427543}
    428544
    429 CairoFont::CairoFont(Ref ref, cairo_font_face_t *cairo_font_face, FT_Face face,
    430     Gushort *codeToGID, int codeToGIDLen, GBool substitute) : ref(ref), cairo_font_face(cairo_font_face),
    431                                             face(face), codeToGID(codeToGID),
    432                                             codeToGIDLen(codeToGIDLen), substitute(substitute) { }
    433 
    434 CairoFont::~CairoFont() {
    435   cairo_font_face_destroy (cairo_font_face);
    436   gfree(codeToGID);
    437 }
    438 
    439 GBool
    440 CairoFont::matches(Ref &other) {
    441   return (other.num == ref.num && other.gen == ref.gen);
    442 }
    443 
    444 cairo_font_face_t *
    445 CairoFont::getFontFace(void) {
    446   return cairo_font_face;
    447 }
    448 
    449 unsigned long
    450 CairoFont::getGlyph(CharCode code,
    451                     Unicode *u, int uLen) {
    452   FT_UInt gid;
    453 
    454   if (codeToGID && code < codeToGIDLen) {
    455     gid = (FT_UInt)codeToGID[code];
    456   } else {
    457     gid = (FT_UInt)code;
    458   }
    459   return gid;
    460 }
    461 
    462 double
    463 CairoFont::getSubstitutionCorrection(GfxFont *gfxFont)
    464 {
    465   double w1, w2,w3;
    466   CharCode code;
     545//------------------------------------------------------------------------
     546// CairoType3Font
     547//------------------------------------------------------------------------
     548
     549static const cairo_user_data_key_t type3_font_key = {0};
     550
     551typedef struct _type3_font_info {
     552  GfxFont *font;
     553  XRef *xref;
     554  Catalog *catalog;
     555  CairoFontEngine *fontEngine;
     556  GBool printing;
     557} type3_font_info_t;
     558
     559static void
     560_free_type3_font_info(void *closure)
     561{
     562  type3_font_info_t *info = (type3_font_info_t *) closure;
     563
     564  info->font->decRefCnt();
     565  free (info);
     566}
     567
     568static cairo_status_t
     569_render_type3_glyph (cairo_scaled_font_t  *scaled_font,
     570                     unsigned long         glyph,
     571                     cairo_t              *cr,
     572                     cairo_text_extents_t *metrics)
     573{
     574  Dict *charProcs;
     575  Object charProc;
     576  CairoOutputDev *output_dev;
     577  cairo_matrix_t matrix, invert_y_axis;
     578  double *mat;
     579  double wx, wy;
     580  PDFRectangle box;
     581  type3_font_info_t *info;
     582  GfxFont *font;
     583  Dict *resDict;
     584  Gfx *gfx;
     585
     586  info = (type3_font_info_t *)
     587    cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
     588                                   &type3_font_key);
     589
     590  font = info->font;
     591  resDict = ((Gfx8BitFont *)font)->getResources();
     592  charProcs = ((Gfx8BitFont *)(info->font))->getCharProcs();
     593  if (!charProcs)
     594    return CAIRO_STATUS_USER_FONT_ERROR;
     595
     596  if ((int)glyph >= charProcs->getLength())
     597    return CAIRO_STATUS_USER_FONT_ERROR;
     598
     599  mat = font->getFontMatrix();
     600  matrix.xx = mat[0];
     601  matrix.yx = mat[1];
     602  matrix.xy = mat[2];
     603  matrix.yy = mat[3];
     604  matrix.x0 = mat[4];
     605  matrix.y0 = mat[5];
     606  cairo_matrix_init_scale (&invert_y_axis, 1, -1);
     607  cairo_matrix_multiply (&matrix, &matrix, &invert_y_axis);
     608  cairo_transform (cr, &matrix);
     609
     610  output_dev = new CairoOutputDev();
     611  output_dev->setCairo(cr);
     612  output_dev->setPrinting(info->printing);
     613
     614  mat = font->getFontBBox();
     615  box.x1 = mat[0];
     616  box.y1 = mat[1];
     617  box.x2 = mat[2];
     618  box.y2 = mat[3];
     619  gfx = new Gfx(info->xref, output_dev, resDict, info->catalog, &box, NULL);
     620  output_dev->startDoc(info->xref, info->catalog, info->fontEngine);
     621  output_dev->startPage (1, gfx->getState());
     622  output_dev->setInType3Char(gTrue);
     623  gfx->display(charProcs->getVal(glyph, &charProc));
     624
     625  output_dev->getType3GlyphWidth (&wx, &wy);
     626  cairo_matrix_transform_distance (&matrix, &wx, &wy);
     627  metrics->x_advance = wx;
     628  metrics->y_advance = wy;
     629  if (output_dev->hasType3GlyphBBox()) {
     630    double *bbox = output_dev->getType3GlyphBBox();
     631
     632    cairo_matrix_transform_point (&matrix, &bbox[0], &bbox[1]);
     633    cairo_matrix_transform_point (&matrix, &bbox[2], &bbox[3]);
     634    metrics->x_bearing = bbox[0];
     635    metrics->y_bearing = bbox[1];
     636    metrics->width = bbox[2] - bbox[0];
     637    metrics->height = bbox[3] - bbox[1];
     638  }
     639
     640  delete gfx;
     641  delete output_dev;
     642  charProc.free();
     643
     644  return CAIRO_STATUS_SUCCESS;
     645}
     646
     647
     648CairoType3Font *CairoType3Font::create(GfxFont *gfxFont, XRef *xref,
     649                                       Catalog *catalog, CairoFontEngine *fontEngine,
     650                                       GBool printing) {
     651  Object refObj, strObj;
     652  type3_font_info_t *info;
     653  cairo_font_face_t *font_face;
     654  Ref ref;
     655  Gushort *codeToGID;
     656  int codeToGIDLen;
     657  int i, j;
     658  char **enc;
     659  Dict *charProcs;
    467660  char *name;
    468661
    469   // for substituted fonts: adjust the font matrix -- compare the
    470   // width of 'm' in the original font and the substituted font
    471   if (isSubstitute() && !gfxFont->isCIDFont()) {
    472     for (code = 0; code < 256; ++code) {
    473       if ((name = ((Gfx8BitFont *)gfxFont)->getCharName(code)) &&
    474           name[0] == 'm' && name[1] == '\0') {
    475         break;
    476       }
    477     }
    478     if (code < 256) {
    479       w1 = ((Gfx8BitFont *)gfxFont)->getWidth(code);
    480       {
    481         cairo_matrix_t m;
    482         cairo_matrix_init_identity(&m);
    483         cairo_font_options_t *options = cairo_font_options_create();
    484         cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_NONE);
    485         cairo_font_options_set_hint_metrics(options, CAIRO_HINT_METRICS_OFF);
    486         cairo_scaled_font_t *scaled_font = cairo_scaled_font_create(cairo_font_face, &m, &m, options);
    487 
    488         cairo_text_extents_t extents;
    489         cairo_scaled_font_text_extents(scaled_font, "m", &extents);
    490 
    491         cairo_scaled_font_destroy(scaled_font);
    492         cairo_font_options_destroy(options);
    493         w3 = extents.width;
    494         w2 = extents.x_advance;
    495       }
    496       if (!gfxFont->isSymbolic()) {
    497         // if real font is substantially narrower than substituted
    498         // font, reduce the font size accordingly
    499         if (w1 > 0.01 && w1 < 0.9 * w2) {
    500           w1 /= w2;
    501           return w1;
     662  charProcs = ((Gfx8BitFont *)gfxFont)->getCharProcs();
     663  info = (type3_font_info_t *) malloc(sizeof(*info));
     664  ref = *gfxFont->getID();
     665  font_face = cairo_user_font_face_create();
     666  cairo_user_font_face_set_render_glyph_func (font_face, _render_type3_glyph);
     667  gfxFont->incRefCnt();
     668  info->font = gfxFont;
     669  info->xref = xref;
     670  info->catalog = catalog;
     671  info->fontEngine = fontEngine;
     672  info->printing = printing;
     673
     674  cairo_font_face_set_user_data (font_face, &type3_font_key, (void *) info, _free_type3_font_info);
     675
     676  enc = ((Gfx8BitFont *)gfxFont)->getEncoding();
     677  codeToGID = (Gushort *)gmallocn(256, sizeof(int));
     678  codeToGIDLen = 256;
     679  for (i = 0; i < 256; ++i) {
     680    codeToGID[i] = 0;
     681    if ((name = enc[i])) {
     682      for (j = 0; j < charProcs->getLength(); j++) {
     683        if (strcmp(name, charProcs->getKey(j)) == 0) {
     684          codeToGID[i] = (Gushort) j;
    502685        }
    503686      }
    504687    }
    505688  }
    506   return 1.0;
    507 }
     689
     690  return new CairoType3Font(ref, xref, catalog, font_face, codeToGID, codeToGIDLen, printing);
     691}
     692
     693CairoType3Font::CairoType3Font(Ref ref,
     694                               XRef *xref,
     695                               Catalog *cat,
     696                               cairo_font_face_t *cairo_font_face,
     697                               Gushort *codeToGID,
     698                               int codeToGIDLen,
     699                               GBool printing) : CairoFont(ref,
     700                                                           cairo_font_face,
     701                                                           codeToGID,
     702                                                           codeToGIDLen,
     703                                                           gFalse,
     704                                                           printing),
     705                                                 xref(xref),
     706                                                 catalog(catalog) { }
     707
     708CairoType3Font::~CairoType3Font() { }
     709
     710GBool
     711CairoType3Font::matches(Ref &other, GBool printingA) {
     712  return (other.num == ref.num && other.gen == ref.gen && printing == printingA);
     713}
     714
    508715
    509716//------------------------------------------------------------------------
     
    536743
    537744CairoFont *
    538 CairoFontEngine::getFont(GfxFont *gfxFont, XRef *xref) {
     745CairoFontEngine::getFont(GfxFont *gfxFont, XRef *xref, Catalog *catalog, GBool printing) {
    539746  int i, j;
    540747  Ref ref;
     
    542749  GfxFontType fontType;
    543750 
    544   fontType = gfxFont->getType();
    545   if (fontType == fontType3) {
    546     /* Need to figure this out later */
    547     //    return NULL;
    548   }
    549 
    550751  ref = *gfxFont->getID();
    551752
    552753  for (i = 0; i < cairoFontCacheSize; ++i) {
    553754    font = fontCache[i];
    554     if (font && font->matches(ref)) {
     755    if (font && font->matches(ref, printing)) {
    555756      for (j = i; j > 0; --j) {
    556757        fontCache[j] = fontCache[j-1];
     
    561762  }
    562763 
    563   font = CairoFont::create (gfxFont, xref, lib, useCIDs);
     764  fontType = gfxFont->getType();
     765  if (fontType == fontType3)
     766    font = CairoType3Font::create (gfxFont, xref, catalog, this, printing);
     767  else
     768    font = CairoFreeTypeFont::create (gfxFont, xref, lib, useCIDs);
     769
    564770  //XXX: if font is null should we still insert it into the cache?
    565771  if (fontCache[cairoFontCacheSize - 1]) {
     
    572778  return font;
    573779}
    574 
  • trunk/poppler/mypoppler/poppler/CairoFontEngine.h

    r257 r277  
    1919// Copyright (C) 2006, 2007 Jeff Muizelaar <jeff@infidigm.net>
    2020// Copyright (C) 2006 Carlos Garcia Campos <carlosgc@gnome.org>
     21// Copyright (C) 2008 Adrian Johnson <ajohnson@redneon.com>
    2122//
    2223// To see a description of the changes please see the Changelog file that
     
    3637
    3738#include "GfxFont.h"
     39#include "Catalog.h"
     40
     41class CairoFontEngine;
    3842
    3943class CairoFont {
    4044public:
    41   static CairoFont *create(GfxFont *gfxFont, XRef *xref, FT_Library lib, GBool useCIDs);
    42   ~CairoFont();
     45  CairoFont(Ref ref,
     46            cairo_font_face_t *face,
     47            Gushort *codeToGID,
     48            int codeToGIDLen,
     49            GBool substitute,
     50            GBool printing);
     51  virtual ~CairoFont();
    4352
    44   GBool matches(Ref &other);
     53  virtual GBool matches(Ref &other, GBool printing);
    4554  cairo_font_face_t *getFontFace(void);
    4655  unsigned long getGlyph(CharCode code, Unicode *u, int uLen);
     
    4857
    4958  GBool isSubstitute() { return substitute; }
    50 private:
    51   CairoFont(Ref ref, cairo_font_face_t *cairo_font_face, FT_Face face,
    52       Gushort *codeToGID, int codeToGIDLen, GBool substitute);
     59protected:
    5360  Ref ref;
    5461  cairo_font_face_t *cairo_font_face;
    55   FT_Face face;
    5662
    5763  Gushort *codeToGID;
     
    5965
    6066  GBool substitute;
     67  GBool printing;
     68};
     69
     70//------------------------------------------------------------------------
     71
     72class CairoFreeTypeFont : public CairoFont {
     73public:
     74  static CairoFreeTypeFont *create(GfxFont *gfxFont, XRef *xref, FT_Library lib, GBool useCIDs);
     75  virtual ~CairoFreeTypeFont();
     76
     77private:
     78  CairoFreeTypeFont(Ref ref, cairo_font_face_t *cairo_font_face, FT_Face face,
     79            Gushort *codeToGID, int codeToGIDLen, GBool substitute);
     80  FT_Face face;
     81};
     82
     83//------------------------------------------------------------------------
     84
     85class CairoType3Font : public CairoFont {
     86public:
     87  static CairoType3Font *create(GfxFont *gfxFont, XRef *xref,
     88                                Catalog *catalog, CairoFontEngine *fontEngine,
     89                                GBool printing);
     90  virtual ~CairoType3Font();
     91
     92  virtual GBool matches(Ref &other, GBool printing);
     93
     94private:
     95  CairoType3Font(Ref ref, XRef *xref, Catalog *catalog,
     96                 cairo_font_face_t *cairo_font_face,
     97                 Gushort *codeToGID, int codeToGIDLen,
     98                 GBool printing);
     99  XRef *xref;
     100  Catalog *catalog;
    61101};
    62102
     
    76116  ~CairoFontEngine();
    77117
    78   CairoFont *getFont(GfxFont *gfxFont, XRef *xref);
     118  CairoFont *getFont(GfxFont *gfxFont, XRef *xref, Catalog *catalog, GBool printing);
    79119
    80120private:
  • trunk/poppler/mypoppler/poppler/CairoOutputDev.cc

    r271 r277  
    1717// Copyright (C) 2005-2008 Jeff Muizelaar <jeff@infidigm.net>
    1818// Copyright (C) 2005, 2006 Kristian HÞgsberg <krh@redhat.com>
    19 // Copyright (C) 2005 Albert Astals Cid <aacid@kde.org>
     19// Copyright (C) 2005, 2009 Albert Astals Cid <aacid@kde.org>
    2020// Copyright (C) 2005 Nickolay V. Shmyrev <nshmyrev@yandex.ru>
    21 // Copyright (C) 2006-2008 Carlos Garcia Campos <carlosgc@gnome.org>
     21// Copyright (C) 2006-2009 Carlos Garcia Campos <carlosgc@gnome.org>
    2222// Copyright (C) 2008 Carl Worth <cworth@cworth.org>
    23 // Copyright (C) 2008 Adrian Johnson <ajohnson@redneon.com>
     23// Copyright (C) 2008, 2009 Adrian Johnson <ajohnson@redneon.com>
    2424// Copyright (C) 2008 Michael Vrable <mvrable@cs.ucsd.edu>
    25 // Copyright (C) 2008 Chris Wilson <chris@chris-wilson.co.uk>
     25// Copyright (C) 2008, 2009 Chris Wilson <chris@chris-wilson.co.uk>
     26// Copyright (C) 2008 Hib Eris <hib@hiberis.nl>
     27// Copyright (C) 2009 David Benjamin <davidben@mit.edu>
    2628//
    2729// To see a description of the changes please see the Changelog file that
     
    4547#include "Error.h"
    4648#include "Object.h"
     49#include "Gfx.h"
    4750#include "GfxState.h"
    4851#include "GfxFont.h"
     52#include "Page.h"
    4953#include "Link.h"
    5054#include "CharCodeToUnicode.h"
    5155#include "FontEncodingTables.h"
     56#include "PDFDocEncoding.h"
    5257#include <fofi/FoFiTrueType.h>
    5358#include <splash/SplashBitmap.h>
     
    108113CairoOutputDev::CairoOutputDev() {
    109114  xref = NULL;
     115  catalog = NULL;
    110116
    111117  if (!ft_lib_initialized) {
     
    115121
    116122  fontEngine = NULL;
     123  fontEngine_owner = gFalse;
    117124  glyphs = NULL;
    118125  fill_pattern = NULL;
     
    121128  fill_opacity = 1.0;
    122129  textClipPath = NULL;
     130  haveCSPattern = gFalse;
    123131  cairo = NULL;
    124132  currentFont = NULL;
    125133  prescaleImages = gTrue;
    126134  printing = gTrue;
     135  inType3Char = gFalse;
     136  t3_glyph_has_bbox = gFalse;
    127137
    128138  groupColorSpaceStack = NULL;
     139  maskStack = NULL;
    129140  group = NULL;
    130141  mask = NULL;
     
    132143  cairo_shape = NULL;
    133144  knockoutCount = 0;
     145
     146  text = NULL;
     147  actualText = NULL;
    134148}
    135149
    136150CairoOutputDev::~CairoOutputDev() {
    137   if (fontEngine) {
     151  if (fontEngine_owner && fontEngine) {
    138152    delete fontEngine;
    139153  }
     
    149163  if (shape)
    150164    cairo_pattern_destroy (shape);
     165  if (text)
     166    text->decRefCnt();
     167  if (actualText)
     168    delete actualText; 
    151169}
    152170
     
    172190}
    173191
    174 void CairoOutputDev::startDoc(XRef *xrefA) {
     192void CairoOutputDev::setTextPage(TextPage *text)
     193{
     194  if (this->text)
     195    this->text->decRefCnt();
     196  if (actualText)
     197    delete actualText;
     198  if (text) {
     199    this->text = text;
     200    this->text->incRefCnt();
     201    actualText = new ActualText(text);
     202  } else {
     203    this->text = NULL;
     204    actualText = NULL;
     205  }
     206}
     207
     208void CairoOutputDev::startDoc(XRef *xrefA, Catalog *catalogA,
     209                              CairoFontEngine *parentFontEngine) {
    175210  xref = xrefA;
    176   if (fontEngine) {
    177     delete fontEngine;
    178   }
    179   fontEngine = new CairoFontEngine(ft_lib);
     211  catalog = catalogA;
     212  if (parentFontEngine) {
     213    fontEngine = parentFontEngine;
     214  } else {
     215    if (fontEngine) {
     216      delete fontEngine;
     217    }
     218    fontEngine = new CairoFontEngine(ft_lib);
     219    fontEngine_owner = gTrue;
     220  }
    180221}
    181222
     
    187228  cairo_pattern_destroy(stroke_pattern);
    188229  stroke_pattern = cairo_pattern_create_rgb(0., 0., 0.);
     230
     231  if (text)
     232    text->startPage(state);
     233}
     234
     235void CairoOutputDev::endPage() {
     236  if (text) {
     237    text->endPage();
     238    text->coalesce(gTrue, gFalse);
     239  }
    189240}
    190241
     
    197248  if (cairo_shape)
    198249      cairo_save (cairo_shape);
     250
     251  MaskStack *ms = new MaskStack;
     252  ms->mask = cairo_pattern_reference(mask);
     253  ms->next = maskStack;
     254  maskStack = ms;
    199255}
    200256
     
    211267  updateFillOpacity(state);
    212268  updateStrokeOpacity(state);
     269  updateBlendMode(state);
     270
     271  MaskStack* ms = maskStack;
     272  if (mask)
     273    cairo_pattern_destroy(mask);
     274
     275  if (ms) {
     276    mask = ms->mask;
     277    maskStack = ms->next;
     278    delete ms;
     279  }
    213280}
    214281
     
    224291  updateFillOpacity(state);
    225292  updateStrokeOpacity(state);
     293  updateBlendMode(state);
    226294  needFontUpdate = gTrue;
     295  if (text)
     296    text->updateFont(state);
    227297}
    228298
     
    398468}
    399469
     470void CairoOutputDev::updateFillColorStop(GfxState *state, double offset) {
     471  state->getFillRGB(&fill_color);
     472
     473  cairo_pattern_add_color_stop_rgba(fill_pattern, offset,
     474                                    fill_color.r / 65535.0,
     475                                    fill_color.g / 65535.0,
     476                                    fill_color.b / 65535.0,
     477                                    fill_opacity);
     478  LOG(printf ("fill color stop: %f (%d, %d, %d)\n",
     479              offset, fill_color.r, fill_color.g, fill_color.b));
     480}
     481
     482void CairoOutputDev::updateBlendMode(GfxState *state) {
     483#ifdef CAIRO_HAS_BLEND_MODES
     484  switch (state->getBlendMode()) {
     485  default:
     486  case gfxBlendNormal:
     487    cairo_set_operator (cairo, CAIRO_OPERATOR_OVER);
     488    break;
     489  case gfxBlendMultiply:
     490    cairo_set_operator (cairo, CAIRO_OPERATOR_MULTIPLY);
     491    break;
     492  case gfxBlendScreen:
     493    cairo_set_operator (cairo, CAIRO_OPERATOR_SCREEN);
     494    break;
     495  case gfxBlendOverlay:
     496    cairo_set_operator (cairo, CAIRO_OPERATOR_OVERLAY);
     497    break;
     498  case gfxBlendDarken:
     499    cairo_set_operator (cairo, CAIRO_OPERATOR_DARKEN);
     500    break;
     501  case gfxBlendLighten:
     502    cairo_set_operator (cairo, CAIRO_OPERATOR_LIGHTEN);
     503    break;
     504  case gfxBlendColorDodge:
     505    cairo_set_operator (cairo, CAIRO_OPERATOR_COLOR_DODGE);
     506    break;
     507  case gfxBlendColorBurn:
     508    cairo_set_operator (cairo, CAIRO_OPERATOR_COLOR_BURN);
     509    break;
     510  case gfxBlendHardLight:
     511    cairo_set_operator (cairo, CAIRO_OPERATOR_HARD_LIGHT);
     512    break;
     513  case gfxBlendSoftLight:
     514    cairo_set_operator (cairo, CAIRO_OPERATOR_SOFT_LIGHT);
     515    break;
     516  case gfxBlendDifference:
     517    cairo_set_operator (cairo, CAIRO_OPERATOR_DIFFERENCE);
     518    break;
     519  case gfxBlendExclusion:
     520    cairo_set_operator (cairo, CAIRO_OPERATOR_EXCLUSION);
     521    break;
     522  case gfxBlendHue:
     523    cairo_set_operator (cairo, CAIRO_OPERATOR_HSL_HUE);
     524    break;
     525  case gfxBlendSaturation:
     526    cairo_set_operator (cairo, CAIRO_OPERATOR_HSL_SATURATION);
     527    break;
     528  case gfxBlendColor:
     529    cairo_set_operator (cairo, CAIRO_OPERATOR_HSL_COLOR);
     530    break;
     531  case gfxBlendLuminosity:
     532    cairo_set_operator (cairo, CAIRO_OPERATOR_HSL_LUMINOSITY);
     533    break;
     534  }
     535  LOG(printf ("blend mode: %d\n", (int)state->getBlendMode()));
     536#endif /* CAIRO_HAS_BLEND_MODES */
     537}
     538
    400539void CairoOutputDev::updateFont(GfxState *state) {
    401540  cairo_font_face_t *font_face;
     
    406545  needFontUpdate = gFalse;
    407546
    408   if (state->getFont()->getType() == fontType3) 
    409     return;
    410 
    411   currentFont = fontEngine->getFont (state->getFont(), xref);
     547  //FIXME: use cairo font engine?
     548  if (text)
     549    text->updateFont(state);
     550 
     551  currentFont = fontEngine->getFont (state->getFont(), xref, catalog, printing);
    412552
    413553  if (!currentFont)
    414554    return;
    415555
    416   LOG(printf ("font matrix: %f %f %f %f\n", m11, m12, m21, m22));
    417  
    418556  font_face = currentFont->getFontFace();
    419557  cairo_set_font_face (cairo, font_face);
     
    432570  matrix.y0 = 0;
    433571
     572  LOG(printf ("font matrix: %f %f %f %f\n", matrix.xx, matrix.yx, matrix.xy, matrix.yy));
     573
    434574 /* Make sure the font matrix is invertible before setting it.  cairo
    435575  * will blow up if we give it a matrix that's not invertible, so we
     
    445585
    446586  cairo_set_font_matrix (cairo, &matrix);
     587}
     588
     589void CairoOutputDev::updateRender(GfxState *state) {
     590  int rm;
     591  rm = state->getRender();
     592  if (rm == 7 && haveCSPattern) {
     593    haveCSPattern = gFalse;
     594    restoreState(state);
     595  }
    447596}
    448597
     
    516665}
    517666
     667GBool CairoOutputDev::tilingPatternFill(GfxState *state, Object *str,
     668                                        int paintType, Dict *resDict,
     669                                        double *mat, double *bbox,
     670                                        int x0, int y0, int x1, int y1,
     671                                        double xStep, double yStep)
     672{
     673  PDFRectangle box;
     674  Gfx *gfx;
     675  cairo_pattern_t *pattern;
     676  cairo_surface_t *surface;
     677  cairo_matrix_t matrix;
     678  cairo_t *old_cairo;
     679  double xMin, yMin, xMax, yMax;
     680
     681  if (xStep != bbox[2] || yStep != bbox[3])
     682    return gFalse;
     683  /* TODO: implement the other cases here too */
     684
     685  surface = cairo_surface_create_similar (cairo_get_target (cairo),
     686                                          CAIRO_CONTENT_COLOR_ALPHA,
     687                                          bbox[2], bbox[3]);
     688  if (cairo_surface_status (surface))
     689    return gFalse;
     690
     691  old_cairo = cairo;
     692  cairo = cairo_create (surface);
     693  cairo_surface_destroy (surface);
     694
     695  box.x1 = bbox[0]; box.y1 = bbox[1];
     696  box.x2 = bbox[2]; box.y2 = bbox[3];
     697  gfx = new Gfx(xref, this, resDict, catalog, &box, NULL);
     698  gfx->display(str);
     699  delete gfx;
     700
     701  pattern = cairo_pattern_create_for_surface (cairo_get_target (cairo));
     702  cairo_destroy (cairo);
     703  cairo = old_cairo;
     704  if (cairo_pattern_status (pattern))
     705    return gFalse;
     706
     707  state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
     708  cairo_rectangle (cairo, xMin, yMin, xMax - xMin, yMax - yMin);
     709
     710  cairo_matrix_init (&matrix, mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
     711  cairo_transform (cairo, &matrix);
     712  cairo_set_source (cairo, pattern);
     713  cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
     714  cairo_fill (cairo);
     715
     716  cairo_pattern_destroy (pattern);
     717
     718  return gTrue;
     719}
     720
     721GBool CairoOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax) {
     722  double x0, y0, x1, y1;
     723  double dx, dy;
     724
     725  shading->getCoords(&x0, &y0, &x1, &y1);
     726  dx = x1 - x0;
     727  dy = y1 - y0;
     728
     729  cairo_pattern_destroy(fill_pattern);
     730  fill_pattern = cairo_pattern_create_linear (x0 + tMin * dx, y0 + tMin * dy,
     731                                              x0 + tMax * dx, y0 + tMax * dy);
     732  if (!shading->getExtend0() && !shading->getExtend1())
     733    cairo_pattern_set_extend (fill_pattern, CAIRO_EXTEND_NONE);
     734  else
     735    cairo_pattern_set_extend (fill_pattern, CAIRO_EXTEND_PAD);
     736
     737  // TODO: use the actual stops in the shading in the case
     738  // of linear interpolation (Type 2 Exponential functions with N=1)
     739  return gFalse;
     740}
     741
     742GBool CairoOutputDev::axialShadedSupportExtend(GfxState *state, GfxAxialShading *shading)
     743{
     744  return (shading->getExtend0() == shading->getExtend1());
     745}
     746
     747GBool CairoOutputDev::radialShadedFill(GfxState *state, GfxRadialShading *shading, double sMin, double sMax) {
     748  double x0, y0, r0, x1, y1, r1;
     749  double dx, dy, dr;
     750
     751  shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1);
     752  dx = x1 - x0;
     753  dy = y1 - y0;
     754  dr = r1 - r0;
     755  cairo_pattern_destroy(fill_pattern);
     756  fill_pattern = cairo_pattern_create_radial (x0 + sMin * dx,
     757                                              y0 + sMin * dy,
     758                                              r0 + sMin * dr,
     759                                              x0 + sMax * dx,
     760                                              y0 + sMax * dy,
     761                                              r0 + sMax * dr);
     762  if (shading->getExtend0() && shading->getExtend1())
     763    cairo_pattern_set_extend (fill_pattern, CAIRO_EXTEND_PAD);
     764  else
     765    cairo_pattern_set_extend (fill_pattern, CAIRO_EXTEND_NONE);
     766
     767  return gFalse;
     768}
     769
     770GBool CairoOutputDev::radialShadedSupportExtend(GfxState *state, GfxRadialShading *shading)
     771{
     772  return (shading->getExtend0() == shading->getExtend1());
     773}
     774
    518775void CairoOutputDev::clip(GfxState *state) {
    519776  doPath (cairo, state, state->getPath());
     
    551808    return;
    552809
    553   glyphs = (cairo_glyph_t *) gmalloc (len * sizeof (cairo_glyph_t));
     810  glyphs = (cairo_glyph_t *) gmallocn (len, sizeof (cairo_glyph_t));
    554811  glyphCount = 0;
    555812}
     
    560817                              CharCode code, int nBytes, Unicode *u, int uLen)
    561818{
    562   if (!currentFont)
     819  if (currentFont) {
     820    glyphs[glyphCount].index = currentFont->getGlyph (code, u, uLen);
     821    glyphs[glyphCount].x = x - originX;
     822    glyphs[glyphCount].y = y - originY;
     823    glyphCount++;
     824  }
     825
     826  if (!text)
    563827    return;
    564  
    565   glyphs[glyphCount].index = currentFont->getGlyph (code, u, uLen);
    566   glyphs[glyphCount].x = x - originX;
    567   glyphs[glyphCount].y = y - originY;
    568   glyphCount++;
     828  actualText->addChar (state, x, y, dx, dy, code, nBytes, u, uLen);
    569829}
    570830
     
    680940
    681941void CairoOutputDev::type3D0(GfxState *state, double wx, double wy) {
     942  t3_glyph_wx = wx;
     943  t3_glyph_wy = wy;
    682944}
    683945
    684946void CairoOutputDev::type3D1(GfxState *state, double wx, double wy,
    685947                             double llx, double lly, double urx, double ury) {
     948  t3_glyph_wx = wx;
     949  t3_glyph_wy = wy;
     950  t3_glyph_bbox[0] = llx;
     951  t3_glyph_bbox[1] = lly;
     952  t3_glyph_bbox[2] = urx;
     953  t3_glyph_bbox[3] = ury;
     954  t3_glyph_has_bbox = gTrue;
     955}
     956
     957void CairoOutputDev::beginTextObject(GfxState *state) {
     958  if (state->getFillColorSpace()->getMode() == csPattern) {
     959    haveCSPattern = gTrue;
     960    saveState(state);
     961    savedRender = state->getRender();
     962    state->setRender(7); // Set clip to text path
     963  }
    686964}
    687965
    688966void CairoOutputDev::endTextObject(GfxState *state) {
     967  if (haveCSPattern) {
     968    state->setRender(savedRender);
     969    haveCSPattern = gFalse;
     970    if (state->getFillColorSpace()->getMode() != csPattern) {
     971      if (textClipPath) {
     972        cairo_new_path (cairo);
     973        cairo_append_path (cairo, textClipPath);
     974        cairo_set_fill_rule (cairo, CAIRO_FILL_RULE_WINDING);
     975        cairo_set_source (cairo, fill_pattern);
     976        cairo_fill (cairo);
     977        if (cairo_shape) {
     978          cairo_new_path (cairo_shape);
     979          cairo_append_path (cairo_shape, textClipPath);
     980          cairo_set_fill_rule (cairo_shape, CAIRO_FILL_RULE_WINDING);
     981          cairo_fill (cairo_shape);
     982        }
     983        cairo_path_destroy (textClipPath);
     984        textClipPath = NULL;
     985      }
     986      restoreState(state);
     987      updateFillColor(state);
     988    }
     989  }
     990
    689991  if (textClipPath) {
    690992    // clip the accumulated text path
     
    6981000    textClipPath = NULL;
    6991001  }
    700 
     1002}
     1003
     1004void CairoOutputDev::beginMarkedContent(char *name, Dict *properties)
     1005{
     1006  if (text)
     1007    actualText->beginMC(properties);
     1008}
     1009
     1010void CairoOutputDev::endMarkedContent(GfxState *state)
     1011{
     1012  if (text)
     1013    actualText->endMC(state);
    7011014}
    7021015
     
    8661179     * and then use that as the mask. */
    8671180
    868     double x1, y1, x2, y2;
     1181    double x1, y1, x2, y2, tmp;
    8691182    cairo_clip_extents(cairo, &x1, &y1, &x2, &y2);
     1183    cairo_user_to_device(cairo, &x1, &y1);
     1184    cairo_user_to_device(cairo, &x2, &y2);
     1185    if (x1 > x2) {
     1186      tmp = x1;
     1187      x1 = x2;
     1188      x2 = tmp;
     1189    }
     1190
     1191    if (y1 > y2) {
     1192      tmp = y1;
     1193      y1 = y2;
     1194      y2 = tmp;
     1195    }
     1196
    8701197    int width = (int)(ceil(x2) - floor(x1));
    8711198    int height = (int)(ceil(y2) - floor(y1));
     
    9221249      }
    9231250    }
     1251    cairo_surface_mark_dirty (source);
    9241252
    9251253    /* setup the new mask pattern */
     
    9551283
    9561284void CairoOutputDev::clearSoftMask(GfxState * /*state*/) {
    957   //XXX: should we be doing anything here?
     1285  if (mask)
     1286    cairo_pattern_destroy(mask);
     1287  mask = NULL;
     1288}
     1289
     1290void CairoOutputDev::endMaskClip(GfxState *state) {
     1291  clearSoftMask(state);
    9581292}
    9591293
    9601294void CairoOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
    961                                     int width, int height, GBool invert,
    962                                     GBool inlineImg) {
     1295                                   int width, int height, GBool invert,
     1296                                   GBool interpolate, GBool inlineImg) {
    9631297
    9641298  /* FIXME: Doesn't the image mask support any colorspace? */
     
    9871321  // we are rendering fonts */
    9881322  if (!printing && prescaleImages && matrix.xy == 0.0 && matrix.yx == 0.0) {
    989     drawImageMaskPrescaled(state, ref, str, width, height, invert, inlineImg);
     1323    drawImageMaskPrescaled(state, ref, str, width, height, invert, interpolate, inlineImg);
    9901324  } else {
    991     drawImageMaskRegular(state, ref, str, width, height, invert, inlineImg);
     1325    drawImageMaskRegular(state, ref, str, width, height, invert, interpolate, inlineImg);
    9921326  }
    9931327}
    9941328
    9951329void CairoOutputDev::drawImageMaskRegular(GfxState *state, Object *ref, Stream *str,
    996                                     int width, int height, GBool invert,
    997                                     GBool inlineImg) {
     1330                                          int width, int height, GBool invert,
     1331                                          GBool interpolate, GBool inlineImg) {
    9981332  unsigned char *buffer;
    9991333  unsigned char *dest;
     
    10071341  int row_stride;
    10081342
    1009   row_stride = (width + 3) & ~3;
    1010   buffer = (unsigned char *) malloc (height * row_stride);
    1011   if (buffer == NULL) {
    1012     error(-1, "Unable to allocate memory for image.");
    1013     return;
    1014   }
    1015 
    10161343  /* TODO: Do we want to cache these? */
    10171344  imgStr = new ImageStream(str, width, 1, 1);
    10181345  imgStr->reset();
     1346
     1347  image = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
     1348  if (cairo_surface_status (image))
     1349    goto cleanup;
     1350
     1351  buffer = cairo_image_surface_get_data (image);
     1352  row_stride = cairo_image_surface_get_stride (image);
    10191353
    10201354  invert_bit = invert ? 1 : 0;
     
    10321366  }
    10331367
    1034   image = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_A8,
    1035                                                width, height, row_stride);
    1036   if (image == NULL) {
    1037     delete imgStr;
    1038     return;
    1039   }
     1368  cairo_surface_mark_dirty (image);
    10401369  pattern = cairo_pattern_create_for_surface (image);
    1041   if (pattern == NULL) {
    1042     delete imgStr;
    1043     return;
    1044   }
    1045 
    1046   cairo_matrix_init_translate (&matrix, 0, height);
    1047   cairo_matrix_scale (&matrix, width, -height);
    1048 
    1049   cairo_pattern_set_matrix (pattern, &matrix);
     1370  cairo_surface_destroy (image);
     1371  if (cairo_pattern_status (pattern))
     1372    goto cleanup;
     1373
     1374  LOG (printf ("drawImageMask %dx%d\n", width, height));
    10501375
    10511376  /* we should actually be using CAIRO_FILTER_NEAREST here. However,
    10521377   * cairo doesn't yet do minifaction filtering causing scaled down
    10531378   * images with CAIRO_FILTER_NEAREST to look really bad */
    1054   cairo_pattern_set_filter (pattern, CAIRO_FILTER_BEST);
    1055 
    1056   cairo_mask (cairo, pattern);
     1379  cairo_pattern_set_filter (pattern,
     1380                            interpolate ? CAIRO_FILTER_BEST : CAIRO_FILTER_FAST);
     1381  cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
     1382
     1383  cairo_matrix_init_translate (&matrix, 0, height);
     1384  cairo_matrix_scale (&matrix, width, -height);
     1385  cairo_pattern_set_matrix (pattern, &matrix);
     1386
     1387  if (state->getFillColorSpace()->getMode() == csPattern) {
     1388    mask = cairo_pattern_reference (pattern);
     1389  } else {
     1390    cairo_save (cairo);
     1391    cairo_rectangle (cairo, 0., 0., 1., 1.);
     1392    cairo_clip (cairo);
     1393    cairo_mask (cairo, pattern);
     1394    cairo_restore (cairo);
     1395  }
    10571396
    10581397  if (cairo_shape) {
    1059 #if 0
    1060     cairo_rectangle (cairo_shape, 0., 0., width, height);
     1398    cairo_save (cairo_shape);
     1399    cairo_set_source (cairo_shape, pattern);
     1400    cairo_rectangle (cairo_shape, 0., 0., 1., 1.);
    10611401    cairo_fill (cairo_shape);
    1062 #else
    1063     cairo_save (cairo_shape);
    1064     /* this should draw a rectangle the size of the image
    1065      * we use this instead of rect,fill because of the lack
    1066      * of EXTEND_PAD */
    1067     /* NOTE: this will multiply the edges of the image twice */
    1068     cairo_set_source (cairo_shape, pattern);
    1069     cairo_mask (cairo_shape, pattern);
    10701402    cairo_restore (cairo_shape);
    1071 #endif
    1072   }
    1073 
     1403  }
    10741404
    10751405  cairo_pattern_destroy (pattern);
    1076   cairo_surface_destroy (image);
    1077   free (buffer);
     1406
     1407cleanup:
     1408  imgStr->close();
    10781409  delete imgStr;
    10791410}
     
    10811412
    10821413void CairoOutputDev::drawImageMaskPrescaled(GfxState *state, Object *ref, Stream *str,
    1083                                     int width, int height, GBool invert,
    1084                                     GBool inlineImg) {
     1414                                            int width, int height, GBool invert,
     1415                                            GBool interpolate, GBool inlineImg) {
    10851416  unsigned char *buffer;
    10861417  cairo_surface_t *image;
     
    11711502  invert_bit = invert ? 1 : 0;
    11721503
    1173   row_stride = (scaledWidth + 3) & ~3;
    1174   buffer = (unsigned char *) malloc (scaledHeight * row_stride);
    1175   if (buffer == NULL) {
    1176     error(-1, "Unable to allocate memory for image.");
     1504  image = cairo_image_surface_create (CAIRO_FORMAT_A8, scaledWidth, scaledHeight);
     1505  if (cairo_surface_status (image)) {
     1506    imgStr->close();
     1507    delete imgStr;
    11771508    return;
    11781509  }
     1510
     1511  buffer = cairo_image_surface_get_data (image);
     1512  row_stride = cairo_image_surface_get_stride (image);
    11791513
    11801514  int yp = height / scaledHeight;
     
    12911625  free(pixBuf);
    12921626
    1293   //XXX: we should handle error's better than this
    1294   image = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_A8,
    1295       scaledWidth, scaledHeight, row_stride);
    1296   if (image == NULL) {
    1297     delete imgStr;
    1298     return;
    1299   }
     1627  cairo_surface_mark_dirty (image);
    13001628  pattern = cairo_pattern_create_for_surface (image);
    1301   if (pattern == NULL) {
     1629  cairo_surface_destroy (image);
     1630  if (cairo_pattern_status (pattern)) {
     1631    imgStr->close();
    13021632    delete imgStr;
    13031633    return;
     
    13071637   * cairo doesn't yet do minifaction filtering causing scaled down
    13081638   * images with CAIRO_FILTER_NEAREST to look really bad */
    1309   cairo_pattern_set_filter (pattern, CAIRO_FILTER_BEST);
    1310 
    1311   cairo_save (cairo);
    1312 
    1313   /* modify our current transformation so that the prescaled image
    1314    * goes where it is supposed to */
    1315   cairo_get_matrix(cairo, &matrix);
    1316   cairo_scale(cairo, 1.0/matrix.xx, 1.0/matrix.yy);
    1317   // get integer co-ords
    1318   cairo_translate (cairo, tx - matrix.x0, ty2 - matrix.y0);
    1319   if (yScale > 0)
    1320     cairo_scale(cairo, 1, -1);
    1321 
    1322   cairo_mask (cairo, pattern);
    1323 
    1324   //cairo_get_matrix(cairo, &matrix);
    1325   //printf("mask at: [%f %f], [%f %f], %f %f\n\n", matrix.xx, matrix.xy, matrix.yx, matrix.yy, matrix.x0, matrix.y0);
    1326   cairo_restore(cairo);
     1639  cairo_pattern_set_filter (pattern,
     1640                            interpolate ? CAIRO_FILTER_BEST : CAIRO_FILTER_FAST);
     1641  cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
     1642
     1643  if (state->getFillColorSpace()->getMode() == csPattern) {
     1644    cairo_matrix_init_translate (&matrix, 0, scaledHeight);
     1645    cairo_matrix_scale (&matrix, scaledWidth, -scaledHeight);
     1646    cairo_pattern_set_matrix (pattern, &matrix);
     1647
     1648    mask = cairo_pattern_reference (pattern);
     1649  } else {
     1650    cairo_save (cairo);
     1651
     1652    /* modify our current transformation so that the prescaled image
     1653     * goes where it is supposed to */
     1654    cairo_get_matrix(cairo, &matrix);
     1655    cairo_scale(cairo, 1.0/matrix.xx, 1.0/matrix.yy);
     1656    // get integer co-ords
     1657    cairo_translate (cairo, tx - matrix.x0, ty2 - matrix.y0);
     1658    if (yScale > 0)
     1659      cairo_scale(cairo, 1, -1);
     1660
     1661    cairo_rectangle (cairo, 0., 0., scaledWidth, scaledHeight);
     1662    cairo_clip (cairo);
     1663    cairo_mask (cairo, pattern);
     1664
     1665    //cairo_get_matrix(cairo, &matrix);
     1666    //printf("mask at: [%f %f], [%f %f], %f %f\n\n", matrix.xx, matrix.xy, matrix.yx, matrix.yy, matrix.x0, matrix.y0);
     1667    cairo_restore(cairo);
     1668  }
    13271669
    13281670  if (cairo_shape) {
     
    13381680      cairo_scale(cairo_shape, 1, -1);
    13391681
    1340     cairo_mask (cairo_shape, pattern);
     1682    cairo_rectangle (cairo_shape, 0., 0., scaledWidth, scaledHeight);
     1683    cairo_fill (cairo_shape);
    13411684
    13421685    cairo_restore(cairo_shape);
    13431686  }
    13441687
    1345 
    13461688  cairo_pattern_destroy (pattern);
    1347   cairo_surface_destroy (image);
    1348   free (buffer);
     1689
     1690  imgStr->close();
    13491691  delete imgStr;
    13501692}
    13511693
    13521694void CairoOutputDev::drawMaskedImage(GfxState *state, Object *ref,
    1353                                 Stream *str, int width, int height,
    1354                                 GfxImageColorMap *colorMap,
    1355                                 Stream *maskStr, int maskWidth,
    1356                                 int maskHeight, GBool maskInvert)
     1695                                     Stream *str, int width, int height,
     1696                                     GfxImageColorMap *colorMap,
     1697                                     GBool interpolate,
     1698                                     Stream *maskStr, int maskWidth,
     1699                                     int maskHeight, GBool maskInvert,
     1700                                     GBool maskInterpolate)
    13571701{
    1358   ImageStream *maskImgStr;
     1702  ImageStream *maskImgStr, *imgStr;
     1703  int row_stride;
     1704  unsigned char *maskBuffer, *buffer;
     1705  unsigned char *maskDest;
     1706  unsigned int *dest;
     1707  cairo_surface_t *maskImage, *image;
     1708  cairo_pattern_t *maskPattern, *pattern;
     1709  cairo_matrix_t matrix;
     1710  Guchar *pix;
     1711  int x, y;
     1712  int invert_bit;
     1713
    13591714  maskImgStr = new ImageStream(maskStr, maskWidth, 1, 1);
    13601715  maskImgStr->reset();
    13611716
    1362   int row_stride = (maskWidth + 3) & ~3;
    1363   unsigned char *maskBuffer;
    1364   maskBuffer = (unsigned char *)gmalloc (row_stride * maskHeight);
    1365   unsigned char *maskDest;
    1366   cairo_surface_t *maskImage;
    1367   cairo_pattern_t *maskPattern;
    1368   Guchar *pix;
    1369   int x, y;
    1370 
    1371   int invert_bit;
    1372  
     1717  maskImage = cairo_image_surface_create (CAIRO_FORMAT_A8, maskWidth, maskHeight);
     1718  if (cairo_surface_status (maskImage)) {
     1719    maskImgStr->close();
     1720    delete maskImgStr;
     1721    return;
     1722  }
     1723
     1724  maskBuffer = cairo_image_surface_get_data (maskImage);
     1725  row_stride = cairo_image_surface_get_stride (maskImage);
     1726
    13731727  invert_bit = maskInvert ? 1 : 0;
    13741728
     
    13841738  }
    13851739
    1386   maskImage = cairo_image_surface_create_for_data (maskBuffer, CAIRO_FORMAT_A8,
    1387                                                  maskWidth, maskHeight, row_stride);
    1388 
     1740  maskImgStr->close();
    13891741  delete maskImgStr;
    1390   maskStr->close();
    1391 
    1392   unsigned char *buffer;
    1393   unsigned int *dest;
    1394   cairo_surface_t *image;
    1395   cairo_pattern_t *pattern;
    1396   ImageStream *imgStr;
    1397   cairo_matrix_t matrix;
     1742
     1743  cairo_surface_mark_dirty (maskImage);
     1744  maskPattern = cairo_pattern_create_for_surface (maskImage);
     1745  cairo_surface_destroy (maskImage);
     1746  if (cairo_pattern_status (maskPattern))
     1747    return;
     1748
     1749#if 0
     1750  /* ICCBased color space doesn't do any color correction
     1751   * so check its underlying color space as well */
    13981752  int is_identity_transform;
    1399 
    1400   buffer = (unsigned char *)gmalloc (width * height * 4);
     1753  is_identity_transform = colorMap->getColorSpace()->getMode() == csDeviceRGB ||
     1754                  (colorMap->getColorSpace()->getMode() == csICCBased &&
     1755                   ((GfxICCBasedColorSpace*)colorMap->getColorSpace())->getAlt()->getMode() == csDeviceRGB);
     1756#endif
    14011757
    14021758  /* TODO: Do we want to cache these? */
     
    14051761                           colorMap->getBits());
    14061762  imgStr->reset();
    1407  
    1408   /* ICCBased color space doesn't do any color correction
    1409    * so check its underlying color space as well */
    1410   is_identity_transform = colorMap->getColorSpace()->getMode() == csDeviceRGB ||
    1411                   colorMap->getColorSpace()->getMode() == csICCBased &&
    1412                   ((GfxICCBasedColorSpace*)colorMap->getColorSpace())->getAlt()->getMode() == csDeviceRGB;
    1413 
     1763
     1764  image = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
     1765  if (cairo_surface_status (image))
     1766    goto cleanup;
     1767
     1768  buffer = cairo_image_surface_get_data (image);
     1769  row_stride = cairo_image_surface_get_stride (image);
    14141770  for (y = 0; y < height; y++) {
    1415     dest = (unsigned int *) (buffer + y * 4 * width);
     1771    dest = (unsigned int *) (buffer + y * row_stride);
    14161772    pix = imgStr->getLine();
    14171773    colorMap->getRGBLine (pix, dest, width);
    14181774  }
    14191775
    1420   image = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_RGB24,
    1421                                                  width, height, width * 4);
    1422 
    1423   if (image == NULL) {
    1424     delete imgStr;
    1425     return;
    1426   }
     1776  cairo_surface_mark_dirty (image);
    14271777  pattern = cairo_pattern_create_for_surface (image);
    1428   maskPattern = cairo_pattern_create_for_surface (maskImage);
    1429   if (pattern == NULL) {
    1430     delete imgStr;
    1431     return;
    1432   }
     1778  cairo_surface_destroy (image);
     1779  if (cairo_pattern_status (pattern))
     1780    goto cleanup;
    14331781
    14341782  LOG (printf ("drawMaskedImage %dx%d\n", width, height));
     1783
     1784  cairo_pattern_set_filter (pattern,
     1785                            interpolate ? CAIRO_FILTER_BILINEAR : CAIRO_FILTER_FAST);
     1786  cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
     1787  cairo_pattern_set_filter (maskPattern,
     1788                            maskInterpolate ? CAIRO_FILTER_BILINEAR : CAIRO_FILTER_FAST);
     1789  cairo_pattern_set_extend (maskPattern, CAIRO_EXTEND_PAD);
    14351790
    14361791  cairo_matrix_init_translate (&matrix, 0, height);
    14371792  cairo_matrix_scale (&matrix, width, -height);
    14381793
    1439   /* scale the mask to the size of the image unlike softMask */
    14401794  cairo_pattern_set_matrix (pattern, &matrix);
    14411795  cairo_pattern_set_matrix (maskPattern, &matrix);
    14421796
    1443   cairo_pattern_set_filter (pattern, CAIRO_FILTER_BILINEAR);
     1797  cairo_save (cairo);
    14441798  cairo_set_source (cairo, pattern);
     1799  cairo_rectangle (cairo, 0., 0., 1., 1.);
     1800  cairo_clip (cairo);
    14451801  cairo_mask (cairo, maskPattern);
     1802  cairo_restore (cairo);
    14461803
    14471804  if (cairo_shape) {
    1448 #if 0
    1449     cairo_rectangle (cairo_shape, 0., 0., width, height);
     1805    cairo_save (cairo_shape);
     1806    cairo_set_source (cairo_shape, pattern);
     1807    cairo_rectangle (cairo_shape, 0., 0., 1., 1.);
    14501808    cairo_fill (cairo_shape);
    1451 #else
    1452     cairo_save (cairo_shape);
    1453     /* this should draw a rectangle the size of the image
    1454      * we use this instead of rect,fill because of the lack
    1455      * of EXTEND_PAD */
    1456     /* NOTE: this will multiply the edges of the image twice */
    1457     cairo_set_source (cairo_shape, pattern);
    1458     cairo_mask (cairo_shape, pattern);
    14591809    cairo_restore (cairo_shape);
    1460 #endif
    14611810  }
    14621811
    14631812  cairo_pattern_destroy (maskPattern);
    1464   cairo_surface_destroy (maskImage);
    14651813  cairo_pattern_destroy (pattern);
    1466   cairo_surface_destroy (image);
    1467   free (buffer);
    1468   free (maskBuffer);
     1814
     1815cleanup:
     1816  imgStr->close();
    14691817  delete imgStr;
    14701818}
     
    14731821//XXX: is this affect by AIS(alpha is shape)?
    14741822void CairoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str,
    1475                                 int width, int height,
    1476                                 GfxImageColorMap *colorMap,
    1477                                 Stream *maskStr,
    1478                                 int maskWidth, int maskHeight,
    1479                                 GfxImageColorMap *maskColorMap)
     1823                                         int width, int height,
     1824                                         GfxImageColorMap *colorMap,
     1825                                         GBool interpolate,
     1826                                         Stream *maskStr,
     1827                                         int maskWidth, int maskHeight,
     1828                                         GfxImageColorMap *maskColorMap,
     1829                                         GBool maskInterpolate)
    14801830{
    1481   ImageStream *maskImgStr;
    1482   maskImgStr = new ImageStream(maskStr, maskWidth,
    1483                                        maskColorMap->getNumPixelComps(),
    1484                                        maskColorMap->getBits());
    1485   maskImgStr->reset();
    1486 
    1487   int row_stride = (maskWidth + 3) & ~3;
    1488   unsigned char *maskBuffer;
    1489   maskBuffer = (unsigned char *)gmalloc (row_stride * maskHeight);
     1831  ImageStream *maskImgStr, *imgStr;
     1832  int row_stride;
     1833  unsigned char *maskBuffer, *buffer;
    14901834  unsigned char *maskDest;
    1491   cairo_surface_t *maskImage;
    1492   cairo_pattern_t *maskPattern;
     1835  unsigned int *dest;
     1836  cairo_surface_t *maskImage, *image;
     1837  cairo_pattern_t *maskPattern, *pattern;
     1838  cairo_matrix_t maskMatrix, matrix;
    14931839  Guchar *pix;
    14941840  int y;
     1841
     1842  maskImgStr = new ImageStream(maskStr, maskWidth,
     1843                               maskColorMap->getNumPixelComps(),
     1844                               maskColorMap->getBits());
     1845  maskImgStr->reset();
     1846
     1847  maskImage = cairo_image_surface_create (CAIRO_FORMAT_A8, maskWidth, maskHeight);
     1848  if (cairo_surface_status (maskImage)) {
     1849    maskImgStr->close();
     1850    delete maskImgStr;
     1851    return;
     1852  }
     1853
     1854  maskBuffer = cairo_image_surface_get_data (maskImage);
     1855  row_stride = cairo_image_surface_get_stride (maskImage);
    14951856  for (y = 0; y < maskHeight; y++) {
    14961857    maskDest = (unsigned char *) (maskBuffer + y * row_stride);
     
    14991860  }
    15001861
    1501   maskImage = cairo_image_surface_create_for_data (maskBuffer, CAIRO_FORMAT_A8,
    1502                                                  maskWidth, maskHeight, row_stride);
    1503 
     1862  maskImgStr->close();
    15041863  delete maskImgStr;
    1505   maskStr->close();
    1506 
    1507   unsigned char *buffer;
    1508   unsigned int *dest;
    1509   cairo_surface_t *image;
    1510   cairo_pattern_t *pattern;
    1511   ImageStream *imgStr;
    1512   cairo_matrix_t matrix;
    1513   cairo_matrix_t maskMatrix;
     1864
     1865  cairo_surface_mark_dirty (maskImage);
     1866  maskPattern = cairo_pattern_create_for_surface (maskImage);
     1867  cairo_surface_destroy (maskImage);
     1868  if (cairo_pattern_status (maskPattern))
     1869    return;
     1870
     1871#if 0
     1872  /* ICCBased color space doesn't do any color correction
     1873   * so check its underlying color space as well */
    15141874  int is_identity_transform;
    1515 
    1516   buffer = (unsigned char *)gmalloc (width * height * 4);
     1875  is_identity_transform = colorMap->getColorSpace()->getMode() == csDeviceRGB ||
     1876                  (colorMap->getColorSpace()->getMode() == csICCBased &&
     1877                   ((GfxICCBasedColorSpace*)colorMap->getColorSpace())->getAlt()->getMode() == csDeviceRGB);
     1878#endif
    15171879
    15181880  /* TODO: Do we want to cache these? */
     
    15211883                           colorMap->getBits());
    15221884  imgStr->reset();
    1523  
    1524   /* ICCBased color space doesn't do any color correction
    1525    * so check its underlying color space as well */
    1526   is_identity_transform = colorMap->getColorSpace()->getMode() == csDeviceRGB ||
    1527                   colorMap->getColorSpace()->getMode() == csICCBased &&
    1528                   ((GfxICCBasedColorSpace*)colorMap->getColorSpace())->getAlt()->getMode() == csDeviceRGB;
    1529 
     1885
     1886  image = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
     1887  if (cairo_surface_status (image))
     1888    goto cleanup;
     1889
     1890  buffer = cairo_image_surface_get_data (image);
     1891  row_stride = cairo_image_surface_get_stride (image);
    15301892  for (y = 0; y < height; y++) {
    1531     dest = (unsigned int *) (buffer + y * 4 * width);
     1893    dest = (unsigned int *) (buffer + y * row_stride);
    15321894    pix = imgStr->getLine();
    15331895    colorMap->getRGBLine (pix, dest, width);
    15341896  }
    15351897
    1536   image = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_RGB24,
    1537                                                  width, height, width * 4);
    1538 
    1539   if (image == NULL) {
    1540     delete imgStr;
    1541     return;
    1542   }
     1898  cairo_surface_mark_dirty (image);
    15431899  pattern = cairo_pattern_create_for_surface (image);
    1544   maskPattern = cairo_pattern_create_for_surface (maskImage);
    1545   if (pattern == NULL) {
    1546     delete imgStr;
    1547     return;
    1548   }
     1900  cairo_surface_destroy (image);
     1901  if (cairo_pattern_status (pattern))
     1902    goto cleanup;
    15491903
    15501904  LOG (printf ("drawSoftMaskedImage %dx%d\n", width, height));
     1905
     1906  //XXX: should set mask filter
     1907  cairo_pattern_set_filter (pattern,
     1908                            interpolate ? CAIRO_FILTER_BILINEAR : CAIRO_FILTER_FAST);
     1909  cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
     1910  cairo_pattern_set_filter (maskPattern,
     1911                            maskInterpolate ? CAIRO_FILTER_BILINEAR : CAIRO_FILTER_FAST);
     1912  cairo_pattern_set_extend (maskPattern, CAIRO_EXTEND_PAD);
    15511913
    15521914  cairo_matrix_init_translate (&matrix, 0, height);
    15531915  cairo_matrix_scale (&matrix, width, -height);
     1916  cairo_pattern_set_matrix (pattern, &matrix);
    15541917
    15551918  cairo_matrix_init_translate (&maskMatrix, 0, maskHeight);
    15561919  cairo_matrix_scale (&maskMatrix, maskWidth, -maskHeight);
    1557 
    1558   cairo_pattern_set_matrix (pattern, &matrix);
    15591920  cairo_pattern_set_matrix (maskPattern, &maskMatrix);
    15601921
    1561   //XXX: should set mask filter
    1562   cairo_pattern_set_filter (pattern, CAIRO_FILTER_BILINEAR);
    1563   cairo_pattern_set_filter (maskPattern, CAIRO_FILTER_BILINEAR);
     1922  cairo_save (cairo);
    15641923  cairo_set_source (cairo, pattern);
     1924  cairo_rectangle (cairo, 0., 0.,
     1925                   MIN (width, maskWidth) / (double)width,
     1926                   MIN (height, maskHeight) / (double)height);
     1927  cairo_clip (cairo);
    15651928  cairo_mask (cairo, maskPattern);
     1929  cairo_restore (cairo);
    15661930
    15671931  if (cairo_shape) {
    1568 #if 0
    1569     cairo_rectangle (cairo_shape, 0., 0., width, height);
     1932    cairo_save (cairo_shape);
     1933    cairo_set_source (cairo_shape, pattern);
     1934    cairo_rectangle (cairo_shape, 0., 0.,
     1935                     MIN (width, maskWidth) / (double)width,
     1936                     MIN (height, maskHeight) / (double)height);
    15701937    cairo_fill (cairo_shape);
    1571 #else
    1572     cairo_save (cairo_shape);
    1573     /* this should draw a rectangle the size of the image
    1574      * we use this instead of rect,fill because of the lack
    1575      * of EXTEND_PAD */
    1576     /* NOTE: this will multiply the edges of the image twice */
    1577     cairo_set_source (cairo_shape, pattern);
    1578     cairo_mask (cairo_shape, pattern);
    15791938    cairo_restore (cairo_shape);
    1580 #endif
    15811939  }
    15821940
    15831941  cairo_pattern_destroy (maskPattern);
    1584   cairo_surface_destroy (maskImage);
    15851942  cairo_pattern_destroy (pattern);
    1586   cairo_surface_destroy (image);
    1587   free (buffer);
    1588   free (maskBuffer);
    1589 
     1943
     1944cleanup:
     1945  imgStr->close();
    15901946  delete imgStr;
    15911947}
     1948
    15921949void CairoOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
    1593                                 int width, int height,
    1594                                 GfxImageColorMap *colorMap,
    1595                                 int *maskColors, GBool inlineImg)
     1950                               int width, int height,
     1951                               GfxImageColorMap *colorMap,
     1952                               GBool interpolate,
     1953                               int *maskColors, GBool inlineImg)
    15961954{
     1955  cairo_surface_t *image;
     1956  cairo_pattern_t *pattern, *maskPattern;
     1957  ImageStream *imgStr;
     1958  cairo_matrix_t matrix;
    15971959  unsigned char *buffer;
    1598   unsigned int *dest;
    1599   cairo_surface_t *image;
    1600   cairo_pattern_t *pattern;
    1601   int x, y;
    1602   ImageStream *imgStr;
    1603   Guchar *pix;
    1604   int i;
    1605   cairo_matrix_t matrix;
    1606   int is_identity_transform;
    1607  
    1608   buffer = (unsigned char *)gmalloc (width * height * 4);
     1960  int stride, i;
     1961  GfxRGB *lookup = NULL;
    16091962
    16101963  /* TODO: Do we want to cache these? */
     
    16131966                           colorMap->getBits());
    16141967  imgStr->reset();
    1615  
     1968
     1969#if 0
    16161970  /* ICCBased color space doesn't do any color correction
    16171971   * so check its underlying color space as well */
     1972  int is_identity_transform;
    16181973  is_identity_transform = colorMap->getColorSpace()->getMode() == csDeviceRGB ||
    1619                   colorMap->getColorSpace()->getMode() == csICCBased &&
    1620                   ((GfxICCBasedColorSpace*)colorMap->getColorSpace())->getAlt()->getMode() == csDeviceRGB;
    1621 
    1622   if (maskColors) {
    1623     for (y = 0; y < height; y++) {
    1624       dest = (unsigned int *) (buffer + y * 4 * width);
    1625       pix = imgStr->getLine();
     1974                  (colorMap->getColorSpace()->getMode() == csICCBased &&
     1975                   ((GfxICCBasedColorSpace*)colorMap->getColorSpace())->getAlt()->getMode() == csDeviceRGB);
     1976#endif
     1977
     1978  image = cairo_image_surface_create (maskColors ?
     1979                                      CAIRO_FORMAT_ARGB32 :
     1980                                      CAIRO_FORMAT_RGB24,
     1981                                      width, height);
     1982  if (cairo_surface_status (image))
     1983    goto cleanup;
     1984
     1985  // special case for one-channel (monochrome/gray/separation) images:
     1986  // build a lookup table here
     1987  if (colorMap->getNumPixelComps() == 1) {
     1988    int n;
     1989    Guchar pix;
     1990
     1991    n = 1 << colorMap->getBits();
     1992    lookup = (GfxRGB *)gmallocn(n, sizeof(GfxRGB));
     1993    for (i = 0; i < n; ++i) {
     1994      pix = (Guchar)i;
     1995
     1996      colorMap->getRGB(&pix, &lookup[i]);
     1997    }
     1998  }
     1999
     2000  buffer = cairo_image_surface_get_data (image);
     2001  stride = cairo_image_surface_get_stride (image);
     2002  for (int y = 0; y < height; y++) {
     2003    uint32_t *dest = (uint32_t *) (buffer + y * stride);
     2004    Guchar *pix = imgStr->getLine();
     2005
     2006    if (lookup) {
     2007      Guchar *p = pix;
     2008      GfxRGB rgb;
     2009
     2010      for (i = 0; i < width; i++) {
     2011        rgb = lookup[*p];
     2012        dest[i] =
     2013                ((int) colToByte(rgb.r) << 16) |
     2014                ((int) colToByte(rgb.g) << 8) |
     2015                ((int) colToByte(rgb.b) << 0);
     2016        p++;
     2017      }
     2018    } else {
    16262019      colorMap->getRGBLine (pix, dest, width);
    1627 
    1628       for (x = 0; x < width; x++) {
    1629         for (i = 0; i < colorMap->getNumPixelComps(); ++i) {
    1630          
    1631           if (pix[i] < maskColors[2*i] * 255||
    1632               pix[i] > maskColors[2*i+1] * 255) {
    1633             *dest = *dest | 0xff000000;
     2020    }
     2021
     2022    if (maskColors) {
     2023      for (int x = 0; x < width; x++) {
     2024        bool is_opaque = false;
     2025        for (int i = 0; i < colorMap->getNumPixelComps(); ++i) {
     2026          if (pix[i] < maskColors[2*i] ||
     2027              pix[i] > maskColors[2*i+1]) {
     2028            is_opaque = true;
    16342029            break;
    16352030          }
    16362031        }
     2032        if (is_opaque)
     2033          *dest |= 0xff000000;
     2034        else
     2035          *dest = 0;
     2036        dest++;
    16372037        pix += colorMap->getNumPixelComps();
    1638         dest++;
    16392038      }
    16402039    }
    1641 
    1642     image = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_ARGB32,
    1643                                                  width, height, width * 4);
    1644   }
    1645   else {
    1646     for (y = 0; y < height; y++) {
    1647       dest = (unsigned int *) (buffer + y * 4 * width);
    1648       pix = imgStr->getLine();
    1649       colorMap->getRGBLine (pix, dest, width);
    1650     }
    1651 
    1652     image = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_RGB24,
    1653                                                  width, height, width * 4);
    1654   }
    1655 
    1656   if (image == NULL) {
    1657    delete imgStr;
    1658    return;
    1659   }
     2040  }
     2041  gfree(lookup);
     2042
     2043  cairo_surface_mark_dirty (image);
    16602044  pattern = cairo_pattern_create_for_surface (image);
    1661   if (pattern == NULL) {
    1662     delete imgStr;
    1663     return;
    1664   }
    1665 
    1666   LOG (printf ("drawImageMask %dx%d\n", width, height));
    1667  
     2045  cairo_surface_destroy (image);
     2046  if (cairo_pattern_status (pattern))
     2047    goto cleanup;
     2048
     2049  LOG (printf ("drawImage %dx%d\n", width, height));
     2050
     2051  cairo_pattern_set_filter (pattern,
     2052                            interpolate ?
     2053                            CAIRO_FILTER_BILINEAR : CAIRO_FILTER_FAST);
     2054  cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
     2055
    16682056  cairo_matrix_init_translate (&matrix, 0, height);
    16692057  cairo_matrix_scale (&matrix, width, -height);
    1670 
    16712058  cairo_pattern_set_matrix (pattern, &matrix);
    16722059
    1673   cairo_pattern_set_filter (pattern, CAIRO_FILTER_BILINEAR);
     2060  if (!mask && fill_opacity != 1.0) {
     2061    maskPattern = cairo_pattern_create_rgba (1., 1., 1., fill_opacity);
     2062  } else if (mask) {
     2063    maskPattern = cairo_pattern_reference (mask);
     2064  } else {
     2065    maskPattern = NULL;
     2066  }
     2067
     2068  cairo_save (cairo);
    16742069  cairo_set_source (cairo, pattern);
    1675   cairo_paint (cairo);
     2070  cairo_rectangle (cairo, 0., 0., 1., 1.);
     2071  if (maskPattern) {
     2072    cairo_clip (cairo);
     2073    cairo_mask (cairo, maskPattern);
     2074  } else {
     2075    cairo_fill (cairo);
     2076  }
     2077  cairo_restore (cairo);
     2078
     2079  cairo_pattern_destroy (maskPattern);
    16762080
    16772081  if (cairo_shape) {
    1678 #if 0
    1679     cairo_rectangle (cairo_shape, 0., 0., width, height);
     2082    cairo_save (cairo_shape);
     2083    cairo_set_source (cairo_shape, pattern);
     2084    cairo_rectangle (cairo_shape, 0., 0., 1., 1.);
    16802085    cairo_fill (cairo_shape);
    1681 #else
    1682     cairo_save (cairo_shape);
    1683     /* this should draw a rectangle the size of the image
    1684      * we use this instead of rect,fill because of the lack
    1685      * of EXTEND_PAD */
    1686     /* NOTE: this will multiply the edges of the image twice */
    1687     cairo_set_source (cairo_shape, pattern);
    1688     cairo_paint(cairo_shape);
    16892086    cairo_restore (cairo_shape);
    1690 #endif
    16912087  }
    16922088
    16932089  cairo_pattern_destroy (pattern);
    1694   cairo_surface_destroy (image);
    1695   free (buffer);
     2090
     2091cleanup:
     2092  imgStr->close();
    16962093  delete imgStr;
    16972094}
     
    17312128void CairoImageOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
    17322129                                        int width, int height, GBool invert,
    1733                                         GBool inlineImg)
     2130                                        GBool interpolate, GBool inlineImg)
    17342131{
    17352132  cairo_t *cr;
     
    17632160    cairo_scale (cr, width, -height);
    17642161
    1765     CairoOutputDev::drawImageMask(state, ref, str, width, height, invert, inlineImg);
     2162    CairoOutputDev::drawImageMask(state, ref, str, width, height, invert, interpolate, inlineImg);
    17662163    image->setImage (surface);
    17672164
     
    17742171void CairoImageOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
    17752172                                    int width, int height, GfxImageColorMap *colorMap,
    1776                                     int *maskColors, GBool inlineImg)
     2173                                    GBool interpolate, int *maskColors, GBool inlineImg)
    17772174{
    17782175  cairo_t *cr;
     
    18062203    cairo_scale (cr, width, -height);
    18072204   
    1808     CairoOutputDev::drawImage(state, ref, str, width, height, colorMap, maskColors, inlineImg);
     2205    CairoOutputDev::drawImage(state, ref, str, width, height, colorMap, interpolate, maskColors, inlineImg);
    18092206    image->setImage (surface);
    18102207   
     
    18182215                                              int width, int height,
    18192216                                              GfxImageColorMap *colorMap,
     2217                                              GBool interpolate,
    18202218                                              Stream *maskStr,
    18212219                                              int maskWidth, int maskHeight,
    1822                                               GfxImageColorMap *maskColorMap)
     2220                                              GfxImageColorMap *maskColorMap,
     2221                                              GBool maskInterpolate)
    18232222{
    18242223  cairo_t *cr;
     
    18522251    cairo_scale (cr, width, -height);
    18532252   
    1854     CairoOutputDev::drawSoftMaskedImage(state, ref, str, width, height, colorMap,
    1855                                         maskStr, maskWidth, maskHeight, maskColorMap);
     2253    CairoOutputDev::drawSoftMaskedImage(state, ref, str, width, height, colorMap, interpolate,
     2254                                        maskStr, maskWidth, maskHeight, maskColorMap, maskInterpolate);
    18562255    image->setImage (surface);
    18572256   
     
    18652264                                          int width, int height,
    18662265                                          GfxImageColorMap *colorMap,
     2266                                          GBool interpolate,
    18672267                                          Stream *maskStr,
    18682268                                          int maskWidth, int maskHeight,
    1869                                           GBool maskInvert)
     2269                                          GBool maskInvert, GBool maskInterpolate)
    18702270{
    18712271  cairo_t *cr;
     
    18992299    cairo_scale (cr, width, -height);
    19002300   
    1901     CairoOutputDev::drawMaskedImage(state, ref, str, width, height, colorMap,
    1902                                     maskStr, maskWidth, maskHeight, maskInvert);
     2301    CairoOutputDev::drawMaskedImage(state, ref, str, width, height, colorMap, interpolate,
     2302                                    maskStr, maskWidth, maskHeight, maskInvert, maskInterpolate);
    19032303    image->setImage (surface);
    19042304   
  • trunk/poppler/mypoppler/poppler/CairoOutputDev.h

    r257 r277  
    1818// Copyright (C) 2005, 2006 Kristian HÞgsberg <krh@redhat.com>
    1919// Copyright (C) 2005 Nickolay V. Shmyrev <nshmyrev@yandex.ru>
    20 // Copyright (C) 2006-2008 Carlos Garcia Campos <carlosgc@gnome.org>
    21 // Copyright (C) 2008 Adrian Johnson <ajohnson@redneon.com>
     20// Copyright (C) 2006-2009 Carlos Garcia Campos <carlosgc@gnome.org>
     21// Copyright (C) 2008, 2009 Adrian Johnson <ajohnson@redneon.com>
    2222// Copyright (C) 2008 Michael Vrable <mvrable@cs.ucsd.edu>
    2323//
     
    3737#include <cairo-ft.h>
    3838#include "OutputDev.h"
     39#include "TextOutputDev.h"
    3940#include "GfxState.h"
    4041
     
    9899  virtual GBool useDrawChar() { return gTrue; }
    99100
     101  // Does this device use tilingPatternFill()?  If this returns false,
     102  // tiling pattern fills will be reduced to a series of other drawing
     103  // operations.
     104  virtual GBool useTilingPatternFill() { return gTrue; }
     105
     106  // Does this device use functionShadedFill(), axialShadedFill(), and
     107  // radialShadedFill()?  If this returns false, these shaded fills
     108  // will be reduced to a series of other drawing operations.
     109  virtual GBool useShadedFills() { return gTrue; }
     110
     111  // Does this device use FillColorStop()?
     112  virtual GBool useFillColorStop() { return gTrue; }
     113
    100114  // Does this device use beginType3Char/endType3Char?  Otherwise,
    101115  // text in Type 3 fonts will be drawn with drawChar/drawString.
    102   virtual GBool interpretType3Chars() { return gTrue; }
     116  virtual GBool interpretType3Chars() { return gFalse; }
    103117
    104118  //----- initialization and control
     
    108122
    109123  // End a page.
    110   virtual void endPage() { }
     124  virtual void endPage();
    111125
    112126  //----- link borders
     
    132146  virtual void updateFillOpacity(GfxState *state);
    133147  virtual void updateStrokeOpacity(GfxState *state);
     148  virtual void updateFillColorStop(GfxState *state, double offset);
     149  virtual void updateBlendMode(GfxState *state);
    134150
    135151  //----- update text state
    136152  virtual void updateFont(GfxState *state);
     153  virtual void updateRender(GfxState *state);
    137154
    138155  //----- path painting
     
    140157  virtual void fill(GfxState *state);
    141158  virtual void eoFill(GfxState *state);
     159  virtual GBool tilingPatternFill(GfxState *state, Object *str,
     160                                  int paintType, Dict *resDict,
     161                                  double *mat, double *bbox,
     162                                  int x0, int y0, int x1, int y1,
     163                                  double xStep, double yStep);
     164  virtual GBool axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax);
     165  virtual GBool axialShadedSupportExtend(GfxState *state, GfxAxialShading *shading);
     166  virtual GBool radialShadedFill(GfxState *state, GfxRadialShading *shading, double sMin, double sMax);
     167  virtual GBool radialShadedSupportExtend(GfxState *state, GfxRadialShading *shading);
    142168
    143169  //----- path clipping
     
    157183                               CharCode code, Unicode *u, int uLen);
    158184  virtual void endType3Char(GfxState *state);
     185  virtual void beginTextObject(GfxState *state);
     186  virtual GBool deviceHasTextClip(GfxState *state) { return textClipPath && haveCSPattern; }
    159187  virtual void endTextObject(GfxState *state);
     188
     189  // If current colorspace is pattern,
     190  // does this device support text in pattern colorspace?
     191  virtual GBool supportTextCSPattern(GfxState *state) {
     192      return state->getFillColorSpace()->getMode() == csPattern; }
     193
     194  // If current colorspace is pattern,
     195  // need this device special handling for masks in pattern colorspace?
     196  virtual GBool fillMaskCSPattern(GfxState * state) {
     197      return state->getFillColorSpace()->getMode() == csPattern; }
     198
     199  virtual void endMaskClip(GfxState *state);
     200
     201  //----- grouping operators
     202  virtual void beginMarkedContent(char *name, Dict *properties);
     203  virtual void endMarkedContent(GfxState *state); 
    160204
    161205  //----- image drawing
    162206  virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
    163                              int width, int height, GBool invert,
     207                             int width, int height, GBool invert, GBool interpolate,
    164208                             GBool inlineImg);
    165209  void drawImageMaskPrescaled(GfxState *state, Object *ref, Stream *str,
    166                              int width, int height, GBool invert,
    167                              GBool inlineImg);
     210                              int width, int height, GBool invert, GBool interpolate,
     211                              GBool inlineImg);
    168212  void drawImageMaskRegular(GfxState *state, Object *ref, Stream *str,
    169                              int width, int height, GBool invert,
    170                              GBool inlineImg);
     213                            int width, int height, GBool invert, GBool interpolate,
     214                            GBool inlineImg);
    171215
    172216  virtual void drawImage(GfxState *state, Object *ref, Stream *str,
    173217                         int width, int height, GfxImageColorMap *colorMap,
    174                          int *maskColors, GBool inlineImg);
     218                         GBool interpolate, int *maskColors, GBool inlineImg);
    175219  virtual void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str,
    176                                 int width, int height,
    177                                 GfxImageColorMap *colorMap,
    178                                 Stream *maskStr,
    179                                 int maskWidth, int maskHeight,
    180                                 GfxImageColorMap *maskColorMap);
     220                                   int width, int height,
     221                                   GfxImageColorMap *colorMap,
     222                                   GBool interpolate,
     223                                   Stream *maskStr,
     224                                   int maskWidth, int maskHeight,
     225                                   GfxImageColorMap *maskColorMap,
     226                                   GBool maskInterpolate);
    181227
    182228  virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str,
    183                                 int width, int height,
    184                                 GfxImageColorMap *colorMap,
    185                                 Stream *maskStr,
    186                                 int maskWidth, int maskHeight,
    187                                 GBool maskInvert);
    188 
     229                               int width, int height,
     230                               GfxImageColorMap *colorMap,
     231                               GBool interpolate,
     232                               Stream *maskStr,
     233                               int maskWidth, int maskHeight,
     234                               GBool maskInvert, GBool maskInterpolate);
    189235
    190236  //----- transparency groups and soft masks
     
    206252
    207253  //----- special access
    208 
     254 
    209255  // Called to indicate that a new PDF document has been loaded.
    210   void startDoc(XRef *xrefA);
     256  void startDoc(XRef *xrefA, Catalog *catalogA, CairoFontEngine *fontEngine = NULL);
    211257 
    212258  GBool isReverseVideo() { return gFalse; }
    213259 
    214260  void setCairo (cairo_t *cr);
    215   void setPrinting (GBool printing) { this->printing = printing; }
     261  void setTextPage (TextPage *text);
     262  void setPrinting (GBool printing) { this->printing = printing; needFontUpdate = gTrue; }
     263
     264  void setInType3Char(GBool inType3Char) { this->inType3Char = inType3Char; }
     265  void getType3GlyphWidth (double *wx, double *wy) { *wx = t3_glyph_wx; *wy = t3_glyph_wy; }
     266  GBool hasType3GlyphBBox () { return t3_glyph_has_bbox; }
     267  double *getType3GlyphBBox () { return t3_glyph_bbox; }
    216268
    217269protected:
     
    225277 
    226278  XRef *xref;                   // xref table for current document
     279  Catalog *catalog;
    227280
    228281  static FT_Library ft_lib;
     
    230283
    231284  CairoFontEngine *fontEngine;
     285  GBool fontEngine_owner;
     286
    232287  cairo_t *cairo;
    233288  cairo_matrix_t orig_matrix;
     
    238293  int glyphCount;
    239294  cairo_path_t *textClipPath;
     295  GBool inType3Char;            // inside a Type 3 CharProc
     296  double t3_glyph_wx, t3_glyph_wy;
     297  GBool t3_glyph_has_bbox;
     298  double t3_glyph_bbox[4];
    240299
    241300  GBool prescaleImages;
     301
     302  TextPage *text;               // text for the current page
     303  ActualText *actualText;
    242304
    243305  cairo_pattern_t *group;
     
    252314    struct ColorSpaceStack *next;
    253315  } * groupColorSpaceStack;
     316
     317  struct MaskStack {
     318      cairo_pattern_t *mask;
     319      struct MaskStack *next;
     320  } *maskStack;
     321
     322  GBool haveCSPattern;  // set if text has been drawn with a
     323                        //   clipping render mode because of pattern colorspace
     324  int savedRender;      // use if pattern colorspace
    254325};
    255326
     
    276347  // Does this device use drawChar() or drawString()?
    277348  virtual GBool useDrawChar() { return gFalse; }
     349
     350  // Does this device use tilingPatternFill()?  If this returns false,
     351  // tiling pattern fills will be reduced to a series of other drawing
     352  // operations.
     353  virtual GBool useTilingPatternFill() { return gTrue; }
     354
     355  // Does this device use functionShadedFill(), axialShadedFill(), and
     356  // radialShadedFill()?  If this returns false, these shaded fills
     357  // will be reduced to a series of other drawing operations.
     358  virtual GBool useShadedFills() { return gTrue; }
     359
     360  // Does this device use FillColorStop()?
     361  virtual GBool useFillColorStop() { return gFalse; }
    278362
    279363  // Does this device use beginType3Char/endType3Char?  Otherwise,
     
    306390  virtual void updateFillOpacity(GfxState *state) { }
    307391  virtual void updateStrokeOpacity(GfxState *state) { }
     392  virtual void updateBlendMode(GfxState *state) { }
    308393
    309394  //----- update text state
     
    314399  virtual void fill(GfxState *state) { }
    315400  virtual void eoFill(GfxState *state) { }
     401  virtual GBool tilingPatternFill(GfxState *state, Object *str,
     402                                  int paintType, Dict *resDict,
     403                                  double *mat, double *bbox,
     404                                  int x0, int y0, int x1, int y1,
     405                                  double xStep, double yStep) { return gTrue; }
     406  virtual GBool axialShadedFill(GfxState *state,
     407                                GfxAxialShading *shading,
     408                                double tMin, double tMax) { return gTrue; }
     409  virtual GBool radialShadedFill(GfxState *state,
     410                                 GfxRadialShading *shading,
     411                                 double sMin, double sMax) { return gTrue; }
    316412
    317413  //----- path clipping
     
    322418  virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
    323419                             int width, int height, GBool invert,
    324                              GBool inlineImg);
     420                             GBool interpolate, GBool inlineImg);
    325421  virtual void drawImage(GfxState *state, Object *ref, Stream *str,
    326422                         int width, int height, GfxImageColorMap *colorMap,
    327                          int *maskColors, GBool inlineImg);
     423                         GBool interpolate, int *maskColors, GBool inlineImg);
    328424  virtual void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str,
    329425                                   int width, int height,
    330426                                   GfxImageColorMap *colorMap,
     427                                   GBool interpolate,
    331428                                   Stream *maskStr,
    332429                                   int maskWidth, int maskHeight,
    333                                    GfxImageColorMap *maskColorMap);
     430                                   GfxImageColorMap *maskColorMap,
     431                                   GBool maskInterpolate);
    334432  virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str,
    335433                               int width, int height,
    336434                               GfxImageColorMap *colorMap,
     435                               GBool interpolate,
    337436                               Stream *maskStr,
    338437                               int maskWidth, int maskHeight,
    339                                GBool maskInvert);
     438                               GBool maskInvert, GBool maskInterpolate);
    340439
    341440  //----- transparency groups and soft masks
  • trunk/poppler/mypoppler/poppler/Catalog.cc

    r264 r277  
    1515//
    1616// Copyright (C) 2005 Kristian HÞgsberg <krh@redhat.com>
    17 // Copyright (C) 2005-2007 Albert Astals Cid <aacid@kde.org>
     17// Copyright (C) 2005-2009 Albert Astals Cid <aacid@kde.org>
    1818// Copyright (C) 2005 Jeff Muizelaar <jrmuizel@nit.ca>
    1919// Copyright (C) 2005 Jonathan Blandford <jrb@redhat.com>
     
    310310    if (kid.isDict("Page")) {
    311311      attrs2 = new PageAttrs(attrs1, kid.getDict());
    312       page = new Page(xref, start+1, kid.getDict(), attrs2, form);
     312      page = new Page(xref, start+1, kid.getDict(), kidRef.getRef(), attrs2, form);
    313313      if (!page->isOk()) {
    314314        ++start;
     
    352352 err2:
    353353  kid.free();
     354  kidRef.free();
    354355 err1:
    355356  kids.free();
     
    464465    js = new GooString();
    465466    stream->reset();
    466     int i;
    467     while ((i = stream->getChar()) != EOF) {
    468       js->append((char)i);
     467    int j;
     468    while ((j = stream->getChar()) != EOF) {
     469      js->append((char)j);
    469470    }
    470471  }
  • trunk/poppler/mypoppler/poppler/Catalog.h

    r257 r277  
    1515//
    1616// Copyright (C) 2005 Kristian HÞgsberg <krh@redhat.com>
    17 // Copyright (C) 2005, 2007 Albert Astals Cid <aacid@kde.org>
     17// Copyright (C) 2005, 2007, 2009 Albert Astals Cid <aacid@kde.org>
    1818// Copyright (C) 2005 Jonathan Blandford <jrb@redhat.com>
    1919// Copyright (C) 2005, 2006, 2008 Brad Hards <bradh@frogmouth.net>
     
    118118  GooString *mimeType() { return m_mimetype; }
    119119  Object &streamObject() { return m_objStr; }
     120  bool isOk() { return m_objStr.isStream(); }
    120121
    121122private:
  • trunk/poppler/mypoppler/poppler/CharCodeToUnicode.cc

    r261 r277  
    1414// under GPL version 2 or later
    1515//
    16 // Copyright (C) 2006, 2008 Albert Astals Cid <aacid@kde.org>
     16// Copyright (C) 2006, 2008, 2009 Albert Astals Cid <aacid@kde.org>
    1717// Copyright (C) 2007 Julien Rebetez <julienr@svn.gnome.org>
    1818// Copyright (C) 2007 Koji Otani <sho@bbr.jp>
     
    282282        if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' &&
    283283              tok2[0] == '<' && tok2[n2 - 1] == '>')) {
    284           error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
    285           continue;
     284          if (!(n1 == 4 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' && tok1[1] == '0' && tok1[2] == '0' &&
     285                tok2[0] == '<' && tok2[n2 - 1] == '>')) {
     286            error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
     287            continue;
     288          }
    286289        }
    287290        tok1[n1 - 1] = tok2[n2 - 1] = '\0';
  • trunk/poppler/mypoppler/poppler/DCTStream.cc

    r271 r277  
    66//
    77// Copyright 2005 Jeff Muizelaar <jeff@infidigm.net>
    8 // Copyright 2005-2008 Albert Astals Cid <aacid@kde.org>
     8// Copyright 2005-2009 Albert Astals Cid <aacid@kde.org>
    99// Copyright 2009 Ryszard Trojnacki <rysiek@menel.com>
    1010//
     
    8888  src.index = 0;
    8989  src.abort = false;
     90  current = NULL;
     91  limit = NULL;
    9092 
    9193  cinfo.err = &jerr;
    9294  jpeg_create_decompress(&cinfo);
    9395  cinfo.src = (jpeg_source_mgr *)&src;
    94   x = 0;
    9596  row_buffer = NULL;
    9697}
     
    142143  if (src.abort) return;
    143144
    144   jpeg_start_decompress(&cinfo);
     145  if (!jpeg_start_decompress(&cinfo))
     146  {
     147    src.abort = true;
     148    return;
     149  }
    145150
    146151  row_stride = cinfo.output_width * cinfo.output_components;
     
    153158  int c;
    154159
    155   if (x == 0) {
     160  if (current == limit) {
    156161    if (cinfo.output_scanline < cinfo.output_height)
    157162    {
    158163      if (!jpeg_read_scanlines(&cinfo, row_buffer, 1)) return EOF;
     164      current = &row_buffer[0][0];
     165      limit = &row_buffer[0][(cinfo.output_width - 1) * cinfo.output_components] + cinfo.output_components;
    159166    }
    160167    else return EOF;
    161168  }
    162   c = row_buffer[0][x];
    163   x++;
    164   if (x == cinfo.output_width * cinfo.output_components)
    165     x = 0;
     169  c = *current;
     170  ++current;
    166171  return c;
    167172}
     
    170175  if (src.abort) return EOF;
    171176 
    172   int c;
    173   c = row_buffer[0][x];
    174   return c;
     177  return *current;
    175178}
    176179
  • trunk/poppler/mypoppler/poppler/DCTStream.h

    r257 r277  
    77// Copyright 2005 Jeff Muizelaar <jeff@infidigm.net>
    88// Copyright 2005 Martin Kretzschmar <martink@gnome.org>
    9 // Copyright 2005-2007 Albert Astals Cid <aacid@kde.org>
     9// Copyright 2005-2007, 2009 Albert Astals Cid <aacid@kde.org>
    1010//
    1111//========================================================================
     
    6969  void init();
    7070
    71   unsigned int x;
     71  JSAMPLE *current;
     72  JSAMPLE *limit;
    7273  struct jpeg_decompress_struct cinfo;
    7374  struct jpeg_error_mgr jerr;
  • trunk/poppler/mypoppler/poppler/DateInfo.cc

    r257 r277  
    44//
    55// Copyright (C) 2008 Albert Astals Cid <aacid@kde.org>
     6// Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
    67//
    78// To see a description of the changes please see the Changelog file that
     
    1718//
    1819//========================================================================
     20
     21#include <config.h>
    1922
    2023#include "DateInfo.h"
     
    6972   return gFalse;
    7073}
     74
     75
     76GooString *timeToDateString(time_t *timet) {
     77  GooString *dateString;
     78  char s[5];
     79  struct tm *gt;
     80  size_t len;
     81  time_t timep = timet ? *timet : time(NULL);
     82 
     83#ifdef HAVE_GMTIME_R
     84  struct tm t;
     85  gt = gmtime_r (&timep, &t);
     86#else
     87  gt = gmtime (&timep);
     88#endif
     89
     90  dateString = new GooString ("D:");
     91
     92  /* Year YYYY */
     93  len = strftime (s, sizeof(s), "%Y", gt);
     94  dateString->append (s, len);
     95
     96  /* Month MM */
     97  len = strftime (s, sizeof(s), "%m", gt);
     98  dateString->append (s, len);
     99
     100  /* Day DD */
     101  len = strftime (s, sizeof(s), "%d", gt);
     102  dateString->append (s, len);
     103
     104  /* Hour HH */
     105  len = strftime (s, sizeof(s), "%H", gt);
     106  dateString->append (s, len);
     107
     108  /* Minute mm */
     109  len = strftime (s, sizeof(s), "%M", gt);
     110  dateString->append (s, len);
     111
     112  /* Second SS */
     113  len = strftime (s, sizeof(s), "%S", gt);
     114  dateString->append (s, len);
     115
     116  return dateString;
     117}
     118
  • trunk/poppler/mypoppler/poppler/DateInfo.h

    r257 r277  
    44//
    55// Copyright (C) 2008 Albert Astals Cid <aacid@kde.org>
     6// Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
    67//
    78// To see a description of the changes please see the Changelog file that
     
    2223
    2324#include "goo/gtypes.h"
     25#include "goo/GooString.h"
     26#include <time.h>
    2427
    2528GBool parseDateString(const char *string, int *year, int *month, int *day, int *hour, int *minute, int *second, char *tz, int *tzHour, int *tzMinute);
    2629
     30/* Converts the time_t into a PDF Date format string.
     31 * If timet is NULL, current time is used.
     32 */
     33GooString *timeToDateString(time_t *timet);
     34
    2735#endif
  • trunk/poppler/mypoppler/poppler/Decrypt.cc

    r257 r277  
    1616// Copyright (C) 2008 Julien Rebetez <julien@fhtagn.net>
    1717// Copyright (C) 2008 Albert Astals Cid <aacid@kde.org>
     18// Copyright (C) 2009 Matthias Franz <matthias@ktug.or.kr>
     19// Copyright (C) 2009 David Benjamin <davidben@mit.edu>
    1820//
    1921// To see a description of the changes please see the Changelog file that
     
    7678    if (encRevision == 3) {
    7779      for (i = 0; i < 50; ++i) {
    78         md5(test, 16, test);
     80        md5(test, keyLength, test);
    7981      }
    8082    }
     
    237239  int i;
    238240
     241  charactersRead = 0;
    239242  str->reset();
    240243  switch (algo) {
     
    252255    break;
    253256  }
     257}
     258
     259int DecryptStream::getPos() {
     260  return charactersRead;
    254261}
    255262
     
    288295    break;
    289296  }
     297  if (c != EOF)
     298    charactersRead++;
    290299  return c;
    291300}
  • trunk/poppler/mypoppler/poppler/Decrypt.h

    r257 r277  
    1515//
    1616// Copyright (C) 2008 Julien Rebetez <julien@fhtagn.net>
     17// Copyright (C) 2009 David Benjamin <davidben@mit.edu>
    1718//
    1819// To see a description of the changes please see the Changelog file that
     
    9192  virtual int getChar();
    9293  virtual int lookChar();
     94  virtual int getPos();
    9395  virtual GBool isBinary(GBool last);
    9496  virtual Stream *getUndecodedStream() { return this; }
     
    99101  int objKeyLength;
    100102  Guchar objKey[16 + 9];
     103  int charactersRead; // so that getPos() can be correct
    101104
    102105  union {
  • trunk/poppler/mypoppler/poppler/FileSpec.cc

    r271 r277  
    66// under GPL version 2 or later
    77//
    8 // Copyright (C) 2008 Carlos Garcia Campos <carlosgc@gnome.org>
     8// Copyright (C) 2008-2009 Carlos Garcia Campos <carlosgc@gnome.org>
     9// Copyright (C) 2009 Kovid Goyal <kovid@kovidgoyal.net>
    910//
    1011// To see a description of the changes please see the Changelog file that
     
    3334 
    3435  if (fileSpec->isDict()) {
     36    fileSpec->dictLookup("UF", fileName);
     37    if (fileName->isString()) {
     38      return gTrue;
     39    }
     40    fileName->free();
     41    fileSpec->dictLookup("F", fileName);
     42    if (fileName->isString()) {
     43      return gTrue;
     44    }
     45    fileName->free();
    3546    fileSpec->dictLookup("DOS", fileName);
    3647    if (fileName->isString()) {
     
    4859    }
    4960    fileName->free();
    50     fileSpec->dictLookup("F", fileName);
    51     if (fileName->isString()) {
    52       return gTrue;
    53     }
    54     fileName->free();
    5561  }
    5662  return gFalse;
     
    6470  }
    6571
    66   Object obj1;
    67   GooString *name;
    68 
    69   name = NULL;
    70  
    7172  if (fileSpec->isDict()) {
    72 #ifdef WIN32
    73     if (!fileSpec->dictLookup("DOS", &obj1)->isString()) {
     73    if (!fileSpec->dictLookup("UF", fileName)->isString ()) {
     74      fileName->free();
     75      if (!fileSpec->dictLookup("F", fileName)->isString ()) {
     76        fileName->free();
     77#ifdef _WIN32
     78        char *platform = "DOS";
    7479#else
    75     if (!fileSpec->dictLookup("Unix", &obj1)->isString()) {
     80        char *platform = "Unix";
    7681#endif
    77       obj1.free();
    78       if (fileSpec->dictLookup("UF", &obj1)->isString ()) {
    79         name = obj1.getString()->copy();
    80       } else if (fileSpec->dictLookup("F", &obj1)->isString ()) {
    81         name = obj1.getString()->copy();
    82       } else {
    83         error(-1, "Illegal file spec in link");
     82        if (!fileSpec->dictLookup(platform, fileName)->isString ()) {
     83          fileName->free();
     84          error(-1, "Illegal file spec");
     85          return gFalse;
     86        }
    8487      }
    8588    }
    86     obj1.free();
    87 
    88   // error
    8989  } else {
    90     error(-1, "Illegal file spec in link");
     90    error(-1, "Illegal file spec");
     91    return gFalse;
    9192  }
    9293
    9394  // system-dependent path manipulation
    94   if (name) {
    95 #ifdef WIN32
    96     int i, j;
    97 
    98     // "//...."             --> "\...."
    99     // "/x/...."            --> "x:\...."
    100     // "/server/share/...." --> "\\server\share\...."
    101     // convert escaped slashes to slashes and unescaped slashes to backslashes
    102     i = 0;
    103     if (name->getChar(0) == '/') {
    104       if (name->getLength() >= 2 && name->getChar(1) == '/') {
    105         name->del(0);
    106         i = 0;
    107       } else if (name->getLength() >= 2 &&
    108                  ((name->getChar(1) >= 'a' && name->getChar(1) <= 'z') ||
    109                   (name->getChar(1) >= 'A' && name->getChar(1) <= 'Z')) &&
    110                  (name->getLength() == 2 || name->getChar(2) == '/')) {
    111         name->setChar(0, name->getChar(1));
    112         name->setChar(1, ':');
    113         i = 2;
    114       } else {
    115         for (j = 2; j < name->getLength(); ++j) {
    116           if (name->getChar(j-1) != '\\' &&
    117               name->getChar(j) == '/') {
    118             break;
    119           }
    120         }
    121         if (j < name->getLength()) {
    122           name->setChar(0, '\\');
    123           name->insert(0, '\\');
    124           i = 2;
     95#ifdef _WIN32
     96  int i, j;
     97  GooString *name = fileName->getString();
     98  // "//...."             --> "\...."
     99  // "/x/...."            --> "x:\...."
     100  // "/server/share/...." --> "\\server\share\...."
     101  // convert escaped slashes to slashes and unescaped slashes to backslashes
     102  i = 0;
     103  if (name->getChar(0) == '/') {
     104    if (name->getLength() >= 2 && name->getChar(1) == '/') {
     105      name->del(0);
     106      i = 0;
     107    } else if (name->getLength() >= 2 &&
     108               ((name->getChar(1) >= 'a' && name->getChar(1) <= 'z') ||
     109                (name->getChar(1) >= 'A' && name->getChar(1) <= 'Z')) &&
     110               (name->getLength() == 2 || name->getChar(2) == '/')) {
     111      name->setChar(0, name->getChar(1));
     112      name->setChar(1, ':');
     113      i = 2;
     114    } else {
     115      for (j = 2; j < name->getLength(); ++j) {
     116        if (name->getChar(j-1) != '\\' &&
     117            name->getChar(j) == '/') {
     118          break;
    125119        }
    126120      }
    127     }
    128     for (; i < name->getLength(); ++i) {
    129       if (name->getChar(i) == '/') {
    130         name->setChar(i, '\\');
    131       } else if (name->getChar(i) == '\\' &&
    132                  i+1 < name->getLength() &&
    133                  name->getChar(i+1) == '/') {
    134         name->del(i);
     121      if (j < name->getLength()) {
     122        name->setChar(0, '\\');
     123        name->insert(0, '\\');
     124        i = 2;
    135125      }
    136126    }
    137 #else
    138     // no manipulation needed for Unix
    139 #endif
    140   } else {
    141     return gFalse;
    142127  }
     128  for (; i < name->getLength(); ++i) {
     129    if (name->getChar(i) == '/') {
     130      name->setChar(i, '\\');
     131    } else if (name->getChar(i) == '\\' &&
     132               i+1 < name->getLength() &&
     133               name->getChar(i+1) == '/') {
     134      name->del(i);
     135    }
     136  }
     137#endif /* _WIN32 */
    143138
    144   fileName->initString (name);
    145139  return gTrue;
    146140}
  • trunk/poppler/mypoppler/poppler/FontInfo.cc

    r257 r277  
    77// Copyright (C) 2005 Brad Hards <bradh@frogmouth.net>
    88// Copyright (C) 2006 Kouhei Sutou <kou@cozmixng.org>
     9// Copyright (C) 2009 Pino Toscano <pino@kde.org>
    910//
    1011// To see a description of the changes please see the Changelog file that
     
    3637#include "FontInfo.h"
    3738
    38 FontInfoScanner::FontInfoScanner(PDFDoc *docA) {
     39FontInfoScanner::FontInfoScanner(PDFDoc *docA, int firstPage) {
    3940  doc = docA;
    40   currentPage = 1;
     41  currentPage = firstPage + 1;
    4142  fonts = NULL;
    4243  fontsLen = fontsSize = 0;
  • trunk/poppler/mypoppler/poppler/FontInfo.h

    r257 r277  
    66// Copyright (C) 2005-2008 Albert Astals Cid <aacid@kde.org>
    77// Copyright (C) 2005 Brad Hards <bradh@frogmouth.net>
     8// Copyright (C) 2009 Pino Toscano <pino@kde.org>
    89//
    910// To see a description of the changes please see the Changelog file that
     
    7475
    7576  // Constructor.
    76   FontInfoScanner(PDFDoc *doc);
     77  FontInfoScanner(PDFDoc *doc, int firstPage = 0);
    7778  // Destructor.
    7879  ~FontInfoScanner();
  • trunk/poppler/mypoppler/poppler/Form.cc

    r264 r277  
    1212// Copyright 2008 Pino Toscano <pino@kde.org>
    1313// Copyright 2008 Michael Vrable <mvrable@cs.ucsd.edu>
    14 //
     14// Copyright 2009 Matthias Drochner <M.Drochner@fz-juelich.de>
     15// Copyright 2009 KDAB via Guillermo Amaral <gamaral@amaral.com.mx>
     16//
    1517//========================================================================
    1618
     
    117119  err2:
    118120    obj1.free();
    119 }
    120 
    121 FormWidget::FormWidget(FormWidget *dest)
    122 {
    123   x1 = dest->x1;
    124   y1 = dest->y1;
    125   x2 = dest->x2;
    126   y2 = dest->x2;
    127 
    128   type = dest->type;
    129   field = dest->field;
    130121}
    131122
     
    277268    if (!onStr) {
    278269      error(-1, "FormWidgetButton:: unable to find the on state for the button\n");
     270      onStr = new GooString(""); // TODO is this the best solution?
    279271    }
    280272  }
     
    547539      for(int i=0; i<parent->getNumChoices(); i++) {
    548540        if (parent->isSelected(i)) {
    549           obj1.initString(new GooString(parent->getExportVal(i)));
     541          obj1.initString(new GooString(parent->getChoice(i)));
    550542          break;
    551543        }
     
    556548        if (parent->isSelected(i)) {
    557549          Object obj2;
    558           obj2.initString(new GooString(parent->getExportVal(i)));
     550          obj2.initString(new GooString(parent->getChoice(i)));
    559551          obj1.arrayAdd(&obj2);
    560552        }
     
    816808  if(terminal) return;
    817809  for (int i=0; i<numChildren; i++) {
    818     children[i]->loadChildrenDefaults();
     810    children[i]->fillChildrenSiblingsID();
    819811  }
    820812}
  • trunk/poppler/mypoppler/poppler/Form.h

    r257 r277  
    77// Copyright 2006 Julien Rebetez <julienr@svn.gnome.org>
    88// Copyright 2007, 2008 Carlos Garcia Campos <carlosgc@gnome.org>
    9 // Copyright 2007, 2008 Albert Astals Cid <aacid@kde.org>
     9// Copyright 2007-2009 Albert Astals Cid <aacid@kde.org>
    1010//
    1111//========================================================================
     
    9595protected:
    9696  FormWidget(XRef *xrefA, Object *aobj, unsigned num, Ref aref, FormField *fieldA);
    97   FormWidget(FormWidget *dest);
    9897
    9998  void updateField (const char *key, Object *value);
  • trunk/poppler/mypoppler/poppler/Function.cc

    r257 r277  
    1414// under GPL version 2 or later
    1515//
    16 // Copyright (C) 2006, 2008 Albert Astals Cid <aacid@kde.org>
     16// Copyright (C) 2006, 2008, 2009 Albert Astals Cid <aacid@kde.org>
    1717// Copyright (C) 2006 Jeff Muizelaar <jeff@infidigm.net>
    1818//
     
    3333#include <math.h>
    3434#include "goo/gmem.h"
     35#include "goo/gstrtod.h"
    3536#include "Object.h"
    3637#include "Dict.h"
     
    3839#include "Error.h"
    3940#include "Function.h"
     41#include "PopplerCache.h"
    4042
    4143#ifndef M_PI
     
    862864public:
    863865
    864   PSStack() { sp = psStackSize; }
    865   void pushBool(GBool booln);
    866   void pushInt(int intg);
    867   void pushReal(double real);
    868   GBool popBool();
    869   int popInt();
    870   double popNum();
     866  PSStack() {sp = psStackSize; }
     867  void clear() { sp = psStackSize; }
     868  void pushBool(GBool booln)
     869  {
     870    if (checkOverflow()) {
     871      stack[--sp].type = psBool;
     872      stack[sp].booln = booln;
     873    }
     874  }
     875  void pushInt(int intg)
     876  {
     877    if (checkOverflow()) {
     878      stack[--sp].type = psInt;
     879      stack[sp].intg = intg;
     880    }
     881  }
     882  void pushReal(double real)
     883  {
     884    if (checkOverflow()) {
     885      stack[--sp].type = psReal;
     886      stack[sp].real = real;
     887    }
     888  }
     889  GBool popBool()
     890  {
     891    if (checkUnderflow() && checkType(psBool, psBool)) {
     892      return stack[sp++].booln;
     893    }
     894    return gFalse;
     895  }
     896  int popInt()
     897  {
     898    if (checkUnderflow() && checkType(psInt, psInt)) {
     899      return stack[sp++].intg;
     900    }
     901    return 0;
     902  }
     903  double popNum()
     904  {
     905    double ret;
     906
     907    if (checkUnderflow() && checkType(psInt, psReal)) {
     908      ret = (stack[sp].type == psInt) ? (double)stack[sp].intg : stack[sp].real;
     909      ++sp;
     910      return ret;
     911    }
     912    return 0;
     913  }
    871914  GBool empty() { return sp == psStackSize; }
    872915  GBool topIsInt() { return sp < psStackSize && stack[sp].type == psInt; }
     
    882925  void copy(int n);
    883926  void roll(int n, int j);
    884   void index(int i);
    885   void pop();
     927  void index(int i)
     928  {
     929    if (!checkOverflow()) {
     930      return;
     931    }
     932    --sp;
     933    stack[sp] = stack[sp + 1 + i];
     934  }
     935  void pop()
     936  {
     937    if (!checkUnderflow()) {
     938      return;
     939    }
     940    ++sp;
     941  }
    886942
    887943private:
    888944
    889   GBool checkOverflow(int n = 1);
    890   GBool checkUnderflow();
    891   GBool checkType(PSObjectType t1, PSObjectType t2);
    892 
     945  GBool checkOverflow(int n = 1)
     946  {
     947    if (sp - n < 0) {
     948      error(-1, "Stack overflow in PostScript function");
     949      return gFalse;
     950    }
     951    return gTrue;
     952  }
     953  GBool checkUnderflow()
     954  {
     955    if (sp == psStackSize) {
     956      error(-1, "Stack underflow in PostScript function");
     957      return gFalse;
     958    }
     959    return gTrue;
     960  }
     961  GBool checkType(PSObjectType t1, PSObjectType t2)
     962  {
     963    if (stack[sp].type != t1 && stack[sp].type != t2) {
     964      error(-1, "Type mismatch in PostScript function");
     965      return gFalse;
     966    }
     967    return gTrue;
     968  }
    893969  PSObject stack[psStackSize];
    894970  int sp;
    895971};
    896972
    897 GBool PSStack::checkOverflow(int n) {
    898   if (sp - n < 0) {
    899     error(-1, "Stack overflow in PostScript function");
    900     return gFalse;
    901   }
    902   return gTrue;
    903 }
    904 
    905 GBool PSStack::checkUnderflow() {
    906   if (sp == psStackSize) {
    907     error(-1, "Stack underflow in PostScript function");
    908     return gFalse;
    909   }
    910   return gTrue;
    911 }
    912 
    913 GBool PSStack::checkType(PSObjectType t1, PSObjectType t2) {
    914   if (stack[sp].type != t1 && stack[sp].type != t2) {
    915     error(-1, "Type mismatch in PostScript function");
    916     return gFalse;
    917   }
    918   return gTrue;
    919 }
    920 
    921 void PSStack::pushBool(GBool booln) {
    922   if (checkOverflow()) {
    923     stack[--sp].type = psBool;
    924     stack[sp].booln = booln;
    925   }
    926 }
    927 
    928 void PSStack::pushInt(int intg) {
    929   if (checkOverflow()) {
    930     stack[--sp].type = psInt;
    931     stack[sp].intg = intg;
    932   }
    933 }
    934 
    935 void PSStack::pushReal(double real) {
    936   if (checkOverflow()) {
    937     stack[--sp].type = psReal;
    938     stack[sp].real = real;
    939   }
    940 }
    941 
    942 GBool PSStack::popBool() {
    943   if (checkUnderflow() && checkType(psBool, psBool)) {
    944     return stack[sp++].booln;
    945   }
    946   return gFalse;
    947 }
    948 
    949 int PSStack::popInt() {
    950   if (checkUnderflow() && checkType(psInt, psInt)) {
    951     return stack[sp++].intg;
    952   }
    953   return 0;
    954 }
    955 
    956 double PSStack::popNum() {
    957   double ret;
    958 
    959   if (checkUnderflow() && checkType(psInt, psReal)) {
    960     ret = (stack[sp].type == psInt) ? (double)stack[sp].intg : stack[sp].real;
    961     ++sp;
    962     return ret;
    963   }
    964   return 0;
    965 }
    966973
    967974void PSStack::copy(int n) {
     
    9961003    return;
    9971004  }
    998   for (i = 0; i < j; ++i) {
    999     obj = stack[sp];
    1000     for (k = sp; k < sp + n - 1; ++k) {
    1001       stack[k] = stack[k+1];
    1002     }
    1003     stack[sp + n - 1] = obj;
    1004   }
    1005 }
    1006 
    1007 void PSStack::index(int i) {
    1008   if (!checkOverflow()) {
    1009     return;
    1010   }
    1011   --sp;
    1012   stack[sp] = stack[sp + 1 + i];
    1013 }
    1014 
    1015 void PSStack::pop() {
    1016   if (!checkUnderflow()) {
    1017     return;
    1018   }
    1019   ++sp;
    1020 }
     1005  if (j <= n / 2) {
     1006    for (i = 0; i < j; ++i) {
     1007      obj = stack[sp];
     1008      for (k = sp; k < sp + n - 1; ++k) {
     1009        stack[k] = stack[k+1];
     1010      }
     1011      stack[sp + n - 1] = obj;
     1012    }
     1013  } else {
     1014    j = n - j;
     1015    obj = stack[sp + n - 1];
     1016    for (k = sp + n - 1; k > sp; --k) {
     1017      stack[k] = stack[k-1];
     1018    }
     1019    stack[sp] = obj;
     1020  }
     1021}
     1022
     1023class PostScriptFunctionKey : public PopplerCacheKey
     1024{
     1025  public:
     1026    PostScriptFunctionKey(int sizeA, double *inA, bool copyA)
     1027    {
     1028      init(sizeA, inA, copyA);
     1029    }
     1030   
     1031    PostScriptFunctionKey(const PostScriptFunctionKey &key)
     1032    {
     1033      init(key.size, key.in, key.copied);
     1034    }
     1035   
     1036    void init(int sizeA, double *inA, bool copyA)
     1037    {
     1038      copied = copyA;
     1039      size = sizeA;
     1040      if (copied) {
     1041        in = new double[size];
     1042        for (int i = 0; i < size; ++i) in[i] = inA[i];
     1043      } else {
     1044        in = inA;
     1045      }
     1046    }
     1047   
     1048    ~PostScriptFunctionKey()
     1049    {
     1050      if (copied) delete[] in;
     1051    }
     1052       
     1053    bool operator==(const PopplerCacheKey &key) const
     1054    {
     1055      const PostScriptFunctionKey *k = static_cast<const PostScriptFunctionKey*>(&key);
     1056      if (size == k->size) {
     1057        bool equal = true;
     1058        for (int i = 0; equal && i < size; ++i) {
     1059          equal = in[i] == k->in[i];
     1060        }
     1061        return equal;
     1062      } else {
     1063        return false;
     1064      }
     1065    }
     1066 
     1067    bool copied;
     1068    int size;
     1069    double *in;
     1070};
     1071
     1072class PostScriptFunctionItem : public PopplerCacheItem
     1073{
     1074  public:
     1075    PostScriptFunctionItem(int sizeA, double *outA)
     1076    {
     1077      init(sizeA, outA);
     1078    }
     1079   
     1080    PostScriptFunctionItem(const PostScriptFunctionItem &item)
     1081    {
     1082      init(item.size, item.out);
     1083    }
     1084   
     1085    void init(int sizeA, double *outA)
     1086    {
     1087      size = sizeA;
     1088      out = new double[size];
     1089      for (int i = 0; i < size; ++i) out[i] = outA[i];
     1090    }
     1091   
     1092    ~PostScriptFunctionItem()
     1093    {
     1094      delete[] out;
     1095    }
     1096   
     1097    int size;
     1098    double *out;
     1099};
    10211100
    10221101PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) {
     
    10291108  codeSize = 0;
    10301109  ok = gFalse;
     1110  cache = new PopplerCache(5);
    10311111
    10321112  //----- initialize the generic stuff
     
    10641144
    10651145  ok = gTrue;
     1146 
     1147  stack = new PSStack();
    10661148
    10671149 err2:
     
    10761158  memcpy(code, func->code, codeSize * sizeof(PSObject));
    10771159  codeString = func->codeString->copy();
     1160  stack = new PSStack();
     1161  memcpy(stack, func->stack, sizeof(PSStack));
     1162 
     1163  cache = new PopplerCache(func->cache->size());
     1164  for (int i = 0; i < func->cache->numberOfItems(); ++i)
     1165  {
     1166    PostScriptFunctionKey *key = new PostScriptFunctionKey(*(PostScriptFunctionKey*)func->cache->key(i));
     1167    PostScriptFunctionItem *item = new PostScriptFunctionItem(*(PostScriptFunctionItem*)func->cache->item(i));
     1168    cache->put(key, item);
     1169  }
    10781170}
    10791171
     
    10811173  gfree(code);
    10821174  delete codeString;
     1175  delete stack;
     1176  delete cache;
    10831177}
    10841178
    10851179void PostScriptFunction::transform(double *in, double *out) {
    1086   PSStack *stack;
    10871180  int i;
    1088 
    1089   stack = new PSStack();
     1181 
     1182  PostScriptFunctionKey key(m, in, false);
     1183  PopplerCacheItem *item = cache->lookup(key);
     1184  if (item) {
     1185    PostScriptFunctionItem *it = static_cast<PostScriptFunctionItem *>(item);
     1186    for (int i = 0; i < n; ++i) {
     1187      out[i] = it->out[i];
     1188    }
     1189    return;
     1190  }
     1191
     1192  stack->clear();
    10901193  for (i = 0; i < m; ++i) {
    10911194    //~ may need to check for integers here
     
    11011204    }
    11021205  }
     1206
     1207  PostScriptFunctionKey *newKey = new PostScriptFunctionKey(m, in, true);
     1208  PostScriptFunctionItem *newItem = new PostScriptFunctionItem(n, out);
     1209  cache->put(newKey, newItem);
     1210 
    11031211  // if (!stack->empty()) {
    11041212  //   error(-1, "Extra values on stack at end of PostScript function");
    11051213  // }
    1106   delete stack;
    11071214}
    11081215
     
    11311238      if (isReal) {
    11321239        code[*codePtr].type = psReal;
    1133           code[*codePtr].real = atof(tok->getCString());
     1240          code[*codePtr].real = gatof(tok->getCString());
    11341241      } else {<