El Dilluns, 1 de desembre de 2014, a les 09:29:44, Volker Grabsch va escriure: > Hi, > > I noticed that this patch changed every single line of perf-test.cc, > making it hard to review properly. > > This happened certainly because of the strange line endlings (DOS > style) of perf-test.cc. A quick search showed that the following > files also have DOS line endings: > > test/perf-test-preview-dummy.cc > test/perf-test-preview-win.cc > splash/SplashState.h > > I propose to convert those from DOS to Unix line endings to prevent > similar issues in the future. See attached patch. While I was at it, > I noticed some strange empty lines at EOF which make no sense to me. > See second patch.
You can use git diff -b to ignore whitespace changes. Cheers, Albert > > > Regards, > Volker > > Albert Astals Cid schrieb: > > poppler/SplashOutputDev.cc | 3 > > test/perf-test.cc | 2559 > > ++++++++++++++++++++++----------------------- 2 files changed, 1283 > > insertions(+), 1279 deletions(-) > > > > New commits: > > commit d3fe0661c6dc6050e14cd5cb4afa089b7d7d66b0 > > Author: Richard PALO <[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 _______________________________________________ poppler mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/poppler
