Package org.apache.harmony.x.print

Source Code of org.apache.harmony.x.print.PSInterpreter

/*
*  Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  See the NOTICE file distributed with
*  this work for additional information regarding copyright ownership.
*  The ASF licenses this file to You under the Apache License, Version 2.0
*  (the "License"); you may not use this file except in compliance with
*  the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
/**
* @author Aleksei V. Ivaschenko
*/

package org.apache.harmony.x.print;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

import javax.print.DocFlavor;
import javax.print.PrintException;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.MediaSize;
import javax.print.attribute.standard.MediaSizeName;
import javax.print.attribute.standard.OrientationRequested;

/*
* This class implements PostScript interpreter, which
* converts PostScript instructions to GDI function calls.
* Renders to specified printer's device context.
*/
public class PSInterpreter {

    private GDIClient client = null;
    private String service = null;
    private int serviceID = -1;
    private PrintRequestAttributeSet attributes = null;
   
    private BufferedReader source = null;
    private ArrayList queue = new ArrayList();
    private String currentLine = null;
    private int lineIndex = 0;
    private int searchingIndex = 0;

    private int translateX = 0, translateY = 0;
    private int scaleWidth = -1, scaleHeight = -1;
    private double scaleX = 1.0, scaleY = 1.0;
    private boolean pathOpened = false;
    private boolean closedPathExists = false;
    private int logWidth = 0;
    private int logHeight = 0;
   
    private static final int COMMAND_MOVETO = 0;
    private static final int COMMAND_LINETO = 1;
    private static final int COMMAND_SETRGBCOLOR = 2;
    private static final int COMMAND_STROKE = 3;
    private static final int COMMAND_COLORIMAGE = 4;
    private static final int COMMAND_TRANSLATE = 5;
    private static final int COMMAND_SCALE = 6;
    private static final int COMMAND_ARC = 7;
    private static final int COMMAND_SHOW = 8;
    private static final int COMMAND_NEWPATH = 9;
    private static final int COMMAND_CLOSEPATH = 10;
    private static final int COMMAND_FILL = 11;
    private static final int COMMAND_FINDFONT = 12;
    private static final int COMMAND_SCALEFONT = 13;
    private static final int COMMAND_SETFONT = 14;
    private static final int COMMAND_ROTATE = 15;
    private static final int COMMAND_CLIP = 16;
   
    private static final String hexLetters = "0123456789abcdef";
   
    private static final String[] commands = {
        "moveto",
        "lineto",
        "setrgbcolor",
        "stroke",
        "colorimage",
        "translate",
        "scale",
        "arc",
        "show",
        "newpath",
        "closepath",
        "fill",
        "findfont",
        "scalefont",
        "setfont",
        "rotate",
        "clip"
    };

    private static final int[] commandsParams = {
        2, 2, 3, 0, 7, 2, 2, 5, 1, 0, 0, 0, 1, 1, 1, 0, 0
    };

    /*
     * Constructs new PSInterpreter instance.
     */
    public PSInterpreter(InputStream source, String service, GDIClient client,
            PrintRequestAttributeSet attributes) {
        this.source = new BufferedReader(new InputStreamReader(source));
        this.service = service;
        this.client = client;
        this.attributes = attributes;
        if (service != null) {
            getPaperDimensions(attributes);
            serviceID = obtainServiceID(service, logWidth, logHeight);
        }
    }
   
    /*
     * Sets up print service. Further rendering is made
     * to new print service's device context.
     */
    public void setPrintService(String service) {
        this.service = service;
        if (serviceID >= 0) {
            releaseServiceID(serviceID);
            serviceID = -1;
        }
        if (service != null) {
            getPaperDimensions(attributes);
            serviceID = obtainServiceID(service, logWidth, logHeight);
        }
    }
   
    /*
     * Starts parsing of source postscript and rendering
     * to print service's device context.
     */
    public void interpret() throws PrintException {
        if (serviceID < 0) {
            throw new PrintException(
                    "Unrecoverable internal error in GDI client.");
        }
        try {
            currentLine = source.readLine();
            while (currentLine != null) {
                if (currentLine.startsWith("%%EOF")) {
//                    /*
//                     * Code for debug. Prints additional page.
//                     */
//                    startPage(serviceID);
//                    setRGBColor(serviceID, 0.5, 0.5, 0.5);
//                    moveTo(serviceID, 50, 50);
//                    drawText(serviceID, "TEXT TEXT TEXT");
//                    endPage(serviceID);
                    if (!endDocument(serviceID)) {
                        releaseServiceID(serviceID);
                        serviceID = -1;
                        throw new PrintException(
                                "Unable to finish document printing.");
                    }
                    releaseServiceID(serviceID);
                    serviceID = -1;
                    return;
                } else if (currentLine.startsWith("%%")) {
                    interpretComment();
                } else if (currentLine.startsWith("%") ||
                           currentLine.startsWith("/")) {
                    // Nothing to do - simple comment.
                } else {
                    String lexem = getNextLexem();
                    while (lexem != null) {
//                        System.out.println("Lexem: " + lexem);
                        queue.add(lexem);
                        for (int i = 0; i < commands.length; i++) {
                            if (lexem.equals(commands[i])) {
                                interpretCommand(i);
                            }
                        }
                        lexem = getNextLexem();
                    }
                }
                currentLine = source.readLine();
                lineIndex = 0;
            }
            endDocument(serviceID);
        } catch (IOException ioe) {
            throw new PrintException(
                    "Unrecoverable internal error in GDI client.");
        }
    }
   
