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 <[email protected]> > 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> > 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 <[email protected]> > // Copyright (C) 2013 Li Junling <[email protected]> > // Copyright (C) 2014 Ed Porras <[email protected]> > +// Copyright (C) 2014 Richard PALO <[email protected]> > // > // 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 > [email protected] > http://lists.freedesktop.org/mailman/listinfo/poppler -- Volker Grabsch ---<<(())>>---
dos_to_unix.patch.gz
Description: application/gzip
remove_empty_lines.patch.gz
Description: application/gzip
_______________________________________________ poppler mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/poppler
