summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Resource/Init/pdf_main.ps188
-rw-r--r--base/gdevflp.c234
-rw-r--r--base/gdevflp.h9
-rw-r--r--base/gsdparam.c3
-rw-r--r--base/gxdevcli.h1
-rw-r--r--base/lib.mak16
-rw-r--r--base/pagelist.c246
-rw-r--r--base/pagelist.h33
-rw-r--r--doc/Language.htm9
-rw-r--r--doc/Use.htm58
-rw-r--r--psi/zpdfops.c37
-rw-r--r--xps/xpszip.c138
12 files changed, 498 insertions, 474 deletions
diff --git a/Resource/Init/pdf_main.ps b/Resource/Init/pdf_main.ps
index 2a622eb88..07cddf5e8 100644
--- a/Resource/Init/pdf_main.ps
+++ b/Resource/Init/pdf_main.ps
@@ -835,125 +835,24 @@ currentdict /PDFSwitches undef
/newpdf_runpdfpagerange
{
/PageList where {
- pop PageList
- (even) anchorsearch {
- pop length 0 gt {
- /runpdfpagerange cvx /syntaxerror signalerror
- } if
- /PDFPageList pdfpagecount 1 add array def
- 2 2 pdfpagecount {
- PDFPageList exch 1 put
- } for
- QUIET not {
- (Processing even-numbered pages\n) print (1 through ) print pdfpagecount =only
- (.) = flush
- } if
- } {
- (odd) anchorsearch {
- pop length 0 gt {
- /runpdfpagerange cvx /syntaxerror signalerror
- } if
- /PDFPageList pdfpagecount 1 add array def
- 1 2 pdfpagecount {
- PDFPageList exch 1 put
- } for
- QUIET not {
- (Processing odd-numbered pages\n) print (1 through ) print pdfpagecount =only
- (.) = flush
- } if
- } {
- %% validate string contents, check for digit comma or minus
- dup
- {
- dup 44 eq not {
- dup 45 eq not {
- dup 48 lt 1 index 57 gt or {
- /runpdfpagerange cvx /syntaxerror signalerror
- } if
- } if
- } if
- pop
- }
- forall
- /PDFPageList pdfpagecount 1 add array def
- {
- (,) search {
- %% We now have (post) (,) (pre)
- exch pop %% get rid of the (,), leave the (post) as the string for the next iteration, deal with the section up to the comma
- (-) search {
- %% Now we have (end) (-) (start)
- exch pop %% get rid of the minus (end) (start)
- 0 exch {48 sub exch 10 mul add} forall
- %% Make sure the start of the range is inside the number of available pages
- dup pdfpagecount le {
- exch
- %% deal with a trailing '-' by replacing it with the number of pages in the file
- dup length 0 eq {
- pop pdfpagecount
- }{
- 0 exch {48 sub exch 10 mul add} forall
- } ifelse
- 1 exch %% start 1 end
- %% Make sure the end of the range is inside the number of available pages
- dup pdfpagecount gt {pop pdfpagecount} if
- {PDFPageList exch 1 put} for
- } {
- %% start of range invalid, drop this range.
- pop pop
- }ifelse
- }{
- %% no minus signs, must be a simple page number
- 0 exch {48 sub exch 10 mul add} forall
- %% ensure its in the valid range of pages
- dup pdfpagecount le {
- PDFPageList exch 1 put
- } {
- pop
- } ifelse
- } ifelse
- }{
- %% no commas separating pages, just the original string (), deal with its as a section, then exit the loop
- (-) search {
- %% Now we have (end) (-) (start)
- exch pop %% get rid of the minus (end) (start)
- 0 exch {48 sub exch 10 mul add} forall
- %% Make sure the start of the range is inside the number of available pages
- dup pdfpagecount le {
- exch
- %% deal with a trailing '-' by replacing it with the number of pages in the file
- dup length 0 eq {
- pop pdfpagecount
- }{
- 0 exch {48 sub exch 10 mul add} forall
- } ifelse
- 1 exch %% start 1 end
- %% Make sure the end of the range is inside the number of available pages
- dup pdfpagecount gt {pop pdfpagecount} if
- {PDFPageList exch 1 put} for
- } {
- %% start of range invalid, drop this range.
- pop pop
- }ifelse
- }{
- %% no minus signs, must be a simple page number
- 0 exch {48 sub exch 10 mul add} forall
- %% ensure its in the valid range of pages
- dup pdfpagecount le {
- PDFPageList exch 1 put
- } {
- pop
- } ifelse
- } ifelse
- exit %% done all the sections.
- } ifelse
- } loop
- QUIET not {
- (Processing pages ) print PageList =only
- (.) = flush
- } if
- } ifelse
- } ifelse
- 1 pdfpagecount
+ pop
+ % make sure string is NUL terminated as C expects.
+ PageList 1 string dup 0 0 put concatstrings
+ pdfpagecount
+ .PDFparsePageList
+ dup 0 eq { % No ranges, error
+ (\n **** Error: Invalid PageList: ) print
+ PageList print
+ (\n No pages will be processed.) = flush
+ /runpdfpagerange cvx /syntaxerror signalerror
+ } if
+ array astore % move integer triples from the stack to the array
+ % newpdf PDFPageList is an array of 3 elements per range: even/odd flag, start, end
+ /PDFPageList exch def
+ QUIET not {
+ (Processing pages ) print PageList =only (.) = flush
+ } if
+ 1 pdfpagecount % dummy parameters for newpdf_dopages
}{
/FirstPage where {
pop FirstPage dup pdfpagecount gt {
@@ -1197,17 +1096,26 @@ currentdict /PDFSwitches undef
% <int> <int> dopdfpages -
% First Page and then LastPage
+% If PDFPageList array exists, the parameters are 1 pdfpagecount and are ignored.
/newpdf_dopdfpages
{
//DisablePageHandlerDevice exec
- 1 exch
- {
- %% If we have a array of pages to render, use it.
- /PDFPageList where {
- pop dup PDFPageList exch get 1 eq
- }
- {//true} ifelse
-
+ %% If we have a array of page ranges to render, use it.
+ /PDFPageList where {
+ pop
+ pop pop % don't use dummy parameters
+ PDFPageList
+ % process the ranges (3 elements per range)
+ 0 3 2 index length 1 sub {
+ 1 index 1 index get % even = 2, odd = 1 any = 0
+ 2 index 2 index 1 add get % start of range
+ exch
+ 3 index 3 index 2 add get % end of range
+ exch
+ % stack: start end even/odd
+ 0 eq { 1 } { 2 } ifelse
+ 2 index 2 index gt { neg } if % negate increment for reverse range
+ exch
{
pdfgetpage
dup //null ne {
@@ -1221,10 +1129,28 @@ currentdict /PDFSwitches undef
( not found.\n) newpdf_pdfformaterror
} ifelse
} ifelse
- }{
- pop
- }ifelse
- } for
+ } for
+ pop % for loop index
+ } for
+ pop % done with array
+ } {
+ % else, Process the pages given by the FirstPage, LastPage
+ 1 exch
+ {
+ pdfgetpage
+ dup //null ne {
+ pdfshowpage
+ } {
+ PDFSTOPONERROR {
+ /dopdfpages cvx /syntaxerror signalerror
+ } {
+ pop pop
+ ( **** Error: page) newpdf_pdfformaterror
+ ( not found.\n) newpdf_pdfformaterror
+ } ifelse
+ } ifelse
+ } for
+ } ifelse
//EnablePageHandlerDevice exec
} bind def
diff --git a/base/gdevflp.c b/base/gdevflp.c
index d144d0cbb..53928044b 100644
--- a/base/gdevflp.c
+++ b/base/gdevflp.c
@@ -30,6 +30,7 @@
*/
#include "math_.h"
+#include "string_.h" /* for strlen */
#include "memory_.h"
#include "gx.h"
#include "gserrors.h"
@@ -49,6 +50,7 @@
#include "gximage.h" /* For gx_image_enum */
#include "gdevsclass.h"
#include "gdevflp.h"
+#include "pagelist.h"
#include <stdlib.h>
/* GC descriptor */
@@ -137,134 +139,8 @@ gx_device_flp gs_flp_device =
static int ParsePageList(gx_device *dev, first_last_subclass_data *psubclass_data, char *PageList)
{
- char *str, *oldstr, *workstr, c, *ArgCopy;
- int LastPage, Page, byte, bit, i, prev_page = -1;
-
- psubclass_data->ProcessedPageList = true;
- if (strcmp(PageList, "even") == 0) {
- psubclass_data->EvenOdd = even;
- } else {
- if (strcmp(PageList, "odd") == 0) {
- psubclass_data->EvenOdd = odd;
- } else {
- psubclass_data->EvenOdd = none;
-
- /* validation of parameter */
- str = PageList;
- do {
- /* Must be digit, ',' or - */
- if (*str != ',' && *str != '-' && (*str < 0x30 || *str > 0x39)) {
- return (gs_note_error(gs_error_typecheck));
- }
- /* Check we don't have 2 special characters (, or -) in a row */
- if ((*str == ',' || *str == '-') && (*(str+1) == ',' || *(str+1) == '-'))
- return (gs_note_error(gs_error_typecheck));
- } while(*(++str));
-
- str = PageList;
- oldstr = str;
- do {
- str = strchr(oldstr, ',');
- /* Check for trailing ',' in parameter, zap it if we find one. */
- if (str) {
- if (*(str + 1))
- oldstr = ++str;
- else {
- *str = 0x00;
- break;
- }
- }
- }while (str);
-
- /* In case last set is a page range */
- str = strchr(oldstr, '-');
- if (!str)
- str = oldstr;
- else {
- /* We permit a trailing '-' to indicate all pages from this one to the end */
- if (*(str + 1))
- str++;
- else {
- *str = 0x00;
- str = oldstr;
- psubclass_data->FromToEnd = atoi(str);
- }
- }
- /* str should now point to the last page number (we hope!) */
- psubclass_data->LastListPage = LastPage = atoi(str);
-
- psubclass_data->PageArraySize = (LastPage + 7) / 8;
- psubclass_data->PageArray = gs_alloc_bytes(dev->memory->non_gc_memory, psubclass_data->PageArraySize, "array of pages selected");
- if (!psubclass_data->PageArray) {
- psubclass_data->PageArraySize = 0;
- return (gs_note_error(gs_error_VMerror));
- }
- memset(psubclass_data->PageArray, 0x00, psubclass_data->PageArraySize);
-
- oldstr = ArgCopy = (char *)gs_alloc_bytes(dev->memory->non_gc_memory, strlen(PageList) + 1, "temp working string");
- if (!ArgCopy) {
- gs_free_object(dev->memory->non_gc_memory, psubclass_data->PageArray, "free array of pages selected");
- psubclass_data->PageArray = 0;
- psubclass_data->PageArraySize = 0;
- return (gs_note_error(gs_error_VMerror));
- }
- memcpy(ArgCopy, PageList, strlen(PageList) + 1);
- do {
- str = strchr(oldstr, ',');
- if (str)
- *str++ = 0x00;
- /* oldstr now points to a null terminated string and is either a number or a number pair */
- workstr = strchr(oldstr, '-');
- if (workstr) {
- *workstr++ = 0x00;
- /* oldstr points to null terminated string of start, workstr to null terminated string of end */
- Page = atoi(oldstr) - 1;
- if (Page < 0)
- Page = 0;
-
- LastPage = atoi(workstr) - 1;
- if (LastPage < 0)
- LastPage = 0;
-
- if (LastPage < Page || Page <= prev_page) {
- /* Strictly monotonic increasing required */
- emprintf(dev->memory, "\n**** Error : rangecheck processing PageList\n");
- return_error(gs_error_rangecheck);
- }
- prev_page = LastPage;
-
- for (i=Page; i<= LastPage;i++) {
- if (i > psubclass_data->LastListPage - 1) {
- emprintf(dev->memory, "\n**** Error : rangecheck processing PageList\n");
- return_error(gs_error_rangecheck);
- }
- byte = (int)(i / 8);
- bit = i % 8;
- c = 0x01 << bit;
- ((char *)psubclass_data->PageArray)[byte] |= c;
- }
- } else {
- Page = atoi(oldstr) - 1;
- if (Page < 0)
- Page = 0;
- if (Page <= prev_page || Page > psubclass_data->LastListPage - 1) {
- /* Strictly monotonic increasing required */
- emprintf(dev->memory, "\n**** Error : rangecheck processing PageList\n");
- return_error(gs_error_rangecheck);
- }
- prev_page = Page;
-
- byte = (int)(Page / 8);
- bit = Page % 8;
- c = 0x01 << bit;
- ((char *)psubclass_data->PageArray)[byte] |= c;
- }
- oldstr = str;
- } while (str);
- gs_free_object(dev->memory->non_gc_memory, ArgCopy, "free temp working string");
- }
- }
- return 0;
+ return pagelist_parse_to_array(PageList, dev->memory->non_gc_memory, 0x7fffffff,
+ &(psubclass_data->page_range_array));
}
static int SkipPage(gx_device *dev)
@@ -277,51 +153,28 @@ static int SkipPage(gx_device *dev)
return 0;
/* If we haven't parsed any extant PageList, do it now */
- if (dev->PageList && !psubclass_data->ProcessedPageList) {
+ if (dev->PageList && psubclass_data->page_range_array == NULL) {
code = ParsePageList(dev, psubclass_data, dev->PageList->Pages);
- if (code < 0)
+ if (code < 0) {
+ emprintf1(dev->memory, "*** Invalid PageList=%s ***\n", dev->PageList->Pages);
return code;
- psubclass_data->ProcessedPageList = true;
+ }
}
- if (psubclass_data->PageArray) {
- if (psubclass_data->FromToEnd != 0 && psubclass_data->PageCount >= psubclass_data->FromToEnd - 1)
- return 0;
- else {
- if (psubclass_data->PageCount > psubclass_data->LastListPage - 1)
- return 1;
- else {
- int byte, bit;
- char c;
-
- byte = (int)((psubclass_data->PageCount) / 8);
- bit = (psubclass_data->PageCount) % 8;
- c = 0x01 << bit;
- if (((char *)psubclass_data->PageArray)[byte] & c)
- return 0;
- else
- return 1;
- }
- }
+ /* SkipPage can only handle PageList that moves forward */
+ if (psubclass_data->page_range_array != NULL &&
+ pagelist_test_ordered(psubclass_data->page_range_array) == false) {
+ emprintf(dev->memory, "*** Bad PageList: Must be increasing order. ***\n");
+ return gs_error_rangecheck;
+ }
+
+ if (psubclass_data->page_range_array != NULL) {
+ /* PageCount is 0 based, page_range_array starts at page 1 */
+ return pagelist_test_printed(psubclass_data->page_range_array, psubclass_data->PageCount + 1) == false;
} else {
- if (psubclass_data->EvenOdd != none) {
- /* Page count is 0 based so the even/odd tests are 'upside down' */
- if (psubclass_data->PageCount % 2 == 0) {
- if (psubclass_data->EvenOdd == odd)
- return 0;
- else
- return 1;
- } else {
- if (psubclass_data->EvenOdd == even)
- return 0;
- else
- return 1;
- }
- } else {
- if (psubclass_data->PageCount >= dev->FirstPage - 1)
- if (!dev->LastPage || psubclass_data->PageCount <= dev->LastPage - 1)
- return 0;
- }
+ if (psubclass_data->PageCount >= dev->FirstPage - 1)
+ if (!dev->LastPage || psubclass_data->PageCount <= dev->LastPage - 1)
+ return 0;
}
return 1;
}
@@ -344,11 +197,10 @@ int flp_close_device(gx_device *dev)
{
first_last_subclass_data *psubclass_data = dev->subclass_data;
- if (psubclass_data->PageArraySize)
+ if (psubclass_data->page_range_array != NULL)
{
- gs_free(dev->memory->non_gc_memory, psubclass_data->PageArray, 1, psubclass_data->PageArraySize, "array of pages selected");
- psubclass_data->PageArray = 0;
- psubclass_data->PageArraySize = 0;
+ pagelist_free_range_array(dev->memory->non_gc_memory, psubclass_data->page_range_array);
+ psubclass_data->page_range_array = NULL;
}
return default_subclass_close_device(dev);
@@ -399,7 +251,7 @@ flp_rc_free_pages_list(gs_memory_t * mem, void *ptr_in, client_name_t cname)
gdev_pagelist *PageList = (gdev_pagelist *)ptr_in;
if (PageList->rc.ref_count <= 1) {
- gs_free(mem->non_gc_memory, PageList->Pages, 1, PagesSize, "free page list");
+ gs_free(mem->non_gc_memory, PageList->Pages, 1, strlen(PageList->Pages), "free page list");
gs_free(mem->non_gc_memory, PageList, 1, sizeof(gdev_pagelist), "free structure to hold page list");
}
}
@@ -420,6 +272,7 @@ flp_put_params(gx_device * dev, gs_param_list * plist)
first_last_subclass_data *psubclass_data = dev->subclass_data;
psubclass_data->PageCount = 0;
+ psubclass_data->page_range_array = NULL;
}
}
@@ -432,14 +285,14 @@ flp_put_params(gx_device * dev, gs_param_list * plist)
dev->DisablePageHandler = false;
psubclass_data->PageCount = 0;
+ psubclass_data->page_range_array = NULL;
if (dev->PageList) {
rc_decrement(dev->PageList, "flp_put_params");
dev->PageList = NULL;
}
- if (psubclass_data->PageArray != NULL) {
- gs_free(dev->memory->non_gc_memory, psubclass_data->PageArray, 1, psubclass_data->PageArraySize, "array of pages selected");
- psubclass_data->PageArray = NULL;
- psubclass_data->PageArraySize = 0;
+ if (psubclass_data->page_range_array != NULL) {
+ pagelist_free_range_array(dev->memory->non_gc_memory, psubclass_data->page_range_array);
+ psubclass_data->page_range_array = NULL;
}
}
@@ -451,14 +304,14 @@ flp_put_params(gx_device * dev, gs_param_list * plist)
dev->DisablePageHandler = false;
psubclass_data->PageCount = 0;
+ psubclass_data->page_range_array = NULL;
if (dev->PageList) {
rc_decrement(dev->PageList, "flp_put_params");
dev->PageList = NULL;
}
- if (psubclass_data->PageArray != NULL) {
- gs_free(dev->memory->non_gc_memory, psubclass_data->PageArray, 1, psubclass_data->PageArraySize, "array of pages selected");
- psubclass_data->PageArray = NULL;
- psubclass_data->PageArraySize = 0;
+ if (psubclass_data->page_range_array != NULL) {
+ pagelist_free_range_array(dev->memory->non_gc_memory, psubclass_data->page_range_array);
+ psubclass_data->page_range_array = NULL;
}
}
@@ -472,10 +325,9 @@ flp_put_params(gx_device * dev, gs_param_list * plist)
if (dev->PageList)
rc_decrement(dev->PageList, "flp_put_params");
- if (psubclass_data->PageArray != NULL) {
- gs_free(dev->memory->non_gc_memory, psubclass_data->PageArray, 1, psubclass_data->PageArraySize, "array of pages selected");
- psubclass_data->PageArray = NULL;
- psubclass_data->PageArraySize = 0;
+ if (psubclass_data->page_range_array != NULL) {
+ pagelist_free_range_array(dev->memory->non_gc_memory, psubclass_data->page_range_array);
+ psubclass_data->page_range_array = NULL;
}
dev->PageList = (gdev_pagelist *)gs_alloc_bytes(dev->memory->non_gc_memory, sizeof(gdev_pagelist), "structure to hold page list");
@@ -489,11 +341,11 @@ flp_put_params(gx_device * dev, gs_param_list * plist)
}
memset(dev->PageList->Pages, 0x00, pagelist.size + 1);
memcpy(dev->PageList->Pages, pagelist.data, pagelist.size);
- dev->PageList->PagesSize = pagelist.size + 1;
rc_init_free(dev->PageList, dev->memory->non_gc_memory, 1, flp_rc_free_pages_list);
- psubclass_data->ProcessedPageList = false;
+ psubclass_data->page_range_array = NULL;
dev->DisablePageHandler = false;
psubclass_data->PageCount = 0;
+ psubclass_data->page_range_array = NULL;
}
}
code = default_subclass_put_params(dev, plist);
@@ -990,11 +842,15 @@ int flp_fill_linear_color_triangle(gx_device *dev, const gs_fill_attributes *fa,
int flp_fillpage(gx_device *dev, gs_gstate * pgs, gx_device_color *pdevc)
{
+ first_last_subclass_data *psubclass_data = dev->subclass_data;
int code = SkipPage(dev);
if (code < 0)
return code;
- if (!code)
+
+ /* allow fillpage to be processed at the first page */
+ /* This is needed to allow all parsers to start with non-ordered PageList */
+ if (!code || psubclass_data->PageCount == 0)
return default_subclass_fillpage(dev, pgs, pdevc);
return 0;
@@ -1176,4 +1032,4 @@ flp_initialize_device_procs(gx_device *dev)
set_dev_proc(dev, process_page, flp_process_page);
set_dev_proc(dev, transform_pixel_region, flp_transform_pixel_region);
set_dev_proc(dev, fill_stroke_path, flp_fill_stroke_path);
-} \ No newline at end of file
+}
diff --git a/base/gdevflp.h b/base/gdevflp.h
index 453f401a9..fb888199f 100644
--- a/base/gdevflp.h
+++ b/base/gdevflp.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -33,12 +33,7 @@ typedef enum {none, even, odd} flp_EOType;
typedef struct {
subclass_common;
int PageCount;
- int ProcessedPageList;
- void *PageArray;
- int PageArraySize;
- int LastListPage;
- int FromToEnd;
- flp_EOType EvenOdd;
+ int *page_range_array;
} first_last_subclass_data;
typedef struct flp_text_enum_s {
diff --git a/base/gsdparam.c b/base/gsdparam.c
index 8913b6301..07863706d 100644
--- a/base/gsdparam.c
+++ b/base/gsdparam.c
@@ -1544,7 +1544,7 @@ rc_free_pages_list(gs_memory_t * mem, void *ptr_in, client_name_t cname)
gdev_pagelist *PageList = (gdev_pagelist *)ptr_in;
if (PageList->rc.ref_count <= 1) {
- gs_free(mem->non_gc_memory, PageList->Pages, 1, PagesSize, "free page list");
+ gs_free(mem->non_gc_memory, PageList->Pages, 1, strlen(PageList->Pages), "free page list");
gs_free(mem->non_gc_memory, PageList, 1, sizeof(gdev_pagelist), "free structure to hold page list");
}
}
@@ -2212,7 +2212,6 @@ label:\
}
memset(dev->PageList->Pages, 0x00, pagelist.size + 1);
memcpy(dev->PageList->Pages, pagelist.data, pagelist.size);
- dev->PageList->PagesSize = pagelist.size + 1;
rc_init_free(dev->PageList, dev->memory->non_gc_memory, 1, rc_free_pages_list);
}
diff --git a/base/gxdevcli.h b/base/gxdevcli.h
index 3fc1c742f..5c9831b93 100644
--- a/base/gxdevcli.h
+++ b/base/gxdevcli.h
@@ -705,7 +705,6 @@ typedef struct gdev_nupcontrol_s {
typedef struct gdev_pagelist_s {
rc_header rc;
char *Pages;
- int PagesSize;
} gdev_pagelist;
#define dev_t_proc_initialize_device_procs(proc, dev_t)\
diff --git a/base/lib.mak b/base/lib.mak
index 37e44dcee..dc3c95015 100644
--- a/base/lib.mak
+++ b/base/lib.mak
@@ -196,6 +196,7 @@ gxsync_h=$(GLSRC)gxsync.h
gxclthrd_h=$(GLSRC)gxclthrd.h
gxdevsop_h=$(GLSRC)gxdevsop.h
gdevflp_h=$(GLSRC)gdevflp.h
+pagelist_h=$(GLSRC)pagelist.h
gdevkrnlsclass_h=$(GLSRC)gdevkrnlsclass.h
gdevsclass_h=$(GLSRC)gdevsclass.h
@@ -1415,11 +1416,15 @@ $(GLOBJ)gxdownscale_1.$(OBJ) : $(GLSRC)gxdownscale.c $(AK) $(string__h)\
$(GLOBJ)gxdownscale.$(OBJ) : $(GLOBJ)gxdownscale_$(WITH_CAL).$(OBJ) $(AK) $(gp_h)
$(CP_) $(GLOBJ)gxdownscale_$(WITH_CAL).$(OBJ) $(GLOBJ)gxdownscale.$(OBJ)
+# ---- Various subclass devices ----
+subclass_=$(GLOBJ)gdevflp.$(OBJ) $(GLOBJ)gdevkrnlsclass.$(OBJ) $(GLOBJ)gdevepo.$(OBJ) \
+ $(GLOBJ)gdevoflt.$(OBJ) $(GLOBJ)gdevnup.$(OBJ) $(GLOBJ)gdevsclass.$(OBJ)
+
###### Create a pseudo-"feature" for the entire graphics library.
-LIB0s=$(GLOBJ)gpmisc.$(OBJ) $(GLOBJ)stream.$(OBJ) $(GLOBJ)strmio.$(OBJ)
-LIB1s=$(GLOBJ)gsalloc.$(OBJ) $(GLOBJ)gxdownscale.$(OBJ) $(downscale_) $(GLOBJ)gdevprn.$(OBJ) $(GLOBJ)gdevflp.$(OBJ) $(GLOBJ)gdevkrnlsclass.$(OBJ) $(GLOBJ)gdevepo.$(OBJ)
-LIB2s=$(GLOBJ)gdevmplt.$(OBJ) $(GLOBJ)gsbitcom.$(OBJ) $(GLOBJ)gsbitops.$(OBJ) $(GLOBJ)gsbittab.$(OBJ) $(GLOBJ)gdevoflt.$(OBJ) $(GLOBJ)gdevnup.$(OBJ) $(GLOBJ)gdevsclass.$(OBJ)
+LIB0s=$(GLOBJ)gpmisc.$(OBJ) $(GLOBJ)stream.$(OBJ) $(GLOBJ)strmio.$(OBJ) $(GLOBJ)pagelist.$(OBJ)
+LIB1s=$(GLOBJ)gsalloc.$(OBJ) $(GLOBJ)gxdownscale.$(OBJ) $(downscale_) $(GLOBJ)gdevprn.$(OBJ) $(subclass_)
+LIB2s=$(GLOBJ)gdevmplt.$(OBJ) $(GLOBJ)gsbitcom.$(OBJ) $(GLOBJ)gsbitops.$(OBJ) $(GLOBJ)gsbittab.$(OBJ)
# Note: gschar.c is no longer required for a standard build;
# we include it only for backward compatibility for library clients.
LIB3s=$(GLOBJ)gscedata.$(OBJ) $(GLOBJ)gscencs.$(OBJ) $(GLOBJ)gschar.$(OBJ) $(GLOBJ)gscolor.$(OBJ)
@@ -2072,11 +2077,14 @@ $(GLOBJ)gdevmplt.$(OBJ) : $(GLSRC)gdevmplt.c $(gdevmplt_h) $(gdevp14_h)\
$(memory__h)
$(GLCC) $(GLO_)gdevmplt.$(OBJ) $(C_) $(GLSRC)gdevmplt.c
+$(GLOBJ)pagelist.$(OBJ) : $(GLSRC)pagelist.c $(pagelist_h) $(gserrors_h) $(memory__h)
+ $(GLCC) $(GLO_)pagelist.$(OBJ) $(C_) $(GLSRC)pagelist.c
+
$(GLOBJ)gdevflp.$(OBJ) : $(GLSRC)gdevflp.c $(gdevflp_h) $(gdevp14_h) \
$(gdevprn_h) $(gdevsclass_h) $(gsdevice_h) $(gserrors_h) $(gsparam_h)\
$(gsstype_h) $(gx_h) $(gxcmap_h) $(gxcpath_h) $(gxdcolor_h) $(gxdevice_h) \
$(gxgstate_h) $(gximage_h) $(gxiparam_h) $(gxpaint_h) $(gxpath_h) $(math__h)\
- $(memory__h)
+ $(string__h) $(memory__h)
$(GLCC) $(GLO_)gdevflp.$(OBJ) $(C_) $(GLSRC)gdevflp.c
$(GLOBJ)gdevepo.$(OBJ) : $(GLSRC)gdevepo.c $(gdevepo_h) $(gdevp14_h) \
diff --git a/base/pagelist.c b/base/pagelist.c
new file mode 100644
index 000000000..c687b7b98
--- /dev/null
+++ b/base/pagelist.c
@@ -0,0 +1,246 @@
+/* Copyright (C) 2022-2022 Artifex Software, Inc.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied,
+ modified or distributed except as expressly authorized under the terms
+ of the license contained in the file LICENSE in this distribution.
+
+ Refer to licensing information at http://www.artifex.com or contact
+ Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato,
+ CA 94945, U.S.A., +1(415)492-9861, for further information.
+*/
+
+/* Functions to parse a PageList string and processing utilitiess */
+
+
+#include "memory_.h"
+#include "string_.h" /* for strcspn */
+#include <stdlib.h> /* for atoi */
+#include "gsmemory.h"
+#include "gserrors.h"
+#include "pagelist.h"
+
+/* array contains an "ordered" flag, then even/odd, start, end triples */
+
+/* Allocate an array of ranges. A range of 0-0 terminates the list */
+/* Note the first int 0 is order unknown, < 0 is unordered, > 0 is */
+/* ordered and thus is suitable for sequential parsers like PS or PCL. */
+/* This first int is also used by test_printed as the offset into the */
+/* array for fast processing by SkipPage. */
+/* returns error code < 0 or number of ranges if success. */
+int
+pagelist_parse_to_array(char *page_list, gs_memory_t *mem, int num_pages, int **parray)
+{
+ int i = 0, range_count = 0;
+ int *pagelist_array = NULL;
+ char *p = page_list;
+ int prev_end = 0; /* used to track if the ranges are ordered */
+ int ordered = 1; /* default is ordered, until it's not */
+ int comma, len;
+
+ *parray = NULL; /* in case PageList is empty */
+ if (page_list[0] == 0)
+ return gs_error_rangecheck; /* empty list not valid */
+
+ do {
+ len = strlen(p);
+ comma = strcspn(p, ",");
+ p += comma + 1;
+ if (comma > 0)
+ range_count++;
+ } while (comma < len);
+ if (range_count == 0)
+ return gs_error_rangecheck; /* not valid */
+
+ range_count++; /* room for the end of list marker: 0, 0, 0 */
+ pagelist_array = (int *)gs_alloc_byte_array(mem, 1 + (range_count * 3), sizeof(int), "pagelist_parse_to_array");
+ *parray = pagelist_array; /* return the array (NULL is OK) */
+ if (pagelist_array == NULL)
+ return gs_error_VMerror;
+
+ memset(pagelist_array, 0, (1 + range_count * 3) * sizeof(int));
+ /* Fill the array */
+
+ p = page_list; /* go back to start of string */
+ for (i=1; i < (range_count - 1) * 3; ) {
+ /* Parsing method from Michael Vrhel's code in xps */
+ int dash, start, end, even_odd;
+
+ even_odd = 0;
+ start = 1;
+ end = -1; /* internal flag for last page */
+ len = strlen(p);
+ comma = strcspn(p, ",");
+ dash = strcspn(p, "-");
+
+ if (comma == 0) {
+ p++;
+ continue; /* skip leading or adjacent commas */
+ }
+ if (strncmp(p, "even", 4) == 0) {
+ even_odd = 2;
+ p += 4;
+ } else if (strncmp(p, "odd", 3) == 0) {
+ even_odd = 1;
+ p += 3;
+ }
+ /* check if the next after "even" or "odd" is ':' */
+ if (even_odd != 0) {
+ start = even_odd; /* default is entire range */
+ end = -1;
+ if (*p == ':')
+ p++; /* skip to the range */
+ len = strlen(p);
+ comma = strcspn(p, ",");
+ dash = strcspn(p, "-");
+ }
+ if (comma > 0 && *p != 0) {
+ /* We have a range to process */
+ if (dash < comma) {
+ /* Dash at start */
+ if (dash == 0) {
+ start = -1;
+ end = atoi(p + dash + 1);
+ } else {
+ start = atoi(p);
+ /* Dash at end */
+ if (p[dash + 1] == 0 || p[dash + 1] == ',') {
+ end = -1;
+ } else {
+ end = atoi(p + dash + 1);
+ }
+ }
+ } else {
+ start = atoi(p);
+ end = start;
+ }
+ }
+ if (comma == len)
+ p += comma;
+ else
+ p += comma + 1;
+
+ /* If even or odd, and we have a "num_pages" flag == -1, adjust to proper value */
+ if (even_odd == 2) {
+ if (start == -1)
+ start = num_pages & -2;
+ if (end == -1)
+ end = num_pages & -2;
+ } else if (even_odd == 1) {
+ if (start == -1)
+ start = num_pages - (1 & (num_pages ^ 1));
+ if (end == -1)
+ end = num_pages - (1 & (num_pages ^ 1));
+ } else {
+ if (start == -1)
+ start = num_pages;
+ if (end == -1)
+ end = num_pages;
+ }
+ /* Store this range, bump the index as we do */
+ pagelist_array[i++] = even_odd;
+ pagelist_array[i++] = start;
+ pagelist_array[i++] = end;
+
+ if (start <= prev_end || start > end)
+ ordered = -1;
+ prev_end = end;
+ }
+ /* Note final array entries are 0, 0, 0 from memset above */
+ pagelist_array[0] = ordered;
+ return range_count;
+}
+
+/* function to calculate the total number of pages to be output */
+int
+pagelist_number_of_pages(const int *parray)
+{
+ int count = 0, i;
+
+ /* loop over ranges until start == 0 */
+ for (i=1; parray[i+1] != 0; i += 3) {
+ int start = parray[i+1];
+ int end = parray[i+2];
+
+ if (end >= start)
+ count += 1 + end - start;
+ else
+ count += 1 + start - end;
+ }
+ return count;
+}
+
+/* Return true if this pagelist is in strict increasing order */
+bool
+pagelist_test_ordered(int *parray)
+{
+ int prev;
+ int i;
+
+ /* check flag (fast for use by the flp SkipPage function */
+ if (parray[0] > 0)
+ return true;
+ if (parray[0] < 0)
+ return false;
+
+ /* parray[0] == 0, scan until start of range is 0 */
+ prev = 0; /* page 1 or more is legal */
+ for (i=1; parray[i+1] != 0; i += 3) {
+ if (parray[i+1] <= prev || parray[i+1] < parray[i+2])
+ break; /* NOT ordered */
+ prev = parray[i+2]; /* advance to end of range */
+ }
+ /* if we made it to the marker at the end, then the list is ordered */
+ parray[0] = (parray[i+1] == 0) ? 1 : -1;
+ return parray[0] > 0;
+}
+
+/* Return true if this page is to be printed. (For sequential processing) */
+/* This assumes/requires that the PageList is strictly sequential. */
+bool
+pagelist_test_printed(int *parray, int pagenum)
+{
+ int i = parray[0];
+
+ if (i <= 0) { /* shouldn't happen */
+ pagelist_test_ordered(parray); /* in case caller didn't do this */
+ i = parray[0];
+ if (i < 0)
+ return false; /* list is NOT ordered, punt */
+ }
+
+ /* advance to next range if pagenum past the end of this range */
+ /* stopping at the 0, 0, 0 marker (start == 0) */
+ while (pagenum > parray[i+2] && parray[i+1] != 0) {
+ i += 3; /* bump to next range for next call */
+ parray[0] = i; /* update for next entry */
+ }
+ if (parray[i+1] == 0)
+ return false; /* reached end of ranges */
+
+ /* First Test even, then odd */
+ if (parray[i] == 2 && (pagenum & 1) == 1)
+ return false;
+ if (parray[i] == 1 && (pagenum & 1) == 0)
+ return false;
+
+ /* Fast case for ordered list and sequential page numbers (FLP device) */
+ if (i > 0) {
+ if (pagenum >= parray[i+1] && pagenum <= parray[i+2]) {
+ return true; /* page was in this range */
+ } else {
+ if (pagenum < parray[i+1])
+ return false; /* pagennum in between ranges that skip */
+ }
+ }
+ return false;
+}
+
+void
+pagelist_free_range_array(gs_memory_t *mem, int *parray)
+{
+ gs_free_object(mem, parray, "flp_close_device");
+}
diff --git a/base/pagelist.h b/base/pagelist.h
new file mode 100644
index 000000000..832b21572
--- /dev/null
+++ b/base/pagelist.h
@@ -0,0 +1,33 @@
+/* Copyright (C) 2022-2022 Artifex Software, Inc.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied,
+ modified or distributed except as expressly authorized under the terms
+ of the license contained in the file LICENSE in this distribution.
+
+ Refer to licensing information at http://www.artifex.com or contact
+ Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato,
+ CA 94945, U.S.A., +1(415)492-9861, for further information.
+*/
+
+/* Functions to parse a PageList string and processing utilitiess */
+
+/* Allocate an array of ranges. A range of 0-0 terminates the list */
+/* array contains even/odd flag, start, end (3 ints per range). */
+/* returns error code < 0 or number of ranges if success */
+int pagelist_parse_to_array(char *pPageList, gs_memory_t *mem, int num_pages, int **parray);
+
+/* function to calculate the total number of pages to be output */
+int pagelist_number_of_pages(const int *parray);
+
+/* Return true if this pagelist is in strict increasing order */
+bool pagelist_test_ordered(int *parray);
+
+/* Return true if this page is to be printed (for sequential processing) */
+/* This assumes that the PageList is strictly sequential, tested by client. */
+bool pagelist_test_printed(int *parray, int pagenum);
+
+void pagelist_free_range_array(gs_memory_t *mem, int *parray);
diff --git a/doc/Language.htm b/doc/Language.htm
index 44c569d96..25aa67ef6 100644
--- a/doc/Language.htm
+++ b/doc/Language.htm
@@ -2096,10 +2096,11 @@ It has no effect in the new PDF interpreter but is maintained for backwards comp
media and render the page.</dd>
<dt><code>&ltint&gt &ltint&gt dopdfpages -</code></dt>
<dd> The integers are the first and last pages to be run from the file. Runs a loop from
- the fist integer to the last. NOTE! If the current dictionary contains a PDFPageList
- array then we 'get' the entry from the array corresponding to the current loop
- index, and use that to determine whether we should draw the page. Otherwise we
- simply draw the page. Uses pdfshowpage to actually render the page.</dd>
+ the fist integer to the last.
+ <p>NOTE! If the current dictionary contains a PDFPageList array the two values on the stack
+ are ignored and we use the range triples from that array (even/odd, start, end) to determine
+ the pages to process. Page numbers for start and end are 1..lastpage and even/odd is 1
+ for odd, 2 for even, otherwise 0. Uses pdfshowpage to actually render the page.</dd>
<dt><code>- runpdfpagerange &ltint&gt &ltint&gt</code></dt>
<dd> Processes the PostScript /FirstPage, /LastPage and /PageList parameters. These are used together to build an internal array
of page numbers to run, which is used by dopdfpages to actually process the pages if PageList is present,
diff --git a/doc/Use.htm b/doc/Use.htm
index 33e4f679b..86668c1c4 100644
--- a/doc/Use.htm
+++ b/doc/Use.htm
@@ -786,32 +786,47 @@ be drawn, whilst those not listed will not be drawn.</p>
<dd>Stop after the designated page of the document.
Pages of all documents in PDF collections are numbered sequentionally.</dd>
</dl>
+<p>
+</pre></blockquote>
+NOTE: The PDF and XPS interpreters allow the use of a -dLastPage less than -dFirstPage. In this
+case the pages will be processed backwards from LastPage to FirstPage.
+</p>
<dl>
- <dt><code>-sPageList=</code><em>pagenumber</em></dt>
+ <dt><code>-sPageList=</code><em>pageranges</em></dt>
-<dd>There are three possible values for this; even, odd or a list of pages to be processed.
-A list can include single pages or ranges of pages.
-Ranges of pages use the minus sign '-', individual pages and ranges of pages are separated
-by commas ','. A trailing minus '-' means process all remaining pages. For example;
+<dd>Page ranges are separated by a comma ','. Each range of pages can consist of:
+<p><blockquote><pre>
+(a) a single page number.
+(b) a range with a starting page number, followed by a dash '-' followed by an ending page number.
+(c) a range with a starting page number, followed by a dash '-' which ends at the last page.
+(d) the keyword "even" or "odd", which optionally can be followed by a colon ':' and a page range.
+ If there is no page range then all even or odd pages are processed in forward order.
+(e) a range with an initial dash '-' followed by and ending page number which starts at the
+ last page and ends at the specified page <i>(PDF and XPS only)</i>.
+</pre></blockquote>
+For example:
<p><blockquote><pre>
-sPageList=1,3,5 indicates that pages 1, 3 and 5 should be processed.
-sPageList=5-10 indicates that pages 5, 6, 7, 8, 9 and 10 should be processed.
-sPageList=1,5-10,12- indicates that pages 1, 5, 6, 7, 8, 9, 10 and 12 onwards should be processed.
+-sPageList=odd:3-7,9-,-1,8 processes pages 3, 5, 7, 9, 10, 11, ..., last, last, last-1, ..., 1, 8
</pre></blockquote>
-Note: Use of PageList overrides FirstPage and/or LastPage, if you set these as well as PageList they will be ignored. The
- list of pages should be given in increasing order, you cannot process pages out of order and inserting higher numbered pages before lower numbered
- pages in the list will generate an error.
+Note: Use of PageList overrides FirstPage and/or LastPage, if you set these as well as PageList they will be ignored.
</p>
-
-<p>The PDF interpreter and the other language interpreters handle these in slightly different ways. Because
-PDF files enable random access to pages in the document the PDF inerpreter only interprets and renders
-the required pages. PCL and PostScript cannot be handled in ths way, and so all the pages must be interpreted.
-However only the requested pages are rendered, which can still lead to savings in time. Be aware that
-using the '%d' syntax for OutputFile does not reflect the page number in the original document. If you
-chose (for example) to process even pages by using <code>-sPageList=even</code>, then the output of
+<p>
+Be aware that using the <code>%d</code> syntax for <code>-sOutputFile=...</code> does not reflect the page number in the original document.
+If you chose (for example) to process even pages by using <code>-sPageList=even</code>, then the output of
<code>-sOutputFile=out%d.png</code> would still be
-out0.png, out1.png, out2.png etc......
+out1.png, out2.png, out3.png etc......
+</p>
+<p>
+For PostScript or PCL input files, the list of pages must be given in increasing order, you cannot process pages out of order or
+repeat pages and this will generate an error. PCL and PostScript require that all the pages must be interpreted,
+however since only the requested pages are rendered, this can still lead to savings in time.
+</p>
+<p>The PDF and XPS interpreters handle this in a slightly different way. Because these file types provide for random access to
+individual pages in the document these inerpreters only need to process the required pages, and can do so in any order.
</p>
<p>
Because the PostScript and PCL interpreters cannot determine when a document terminates, sending multple
@@ -824,17 +839,6 @@ is applied to each PDF file separately. So if you were to set <code>-sPageList=1
exercise caution when using this switch, and probably should not use it at all when processing a mixture of PostScript
and PDF files on the same command line.
</p>
-<p>
-The XPS language like the PDF language allows random access to pages. The XPS interpreter handles all the PageList cases
-discussed above. It also handles cases such as:
-<blockquote><pre>
--sPageList=1,2,1,2 indicates repeated pages. Pages processed in order 1, 2, 1, 2.
--sPageList=10-5 indicates pages will be processed in the order 10, 9, 8, 7, 6, 5.
--sPageList=1-,-1 indicates first processing from page 1 to end and then from end to page 1.
-</pre></blockquote>
-In addition, the XPS interpreter allows the use of a -dLastPage < -dFirstPage. In this
-case the pages will be processed backwards from LastPage to FirstPage.
-</p>
</dd>
</dl>
diff --git a/psi/zpdfops.c b/psi/zpdfops.c
index 7023592b0..50b8b1b5a 100644
--- a/psi/zpdfops.c
+++ b/psi/zpdfops.c
@@ -30,6 +30,7 @@
#include "iminst.h"
#include "dstack.h"
#include "gsicc_profilecache.h"
+#include "pagelist.h"
#endif
#include "ghost.h"
@@ -1453,6 +1454,36 @@ error:
}
return code;
}
+
+/* <Pagelist_string> num_pages .PDFparsePageList even/odd, start, end ... range_count */
+/* PostScript will create an array of 3 integers per range */
+static int zPDFparsePageList(i_ctx_t *i_ctx_p)
+{
+ int code = 0, size = 0, i;
+ os_ptr op = osp;
+ int *page_range_array;
+ int num_pages = op->value.intval;
+
+ code = pagelist_parse_to_array((char *)((op - 1)->value.const_bytes), imemory, num_pages, &page_range_array);
+ make_int(op, 0); /* default return 0 */
+ if (code < 0) {
+ return code;
+ }
+ /* code returned is the number of ranges */
+ size = 3 * (code - 1); /* runpdfpagerange doesn't use 0, 0, 0 marker at end */
+ code = ref_stack_push(&o_stack, size - 1);
+ if (code < 0) {
+ return code;
+ }
+ /* push the even/odd, start, end triples on the stack */
+ for (i=0; i < size; i++) {
+ /* skip the initial "ordered" flag */
+ make_int(ref_stack_index(&o_stack, size - i), page_range_array[i+1]);
+ }
+ make_int(ref_stack_index(&o_stack, 0), size);
+ pagelist_free_range_array(imemory, page_range_array); /* all done with C array */
+ return 0;
+}
#else
static int zPDFfile(i_ctx_t *i_ctx_p)
@@ -1499,6 +1530,11 @@ static int zPDFInit(i_ctx_t *i_ctx_p)
{
return_error(gs_error_undefined);
}
+
+static int zPDFparsePageList(i_ctx_t *i_ctx_p)
+{
+ return_error(gs_error_undefined);
+}
#endif
/* ------ Initialization procedure ------ */
@@ -1518,6 +1554,7 @@ const op_def zpdfops_op_defs[] =
{"1.PDFDrawPage", zPDFdrawpage},
{"1.PDFDrawAnnots", zPDFdrawannots},
{"1.PDFInit", zPDFInit},
+ {"1.PDFparsePageList", zPDFparsePageList},
#ifdef HAVE_LIBIDN
{"1.saslprep", zsaslprep},
#endif
diff --git a/xps/xpszip.c b/xps/xpszip.c
index 13f698ac5..c71bb9684 100644
--- a/xps/xpszip.c
+++ b/xps/xpszip.c
@@ -17,6 +17,7 @@
/* XPS interpreter - zip container parsing */
#include "ghostxps.h"
+#include "pagelist.h"
static int isfile(gs_memory_t *mem, char *path)
{
@@ -263,7 +264,7 @@ xps_read_zip_dir(xps_context_t *ctx, int start_offset)
(void) getlong(ctx->file); /* ext file atts */
ctx->zip_table[i].offset = getlong(ctx->file);
- if (ctx->zip_table[i].csize < 0 || ctx->zip_table[i].usize < 0)
+ if (ctx->zip_table[i].csize < 0 || ctx->zip_table[i].usize < 0)
return gs_throw(gs_error_ioerror, "cannot read zip entries larger than 2GB");
ctx->zip_table[i].name = xps_alloc(ctx, namesize + 1);
@@ -611,51 +612,11 @@ xps_reorder_add_page(xps_context_t* ctx, xps_page_t ***page_ptr, xps_page_t* pag
return 0;
}
-static char*
-xps_reorder_get_range(xps_context_t *ctx, char *page_list, int *start, int *end, int num_pages)
-{
- int comma, dash, len;
-
- len = strlen(page_list);
- comma = strcspn(page_list, ",");
- dash = strcspn(page_list, "-");
-
- if (dash < comma)
- {
- /* Dash at start */
- if (dash == 0)
- {
- *start = num_pages;
- *end = atoi(&(page_list[dash + 1]));
- }
- else
- {
- *start = atoi(page_list);
-
- /* Dash at end */
- if (page_list[dash + 1] == 0 || page_list[dash + 1] == ',')
- {
- *end = num_pages;
- }
- else
- {
- *end = atoi(&(page_list[dash + 1]));
- }
- }
- }
- else
- {
- *start = atoi(page_list);
- *end = *start;
- }
- return comma == len ? page_list + comma : page_list + comma + 1;
-}
static int
xps_reorder_pages(xps_context_t *ctx)
{
char *page_list = ctx->page_range->page_list;
- char *str;
xps_page_t **page_ptr_array, *page = ctx->first_page;
int count = 0, k;
int code;
@@ -664,6 +625,8 @@ xps_reorder_pages(xps_context_t *ctx)
xps_page_t* first_page = NULL;
xps_page_t* last_page;
xps_page_t** page_tail = &first_page;
+ int *page_range_array;
+ int ranges_count = 0;
if (page == NULL)
return 0;
@@ -686,80 +649,37 @@ xps_reorder_pages(xps_context_t *ctx)
page = page->next;
}
- if (strcmp(page_list, "even") == 0)
- {
- for (k = 1; k < count; k += 2)
- {
- code = xps_reorder_add_page(ctx, &page_tail, page_ptr_array[k]);
- if (code < 0)
- return code;
- }
- }
- else if (strcmp(page_list, "odd") == 0)
- {
- for (k = 0; k < count; k += 2)
- {
- code = xps_reorder_add_page(ctx, &page_tail, page_ptr_array[k]);
- if (code < 0)
- return code;
- }
- }
- else
- {
- /* Requirements. All characters must be 0 to 9 or - and ,
- No ,, or -- */
- str = page_list;
- do
- {
- if (*str != ',' && *str != '-' && (*str < 0x30 || *str > 0x39))
- return gs_throw(gs_error_typecheck, "Bad page list: xps_reorder_pages\n");
-
- if ((*str == ',' && *(str + 1) == ',') || (*str == '-' && *(str + 1) == '-'))
- return gs_throw(gs_error_typecheck, "Bad page list: xps_reorder_pages\n");
- }
- while (*(++str));
-
- str = page_list;
- do
- {
- /* Process each comma separated item. */
- str = xps_reorder_get_range(ctx, str, &start, &end, count);
+ /* Use the common function to parse the page_list into a 'page_range_array' */
+ ranges_count = pagelist_parse_to_array(page_list, ctx->memory, count, &page_range_array);
+ if (ranges_count <= 0)
+ return gs_throw(gs_error_typecheck, "Bad page list: xps_reorder_pages\n");
- /* Threshold page range */
- if (start > count)
- start = count;
+ ranges_count--; /* ignore the final marker range 0, 0, 0 */
- if (end > count)
- end = count;
+ /* start processing ranges, ignoring the "ordered" flag at the start of the array */
+ for (k = 1; k < 1 + 3 * ranges_count; k += 3) {
+ start = page_range_array[k+1];
+ end = page_range_array[k+2];
- /* Add page(s) */
- if (start == end)
- {
+ if (start == end)
+ code = xps_reorder_add_page(ctx, &page_tail, page_ptr_array[start - 1]);
+ else if (start < end) {
+ do {
code = xps_reorder_add_page(ctx, &page_tail, page_ptr_array[start - 1]);
if (code < 0)
- return code;
- }
- else if (start < end)
- {
- for (k = start - 1; k < end; k++)
- {
- code = xps_reorder_add_page(ctx, &page_tail, page_ptr_array[k]);
- if (code < 0)
- return code;
- }
- }
- else
- {
- for (k = start; k >= end; k--)
- {
- code = xps_reorder_add_page(ctx, &page_tail, page_ptr_array[k - 1]);
- if (code < 0)
- return code;
- }
- }
+ break;
+ start += ((page_range_array[k] == 0) ? 1 : 2); /* double bump for even/odd */
+ } while (start <= end);
+ } else { /* start > end -- reverse direction */
+ do {
+ code = xps_reorder_add_page(ctx, &page_tail, page_ptr_array[start - 1]);
+ if (code < 0)
+ break;
+ start -= ((page_range_array[k] == 0) ? 1 : 2); /* double bump for even/odd */
+ } while (start >= end);
}
- while (*str);
}
+ pagelist_free_range_array(ctx->memory, page_range_array); /* done with all ranges */
/* Replace the pages. */
if (first_page != NULL)
@@ -775,7 +695,7 @@ xps_reorder_pages(xps_context_t *ctx)
else
return gs_throw(gs_error_rangecheck, "Bad page list: xps_reorder_pages\n");
- return 0;
+ return code;
}
/*