    private String getNextLexem() throws IOException {
        String lexem = getNextLexem(currentLine, lineIndex);
        if (lexem.endsWith(")") || lexem.endsWith("]")) {
            currentLine = source.readLine();
            lineIndex = 0;
            String prefix = (lexem.endsWith(")")) ? "( " : "[ ";
            String endOfLexem = getNextLexem(prefix + currentLine, lineIndex);
            if (lexem.length() == 1) {
                lexem = endOfLexem;
            } else {
                lexem = lexem.substring(0, lexem.length() - 1) + endOfLexem;
            }
            lineIndex = searchingIndex - 2;
        } else if (lexem.equals("}")) {
            while (lexem.equals("}")) {
                currentLine = source.readLine();
                lineIndex = 0;
                lexem = getNextLexem("{" + currentLine, lineIndex);
                lineIndex = searchingIndex;
            }
        } else {
            lineIndex = searchingIndex;
            if (lexem.equals("") && lineIndex >= currentLine.length()) {
                return null;
            }
        }
        return lexem;
    }

    private String getNextLexem(String line, int index) {
        String lexem = "";
        if (index < line.length()) {
            String character = line.substring(index++, index);
            while (index < line.length() && character.equals(" ")) {
                character = line.substring(index++, index);
            }
            if (!character.equals(" ")) {
                if (character.equals("%")) {
                    searchingIndex = line.length();
                    return lexem;
                } else if (character.equals("(")) {
                    if (index >= line.length()) {
                        searchingIndex = index;
                        return ")";
                    }
                    character = line.substring(index++, index);
                    while (!character.equals(")")) {
                        lexem += character;
                        if (index < line.length()) {
                            character = line.substring(index++, index);
                        } else {
                            lexem += ")";
                            break;
                        }
                    }
                } else if (character.equals("[")) {
                    if (index >= line.length()) {
                        searchingIndex = index;
                        return "]";
                    }
                    character = line.substring(index++, index);
                    while (!character.equals("]")) {
                        lexem += character;
                        if (index < line.length()) {
                            character = line.substring(index++, index);
                        } else {
                            lexem += "]";
                            break;
                        }
                    }
                } else if (character.equals("{")) {
                    if (index >= line.length()) {
                        searchingIndex = index;
                        return "}";
                    }
                    character = line.substring(index++, index);
                    while (!character.equals("}")) {
                        if (index < line.length()) {
                            character = line.substring(index++, index);
                        } else {
                            lexem = "}";
                            break;
                        }
                    }
                } else {
                    if (index >= line.length()) {
                        searchingIndex = index;
                        return character;
                    }
                    while (!character.equals(" ")) {
                        lexem += character;
                        if (index < line.length()) {
                            character = line.substring(index++, index);
                        } else {
                            break;
                        }
                    }
                }
            }
        }
        searchingIndex = index;
        return lexem;
    }

    private String getNextHexLetter() throws IOException {
        String hex = null;
        if (lineIndex < currentLine.length()) {
            String character =
                currentLine.substring(lineIndex++, lineIndex).toLowerCase();
            while (hexLetters.indexOf(character) < 0) {
                if (lineIndex < currentLine.length()) {
                    character =
                        currentLine.substring(lineIndex++,
                                              lineIndex).toLowerCase();
                } else {
                    currentLine = source.readLine();
                    lineIndex = 0;
                    return getNextHexLetter();
                }
            }
            hex = character;
        } else {
            currentLine = source.readLine();
            lineIndex = 0;
            return getNextHexLetter();
        }
        return hex;
    }

    private String getNextHex() throws IOException {
        return getNextHexLetter() + getNextHexLetter();
    }
   
    private int hex2decimal(String hex) {
        int multiplier = 1;
        int decimal = 0;
        for (int i = hex.length() - 1; i >= 0; i--) {
            decimal += hexLetters.indexOf(hex.substring(i, i + 1)) * multiplier;
            multiplier *= 16;
        }
        return decimal;
    }
   
