[poppler] 2 commits - poppler/SplashOutputDev.cc test/perf-test.cc
Volker Grabsch
v at njh.eu
Mon Dec 1 00:29:44 PST 2014
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.
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
--
Volker Grabsch
---<<(())>>---
-------------- next part --------------
A non-text attachment was scrubbed...
Name: dos_to_unix.patch.gz
Type: application/gzip
Size: 5256 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/poppler/attachments/20141201/f80a46e0/attachment-0002.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: remove_empty_lines.patch.gz
Type: application/gzip
Size: 518 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/poppler/attachments/20141201/f80a46e0/attachment-0003.bin>
More information about the poppler
mailing list