001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /* $Id$ */
019:
020: package org.apache.xmlgraphics.ps.dsc.tools;
021:
022: import java.io.IOException;
023: import java.io.InputStream;
024: import java.io.OutputStream;
025:
026: import org.apache.xmlgraphics.ps.DSCConstants;
027: import org.apache.xmlgraphics.ps.PSGenerator;
028: import org.apache.xmlgraphics.ps.dsc.DSCException;
029: import org.apache.xmlgraphics.ps.dsc.DSCFilter;
030: import org.apache.xmlgraphics.ps.dsc.DSCParser;
031: import org.apache.xmlgraphics.ps.dsc.DSCParserConstants;
032: import org.apache.xmlgraphics.ps.dsc.DefaultNestedDocumentHandler;
033: import org.apache.xmlgraphics.ps.dsc.events.DSCComment;
034: import org.apache.xmlgraphics.ps.dsc.events.DSCCommentPage;
035: import org.apache.xmlgraphics.ps.dsc.events.DSCCommentPages;
036: import org.apache.xmlgraphics.ps.dsc.events.DSCEvent;
037: import org.apache.xmlgraphics.ps.dsc.events.DSCHeaderComment;
038:
039: /**
040: * This class can extract a certain range of pages from a DSC-compliant PostScript file.
041: */
042: public class PageExtractor implements DSCParserConstants {
043:
044: /**
045: * Parses a DSC-compliant file and pipes the content through to the OutputStream omitting
046: * all pages not within the range.
047: * @param in the InputStream to parse from
048: * @param out the OutputStream to write the modified file to
049: * @param from the starting page (1-based)
050: * @param to the last page (inclusive, 1-based)
051: * @throws IOException In case of an I/O error
052: * @throws DSCException In case of a violation of the DSC spec
053: */
054: public static void extractPages(InputStream in, OutputStream out,
055: int from, int to) throws IOException, DSCException {
056: if (from <= 0) {
057: throw new IllegalArgumentException(
058: "'from' page number must be 1 or higher");
059: }
060: if (to < from) {
061: throw new IllegalArgumentException(
062: "'to' page number must be equal or larger than the 'from' page number");
063: }
064:
065: DSCParser parser = new DSCParser(in);
066: PSGenerator gen = new PSGenerator(out);
067: parser
068: .setNestedDocumentHandler(new DefaultNestedDocumentHandler(
069: gen));
070: int pageCount = 0;
071:
072: //Skip DSC header
073: DSCHeaderComment header = DSCTools
074: .checkAndSkipDSC30Header(parser);
075: header.generate(gen);
076: //Set number of pages
077: DSCCommentPages pages = new DSCCommentPages(to - from + 1);
078: pages.generate(gen);
079:
080: parser.setFilter(new DSCFilter() {
081: public boolean accept(DSCEvent event) {
082: if (event.isDSCComment()) {
083: //Filter %%Pages which we add manually above
084: return !event.asDSCComment().getName().equals(
085: DSCConstants.PAGES);
086: } else {
087: return true;
088: }
089: }
090: });
091:
092: //Skip the prolog and to the first page
093: DSCComment pageOrTrailer = parser.nextDSCComment(
094: DSCConstants.PAGE, gen);
095: if (pageOrTrailer == null) {
096: throw new DSCException("Page expected, but none found");
097: }
098: parser.setFilter(null); //Remove filter
099:
100: //Process individual pages (and skip as necessary)
101: while (true) {
102: DSCCommentPage page = (DSCCommentPage) pageOrTrailer;
103: boolean validPage = (page.getPagePosition() >= from && page
104: .getPagePosition() <= to);
105: if (validPage) {
106: page.setPagePosition(page.getPagePosition() - from + 1);
107: page.generate(gen);
108: pageCount++;
109: }
110: pageOrTrailer = DSCTools.nextPageOrTrailer(parser,
111: (validPage ? gen : null));
112: if (pageOrTrailer == null) {
113: throw new DSCException(
114: "File is not DSC-compliant: Unexpected end of file");
115: } else if (!DSCConstants.PAGE.equals(pageOrTrailer
116: .getName())) {
117: pageOrTrailer.generate(gen);
118: break;
119: }
120: }
121:
122: //Write the rest
123: while (parser.hasNext()) {
124: DSCEvent event = parser.nextEvent();
125: event.generate(gen);
126: }
127: }
128:
129: }
|