    private void interpretComment() throws PrintException {
        if (currentLine.startsWith("%%Page:")) {
            try {
                String pageName = getNextLexem(currentLine, 7);
                String pageNumber = getNextLexem(currentLine, searchingIndex);
                int number = Integer.parseInt(pageNumber);
                if (!startPage(serviceID)) {
                    endDocument(serviceID);
                    throw new PrintException("Unable to start page printing.");
                }
            } catch (NumberFormatException nfe) {
                System.out.println("NumberFormatException occured: " + nfe);
                nfe.printStackTrace(System.out);
            }
        } else if (currentLine.startsWith("%%EndPage:")) {
            try {
                String pageName = getNextLexem(currentLine, 10);
                String pageNumber = getNextLexem(currentLine, searchingIndex);
                int number = Integer.parseInt(pageNumber);
                if (pathOpened) {
                    closePath(serviceID);
                    pathOpened = false;
                }
                endPage(serviceID);
            } catch (NumberFormatException nfe) {
                System.out.println("NumberFormatException occured: " + nfe);
                nfe.printStackTrace(System.out);
            }
        } else if (currentLine.startsWith("%%EndSetup") ||
                   currentLine.startsWith("%%EndComments")) {
            if (!startDocument(service, serviceID, client.convertAttributes(
                    attributes,
                    new DocFlavor.INPUT_STREAM("INTERNAL/postscript")),
                    client.getJobName(attributes),
                    client.getDestination(attributes))) {
                throw new PrintException("Unable to start document printing.");
            }
        }
    }

    private void interpretCommand(int command) throws IOException {
        if (queue.size() < commandsParams[command] + 1) {
            System.out.println("Not enough parameters for PS command "
                    + commands[command]);
            return;
        }
        queue.remove(queue.size() - 1);
        switch (command) {
            case COMMAND_MOVETO:
                try {
                    double x, y;
                    y = Double.parseDouble(extractQueueLast());
                    x = Double.parseDouble(extractQueueLast());
                    if (!pathOpened) {
                        beginPath(serviceID);
                        pathOpened = true;
                    }
                    moveTo(serviceID, x, y);
                } catch (NumberFormatException nfe) {
                    System.out.println("NumberFormatException occured: " + nfe);
                    nfe.printStackTrace(System.out);
                }
                break;
            case COMMAND_LINETO:
                try {
                    double x, y;
                    y = Double.parseDouble(extractQueueLast());
                    x = Double.parseDouble(extractQueueLast());
                    if (!pathOpened) {
                        beginPath(serviceID);
                        pathOpened = true;
                    }
                    lineTo(serviceID, x, y);
                } catch (NumberFormatException nfe) {
                    System.out.println("NumberFormatException occured: " + nfe);
                    nfe.printStackTrace(System.out);
                }
                break;
            case COMMAND_SETRGBCOLOR:
                try {
                    double r, g, b;
                    b = Double.parseDouble(extractQueueLast());
                    g = Double.parseDouble(extractQueueLast());
                    r = Double.parseDouble(extractQueueLast());
                    setRGBColor(serviceID, r, g, b);
                } catch (NumberFormatException nfe) {
                    System.out.println("NumberFormatException occured: " + nfe);
                    nfe.printStackTrace(System.out);
                }
                break;
            case COMMAND_NEWPATH:
                beginPath(serviceID);
                pathOpened = true;
                break;
            case COMMAND_CLOSEPATH:
                if (pathOpened) {
                    closePath(serviceID);
                    pathOpened = false;
                    closedPathExists = true;
                }
                break;
            case COMMAND_STROKE:
                if (pathOpened) {
                    closePath(serviceID);
                    strokePath(serviceID);
                    pathOpened = false;
                } else if (closedPathExists) {
                    strokePath(serviceID);
                    closedPathExists = false;
                }
                break;
            case COMMAND_FILL:
                if (pathOpened) {
                    closePath(serviceID);
                    fillPath(serviceID);
                    pathOpened = false;
                } else if (closedPathExists) {
                    fillPath(serviceID);
                    closedPathExists = false;
                }
                break;
            case COMMAND_COLORIMAGE:
                if (extractQueueLast().equals("3") &&
                    extractQueueLast().equals("false")) {
                    try {
                        extractQueueLast(); // removing reading procedure
                        String imageParams = extractQueueLast();
                        int depth = Integer.parseInt(extractQueueLast());
                        int height = Integer.parseInt(extractQueueLast());
                        int width = Integer.parseInt(extractQueueLast());
                        if (depth == 8) {
                            int[] imageData = new int[width * height];
                            for (int j = 0; j < height; j++) {
                                for (int i = 0; i < width; i++) {
                                    int color = hex2decimal(getNextHex() +
                                                            getNextHex() +
                                                            getNextHex());
                                    imageData[j * width + i] = color;
                                }
                            }
                            if (scaleWidth < 0 || scaleHeight < 0) {
                                drawImage(serviceID, translateX, translateY,
                                       width * scaleX, height * scaleY,
                                       imageData, width, height);
                            } else {
                                drawImage(serviceID, translateX, translateY,
                                        scaleWidth, scaleHeight,
                                        imageData, width, height);
                            }
                        }
                    } catch (NumberFormatException nfe) {
                        System.out.println("NumberFormatException occured: " +
                                nfe);
                        nfe.printStackTrace(System.out);
                    }
                }
                break;
            case COMMAND_TRANSLATE:
                try {
                    translateY = Integer.parseInt(extractQueueLast());
                    translateX = Integer.parseInt(extractQueueLast());
                } catch (NumberFormatException nfe) {
                    System.out.println("NumberFormatException occured: " + nfe);
                    nfe.printStackTrace(System.out);
                }
                break;
            case COMMAND_SCALE:
                try {
                    scaleY = Double.parseDouble(extractQueueLast());
                    scaleX = Double.parseDouble(extractQueueLast());
                } catch (NumberFormatException nfe) {
                    System.out.println("NumberFormatException occured: " + nfe);
                    nfe.printStackTrace(System.out);
                }
                break;
            case COMMAND_ARC:
                try {
                    double x, y, r, a, b;
                    b = Double.parseDouble(extractQueueLast());
                    a = Double.parseDouble(extractQueueLast());
                    r = Double.parseDouble(extractQueueLast());
                    y = Double.parseDouble(extractQueueLast());
                    x = Double.parseDouble(extractQueueLast());
                    if (!pathOpened) {
                        beginPath(serviceID);
                        pathOpened = true;
                    }
                    drawArc(serviceID, x, y, r, a, b);
                } catch (NumberFormatException nfe) {
                    System.out.println("NumberFormatException occured: " + nfe);
                    nfe.printStackTrace(System.out);
                }
                break;
            case COMMAND_SHOW:
                String text = extractQueueLast();
                drawText(serviceID, text);
                break;
            default:
        }
    }

