[poppler] 2 commits - poppler/SplashOutputDev.cc test/perf-test.cc

Albert Astals Cid aacid at kde.org
Mon Dec 1 11:51:57 PST 2014


El Dilluns, 1 de desembre de 2014, a les 09:29:44, Volker Grabsch va escriure:
> Hi,
> 
> I noticed that this patch changed every single line of perf-test.cc,
> making it hard to review properly.
> 
> This happened certainly because of the strange line endlings (DOS
> style) of perf-test.cc.  A quick search showed that the following
> files also have DOS line endings:
> 
> test/perf-test-preview-dummy.cc
> test/perf-test-preview-win.cc
> splash/SplashState.h
> 
> I propose to convert those from DOS to Unix line endings to prevent
> similar issues in the future.  See attached patch.  While I was at it,
> I noticed some strange empty lines at EOF which make no sense to me.
> See second patch.

You can use git diff -b to ignore whitespace changes.

Cheers,
  Albert

> 
> 
> Regards,
> Volker
> 
> Albert Astals Cid schrieb:
> >  poppler/SplashOutputDev.cc |    3
> >  test/perf-test.cc          | 2559
> >  ++++++++++++++++++++++----------------------- 2 files changed, 1283
> >  insertions(+), 1279 deletions(-)
> > 
> > New commits:
> > commit d3fe0661c6dc6050e14cd5cb4afa089b7d7d66b0
> > Author: Richard PALO <richard at netbsd.org>
> > Date:   Sun Nov 30 22:46:22 2014 +0100
> > 
> >     warning: "_FILE_OFFSET_BITS" redefined
> >     
> >     Bug #86870
> > 
> > diff --git a/test/perf-test.cc b/test/perf-test.cc
> > index 04adec3..4fb15d9 100644
> > --- a/test/perf-test.cc
> > +++ b/test/perf-test.cc
> > @@ -1,1279 +1,1280 @@
> > -/* Copyright Krzysztof Kowalczyk 2006-2007
> > -   Copyright Hib Eris <hib at hiberis.nl> 2008, 2013
> > -   License: GPLv2 */
> > -/*
> > -  A tool to stress-test poppler rendering and measure rendering times for
> > -  very simplistic performance measuring.
> > -
> > -  TODO:
> > -   * make it work with cairo output as well
> > -   * print more info about document like e.g. enumarate images,
> > -     streams, compression, encryption, password-protection. Each should
> > have -     a command-line arguments to turn it on/off
> > -   * never over-write file given as -out argument (optionally, provide
> > -force -     option to force writing the -out file). It's way too easy
> > too lose results -     of a previous run.
> > -*/
> > -
> > -#ifdef _MSC_VER
> > -// this sucks but I don't know any other way
> > -#pragma comment(linker,"/manifestdependency:\"type='win32'
> > name='Microsoft.Windows.Common-Controls' version='6.0.0.0'
> > processorArchitecture='x86' publicKeyToken='6595b64144ccf1df'
> > language='*'\"") -#endif
> > -
> > -#ifdef _WIN32
> > -#include <windows.h>
> > -#else
> > -#include <strings.h>
> > -#endif
> > -
> > -// Define COPY_FILE if you want the file to be copied to a local disk
> > first -// before it's tested. This is desired if a file is on a slow
> > drive. -// Currently copying only works on Windows.
> > -// Not enabled by default.
> > -//#define COPY_FILE 1
> > -
> > -#include <assert.h>
> > -#include <config.h>
> > -#include <stdio.h>
> > -#include <stdarg.h>
> > -#include <ctype.h>
> > -#include <stdlib.h>
> > -#include <string.h>
> > -#include <errno.h>
> > -#include <time.h>
> > -
> > -#ifdef HAVE_DIRENT_H
> > -#include <dirent.h>
> > -#endif
> > -
> > -#include "Error.h"
> > -#include "ErrorCodes.h"
> > -#include "goo/GooString.h"
> > -#include "goo/GooList.h"
> > -#include "goo/GooTimer.h"
> > -#include "GlobalParams.h"
> > -#include "splash/SplashBitmap.h"
> > -#include "Object.h" /* must be included before SplashOutputDev.h because
> > of sloppiness in SplashOutputDev.h */ -#include "SplashOutputDev.h"
> > -#include "TextOutputDev.h"
> > -#include "PDFDoc.h"
> > -#include "Link.h"
> > -
> > -#ifdef _MSC_VER
> > -#define strdup _strdup
> > -#define strcasecmp _stricmp
> > -#endif
> > -
> > -#define dimof(X)    (sizeof(X)/sizeof((X)[0]))
> > -
> > -#define INVALID_PAGE_NO     -1
> > -
> > -/* Those must be implemented in order to provide preview during
> > execution.
> > -   They can be no-ops. An implementation for windows is in
> > -   perf-test-preview-win.cc
> > -*/
> > -extern void PreviewBitmapInit(void);
> > -extern void PreviewBitmapDestroy(void);
> > -extern void PreviewBitmapSplash(SplashBitmap *bmpSplash);
> > -
> > -class PdfEnginePoppler {
> > -public:
> > -    PdfEnginePoppler();
> > -    ~PdfEnginePoppler();
> > -
> > -    const char *fileName(void) const { return _fileName; };
> > -
> > -    void setFileName(const char *fileName) {
> > -        assert(!_fileName);
> > -        _fileName = (char*)strdup(fileName);
> > -    }
> > -
> > -    int pageCount(void) const { return _pageCount; }
> > -
> > -    bool load(const char *fileName);
> > -    SplashBitmap *renderBitmap(int pageNo, double zoomReal, int
> > rotation);
> > -
> > -    SplashOutputDev *   outputDevice();
> > -private:
> > -    char *              _fileName;
> > -    int                 _pageCount;
> > -
> > -    PDFDoc *            _pdfDoc;
> > -    SplashOutputDev *   _outputDev;
> > -};
> > -
> > -typedef struct StrList {
> > -    struct StrList *next;
> > -    char *          str;
> > -} StrList;
> > -
> > -/* List of all command-line arguments that are not switches.
> > -   We assume those are:
> > -     - names of PDF files
> > -     - names of a file with a list of PDF files
> > -     - names of directories with PDF files
> > -*/
> > -static StrList *gArgsListRoot = NULL;
> > -
> > -/* Names of all command-line switches we recognize */
> > -#define TIMINGS_ARG         "-timings"
> > -#define RESOLUTION_ARG      "-resolution"
> > -#define RECURSIVE_ARG       "-recursive"
> > -#define OUT_ARG             "-out"
> > -#define PREVIEW_ARG         "-preview"
> > -#define SLOW_PREVIEW_ARG    "-slowpreview"
> > -#define LOAD_ONLY_ARG       "-loadonly"
> > -#define PAGE_ARG            "-page"
> > -#define TEXT_ARG            "-text"
> > -
> > -/* Should we record timings? True if -timings command-line argument was
> > given. */ -static bool gfTimings = false;
> > -
> > -/* If true, we use render each page at resolution
> > 'gResolutionX'/'gResolutionY'. -   If false, we render each page at its
> > native resolution.
> > -   True if -resolution NxM command-line argument was given. */
> > -static bool gfForceResolution = false;
> > -static int  gResolutionX = 0;
> > -static int  gResolutionY = 0;
> > -/* If NULL, we output the log info to stdout. If not NULL, should be a
> > name -   of the file to which we output log info.
> > -   Controled by -out command-line argument. */
> > -static char *   gOutFileName = NULL;
> > -/* FILE * correspondig to gOutFileName or stdout if gOutFileName is NULL
> > or -   was invalid name */
> > -static FILE *   gOutFile = NULL;
> > -/* FILE * correspondig to gOutFileName or stderr if gOutFileName is NULL
> > or -   was invalid name */
> > -static FILE *   gErrFile = NULL;
> > -
> > -/* If True and a directory is given as a command-line argument, we'll
> > process -   pdf files in sub-directories as well.
> > -   Controlled by -recursive command-line argument */
> > -static bool gfRecursive = false;
> > -
> > -/* If true, preview rendered image. To make sure that they're being
> > rendered correctly. */ -static bool gfPreview = false;
> > -
> > -/* 1 second (1000 milliseconds) */
> > -#define SLOW_PREVIEW_TIME 1000
> > -
> > -/* If true, preview rendered image in a slow mode i.e. delay displaying
> > for -   SLOW_PREVIEW_TIME. This is so that a human has enough time to see
> > if the -   PDF renders ok. In release mode on fast processor pages take
> > only ~100-200 ms -   to render and they go away too quickly to be
> > inspected by a human. */ -static bool gfSlowPreview = false;
> > -
> > -/* If true, we only dump the text, not render */
> > -static bool gfTextOnly = false;
> > -
> > -#define PAGE_NO_NOT_GIVEN -1
> > -
> > -/* If equals PAGE_NO_NOT_GIVEN, we're in default mode where we render all
> > pages. -   If different, will only render this page */
> > -static int  gPageNo = PAGE_NO_NOT_GIVEN;
> > -/* If true, will only load the file, not render any pages. Mostly for
> > -   profiling load time */
> > -static bool gfLoadOnly = false;
> > -
> > -#define PDF_FILE_DPI 72
> > -
> > -#define MAX_FILENAME_SIZE 1024
> > -
> > -/* DOS is 0xd 0xa */
> > -#define DOS_NEWLINE "\x0d\x0a"
> > -/* Mac is single 0xd */
> > -#define MAC_NEWLINE "\x0d"
> > -/* Unix is single 0xa (10) */
> > -#define UNIX_NEWLINE "\x0a"
> > -#define UNIX_NEWLINE_C 0xa
> > -
> > -#ifdef _WIN32
> > -  #define DIR_SEP_CHAR '\\'
> > -  #define DIR_SEP_STR  "\\"
> > -#else
> > -  #define DIR_SEP_CHAR '/'
> > -  #define DIR_SEP_STR  "/"
> > -#endif
> > -
> > -void memzero(void *data, size_t len)
> > -{
> > -    memset(data, 0, len);
> > -}
> > -
> > -void *zmalloc(size_t len)
> > -{
> > -    void *data = malloc(len);
> > -    if (data)
> > -        memzero(data, len);
> > -    return data;
> > -}
> > -
> > -/* Concatenate 4 strings. Any string can be NULL.
> > -   Caller needs to free() memory. */
> > -char *str_cat4(const char *str1, const char *str2, const char *str3,
> > const char *str4) -{
> > -    char *str;
> > -    char *tmp;
> > -    size_t str1_len = 0;
> > -    size_t str2_len = 0;
> > -    size_t str3_len = 0;
> > -    size_t str4_len = 0;
> > -
> > -    if (str1)
> > -        str1_len = strlen(str1);
> > -    if (str2)
> > -        str2_len = strlen(str2);
> > -    if (str3)
> > -        str3_len = strlen(str3);
> > -    if (str4)
> > -        str4_len = strlen(str4);
> > -
> > -    str = (char*)zmalloc(str1_len + str2_len + str3_len + str4_len + 1);
> > -    if (!str)
> > -        return NULL;
> > -
> > -    tmp = str;
> > -    if (str1) {
> > -        memcpy(tmp, str1, str1_len);
> > -        tmp += str1_len;
> > -    }
> > -    if (str2) {
> > -        memcpy(tmp, str2, str2_len);
> > -        tmp += str2_len;
> > -    }
> > -    if (str3) {
> > -        memcpy(tmp, str3, str3_len);
> > -        tmp += str3_len;
> > -    }
> > -    if (str4) {
> > -        memcpy(tmp, str4, str1_len);
> > -    }
> > -    return str;
> > -}
> > -
> > -char *str_dup(const char *str)
> > -{
> > -    return str_cat4(str, NULL, NULL, NULL);
> > -}
> > -
> > -bool str_eq(const char *str1, const char *str2)
> > -{
> > -    if (!str1 && !str2)
> > -        return true;
> > -    if (!str1 || !str2)
> > -        return false;
> > -    if (0 == strcmp(str1, str2))
> > -        return true;
> > -    return false;
> > -}
> > -
> > -bool str_ieq(const char *str1, const char *str2)
> > -{
> > -    if (!str1 && !str2)
> > -        return true;
> > -    if (!str1 || !str2)
> > -        return false;
> > -    if (0 == strcasecmp(str1, str2))
> > -        return true;
> > -    return false;
> > -}
> > -
> > -bool str_endswith(const char *txt, const char *end)
> > -{
> > -    size_t end_len;
> > -    size_t txt_len;
> > -
> > -    if (!txt || !end)
> > -        return false;
> > -
> > -    txt_len = strlen(txt);
> > -    end_len = strlen(end);
> > -    if (end_len > txt_len)
> > -        return false;
> > -    if (str_eq(txt+txt_len-end_len, end))
> > -        return true;
> > -    return false;
> > -}
> > -
> > -/* TODO: probably should move to some other file and change name to
> > -   sleep_milliseconds */
> > -void sleep_milliseconds(int milliseconds)
> > -{
> > -#ifdef _WIN32
> > -    Sleep((DWORD)milliseconds);
> > -#else
> > -    struct timespec tv;
> > -    int             secs, nanosecs;
> > -    secs = milliseconds / 1000;
> > -    nanosecs = (milliseconds - (secs * 1000)) * 1000;
> > -    tv.tv_sec = (time_t) secs;
> > -    tv.tv_nsec = (long) nanosecs;
> > -    while (1)
> > -    {
> > -        int rval = nanosleep(&tv, &tv);
> > -        if (rval == 0)
> > -            /* Completed the entire sleep time; all done. */
> > -            return;
> > -        else if (errno == EINTR)
> > -            /* Interrupted by a signal. Try again. */
> > -            continue;
> > -        else
> > -            /* Some other error; bail out. */
> > -            return;
> > -    }
> > -    return;
> > -#endif
> > -}
> > -
> > -#ifndef HAVE_STRCPY_S
> > -void strcpy_s(char* dst, size_t dst_size, const char* src)
> > -{
> > -    size_t src_size = strlen(src) + 1;
> > -    if (src_size <= dst_size)
> > -        memcpy(dst, src, src_size);
> > -    else {
> > -        if (dst_size > 0) {
> > -            memcpy(dst, src, dst_size);
> > -            dst[dst_size-1] = 0;
> > -        }
> > -    }
> > -}
> > -#endif
> > -
> > -#ifndef HAVE_STRCAT_S
> > -void strcat_s(char *dst, size_t dst_size, const char* src)
> > -{
> > -    size_t dst_len = strlen(dst);
> > -    if (dst_len >= dst_size) {
> > -        if (dst_size > 0)
> > -            dst[dst_size-1] = 0;
> > -        return;
> > -    }
> > -    strcpy_s(dst+dst_len, dst_size - dst_len, src);
> > -}
> > -#endif
> > -
> > -static SplashColorMode gSplashColorMode = splashModeBGR8;
> > -
> > -static SplashColor splashColRed;
> > -static SplashColor splashColGreen;
> > -static SplashColor splashColBlue;
> > -static SplashColor splashColWhite;
> > -static SplashColor splashColBlack;
> > -
> > -#define SPLASH_COL_RED_PTR (SplashColorPtr)&(splashColRed[0])
> > -#define SPLASH_COL_GREEN_PTR (SplashColorPtr)&(splashColGreen[0])
> > -#define SPLASH_COL_BLUE_PTR (SplashColorPtr)&(splashColBlue[0])
> > -#define SPLASH_COL_WHITE_PTR (SplashColorPtr)&(splashColWhite[0])
> > -#define SPLASH_COL_BLACK_PTR (SplashColorPtr)&(splashColBlack[0])
> > -
> > -static SplashColorPtr  gBgColor = SPLASH_COL_WHITE_PTR;
> > -
> > -static void splashColorSet(SplashColorPtr col, Guchar red, Guchar green,
> > Guchar blue, Guchar alpha) -{
> > -    switch (gSplashColorMode)
> > -    {
> > -        case splashModeBGR8:
> > -            col[0] = blue;
> > -            col[1] = green;
> > -            col[2] = red;
> > -            break;
> > -        case splashModeRGB8:
> > -            col[0] = red;
> > -            col[1] = green;
> > -            col[2] = blue;
> > -            break;
> > -        default:
> > -            assert(0);
> > -            break;
> > -    }
> > -}
> > -
> > -void SplashColorsInit(void)
> > -{
> > -    splashColorSet(SPLASH_COL_RED_PTR, 0xff, 0, 0, 0);
> > -    splashColorSet(SPLASH_COL_GREEN_PTR, 0, 0xff, 0, 0);
> > -    splashColorSet(SPLASH_COL_BLUE_PTR, 0, 0, 0xff, 0);
> > -    splashColorSet(SPLASH_COL_BLACK_PTR, 0, 0, 0, 0);
> > -    splashColorSet(SPLASH_COL_WHITE_PTR, 0xff, 0xff, 0xff, 0);
> > -}
> > -
> > -PdfEnginePoppler::PdfEnginePoppler() :
> > -   _fileName(0)
> > -   , _pageCount(INVALID_PAGE_NO)
> > -   , _pdfDoc(NULL)
> > -   , _outputDev(NULL)
> > -{
> > -}
> > -
> > -PdfEnginePoppler::~PdfEnginePoppler()
> > -{
> > -    free(_fileName);
> > -    delete _outputDev;
> > -    delete _pdfDoc;
> > -}
> > -
> > -bool PdfEnginePoppler::load(const char *fileName)
> > -{
> > -    setFileName(fileName);
> > -    /* note: don't delete fileNameStr since PDFDoc takes ownership and
> > deletes them itself */ -    GooString *fileNameStr = new
> > GooString(fileName);
> > -    if (!fileNameStr) return false;
> > -
> > -    _pdfDoc = new PDFDoc(fileNameStr, NULL, NULL, (void*)NULL);
> > -    if (!_pdfDoc->isOk()) {
> > -        return false;
> > -    }
> > -    _pageCount = _pdfDoc->getNumPages();
> > -    return true;
> > -}
> > -
> > -SplashOutputDev * PdfEnginePoppler::outputDevice() {
> > -    if (!_outputDev) {
> > -        GBool bitmapTopDown = gTrue;
> > -        _outputDev = new SplashOutputDev(gSplashColorMode, 4, gFalse,
> > gBgColor, bitmapTopDown); -        if (_outputDev)
> > -            _outputDev->startDoc(_pdfDoc);
> > -    }
> > -    return _outputDev;
> > -}
> > -
> > -SplashBitmap *PdfEnginePoppler::renderBitmap(int pageNo, double zoomReal,
> > int rotation) -{
> > -    assert(outputDevice());
> > -    if (!outputDevice()) return NULL;
> > -
> > -    double hDPI = (double)PDF_FILE_DPI * zoomReal * 0.01;
> > -    double vDPI = (double)PDF_FILE_DPI * zoomReal * 0.01;
> > -    GBool  useMediaBox = gFalse;
> > -    GBool  crop        = gTrue;
> > -    GBool  doLinks     = gTrue;
> > -    _pdfDoc->displayPage(_outputDev, pageNo, hDPI, vDPI, rotation,
> > useMediaBox, -        crop, doLinks, NULL, NULL);
> > -
> > -    SplashBitmap* bmp = _outputDev->takeBitmap();
> > -    return bmp;
> > -}
> > -
> > -struct FindFileState {
> > -    char path[MAX_FILENAME_SIZE];
> > -    char dirpath[MAX_FILENAME_SIZE]; /* current dir path */
> > -    char pattern[MAX_FILENAME_SIZE]; /* search pattern */
> > -    const char *bufptr;
> > -#ifdef _WIN32
> > -    WIN32_FIND_DATA fileinfo;
> > -    HANDLE dir;
> > -#else
> > -    DIR *dir;
> > -#endif
> > -};
> > -
> > -#ifdef _WIN32
> > -#include <sys/timeb.h>
> > -#include <direct.h>
> > -
> > -__inline char *getcwd(char *buffer, int maxlen)
> > -{
> > -    return _getcwd(buffer, maxlen);
> > -}
> > -
> > -int fnmatch(const char *pattern, const char *string, int flags)
> > -{
> > -    int prefix_len;
> > -    const char *star_pos = strchr(pattern, '*');
> > -    if (!star_pos)
> > -        return strcmp(pattern, string) != 0;
> > -
> > -    prefix_len = (int)(star_pos-pattern);
> > -    if (0 == prefix_len)
> > -        return 0;
> > -
> > -    if (0 == _strnicmp(pattern, string, prefix_len))
> > -        return 0;
> > -
> > -    return 1;
> > -}
> > -
> > -#else
> > -#include <fnmatch.h>
> > -#endif
> > -
> > -#ifdef _WIN32
> > -/* on windows to query dirs we need foo\* to get files in this directory.
> > -    foo\ always fails and foo will return just info about foo directory,
> > -    not files in this directory */
> > -static void win_correct_path_for_FindFirstFile(char *path, int
> > path_max_len) -{
> > -    int path_len = strlen(path);
> > -    if (path_len >= path_max_len-4)
> > -        return;
> > -    if (DIR_SEP_CHAR != path[path_len])
> > -        path[path_len++] = DIR_SEP_CHAR;
> > -    path[path_len++] = '*';
> > -    path[path_len] = 0;
> > -}
> > -#endif
> > -
> > -FindFileState *find_file_open(const char *path, const char *pattern)
> > -{
> > -    FindFileState *s;
> > -
> > -    s = (FindFileState*)malloc(sizeof(FindFileState));
> > -    if (!s)
> > -        return NULL;
> > -    strcpy_s(s->path, sizeof(s->path), path);
> > -    strcpy_s(s->dirpath, sizeof(s->path), path);
> > -#ifdef _WIN32
> > -    win_correct_path_for_FindFirstFile(s->path, sizeof(s->path));
> > -#endif
> > -    strcpy_s(s->pattern, sizeof(s->pattern), pattern);
> > -    s->bufptr = s->path;
> > -#ifdef _WIN32
> > -    s->dir = INVALID_HANDLE_VALUE;
> > -#else
> > -    s->dir = NULL;
> > -#endif
> > -    return s;
> > -}
> > -
> > -#if 0 /* re-enable if we #define USE_OWN_GET_AUTH_DATA */
> > -void *StandardSecurityHandler::getAuthData()
> > -{
> > -    return NULL;
> > -}
> > -#endif
> > -
> > -char *makepath(char *buf, int buf_size, const char *path,
> > -               const char *filename)
> > -{
> > -    strcpy_s(buf, buf_size, path);
> > -    int len = strlen(path);
> > -    if (len > 0 && path[len - 1] != DIR_SEP_CHAR && len + 1 < buf_size) {
> > -        buf[len++] = DIR_SEP_CHAR;
> > -        buf[len] = '\0';
> > -    }
> > -    strcat_s(buf, buf_size, filename);
> > -    return buf;
> > -}
> > -
> > -#ifdef _WIN32
> > -static int skip_matching_file(const char *filename)
> > -{
> > -    if (0 == strcmp(".", filename))
> > -        return 1;
> > -    if (0 == strcmp("..", filename))
> > -        return 1;
> > -    return 0;
> > -}
> > -#endif
> > -
> > -int find_file_next(FindFileState *s, char *filename, int
> > filename_size_max) -{
> > -#ifdef _WIN32
> > -    int    fFound;
> > -    if (INVALID_HANDLE_VALUE == s->dir) {
> > -        s->dir = FindFirstFile(s->path, &(s->fileinfo));
> > -        if (INVALID_HANDLE_VALUE == s->dir)
> > -            return -1;
> > -        goto CheckFile;
> > -    }
> > -
> > -    while (1) {
> > -        fFound = FindNextFile(s->dir, &(s->fileinfo));
> > -        if (!fFound)
> > -            return -1;
> > -CheckFile:
> > -        if (skip_matching_file(s->fileinfo.cFileName))
> > -            continue;
> > -        if (0 == fnmatch(s->pattern, s->fileinfo.cFileName, 0) ) {
> > -            makepath(filename, filename_size_max, s->dirpath,
> > s->fileinfo.cFileName); -            return 0;
> > -        }
> > -    }
> > -#else
> > -    struct dirent *dirent;
> > -    const char *p;
> > -    char *q;
> > -
> > -    if (s->dir == NULL)
> > -        goto redo;
> > -
> > -    for (;;) {
> > -        dirent = readdir(s->dir);
> > -        if (dirent == NULL) {
> > -        redo:
> > -            if (s->dir) {
> > -                closedir(s->dir);
> > -                s->dir = NULL;
> > -            }
> > -            p = s->bufptr;
> > -            if (*p == '\0')
> > -                return -1;
> > -            /* CG: get_str(&p, s->dirpath, sizeof(s->dirpath), ":") */
> > -            q = s->dirpath;
> > -            while (*p != ':' && *p != '\0') {
> > -                if ((q - s->dirpath) < (int)sizeof(s->dirpath) - 1)
> > -                    *q++ = *p;
> > -                p++;
> > -            }
> > -            *q = '\0';
> > -            if (*p == ':')
> > -                p++;
> > -            s->bufptr = p;
> > -            s->dir = opendir(s->dirpath);
> > -            if (!s->dir)
> > -                goto redo;
> > -        } else {
> > -            if (fnmatch(s->pattern, dirent->d_name, 0) == 0) {
> > -                makepath(filename, filename_size_max,
> > -                         s->dirpath, dirent->d_name);
> > -                return 0;
> > -            }
> > -        }
> > -    }
> > -#endif
> > -}
> > -
> > -void find_file_close(FindFileState *s)
> > -{
> > -#ifdef _WIN32
> > -    if (INVALID_HANDLE_VALUE != s->dir)
> > -       FindClose(s->dir);
> > -#else
> > -    if (s->dir)
> > -        closedir(s->dir);
> > -#endif
> > -    free(s);
> > -}
> > -
> > -int StrList_Len(StrList **root)
> > -{
> > -    int         len = 0;
> > -    StrList *   cur;
> > -    assert(root);
> > -    if (!root)
> > -        return 0;
> > -    cur = *root;
> > -    while (cur) {
> > -        ++len;
> > -        cur = cur->next;
> > -    }
> > -    return len;
> > -}
> > -
> > -int StrList_InsertAndOwn(StrList **root, char *txt)
> > -{
> > -    StrList *   el;
> > -    assert(root && txt);
> > -    if (!root || !txt)
> > -        return false;
> > -
> > -    el = (StrList*)malloc(sizeof(StrList));
> > -    if (!el)
> > -        return false;
> > -    el->str = txt;
> > -    el->next = *root;
> > -    *root = el;
> > -    return true;
> > -}
> > -
> > -int StrList_Insert(StrList **root, char *txt)
> > -{
> > -    char *txtDup;
> > -
> > -    assert(root && txt);
> > -    if (!root || !txt)
> > -        return false;
> > -    txtDup = str_dup(txt);
> > -    if (!txtDup)
> > -        return false;
> > -
> > -    if (!StrList_InsertAndOwn(root, txtDup)) {
> > -        free((void*)txtDup);
> > -        return false;
> > -    }
> > -    return true;
> > -}
> > -
> > -StrList* StrList_RemoveHead(StrList **root)
> > -{
> > -    StrList *tmp;
> > -    assert(root);
> > -    if (!root)
> > -        return NULL;
> > -
> > -    if (!*root)
> > -        return NULL;
> > -    tmp = *root;
> > -    *root = tmp->next;
> > -    tmp->next = NULL;
> > -    return tmp;
> > -}
> > -
> > -void StrList_FreeElement(StrList *el)
> > -{
> > -    if (!el)
> > -        return;
> > -    free((void*)el->str);
> > -    free((void*)el);
> > -}
> > -
> > -void StrList_Destroy(StrList **root)
> > -{
> > -    StrList *   cur;
> > -    StrList *   next;
> > -
> > -    if (!root)
> > -        return;
> > -    cur = *root;
> > -    while (cur) {
> > -        next = cur->next;
> > -        StrList_FreeElement(cur);
> > -        cur = next;
> > -    }
> > -    *root = NULL;
> > -}
> > -
> > -#ifndef _WIN32
> > -void OutputDebugString(const char *txt)
> > -{
> > -    /* do nothing */
> > -}
> > -#define _snprintf snprintf
> > -#define _vsnprintf vsnprintf
> > -#endif
> > -
> > -void my_error(void *, ErrorCategory, Goffset pos, char *msg) {
> > -#if 0
> > -    char        buf[4096], *p = buf;
> > -
> > -    // NB: this can be called before the globalParams object is created
> > -    if (globalParams && globalParams->getErrQuiet()) {
> > -        return;
> > -    }
> > -
> > -    if (pos >= 0) {
> > -      p += _snprintf(p, sizeof(buf)-1, "Error (%lld): ", (long long)pos);
> > -        *p   = '\0';
> > -        OutputDebugString(p);
> > -    } else {
> > -        OutputDebugString("Error: ");
> > -    }
> > -
> > -    p = buf;
> > -    p += _vsnprintf(p, sizeof(buf) - 1, msg, args);
> > -    while ( p > buf  &&  isspace(p[-1]) )
> > -            *--p = '\0';
> > -    *p++ = '\r';
> > -    *p++ = '\n';
> > -    *p   = '\0';
> > -    OutputDebugString(buf);
> > -
> > -    if (pos >= 0) {
> > -        p += _snprintf(p, sizeof(buf)-1, "Error (%lld): ", (long
> > long)pos); -        *p   = '\0';
> > -        OutputDebugString(buf);
> > -        if (gErrFile)
> > -            fprintf(gErrFile, buf);
> > -    } else {
> > -        OutputDebugString("Error: ");
> > -        if (gErrFile)
> > -            fprintf(gErrFile, "Error: ");
> > -    }
> > -#endif
> > -#if 0
> > -    p = buf;
> > -    va_start(args, msg);
> > -    p += _vsnprintf(p, sizeof(buf) - 3, msg, args);
> > -    while ( p > buf  &&  isspace(p[-1]) )
> > -            *--p = '\0';
> > -    *p++ = '\r';
> > -    *p++ = '\n';
> > -    *p   = '\0';
> > -    OutputDebugString(buf);
> > -    if (gErrFile)
> > -        fprintf(gErrFile, buf);
> > -    va_end(args);
> > -#endif
> > -}
> > -
> > -void LogInfo(const char *fmt, ...)
> > -{
> > -    va_list args;
> > -    char        buf[4096], *p = buf;
> > -
> > -    p = buf;
> > -    va_start(args, fmt);
> > -    p += _vsnprintf(p, sizeof(buf) - 1, fmt, args);
> > -    *p   = '\0';
> > -    fprintf(gOutFile, "%s", buf);
> > -    va_end(args);
> > -    fflush(gOutFile);
> > -}
> > -
> > -static void PrintUsageAndExit(int argc, char **argv)
> > -{
> > -    printf("Usage: pdftest [-preview|-slowpreview] [-loadonly] [-timings]
> > [-text] [-resolution NxM] [-recursive] [-page N] [-out out.txt]
> > pdf-files-to-process\n"); -    for (int i=0; i < argc; i++) {
> > -        printf("i=%d, '%s'\n", i, argv[i]);
> > -    }
> > -    exit(0);
> > -}
> > -
> > -static bool ShowPreview(void)
> > -{
> > -    if (gfPreview || gfSlowPreview)
> > -        return true;
> > -    return false;
> > -}
> > -
> > -static void RenderPdfAsText(const char *fileName)
> > -{
> > -    GooString *         fileNameStr = NULL;
> > -    PDFDoc *            pdfDoc = NULL;
> > -    GooString *         txt = NULL;
> > -    int                 pageCount;
> > -    double              timeInMs;
> > -
> > -    assert(fileName);
> > -    if (!fileName)
> > -        return;
> > -
> > -    LogInfo("started: %s\n", fileName);
> > -
> > -    TextOutputDev * textOut = new TextOutputDev(NULL, gTrue, 0, gFalse,
> > gFalse); -    if (!textOut->isOk()) {
> > -        delete textOut;
> > -        return;
> > -    }
> > -
> > -    GooTimer msTimer;
> > -    /* note: don't delete fileNameStr since PDFDoc takes ownership and
> > deletes them itself */ -    fileNameStr = new GooString(fileName);
> > -    if (!fileNameStr)
> > -        goto Exit;
> > -
> > -    pdfDoc = new PDFDoc(fileNameStr, NULL, NULL, NULL);
> > -    if (!pdfDoc->isOk()) {
> > -        error(errIO, -1, "RenderPdfFile(): failed to open PDF file
> > {0:s}\n", fileName); -        goto Exit;
> > -    }
> > -
> > -    msTimer.stop();
> > -    timeInMs = msTimer.getElapsed();
> > -    LogInfo("load: %.2f ms\n", timeInMs);
> > -
> > -    pageCount = pdfDoc->getNumPages();
> > -    LogInfo("page count: %d\n", pageCount);
> > -
> > -    for (int curPage = 1; curPage <= pageCount; curPage++) {
> > -        if ((gPageNo != PAGE_NO_NOT_GIVEN) && (gPageNo != curPage))
> > -            continue;
> > -
> > -        msTimer.start();
> > -        int rotate = 0;
> > -        GBool useMediaBox = gFalse;
> > -        GBool crop = gTrue;
> > -        GBool doLinks = gFalse;
> > -        pdfDoc->displayPage(textOut, curPage, 72, 72, rotate,
> > useMediaBox, crop, doLinks); -        txt = textOut->getText(0.0, 0.0,
> > 10000.0, 10000.0);
> > -        msTimer.stop();
> > -        timeInMs = msTimer.getElapsed();
> > -        if (gfTimings)
> > -            LogInfo("page %d: %.2f ms\n", curPage, timeInMs);
> > -        printf("%s\n", txt->getCString());
> > -        delete txt;
> > -        txt = NULL;
> > -    }
> > -
> > -Exit:
> > -    LogInfo("finished: %s\n", fileName);
> > -    delete textOut;
> > -    delete pdfDoc;
> > -}
> > -
> > -#ifdef _MSC_VER
> > -#define POPPLER_TMP_NAME "c:\\poppler_tmp.pdf"
> > -#else
> > -#define POPPLER_TMP_NAME "/tmp/poppler_tmp.pdf"
> > -#endif
> > -
> > -static void RenderPdf(const char *fileName)
> > -{
> > -    const char *        fileNameSplash = NULL;
> > -    PdfEnginePoppler *  engineSplash = NULL;
> > -    int                 pageCount;
> > -    double              timeInMs;
> > -
> > -#ifdef COPY_FILE
> > -    // TODO: fails if file already exists and has read-only attribute
> > -    CopyFile(fileName, POPPLER_TMP_NAME, false);
> > -    fileNameSplash = POPPLER_TMP_NAME;
> > -#else
> > -    fileNameSplash = fileName;
> > -#endif
> > -    LogInfo("started: %s\n", fileName);
> > -
> > -    engineSplash = new PdfEnginePoppler();
> > -
> > -    GooTimer msTimer;
> > -    if (!engineSplash->load(fileNameSplash)) {
> > -        LogInfo("failed to load splash\n");
> > -        goto Error;
> > -    }
> > -    msTimer.stop();
> > -    timeInMs = msTimer.getElapsed();
> > -    LogInfo("load splash: %.2f ms\n", timeInMs);
> > -    pageCount = engineSplash->pageCount();
> > -
> > -    LogInfo("page count: %d\n", pageCount);
> > -    if (gfLoadOnly)
> > -        goto Error;
> > -
> > -    for (int curPage = 1; curPage <= pageCount; curPage++) {
> > -        if ((gPageNo != PAGE_NO_NOT_GIVEN) && (gPageNo != curPage))
> > -            continue;
> > -
> > -        SplashBitmap *bmpSplash = NULL;
> > -
> > -        GooTimer msTimer;
> > -        bmpSplash = engineSplash->renderBitmap(curPage, 100.0, 0);
> > -        msTimer.stop();
> > -        double timeInMs = msTimer.getElapsed();
> > -        if (gfTimings) {
> > -            if (!bmpSplash)
> > -                LogInfo("page splash %d: failed to render\n", curPage);
> > -            else
> > -                LogInfo("page splash %d (%dx%d): %.2f ms\n", curPage,
> > bmpSplash->getWidth(), bmpSplash->getHeight(), timeInMs); -        }
> > -
> > -        if (ShowPreview()) {
> > -            PreviewBitmapSplash(bmpSplash);
> > -            if (gfSlowPreview)
> > -                sleep_milliseconds(SLOW_PREVIEW_TIME);
> > -        }
> > -        delete bmpSplash;
> > -    }
> > -Error:
> > -    delete engineSplash;
> > -    LogInfo("finished: %s\n", fileName);
> > -}
> > -
> > -static void RenderFile(const char *fileName)
> > -{
> > -    if (gfTextOnly) {
> > -        RenderPdfAsText(fileName);
> > -        return;
> > -    }
> > -
> > -    RenderPdf(fileName);
> > -}
> > -
> > -static bool ParseInteger(const char *start, const char *end, int *intOut)
> > -{
> > -    char            numBuf[16];
> > -    int             digitsCount;
> > -    const char *    tmp;
> > -
> > -    assert(start && end && intOut);
> > -    assert(end >= start);
> > -    if (!start || !end || !intOut || (start > end))
> > -        return false;
> > -
> > -    digitsCount = 0;
> > -    tmp = start;
> > -    while (tmp <= end) {
> > -        if (isspace(*tmp)) {
> > -            /* do nothing, we allow whitespace */
> > -        } else if (!isdigit(*tmp))
> > -            return false;
> > -        numBuf[digitsCount] = *tmp;
> > -        ++digitsCount;
> > -        if (digitsCount == dimof(numBuf)-3) /* -3 to be safe */
> > -            return false;
> > -        ++tmp;
> > -    }
> > -    if (0 == digitsCount)
> > -        return false;
> > -    numBuf[digitsCount] = 0;
> > -    *intOut = atoi(numBuf);
> > -    return true;
> > -}
> > -
> > -/* Given 'resolutionString' in format NxM (e.g. "100x200"), parse the
> > string and put N -   into 'resolutionXOut' and M into 'resolutionYOut'.
> > -   Return false if there was an error (e.g. string is not in the right
> > format */ -static bool ParseResolutionString(const char
> > *resolutionString, int *resolutionXOut, int *resolutionYOut) -{
> > -    const char *    posOfX;
> > -
> > -    assert(resolutionString);
> > -    assert(resolutionXOut);
> > -    assert(resolutionYOut);
> > -    if (!resolutionString || !resolutionXOut || !resolutionYOut)
> > -        return false;
> > -    *resolutionXOut = 0;
> > -    *resolutionYOut = 0;
> > -    posOfX = strchr(resolutionString, 'X');
> > -    if (!posOfX)
> > -        posOfX = strchr(resolutionString, 'x');
> > -    if (!posOfX)
> > -        return false;
> > -    if (posOfX == resolutionString)
> > -        return false;
> > -    if (!ParseInteger(resolutionString, posOfX-1, resolutionXOut))
> > -        return false;
> > -    if (!ParseInteger(posOfX+1,
> > resolutionString+strlen(resolutionString)-1, resolutionYOut)) -       
> > return false;
> > -    return true;
> > -}
> > -
> > -static void ParseCommandLine(int argc, char **argv)
> > -{
> > -    char *      arg;
> > -
> > -    if (argc < 2)
> > -        PrintUsageAndExit(argc, argv);
> > -
> > -    for (int i=1; i < argc; i++) {
> > -        arg = argv[i];
> > -        assert(arg);
> > -        if ('-' == arg[0]) {
> > -            if (str_ieq(arg, TIMINGS_ARG)) {
> > -                gfTimings = true;
> > -            } else if (str_ieq(arg, RESOLUTION_ARG)) {
> > -                ++i;
> > -                if (i == argc)
> > -                    PrintUsageAndExit(argc, argv); /* expect a file name
> > after that */ -                if (!ParseResolutionString(argv[i],
> > &gResolutionX, &gResolutionY)) -                   
> > PrintUsageAndExit(argc, argv);
> > -                gfForceResolution = true;
> > -            } else if (str_ieq(arg, RECURSIVE_ARG)) {
> > -                gfRecursive = true;
> > -            } else if (str_ieq(arg, OUT_ARG)) {
> > -                /* expect a file name after that */
> > -                ++i;
> > -                if (i == argc)
> > -                    PrintUsageAndExit(argc, argv);
> > -                gOutFileName = str_dup(argv[i]);
> > -            } else if (str_ieq(arg, PREVIEW_ARG)) {
> > -                gfPreview = true;
> > -            } else if (str_ieq(arg, TEXT_ARG)) {
> > -                gfTextOnly = true;
> > -            } else if (str_ieq(arg, SLOW_PREVIEW_ARG)) {
> > -                gfSlowPreview = true;
> > -            } else if (str_ieq(arg, LOAD_ONLY_ARG)) {
> > -                gfLoadOnly = true;
> > -            } else if (str_ieq(arg, PAGE_ARG)) {
> > -                /* expect an integer after that */
> > -                ++i;
> > -                if (i == argc)
> > -                    PrintUsageAndExit(argc, argv);
> > -                gPageNo = atoi(argv[i]);
> > -                if (gPageNo < 1)
> > -                    PrintUsageAndExit(argc, argv);
> > -            } else {
> > -                /* unknown option */
> > -                PrintUsageAndExit(argc, argv);
> > -            }
> > -        } else {
> > -            /* we assume that this is not an option hence it must be
> > -               a name of PDF/directory/file with PDF names */
> > -            StrList_Insert(&gArgsListRoot, arg);
> > -        }
> > -    }
> > -}
> > -
> > -#if 0
> > -void RenderFileList(char *pdfFileList)
> > -{
> > -    char *data = NULL;
> > -    char *dataNormalized = NULL;
> > -    char *pdfFileName;
> > -    uint64_t fileSize;
> > -
> > -    assert(pdfFileList);
> > -    if (!pdfFileList)
> > -        return;
> > -    data = file_read_all(pdfFileList, &fileSize);
> > -    if (!data) {
> > -        error(-1, "couldn't load file '%s'", pdfFileList);
> > -        return;
> > -    }
> > -    dataNormalized = str_normalize_newline(data, UNIX_NEWLINE);
> > -    if (!dataNormalized) {
> > -        error(-1, "couldn't normalize data of file '%s'", pdfFileList);
> > -        goto Exit;
> > -    }
> > -    for (;;) {
> > -        pdfFileName = str_split_iter(&dataNormalized, UNIX_NEWLINE_C);
> > -        if (!pdfFileName)
> > -            break;
> > -        str_strip_ws_both(pdfFileName);
> > -        if (str_empty(pdfFileName)) {
> > -            free((void*)pdfFileName);
> > -            continue;
> > -        }
> > -        RenderFile(pdfFileName);
> > -        free((void*)pdfFileName);
> > -    }
> > -Exit:
> > -    free((void*)dataNormalized);
> > -    free((void*)data);
> > -}
> > -#endif
> > -
> > -#ifdef _WIN32
> > -#include <sys/types.h>
> > -#include <sys/stat.h>
> > -
> > -bool IsDirectoryName(char *path)
> > -{
> > -    struct _stat    buf;
> > -    int             result;
> > -
> > -    result = _stat(path, &buf );
> > -    if (0 != result)
> > -        return false;
> > -
> > -    if (buf.st_mode & _S_IFDIR)
> > -        return true;
> > -
> > -    return false;
> > -}
> > -
> > -bool IsFileName(char *path)
> > -{
> > -    struct _stat    buf;
> > -    int             result;
> > -
> > -    result = _stat(path, &buf );
> > -    if (0 != result)
> > -        return false;
> > -
> > -    if (buf.st_mode & _S_IFREG)
> > -        return true;
> > -
> > -    return false;
> > -}
> > -#else
> > -bool IsDirectoryName(char *path)
> > -{
> > -    /* TODO: implement me */
> > -    return false;
> > -}
> > -
> > -bool IsFileName(char *path)
> > -{
> > -    /* TODO: implement me */
> > -    return true;
> > -}
> > -#endif
> > -
> > -bool IsPdfFileName(char *path)
> > -{
> > -    if (str_endswith(path, ".pdf"))
> > -        return true;
> > -    return false;
> > -}
> > -
> > -static void RenderDirectory(char *path)
> > -{
> > -    FindFileState * ffs;
> > -    char            filename[MAX_FILENAME_SIZE];
> > -    StrList *       dirList = NULL;
> > -    StrList *       el;
> > -
> > -    StrList_Insert(&dirList, path);
> > -
> > -    while (0 != StrList_Len(&dirList)) {
> > -        el = StrList_RemoveHead(&dirList);
> > -        ffs = find_file_open(el->str, "*");
> > -        while (!find_file_next(ffs, filename, sizeof(filename))) {
> > -            if (IsDirectoryName(filename)) {
> > -                if (gfRecursive) {
> > -                    StrList_Insert(&dirList, filename);
> > -                }
> > -            } else if (IsFileName(filename)) {
> > -                if (IsPdfFileName(filename)) {
> > -                    RenderFile(filename);
> > -                }
> > -            }
> > -        }
> > -        find_file_close(ffs);
> > -        StrList_FreeElement(el);
> > -    }
> > -    StrList_Destroy(&dirList);
> > -}
> > -
> > -/* Render 'cmdLineArg', which can be:
> > -   - directory name
> > -   - name of PDF file
> > -   - name of text file with names of PDF files
> > -*/
> > -static void RenderCmdLineArg(char *cmdLineArg)
> > -{
> > -    assert(cmdLineArg);
> > -    if (!cmdLineArg)
> > -        return;
> > -    if (IsDirectoryName(cmdLineArg)) {
> > -        RenderDirectory(cmdLineArg);
> > -    } else if (IsFileName(cmdLineArg)) {
> > -        if (IsPdfFileName(cmdLineArg))
> > -            RenderFile(cmdLineArg);
> > -#if 0
> > -        else
> > -            RenderFileList(cmdLineArg);
> > -#endif
> > -    } else {
> > -        error(errCommandLine, -1, "unexpected argument '{0:s}'",
> > cmdLineArg); -    }
> > -}
> > -
> > -int main(int argc, char **argv)
> > -{
> > -    setErrorCallback(my_error, NULL);
> > -    ParseCommandLine(argc, argv);
> > -    if (0 == StrList_Len(&gArgsListRoot))
> > -        PrintUsageAndExit(argc, argv);
> > -    assert(gArgsListRoot);
> > -
> > -    SplashColorsInit();
> > -    globalParams = new GlobalParams();
> > -    if (!globalParams)
> > -        return 1;
> > -    globalParams->setErrQuiet(gFalse);
> > -
> > -    FILE * outFile = NULL;
> > -    if (gOutFileName) {
> > -        outFile = fopen(gOutFileName, "wb");
> > -        if (!outFile) {
> > -            printf("failed to open -out file %s\n", gOutFileName);
> > -            return 1;
> > -        }
> > -        gOutFile = outFile;
> > -    }
> > -    else
> > -        gOutFile = stdout;
> > -
> > -    if (gOutFileName)
> > -        gErrFile = outFile;
> > -    else
> > -        gErrFile = stderr;
> > -
> > -    PreviewBitmapInit();
> > -
> > -    StrList * curr = gArgsListRoot;
> > -    while (curr) {
> > -        RenderCmdLineArg(curr->str);
> > -        curr = curr->next;
> > -    }
> > -    if (outFile)
> > -        fclose(outFile);
> > -    PreviewBitmapDestroy();
> > -    StrList_Destroy(&gArgsListRoot);
> > -    delete globalParams;
> > -    free(gOutFileName);
> > -    return 0;
> > -}
> > -
> > +/* Copyright Krzysztof Kowalczyk 2006-2007
> > +   Copyright Hib Eris <hib at hiberis.nl> 2008, 2013
> > +   License: GPLv2 */
> > +/*
> > +  A tool to stress-test poppler rendering and measure rendering times for
> > +  very simplistic performance measuring.
> > +
> > +  TODO:
> > +   * make it work with cairo output as well
> > +   * print more info about document like e.g. enumarate images,
> > +     streams, compression, encryption, password-protection. Each should
> > have +     a command-line arguments to turn it on/off
> > +   * never over-write file given as -out argument (optionally, provide
> > -force +     option to force writing the -out file). It's way too easy
> > too lose results +     of a previous run.
> > +*/
> > +
> > +#ifdef _MSC_VER
> > +// this sucks but I don't know any other way
> > +#pragma comment(linker,"/manifestdependency:\"type='win32'
> > name='Microsoft.Windows.Common-Controls' version='6.0.0.0'
> > processorArchitecture='x86' publicKeyToken='6595b64144ccf1df'
> > language='*'\"") +#endif
> > +
> > +#include <config.h>
> > +
> > +#ifdef _WIN32
> > +#include <windows.h>
> > +#else
> > +#include <strings.h>
> > +#endif
> > +
> > +// Define COPY_FILE if you want the file to be copied to a local disk
> > first +// before it's tested. This is desired if a file is on a slow
> > drive. +// Currently copying only works on Windows.
> > +// Not enabled by default.
> > +//#define COPY_FILE 1
> > +
> > +#include <assert.h>
> > +#include <stdio.h>
> > +#include <stdarg.h>
> > +#include <ctype.h>
> > +#include <stdlib.h>
> > +#include <string.h>
> > +#include <errno.h>
> > +#include <time.h>
> > +
> > +#ifdef HAVE_DIRENT_H
> > +#include <dirent.h>
> > +#endif
> > +
> > +#include "Error.h"
> > +#include "ErrorCodes.h"
> > +#include "goo/GooString.h"
> > +#include "goo/GooList.h"
> > +#include "goo/GooTimer.h"
> > +#include "GlobalParams.h"
> > +#include "splash/SplashBitmap.h"
> > +#include "Object.h" /* must be included before SplashOutputDev.h because
> > of sloppiness in SplashOutputDev.h */ +#include "SplashOutputDev.h"
> > +#include "TextOutputDev.h"
> > +#include "PDFDoc.h"
> > +#include "Link.h"
> > +
> > +#ifdef _MSC_VER
> > +#define strdup _strdup
> > +#define strcasecmp _stricmp
> > +#endif
> > +
> > +#define dimof(X)    (sizeof(X)/sizeof((X)[0]))
> > +
> > +#define INVALID_PAGE_NO     -1
> > +
> > +/* Those must be implemented in order to provide preview during
> > execution.
> > +   They can be no-ops. An implementation for windows is in
> > +   perf-test-preview-win.cc
> > +*/
> > +extern void PreviewBitmapInit(void);
> > +extern void PreviewBitmapDestroy(void);
> > +extern void PreviewBitmapSplash(SplashBitmap *bmpSplash);
> > +
> > +class PdfEnginePoppler {
> > +public:
> > +    PdfEnginePoppler();
> > +    ~PdfEnginePoppler();
> > +
> > +    const char *fileName(void) const { return _fileName; };
> > +
> > +    void setFileName(const char *fileName) {
> > +        assert(!_fileName);
> > +        _fileName = (char*)strdup(fileName);
> > +    }
> > +
> > +    int pageCount(void) const { return _pageCount; }
> > +
> > +    bool load(const char *fileName);
> > +    SplashBitmap *renderBitmap(int pageNo, double zoomReal, int
> > rotation);
> > +
> > +    SplashOutputDev *   outputDevice();
> > +private:
> > +    char *              _fileName;
> > +    int                 _pageCount;
> > +
> > +    PDFDoc *            _pdfDoc;
> > +    SplashOutputDev *   _outputDev;
> > +};
> > +
> > +typedef struct StrList {
> > +    struct StrList *next;
> > +    char *          str;
> > +} StrList;
> > +
> > +/* List of all command-line arguments that are not switches.
> > +   We assume those are:
> > +     - names of PDF files
> > +     - names of a file with a list of PDF files
> > +     - names of directories with PDF files
> > +*/
> > +static StrList *gArgsListRoot = NULL;
> > +
> > +/* Names of all command-line switches we recognize */
> > +#define TIMINGS_ARG         "-timings"
> > +#define RESOLUTION_ARG      "-resolution"
> > +#define RECURSIVE_ARG       "-recursive"
> > +#define OUT_ARG             "-out"
> > +#define PREVIEW_ARG         "-preview"
> > +#define SLOW_PREVIEW_ARG    "-slowpreview"
> > +#define LOAD_ONLY_ARG       "-loadonly"
> > +#define PAGE_ARG            "-page"
> > +#define TEXT_ARG            "-text"
> > +
> > +/* Should we record timings? True if -timings command-line argument was
> > given. */ +static bool gfTimings = false;
> > +
> > +/* If true, we use render each page at resolution
> > 'gResolutionX'/'gResolutionY'. +   If false, we render each page at its
> > native resolution.
> > +   True if -resolution NxM command-line argument was given. */
> > +static bool gfForceResolution = false;
> > +static int  gResolutionX = 0;
> > +static int  gResolutionY = 0;
> > +/* If NULL, we output the log info to stdout. If not NULL, should be a
> > name +   of the file to which we output log info.
> > +   Controled by -out command-line argument. */
> > +static char *   gOutFileName = NULL;
> > +/* FILE * correspondig to gOutFileName or stdout if gOutFileName is NULL
> > or +   was invalid name */
> > +static FILE *   gOutFile = NULL;
> > +/* FILE * correspondig to gOutFileName or stderr if gOutFileName is NULL
> > or +   was invalid name */
> > +static FILE *   gErrFile = NULL;
> > +
> > +/* If True and a directory is given as a command-line argument, we'll
> > process +   pdf files in sub-directories as well.
> > +   Controlled by -recursive command-line argument */
> > +static bool gfRecursive = false;
> > +
> > +/* If true, preview rendered image. To make sure that they're being
> > rendered correctly. */ +static bool gfPreview = false;
> > +
> > +/* 1 second (1000 milliseconds) */
> > +#define SLOW_PREVIEW_TIME 1000
> > +
> > +/* If true, preview rendered image in a slow mode i.e. delay displaying
> > for +   SLOW_PREVIEW_TIME. This is so that a human has enough time to see
> > if the +   PDF renders ok. In release mode on fast processor pages take
> > only ~100-200 ms +   to render and they go away too quickly to be
> > inspected by a human. */ +static bool gfSlowPreview = false;
> > +
> > +/* If true, we only dump the text, not render */
> > +static bool gfTextOnly = false;
> > +
> > +#define PAGE_NO_NOT_GIVEN -1
> > +
> > +/* If equals PAGE_NO_NOT_GIVEN, we're in default mode where we render all
> > pages. +   If different, will only render this page */
> > +static int  gPageNo = PAGE_NO_NOT_GIVEN;
> > +/* If true, will only load the file, not render any pages. Mostly for
> > +   profiling load time */
> > +static bool gfLoadOnly = false;
> > +
> > +#define PDF_FILE_DPI 72
> > +
> > +#define MAX_FILENAME_SIZE 1024
> > +
> > +/* DOS is 0xd 0xa */
> > +#define DOS_NEWLINE "\x0d\x0a"
> > +/* Mac is single 0xd */
> > +#define MAC_NEWLINE "\x0d"
> > +/* Unix is single 0xa (10) */
> > +#define UNIX_NEWLINE "\x0a"
> > +#define UNIX_NEWLINE_C 0xa
> > +
> > +#ifdef _WIN32
> > +  #define DIR_SEP_CHAR '\\'
> > +  #define DIR_SEP_STR  "\\"
> > +#else
> > +  #define DIR_SEP_CHAR '/'
> > +  #define DIR_SEP_STR  "/"
> > +#endif
> > +
> > +void memzero(void *data, size_t len)
> > +{
> > +    memset(data, 0, len);
> > +}
> > +
> > +void *zmalloc(size_t len)
> > +{
> > +    void *data = malloc(len);
> > +    if (data)
> > +        memzero(data, len);
> > +    return data;
> > +}
> > +
> > +/* Concatenate 4 strings. Any string can be NULL.
> > +   Caller needs to free() memory. */
> > +char *str_cat4(const char *str1, const char *str2, const char *str3,
> > const char *str4) +{
> > +    char *str;
> > +    char *tmp;
> > +    size_t str1_len = 0;
> > +    size_t str2_len = 0;
> > +    size_t str3_len = 0;
> > +    size_t str4_len = 0;
> > +
> > +    if (str1)
> > +        str1_len = strlen(str1);
> > +    if (str2)
> > +        str2_len = strlen(str2);
> > +    if (str3)
> > +        str3_len = strlen(str3);
> > +    if (str4)
> > +        str4_len = strlen(str4);
> > +
> > +    str = (char*)zmalloc(str1_len + str2_len + str3_len + str4_len + 1);
> > +    if (!str)
> > +        return NULL;
> > +
> > +    tmp = str;
> > +    if (str1) {
> > +        memcpy(tmp, str1, str1_len);
> > +        tmp += str1_len;
> > +    }
> > +    if (str2) {
> > +        memcpy(tmp, str2, str2_len);
> > +        tmp += str2_len;
> > +    }
> > +    if (str3) {
> > +        memcpy(tmp, str3, str3_len);
> > +        tmp += str3_len;
> > +    }
> > +    if (str4) {
> > +        memcpy(tmp, str4, str1_len);
> > +    }
> > +    return str;
> > +}
> > +
> > +char *str_dup(const char *str)
> > +{
> > +    return str_cat4(str, NULL, NULL, NULL);
> > +}
> > +
> > +bool str_eq(const char *str1, const char *str2)
> > +{
> > +    if (!str1 && !str2)
> > +        return true;
> > +    if (!str1 || !str2)
> > +        return false;
> > +    if (0 == strcmp(str1, str2))
> > +        return true;
> > +    return false;
> > +}
> > +
> > +bool str_ieq(const char *str1, const char *str2)
> > +{
> > +    if (!str1 && !str2)
> > +        return true;
> > +    if (!str1 || !str2)
> > +        return false;
> > +    if (0 == strcasecmp(str1, str2))
> > +        return true;
> > +    return false;
> > +}
> > +
> > +bool str_endswith(const char *txt, const char *end)
> > +{
> > +    size_t end_len;
> > +    size_t txt_len;
> > +
> > +    if (!txt || !end)
> > +        return false;
> > +
> > +    txt_len = strlen(txt);
> > +    end_len = strlen(end);
> > +    if (end_len > txt_len)
> > +        return false;
> > +    if (str_eq(txt+txt_len-end_len, end))
> > +        return true;
> > +    return false;
> > +}
> > +
> > +/* TODO: probably should move to some other file and change name to
> > +   sleep_milliseconds */
> > +void sleep_milliseconds(int milliseconds)
> > +{
> > +#ifdef _WIN32
> > +    Sleep((DWORD)milliseconds);
> > +#else
> > +    struct timespec tv;
> > +    int             secs, nanosecs;
> > +    secs = milliseconds / 1000;
> > +    nanosecs = (milliseconds - (secs * 1000)) * 1000;
> > +    tv.tv_sec = (time_t) secs;
> > +    tv.tv_nsec = (long) nanosecs;
> > +    while (1)
> > +    {
> > +        int rval = nanosleep(&tv, &tv);
> > +        if (rval == 0)
> > +            /* Completed the entire sleep time; all done. */
> > +            return;
> > +        else if (errno == EINTR)
> > +            /* Interrupted by a signal. Try again. */
> > +            continue;
> > +        else
> > +            /* Some other error; bail out. */
> > +            return;
> > +    }
> > +    return;
> > +#endif
> > +}
> > +
> > +#ifndef HAVE_STRCPY_S
> > +void strcpy_s(char* dst, size_t dst_size, const char* src)
> > +{
> > +    size_t src_size = strlen(src) + 1;
> > +    if (src_size <= dst_size)
> > +        memcpy(dst, src, src_size);
> > +    else {
> > +        if (dst_size > 0) {
> > +            memcpy(dst, src, dst_size);
> > +            dst[dst_size-1] = 0;
> > +        }
> > +    }
> > +}
> > +#endif
> > +
> > +#ifndef HAVE_STRCAT_S
> > +void strcat_s(char *dst, size_t dst_size, const char* src)
> > +{
> > +    size_t dst_len = strlen(dst);
> > +    if (dst_len >= dst_size) {
> > +        if (dst_size > 0)
> > +            dst[dst_size-1] = 0;
> > +        return;
> > +    }
> > +    strcpy_s(dst+dst_len, dst_size - dst_len, src);
> > +}
> > +#endif
> > +
> > +static SplashColorMode gSplashColorMode = splashModeBGR8;
> > +
> > +static SplashColor splashColRed;
> > +static SplashColor splashColGreen;
> > +static SplashColor splashColBlue;
> > +static SplashColor splashColWhite;
> > +static SplashColor splashColBlack;
> > +
> > +#define SPLASH_COL_RED_PTR (SplashColorPtr)&(splashColRed[0])
> > +#define SPLASH_COL_GREEN_PTR (SplashColorPtr)&(splashColGreen[0])
> > +#define SPLASH_COL_BLUE_PTR (SplashColorPtr)&(splashColBlue[0])
> > +#define SPLASH_COL_WHITE_PTR (SplashColorPtr)&(splashColWhite[0])
> > +#define SPLASH_COL_BLACK_PTR (SplashColorPtr)&(splashColBlack[0])
> > +
> > +static SplashColorPtr  gBgColor = SPLASH_COL_WHITE_PTR;
> > +
> > +static void splashColorSet(SplashColorPtr col, Guchar red, Guchar green,
> > Guchar blue, Guchar alpha) +{
> > +    switch (gSplashColorMode)
> > +    {
> > +        case splashModeBGR8:
> > +            col[0] = blue;
> > +            col[1] = green;
> > +            col[2] = red;
> > +            break;
> > +        case splashModeRGB8:
> > +            col[0] = red;
> > +            col[1] = green;
> > +            col[2] = blue;
> > +            break;
> > +        default:
> > +            assert(0);
> > +            break;
> > +    }
> > +}
> > +
> > +void SplashColorsInit(void)
> > +{
> > +    splashColorSet(SPLASH_COL_RED_PTR, 0xff, 0, 0, 0);
> > +    splashColorSet(SPLASH_COL_GREEN_PTR, 0, 0xff, 0, 0);
> > +    splashColorSet(SPLASH_COL_BLUE_PTR, 0, 0, 0xff, 0);
> > +    splashColorSet(SPLASH_COL_BLACK_PTR, 0, 0, 0, 0);
> > +    splashColorSet(SPLASH_COL_WHITE_PTR, 0xff, 0xff, 0xff, 0);
> > +}
> > +
> > +PdfEnginePoppler::PdfEnginePoppler() :
> > +   _fileName(0)
> > +   , _pageCount(INVALID_PAGE_NO)
> > +   , _pdfDoc(NULL)
> > +   , _outputDev(NULL)
> > +{
> > +}
> > +
> > +PdfEnginePoppler::~PdfEnginePoppler()
> > +{
> > +    free(_fileName);
> > +    delete _outputDev;
> > +    delete _pdfDoc;
> > +}
> > +
> > +bool PdfEnginePoppler::load(const char *fileName)
> > +{
> > +    setFileName(fileName);
> > +    /* note: don't delete fileNameStr since PDFDoc takes ownership and
> > deletes them itself */ +    GooString *fileNameStr = new
> > GooString(fileName);
> > +    if (!fileNameStr) return false;
> > +
> > +    _pdfDoc = new PDFDoc(fileNameStr, NULL, NULL, (void*)NULL);
> > +    if (!_pdfDoc->isOk()) {
> > +        return false;
> > +    }
> > +    _pageCount = _pdfDoc->getNumPages();
> > +    return true;
> > +}
> > +
> > +SplashOutputDev * PdfEnginePoppler::outputDevice() {
> > +    if (!_outputDev) {
> > +        GBool bitmapTopDown = gTrue;
> > +        _outputDev = new SplashOutputDev(gSplashColorMode, 4, gFalse,
> > gBgColor, bitmapTopDown); +        if (_outputDev)
> > +            _outputDev->startDoc(_pdfDoc);
> > +    }
> > +    return _outputDev;
> > +}
> > +
> > +SplashBitmap *PdfEnginePoppler::renderBitmap(int pageNo, double zoomReal,
> > int rotation) +{
> > +    assert(outputDevice());
> > +    if (!outputDevice()) return NULL;
> > +
> > +    double hDPI = (double)PDF_FILE_DPI * zoomReal * 0.01;
> > +    double vDPI = (double)PDF_FILE_DPI * zoomReal * 0.01;
> > +    GBool  useMediaBox = gFalse;
> > +    GBool  crop        = gTrue;
> > +    GBool  doLinks     = gTrue;
> > +    _pdfDoc->displayPage(_outputDev, pageNo, hDPI, vDPI, rotation,
> > useMediaBox, +        crop, doLinks, NULL, NULL);
> > +
> > +    SplashBitmap* bmp = _outputDev->takeBitmap();
> > +    return bmp;
> > +}
> > +
> > +struct FindFileState {
> > +    char path[MAX_FILENAME_SIZE];
> > +    char dirpath[MAX_FILENAME_SIZE]; /* current dir path */
> > +    char pattern[MAX_FILENAME_SIZE]; /* search pattern */
> > +    const char *bufptr;
> > +#ifdef _WIN32
> > +    WIN32_FIND_DATA fileinfo;
> > +    HANDLE dir;
> > +#else
> > +    DIR *dir;
> > +#endif
> > +};
> > +
> > +#ifdef _WIN32
> > +#include <sys/timeb.h>
> > +#include <direct.h>
> > +
> > +__inline char *getcwd(char *buffer, int maxlen)
> > +{
> > +    return _getcwd(buffer, maxlen);
> > +}
> > +
> > +int fnmatch(const char *pattern, const char *string, int flags)
> > +{
> > +    int prefix_len;
> > +    const char *star_pos = strchr(pattern, '*');
> > +    if (!star_pos)
> > +        return strcmp(pattern, string) != 0;
> > +
> > +    prefix_len = (int)(star_pos-pattern);
> > +    if (0 == prefix_len)
> > +        return 0;
> > +
> > +    if (0 == _strnicmp(pattern, string, prefix_len))
> > +        return 0;
> > +
> > +    return 1;
> > +}
> > +
> > +#else
> > +#include <fnmatch.h>
> > +#endif
> > +
> > +#ifdef _WIN32
> > +/* on windows to query dirs we need foo\* to get files in this directory.
> > +    foo\ always fails and foo will return just info about foo directory,
> > +    not files in this directory */
> > +static void win_correct_path_for_FindFirstFile(char *path, int
> > path_max_len) +{
> > +    int path_len = strlen(path);
> > +    if (path_len >= path_max_len-4)
> > +        return;
> > +    if (DIR_SEP_CHAR != path[path_len])
> > +        path[path_len++] = DIR_SEP_CHAR;
> > +    path[path_len++] = '*';
> > +    path[path_len] = 0;
> > +}
> > +#endif
> > +
> > +FindFileState *find_file_open(const char *path, const char *pattern)
> > +{
> > +    FindFileState *s;
> > +
> > +    s = (FindFileState*)malloc(sizeof(FindFileState));
> > +    if (!s)
> > +        return NULL;
> > +    strcpy_s(s->path, sizeof(s->path), path);
> > +    strcpy_s(s->dirpath, sizeof(s->path), path);
> > +#ifdef _WIN32
> > +    win_correct_path_for_FindFirstFile(s->path, sizeof(s->path));
> > +#endif
> > +    strcpy_s(s->pattern, sizeof(s->pattern), pattern);
> > +    s->bufptr = s->path;
> > +#ifdef _WIN32
> > +    s->dir = INVALID_HANDLE_VALUE;
> > +#else
> > +    s->dir = NULL;
> > +#endif
> > +    return s;
> > +}
> > +
> > +#if 0 /* re-enable if we #define USE_OWN_GET_AUTH_DATA */
> > +void *StandardSecurityHandler::getAuthData()
> > +{
> > +    return NULL;
> > +}
> > +#endif
> > +
> > +char *makepath(char *buf, int buf_size, const char *path,
> > +               const char *filename)
> > +{
> > +    strcpy_s(buf, buf_size, path);
> > +    int len = strlen(path);
> > +    if (len > 0 && path[len - 1] != DIR_SEP_CHAR && len + 1 < buf_size) {
> > +        buf[len++] = DIR_SEP_CHAR;
> > +        buf[len] = '\0';
> > +    }
> > +    strcat_s(buf, buf_size, filename);
> > +    return buf;
> > +}
> > +
> > +#ifdef _WIN32
> > +static int skip_matching_file(const char *filename)
> > +{
> > +    if (0 == strcmp(".", filename))
> > +        return 1;
> > +    if (0 == strcmp("..", filename))
> > +        return 1;
> > +    return 0;
> > +}
> > +#endif
> > +
> > +int find_file_next(FindFileState *s, char *filename, int
> > filename_size_max) +{
> > +#ifdef _WIN32
> > +    int    fFound;
> > +    if (INVALID_HANDLE_VALUE == s->dir) {
> > +        s->dir = FindFirstFile(s->path, &(s->fileinfo));
> > +        if (INVALID_HANDLE_VALUE == s->dir)
> > +            return -1;
> > +        goto CheckFile;
> > +    }
> > +
> > +    while (1) {
> > +        fFound = FindNextFile(s->dir, &(s->fileinfo));
> > +        if (!fFound)
> > +            return -1;
> > +CheckFile:
> > +        if (skip_matching_file(s->fileinfo.cFileName))
> > +            continue;
> > +        if (0 == fnmatch(s->pattern, s->fileinfo.cFileName, 0) ) {
> > +            makepath(filename, filename_size_max, s->dirpath,
> > s->fileinfo.cFileName); +            return 0;
> > +        }
> > +    }
> > +#else
> > +    struct dirent *dirent;
> > +    const char *p;
> > +    char *q;
> > +
> > +    if (s->dir == NULL)
> > +        goto redo;
> > +
> > +    for (;;) {
> > +        dirent = readdir(s->dir);
> > +        if (dirent == NULL) {
> > +        redo:
> > +            if (s->dir) {
> > +                closedir(s->dir);
> > +                s->dir = NULL;
> > +            }
> > +            p = s->bufptr;
> > +            if (*p == '\0')
> > +                return -1;
> > +            /* CG: get_str(&p, s->dirpath, sizeof(s->dirpath), ":") */
> > +            q = s->dirpath;
> > +            while (*p != ':' && *p != '\0') {
> > +                if ((q - s->dirpath) < (int)sizeof(s->dirpath) - 1)
> > +                    *q++ = *p;
> > +                p++;
> > +            }
> > +            *q = '\0';
> > +            if (*p == ':')
> > +                p++;
> > +            s->bufptr = p;
> > +            s->dir = opendir(s->dirpath);
> > +            if (!s->dir)
> > +                goto redo;
> > +        } else {
> > +            if (fnmatch(s->pattern, dirent->d_name, 0) == 0) {
> > +                makepath(filename, filename_size_max,
> > +                         s->dirpath, dirent->d_name);
> > +                return 0;
> > +            }
> > +        }
> > +    }
> > +#endif
> > +}
> > +
> > +void find_file_close(FindFileState *s)
> > +{
> > +#ifdef _WIN32
> > +    if (INVALID_HANDLE_VALUE != s->dir)
> > +       FindClose(s->dir);
> > +#else
> > +    if (s->dir)
> > +        closedir(s->dir);
> > +#endif
> > +    free(s);
> > +}
> > +
> > +int StrList_Len(StrList **root)
> > +{
> > +    int         len = 0;
> > +    StrList *   cur;
> > +    assert(root);
> > +    if (!root)
> > +        return 0;
> > +    cur = *root;
> > +    while (cur) {
> > +        ++len;
> > +        cur = cur->next;
> > +    }
> > +    return len;
> > +}
> > +
> > +int StrList_InsertAndOwn(StrList **root, char *txt)
> > +{
> > +    StrList *   el;
> > +    assert(root && txt);
> > +    if (!root || !txt)
> > +        return false;
> > +
> > +    el = (StrList*)malloc(sizeof(StrList));
> > +    if (!el)
> > +        return false;
> > +    el->str = txt;
> > +    el->next = *root;
> > +    *root = el;
> > +    return true;
> > +}
> > +
> > +int StrList_Insert(StrList **root, char *txt)
> > +{
> > +    char *txtDup;
> > +
> > +    assert(root && txt);
> > +    if (!root || !txt)
> > +        return false;
> > +    txtDup = str_dup(txt);
> > +    if (!txtDup)
> > +        return false;
> > +
> > +    if (!StrList_InsertAndOwn(root, txtDup)) {
> > +        free((void*)txtDup);
> > +        return false;
> > +    }
> > +    return true;
> > +}
> > +
> > +StrList* StrList_RemoveHead(StrList **root)
> > +{
> > +    StrList *tmp;
> > +    assert(root);
> > +    if (!root)
> > +        return NULL;
> > +
> > +    if (!*root)
> > +        return NULL;
> > +    tmp = *root;
> > +    *root = tmp->next;
> > +    tmp->next = NULL;
> > +    return tmp;
> > +}
> > +
> > +void StrList_FreeElement(StrList *el)
> > +{
> > +    if (!el)
> > +        return;
> > +    free((void*)el->str);
> > +    free((void*)el);
> > +}
> > +
> > +void StrList_Destroy(StrList **root)
> > +{
> > +    StrList *   cur;
> > +    StrList *   next;
> > +
> > +    if (!root)
> > +        return;
> > +    cur = *root;
> > +    while (cur) {
> > +        next = cur->next;
> > +        StrList_FreeElement(cur);
> > +        cur = next;
> > +    }
> > +    *root = NULL;
> > +}
> > +
> > +#ifndef _WIN32
> > +void OutputDebugString(const char *txt)
> > +{
> > +    /* do nothing */
> > +}
> > +#define _snprintf snprintf
> > +#define _vsnprintf vsnprintf
> > +#endif
> > +
> > +void my_error(void *, ErrorCategory, Goffset pos, char *msg) {
> > +#if 0
> > +    char        buf[4096], *p = buf;
> > +
> > +    // NB: this can be called before the globalParams object is created
> > +    if (globalParams && globalParams->getErrQuiet()) {
> > +        return;
> > +    }
> > +
> > +    if (pos >= 0) {
> > +      p += _snprintf(p, sizeof(buf)-1, "Error (%lld): ", (long long)pos);
> > +        *p   = '\0';
> > +        OutputDebugString(p);
> > +    } else {
> > +        OutputDebugString("Error: ");
> > +    }
> > +
> > +    p = buf;
> > +    p += _vsnprintf(p, sizeof(buf) - 1, msg, args);
> > +    while ( p > buf  &&  isspace(p[-1]) )
> > +            *--p = '\0';
> > +    *p++ = '\r';
> > +    *p++ = '\n';
> > +    *p   = '\0';
> > +    OutputDebugString(buf);
> > +
> > +    if (pos >= 0) {
> > +        p += _snprintf(p, sizeof(buf)-1, "Error (%lld): ", (long
> > long)pos); +        *p   = '\0';
> > +        OutputDebugString(buf);
> > +        if (gErrFile)
> > +            fprintf(gErrFile, buf);
> > +    } else {
> > +        OutputDebugString("Error: ");
> > +        if (gErrFile)
> > +            fprintf(gErrFile, "Error: ");
> > +    }
> > +#endif
> > +#if 0
> > +    p = buf;
> > +    va_start(args, msg);
> > +    p += _vsnprintf(p, sizeof(buf) - 3, msg, args);
> > +    while ( p > buf  &&  isspace(p[-1]) )
> > +            *--p = '\0';
> > +    *p++ = '\r';
> > +    *p++ = '\n';
> > +    *p   = '\0';
> > +    OutputDebugString(buf);
> > +    if (gErrFile)
> > +        fprintf(gErrFile, buf);
> > +    va_end(args);
> > +#endif
> > +}
> > +
> > +void LogInfo(const char *fmt, ...)
> > +{
> > +    va_list args;
> > +    char        buf[4096], *p = buf;
> > +
> > +    p = buf;
> > +    va_start(args, fmt);
> > +    p += _vsnprintf(p, sizeof(buf) - 1, fmt, args);
> > +    *p   = '\0';
> > +    fprintf(gOutFile, "%s", buf);
> > +    va_end(args);
> > +    fflush(gOutFile);
> > +}
> > +
> > +static void PrintUsageAndExit(int argc, char **argv)
> > +{
> > +    printf("Usage: pdftest [-preview|-slowpreview] [-loadonly] [-timings]
> > [-text] [-resolution NxM] [-recursive] [-page N] [-out out.txt]
> > pdf-files-to-process\n"); +    for (int i=0; i < argc; i++) {
> > +        printf("i=%d, '%s'\n", i, argv[i]);
> > +    }
> > +    exit(0);
> > +}
> > +
> > +static bool ShowPreview(void)
> > +{
> > +    if (gfPreview || gfSlowPreview)
> > +        return true;
> > +    return false;
> > +}
> > +
> > +static void RenderPdfAsText(const char *fileName)
> > +{
> > +    GooString *         fileNameStr = NULL;
> > +    PDFDoc *            pdfDoc = NULL;
> > +    GooString *         txt = NULL;
> > +    int                 pageCount;
> > +    double              timeInMs;
> > +
> > +    assert(fileName);
> > +    if (!fileName)
> > +        return;
> > +
> > +    LogInfo("started: %s\n", fileName);
> > +
> > +    TextOutputDev * textOut = new TextOutputDev(NULL, gTrue, 0, gFalse,
> > gFalse); +    if (!textOut->isOk()) {
> > +        delete textOut;
> > +        return;
> > +    }
> > +
> > +    GooTimer msTimer;
> > +    /* note: don't delete fileNameStr since PDFDoc takes ownership and
> > deletes them itself */ +    fileNameStr = new GooString(fileName);
> > +    if (!fileNameStr)
> > +        goto Exit;
> > +
> > +    pdfDoc = new PDFDoc(fileNameStr, NULL, NULL, NULL);
> > +    if (!pdfDoc->isOk()) {
> > +        error(errIO, -1, "RenderPdfFile(): failed to open PDF file
> > {0:s}\n", fileName); +        goto Exit;
> > +    }
> > +
> > +    msTimer.stop();
> > +    timeInMs = msTimer.getElapsed();
> > +    LogInfo("load: %.2f ms\n", timeInMs);
> > +
> > +    pageCount = pdfDoc->getNumPages();
> > +    LogInfo("page count: %d\n", pageCount);
> > +
> > +    for (int curPage = 1; curPage <= pageCount; curPage++) {
> > +        if ((gPageNo != PAGE_NO_NOT_GIVEN) && (gPageNo != curPage))
> > +            continue;
> > +
> > +        msTimer.start();
> > +        int rotate = 0;
> > +        GBool useMediaBox = gFalse;
> > +        GBool crop = gTrue;
> > +        GBool doLinks = gFalse;
> > +        pdfDoc->displayPage(textOut, curPage, 72, 72, rotate,
> > useMediaBox, crop, doLinks); +        txt = textOut->getText(0.0, 0.0,
> > 10000.0, 10000.0);
> > +        msTimer.stop();
> > +        timeInMs = msTimer.getElapsed();
> > +        if (gfTimings)
> > +            LogInfo("page %d: %.2f ms\n", curPage, timeInMs);
> > +        printf("%s\n", txt->getCString());
> > +        delete txt;
> > +        txt = NULL;
> > +    }
> > +
> > +Exit:
> > +    LogInfo("finished: %s\n", fileName);
> > +    delete textOut;
> > +    delete pdfDoc;
> > +}
> > +
> > +#ifdef _MSC_VER
> > +#define POPPLER_TMP_NAME "c:\\poppler_tmp.pdf"
> > +#else
> > +#define POPPLER_TMP_NAME "/tmp/poppler_tmp.pdf"
> > +#endif
> > +
> > +static void RenderPdf(const char *fileName)
> > +{
> > +    const char *        fileNameSplash = NULL;
> > +    PdfEnginePoppler *  engineSplash = NULL;
> > +    int                 pageCount;
> > +    double              timeInMs;
> > +
> > +#ifdef COPY_FILE
> > +    // TODO: fails if file already exists and has read-only attribute
> > +    CopyFile(fileName, POPPLER_TMP_NAME, false);
> > +    fileNameSplash = POPPLER_TMP_NAME;
> > +#else
> > +    fileNameSplash = fileName;
> > +#endif
> > +    LogInfo("started: %s\n", fileName);
> > +
> > +    engineSplash = new PdfEnginePoppler();
> > +
> > +    GooTimer msTimer;
> > +    if (!engineSplash->load(fileNameSplash)) {
> > +        LogInfo("failed to load splash\n");
> > +        goto Error;
> > +    }
> > +    msTimer.stop();
> > +    timeInMs = msTimer.getElapsed();
> > +    LogInfo("load splash: %.2f ms\n", timeInMs);
> > +    pageCount = engineSplash->pageCount();
> > +
> > +    LogInfo("page count: %d\n", pageCount);
> > +    if (gfLoadOnly)
> > +        goto Error;
> > +
> > +    for (int curPage = 1; curPage <= pageCount; curPage++) {
> > +        if ((gPageNo != PAGE_NO_NOT_GIVEN) && (gPageNo != curPage))
> > +            continue;
> > +
> > +        SplashBitmap *bmpSplash = NULL;
> > +
> > +        GooTimer msTimer;
> > +        bmpSplash = engineSplash->renderBitmap(curPage, 100.0, 0);
> > +        msTimer.stop();
> > +        double timeInMs = msTimer.getElapsed();
> > +        if (gfTimings) {
> > +            if (!bmpSplash)
> > +                LogInfo("page splash %d: failed to render\n", curPage);
> > +            else
> > +                LogInfo("page splash %d (%dx%d): %.2f ms\n", curPage,
> > bmpSplash->getWidth(), bmpSplash->getHeight(), timeInMs); +        }
> > +
> > +        if (ShowPreview()) {
> > +            PreviewBitmapSplash(bmpSplash);
> > +            if (gfSlowPreview)
> > +                sleep_milliseconds(SLOW_PREVIEW_TIME);
> > +        }
> > +        delete bmpSplash;
> > +    }
> > +Error:
> > +    delete engineSplash;
> > +    LogInfo("finished: %s\n", fileName);
> > +}
> > +
> > +static void RenderFile(const char *fileName)
> > +{
> > +    if (gfTextOnly) {
> > +        RenderPdfAsText(fileName);
> > +        return;
> > +    }
> > +
> > +    RenderPdf(fileName);
> > +}
> > +
> > +static bool ParseInteger(const char *start, const char *end, int *intOut)
> > +{
> > +    char            numBuf[16];
> > +    int             digitsCount;
> > +    const char *    tmp;
> > +
> > +    assert(start && end && intOut);
> > +    assert(end >= start);
> > +    if (!start || !end || !intOut || (start > end))
> > +        return false;
> > +
> > +    digitsCount = 0;
> > +    tmp = start;
> > +    while (tmp <= end) {
> > +        if (isspace(*tmp)) {
> > +            /* do nothing, we allow whitespace */
> > +        } else if (!isdigit(*tmp))
> > +            return false;
> > +        numBuf[digitsCount] = *tmp;
> > +        ++digitsCount;
> > +        if (digitsCount == dimof(numBuf)-3) /* -3 to be safe */
> > +            return false;
> > +        ++tmp;
> > +    }
> > +    if (0 == digitsCount)
> > +        return false;
> > +    numBuf[digitsCount] = 0;
> > +    *intOut = atoi(numBuf);
> > +    return true;
> > +}
> > +
> > +/* Given 'resolutionString' in format NxM (e.g. "100x200"), parse the
> > string and put N +   into 'resolutionXOut' and M into 'resolutionYOut'.
> > +   Return false if there was an error (e.g. string is not in the right
> > format */ +static bool ParseResolutionString(const char
> > *resolutionString, int *resolutionXOut, int *resolutionYOut) +{
> > +    const char *    posOfX;
> > +
> > +    assert(resolutionString);
> > +    assert(resolutionXOut);
> > +    assert(resolutionYOut);
> > +    if (!resolutionString || !resolutionXOut || !resolutionYOut)
> > +        return false;
> > +    *resolutionXOut = 0;
> > +    *resolutionYOut = 0;
> > +    posOfX = strchr(resolutionString, 'X');
> > +    if (!posOfX)
> > +        posOfX = strchr(resolutionString, 'x');
> > +    if (!posOfX)
> > +        return false;
> > +    if (posOfX == resolutionString)
> > +        return false;
> > +    if (!ParseInteger(resolutionString, posOfX-1, resolutionXOut))
> > +        return false;
> > +    if (!ParseInteger(posOfX+1,
> > resolutionString+strlen(resolutionString)-1, resolutionYOut)) +       
> > return false;
> > +    return true;
> > +}
> > +
> > +static void ParseCommandLine(int argc, char **argv)
> > +{
> > +    char *      arg;
> > +
> > +    if (argc < 2)
> > +        PrintUsageAndExit(argc, argv);
> > +
> > +    for (int i=1; i < argc; i++) {
> > +        arg = argv[i];
> > +        assert(arg);
> > +        if ('-' == arg[0]) {
> > +            if (str_ieq(arg, TIMINGS_ARG)) {
> > +                gfTimings = true;
> > +            } else if (str_ieq(arg, RESOLUTION_ARG)) {
> > +                ++i;
> > +                if (i == argc)
> > +                    PrintUsageAndExit(argc, argv); /* expect a file name
> > after that */ +                if (!ParseResolutionString(argv[i],
> > &gResolutionX, &gResolutionY)) +                   
> > PrintUsageAndExit(argc, argv);
> > +                gfForceResolution = true;
> > +            } else if (str_ieq(arg, RECURSIVE_ARG)) {
> > +                gfRecursive = true;
> > +            } else if (str_ieq(arg, OUT_ARG)) {
> > +                /* expect a file name after that */
> > +                ++i;
> > +                if (i == argc)
> > +                    PrintUsageAndExit(argc, argv);
> > +                gOutFileName = str_dup(argv[i]);
> > +            } else if (str_ieq(arg, PREVIEW_ARG)) {
> > +                gfPreview = true;
> > +            } else if (str_ieq(arg, TEXT_ARG)) {
> > +                gfTextOnly = true;
> > +            } else if (str_ieq(arg, SLOW_PREVIEW_ARG)) {
> > +                gfSlowPreview = true;
> > +            } else if (str_ieq(arg, LOAD_ONLY_ARG)) {
> > +                gfLoadOnly = true;
> > +            } else if (str_ieq(arg, PAGE_ARG)) {
> > +                /* expect an integer after that */
> > +                ++i;
> > +                if (i == argc)
> > +                    PrintUsageAndExit(argc, argv);
> > +                gPageNo = atoi(argv[i]);
> > +                if (gPageNo < 1)
> > +                    PrintUsageAndExit(argc, argv);
> > +            } else {
> > +                /* unknown option */
> > +                PrintUsageAndExit(argc, argv);
> > +            }
> > +        } else {
> > +            /* we assume that this is not an option hence it must be
> > +               a name of PDF/directory/file with PDF names */
> > +            StrList_Insert(&gArgsListRoot, arg);
> > +        }
> > +    }
> > +}
> > +
> > +#if 0
> > +void RenderFileList(char *pdfFileList)
> > +{
> > +    char *data = NULL;
> > +    char *dataNormalized = NULL;
> > +    char *pdfFileName;
> > +    uint64_t fileSize;
> > +
> > +    assert(pdfFileList);
> > +    if (!pdfFileList)
> > +        return;
> > +    data = file_read_all(pdfFileList, &fileSize);
> > +    if (!data) {
> > +        error(-1, "couldn't load file '%s'", pdfFileList);
> > +        return;
> > +    }
> > +    dataNormalized = str_normalize_newline(data, UNIX_NEWLINE);
> > +    if (!dataNormalized) {
> > +        error(-1, "couldn't normalize data of file '%s'", pdfFileList);
> > +        goto Exit;
> > +    }
> > +    for (;;) {
> > +        pdfFileName = str_split_iter(&dataNormalized, UNIX_NEWLINE_C);
> > +        if (!pdfFileName)
> > +            break;
> > +        str_strip_ws_both(pdfFileName);
> > +        if (str_empty(pdfFileName)) {
> > +            free((void*)pdfFileName);
> > +            continue;
> > +        }
> > +        RenderFile(pdfFileName);
> > +        free((void*)pdfFileName);
> > +    }
> > +Exit:
> > +    free((void*)dataNormalized);
> > +    free((void*)data);
> > +}
> > +#endif
> > +
> > +#ifdef _WIN32
> > +#include <sys/types.h>
> > +#include <sys/stat.h>
> > +
> > +bool IsDirectoryName(char *path)
> > +{
> > +    struct _stat    buf;
> > +    int             result;
> > +
> > +    result = _stat(path, &buf );
> > +    if (0 != result)
> > +        return false;
> > +
> > +    if (buf.st_mode & _S_IFDIR)
> > +        return true;
> > +
> > +    return false;
> > +}
> > +
> > +bool IsFileName(char *path)
> > +{
> > +    struct _stat    buf;
> > +    int             result;
> > +
> > +    result = _stat(path, &buf );
> > +    if (0 != result)
> > +        return false;
> > +
> > +    if (buf.st_mode & _S_IFREG)
> > +        return true;
> > +
> > +    return false;
> > +}
> > +#else
> > +bool IsDirectoryName(char *path)
> > +{
> > +    /* TODO: implement me */
> > +    return false;
> > +}
> > +
> > +bool IsFileName(char *path)
> > +{
> > +    /* TODO: implement me */
> > +    return true;
> > +}
> > +#endif
> > +
> > +bool IsPdfFileName(char *path)
> > +{
> > +    if (str_endswith(path, ".pdf"))
> > +        return true;
> > +    return false;
> > +}
> > +
> > +static void RenderDirectory(char *path)
> > +{
> > +    FindFileState * ffs;
> > +    char            filename[MAX_FILENAME_SIZE];
> > +    StrList *       dirList = NULL;
> > +    StrList *       el;
> > +
> > +    StrList_Insert(&dirList, path);
> > +
> > +    while (0 != StrList_Len(&dirList)) {
> > +        el = StrList_RemoveHead(&dirList);
> > +        ffs = find_file_open(el->str, "*");
> > +        while (!find_file_next(ffs, filename, sizeof(filename))) {
> > +            if (IsDirectoryName(filename)) {
> > +                if (gfRecursive) {
> > +                    StrList_Insert(&dirList, filename);
> > +                }
> > +            } else if (IsFileName(filename)) {
> > +                if (IsPdfFileName(filename)) {
> > +                    RenderFile(filename);
> > +                }
> > +            }
> > +        }
> > +        find_file_close(ffs);
> > +        StrList_FreeElement(el);
> > +    }
> > +    StrList_Destroy(&dirList);
> > +}
> > +
> > +/* Render 'cmdLineArg', which can be:
> > +   - directory name
> > +   - name of PDF file
> > +   - name of text file with names of PDF files
> > +*/
> > +static void RenderCmdLineArg(char *cmdLineArg)
> > +{
> > +    assert(cmdLineArg);
> > +    if (!cmdLineArg)
> > +        return;
> > +    if (IsDirectoryName(cmdLineArg)) {
> > +        RenderDirectory(cmdLineArg);
> > +    } else if (IsFileName(cmdLineArg)) {
> > +        if (IsPdfFileName(cmdLineArg))
> > +            RenderFile(cmdLineArg);
> > +#if 0
> > +        else
> > +            RenderFileList(cmdLineArg);
> > +#endif
> > +    } else {
> > +        error(errCommandLine, -1, "unexpected argument '{0:s}'",
> > cmdLineArg); +    }
> > +}
> > +
> > +int main(int argc, char **argv)
> > +{
> > +    setErrorCallback(my_error, NULL);
> > +    ParseCommandLine(argc, argv);
> > +    if (0 == StrList_Len(&gArgsListRoot))
> > +        PrintUsageAndExit(argc, argv);
> > +    assert(gArgsListRoot);
> > +
> > +    SplashColorsInit();
> > +    globalParams = new GlobalParams();
> > +    if (!globalParams)
> > +        return 1;
> > +    globalParams->setErrQuiet(gFalse);
> > +
> > +    FILE * outFile = NULL;
> > +    if (gOutFileName) {
> > +        outFile = fopen(gOutFileName, "wb");
> > +        if (!outFile) {
> > +            printf("failed to open -out file %s\n", gOutFileName);
> > +            return 1;
> > +        }
> > +        gOutFile = outFile;
> > +    }
> > +    else
> > +        gOutFile = stdout;
> > +
> > +    if (gOutFileName)
> > +        gErrFile = outFile;
> > +    else
> > +        gErrFile = stderr;
> > +
> > +    PreviewBitmapInit();
> > +
> > +    StrList * curr = gArgsListRoot;
> > +    while (curr) {
> > +        RenderCmdLineArg(curr->str);
> > +        curr = curr->next;
> > +    }
> > +    if (outFile)
> > +        fclose(outFile);
> > +    PreviewBitmapDestroy();
> > +    StrList_Destroy(&gArgsListRoot);
> > +    delete globalParams;
> > +    free(gOutFileName);
> > +    return 0;
> > +}
> > +
> > commit 18884065e11fee82506915095619107a43172ecb
> > Author: Richard PALO <richard at netbsd.org>
> > Date:   Sun Nov 30 22:36:29 2014 +0100
> > 
> >     The isfinite macro is defined on SunOS under c99
> >     
> >     Bug #86869
> > 
> > diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc
> > index 1faa6f7..bfb07eb 100644
> > --- a/poppler/SplashOutputDev.cc
> > +++ b/poppler/SplashOutputDev.cc
> > @@ -33,6 +33,7 @@
> > 
> >  // Copyright (C) 2013 Lu Wang <coolwanglu at gmail.com>
> >  // Copyright (C) 2013 Li Junling <lijunling at sina.com>
> >  // Copyright (C) 2014 Ed Porras <ed at moto-research.com>
> > 
> > +// Copyright (C) 2014 Richard PALO <richard at netbsd.org>
> > 
> >  //
> >  // To see a description of the changes please see the Changelog file that
> >  // came with your tarball or type make ChangeLog if you are building from
> >  git> 
> > @@ -85,8 +86,10 @@ extern "C" int unlink(char *filename);
> > 
> >  #ifdef __sun
> >  #include <ieeefp.h>
> > 
> > +#ifndef isfinite
> > 
> >  #define isfinite(x) finite(x)
> >  #endif
> > 
> > +#endif
> > 
> >  static inline void convertGfxColor(SplashColorPtr dest,
> >  
> >                                     SplashColorMode colorMode,
> > 
> > _______________________________________________
> > poppler mailing list
> > poppler at lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/poppler



More information about the poppler mailing list