[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