    private String extractQueueLast() {
        String lexem = (String)queue.get(queue.size() - 1);
        queue.remove(queue.size() - 1);
        return lexem;
    }

    private void getPaperDimensions(PrintRequestAttributeSet attrs) {
        MediaSize size = null;
        if (attrs != null) {
            if (attrs.containsKey(MediaSize.class)) {
                size = (MediaSize) attrs.get(MediaSize.class);
            } else if (attrs.containsKey(MediaSizeName.class)) {
                MediaSizeName name =
                    (MediaSizeName)attrs.get(MediaSizeName.class);
                size = MediaSize.getMediaSizeForName(name);
            } else {
                size = MediaSize.getMediaSizeForName(MediaSizeName.ISO_A4);
            }
        } else {
            size = MediaSize.getMediaSizeForName(MediaSizeName.ISO_A4);
        }
        logWidth = (int) (size.getX(MediaSize.INCH) * 72.0);
        logHeight = (int) (size.getY(MediaSize.INCH) * 72.0);
        if (attributes != null) {
            if (attributes.containsValue(
                    OrientationRequested.LANDSCAPE)) {
                int temp = logWidth;
                logWidth = logHeight;
                logHeight = temp;
            }
        }
    }
   
    private synchronized static native int obtainServiceID(String name,
            int width, int height);
    private synchronized static native void releaseServiceID(int serviceID);
    private static native boolean startDocument(String name, int serviceID,
            int[] attributes, String jobName, String destination);
    private static native boolean startPage(int serviceID);
    private static native boolean endPage(int serviceID);
    private static native boolean endDocument(int serviceID);
   
    private static native boolean setRGBColor(int serviceID, double red,
            double green, double blue);
    private static native boolean moveTo(int serviceID, double x, double y);
    private static native boolean lineTo(int serviceID, double x, double y);
    private static native boolean drawArc(int serviceID, double x, double y,
            double r, double a, double b);
    private static native boolean drawText(int serviceID, String text);
    private static native boolean drawImage(int serviceID, double x, double y,
            double scalew, double scaleh, int[] image, int w, int h);
    private static native boolean beginPath(int serviceID);
    private static native boolean closePath(int serviceID);
    private static native boolean strokePath(int serviceID);
    private static native boolean fillPath(int serviceID);
    private static native boolean clipPath(int serviceID);
    private static native boolean rotate(int serviceID, double alpha);
    private static native boolean setFont(int serviceID, String font);
}
TOP

Related Classes of org.apache.harmony.x.print.PSInterpreter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.