All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.fop.afp.ptoca.PtocaBuilder Maven / Gradle / Ivy

Go to download

Apache FOP (Formatting Objects Processor) is the world's first print formatter driven by XSL formatting objects (XSL-FO) and the world's first output independent formatter. It is a Java application that reads a formatting object (FO) tree and renders the resulting pages to a specified output. Output formats currently supported include PDF, PCL, PS, AFP, TIFF, PNG, SVG, XML (area tree representation), Print, AWT and TXT. The primary output target is PDF.

There is a newer version: 2.9
Show newest version
/*
 * 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.
 */

/* $Id: PtocaBuilder.java 1658659 2015-02-10 10:22:58Z lbernardo $ */

package org.apache.fop.afp.ptoca;

import java.awt.Color;
import java.awt.color.ColorSpace;
import java.io.IOException;
import java.io.OutputStream;

import org.apache.commons.io.output.ByteArrayOutputStream;

import org.apache.xmlgraphics.java2d.color.CIELabColorSpace;
import org.apache.xmlgraphics.java2d.color.ColorUtil;
import org.apache.xmlgraphics.java2d.color.ColorWithAlternatives;

import org.apache.fop.afp.fonts.CharactersetEncoder.EncodedChars;
import org.apache.fop.afp.modca.AxisOrientation;
import org.apache.fop.afp.ptoca.TransparentDataControlSequence.TransparentData;
import org.apache.fop.util.OCAColor;
import org.apache.fop.util.OCAColorSpace;

/**
 * Generator class for PTOCA data structures.
 */
public abstract class PtocaBuilder implements PtocaConstants {

    private ByteArrayOutputStream baout = new ByteArrayOutputStream(256);

    /** the current x coordinate. */
    private int currentX = -1;

    /** the current y coordinate */
    private int currentY = -1;

    /** the current font */
    private int currentFont = Integer.MIN_VALUE;

    /** the current orientation */
    private int currentOrientation;

    /** the current color */
    private Color currentColor = Color.BLACK;

    /** the current variable space increment */
    private int currentVariableSpaceCharacterIncrement;

    /** the current inter character adjustment */
    private int currentInterCharacterAdjustment;


    /**
     * Returns an {@link OutputStream} for the next control sequence. This gives a subclass a
     * chance to do chunking of control sequences into multiple presentation text data objects.
     * @param length the length of the following control sequence
     * @return the output stream where the control sequence will be written to
     */
    protected abstract OutputStream getOutputStreamForControlSequence(int length);

    private static byte chained(byte functionType) {
        return (byte)(functionType | CHAIN_BIT);
    }

    private void newControlSequence() {
        baout.reset();
    }

    private void commit(byte functionType) throws IOException {
        int length = baout.size() + 2;
        assert length < 256;

        OutputStream out = getOutputStreamForControlSequence(length);
        out.write(length);
        out.write(functionType);
        baout.writeTo(out);
    }

    private void writeBytes(int... data) {
        for (int d : data) {
            baout.write(d);
        }
    }

    private void writeShort(int data) {
        baout.write((data >>> 8) & 0xFF);
        baout.write(data & 0xFF);
    }

    /**
     * Writes the introducer for a chained control sequence.
     * @throws IOException if an I/O error occurs
     */
    public void writeIntroducer() throws IOException {
        OutputStream out = getOutputStreamForControlSequence(ESCAPE.length);
        out.write(ESCAPE);
    }

    /**
     * The Set Coded Font Local control sequence activates a coded font and
     * specifies the character attributes to be used.
     * 

* This is a modal control sequence. * * @param font The font local identifier. * @throws IOException if an I/O error occurs */ public void setCodedFont(byte font) throws IOException { // Avoid unnecessary specification of the font if (currentFont == font) { return; } else { currentFont = font; } newControlSequence(); writeBytes(font); commit(chained(SCFL)); } /** * Establishes the current presentation position on the baseline at a new * I-axis coordinate, which is a specified number of measurement units from * the B-axis. There is no change to the current B-axis coordinate. * * @param coordinate The coordinate for the inline move. * @throws IOException if an I/O error occurs */ public void absoluteMoveInline(int coordinate) throws IOException { if (coordinate == this.currentX) { return; } newControlSequence(); writeShort(coordinate); commit(chained(AMI)); currentX = coordinate; } /** * Moves the inline coordinate of the presentation position relative to the current * inline position. * @param increment the increment in 1/1440 inch units * @throws IOException if an I/O error occurs */ public void relativeMoveInline(int increment) throws IOException { newControlSequence(); writeShort(increment); commit(chained(RMI)); } /** * Establishes the baseline and the current presentation position at a new * B-axis coordinate, which is a specified number of measurement units from * the I-axis. There is no change to the current I-axis coordinate. * * @param coordinate The coordinate for the baseline move. * @throws IOException if an I/O error occurs */ public void absoluteMoveBaseline(int coordinate) throws IOException { if (coordinate == this.currentY) { return; } newControlSequence(); writeShort(coordinate); commit(chained(AMB)); currentY = coordinate; currentX = -1; } /** * The Transparent Data control sequence contains a sequence of code points * that are presented without a scan for embedded control sequences. If the data is larger * than fits in one chunk, additional chunks are automatically generated. * * @param encodedChars The encoded text data to add. * @throws IOException if an I/O error occurs */ public void addTransparentData(EncodedChars encodedChars) throws IOException { for (TransparentData trn : new TransparentDataControlSequence(encodedChars)) { newControlSequence(); trn.writeTo(baout); commit(chained(TRN)); } } /** * Draws a line of specified length and specified width in the B-direction * from the current presentation position. The location of the current * presentation position is unchanged. * * @param length The length of the rule. * @param width The width of the rule. * @throws IOException if an I/O error occurs */ public void drawBaxisRule(int length, int width) throws IOException { newControlSequence(); writeShort(length); // Rule length writeShort(width); // Rule width writeBytes(0); // Rule width fraction is always null. enough? commit(chained(DBR)); } /** * Draws a line of specified length and specified width in the I-direction * from the current presentation position. The location of the current * presentation position is unchanged. * * @param length The length of the rule. * @param width The width of the rule. * @throws IOException if an I/O error occurs */ public void drawIaxisRule(int length, int width) throws IOException { newControlSequence(); writeShort(length); // Rule length writeShort(width); // Rule width writeBytes(0); // Rule width fraction is always null. enough? commit(chained(DIR)); } /** * The Set Text Orientation control sequence establishes the I-direction and * B-direction for the subsequent text. This is a modal control sequence. * * Semantics: This control sequence specifies the I-axis and B-axis * orientations with respect to the Xp-axis for the current Presentation * Text object. The orientations are rotational values expressed in degrees * and minutes. * * @param orientation The text orientation (0, 90, 180, 270). * @throws IOException if an I/O error occurs */ public void setTextOrientation(int orientation) throws IOException { if (orientation == this.currentOrientation) { return; } newControlSequence(); AxisOrientation.getRightHandedAxisOrientationFor(orientation).writeTo(baout); commit(chained(STO)); this.currentOrientation = orientation; currentX = -1; currentY = -1; } /** * The Set Extended Text Color control sequence specifies a color value and * defines the color space and encoding for that value. The specified color * value is applied to foreground areas of the text presentation space. *

* This is a modal control sequence. * * @param col The color to be set. * @throws IOException if an I/O error occurs */ public void setExtendedTextColor(Color col) throws IOException { if (ColorUtil.isSameColor(col, currentColor)) { return; } if (col instanceof ColorWithAlternatives) { ColorWithAlternatives cwa = (ColorWithAlternatives)col; Color alt = cwa.getFirstAlternativeOfType(ColorSpace.TYPE_CMYK); if (alt != null) { col = alt; } } ColorSpace cs = col.getColorSpace(); newControlSequence(); if (col.getColorSpace().getType() == ColorSpace.TYPE_CMYK) { // Color space - 0x04 = CMYK, all else are reserved and must be zero writeBytes(0x00, 0x04, 0x00, 0x00, 0x00, 0x00); writeBytes(8, 8, 8, 8); // Number of bits in component 1, 2, 3 & 4 respectively float[] comps = col.getColorComponents(null); assert comps.length == 4; for (int i = 0; i < 4; i++) { int component = Math.round(comps[i] * 255); writeBytes(component); } } else if (cs instanceof CIELabColorSpace) { // Color space - 0x08 = CIELAB, all else are reserved and must be zero writeBytes(0x00, 0x08, 0x00, 0x00, 0x00, 0x00); writeBytes(8, 8, 8, 0); // Number of bits in component 1,2,3 & 4 //Sadly, 16 bit components don't seem to work float[] colorComponents = col.getColorComponents(null); int l = Math.round(colorComponents[0] * 255f); int a = Math.round(colorComponents[1] * 255f) - 128; int b = Math.round(colorComponents[2] * 255f) - 128; writeBytes(l, a, b); // l*, a* and b* } else if (cs instanceof OCAColorSpace) { // Color space - 0x40 = OCA, all else are reserved and must be zero writeBytes(0x00, 0x40, 0x00, 0x00, 0x00, 0x00); writeBytes(16, 0, 0, 0); // Number of bits in each component int ocaColor = ((OCAColor) col).getOCA(); writeBytes((ocaColor & 0xFF00) >> 8, ocaColor & 0xFF); } else { // Color space - 0x01 = RGB, all else are reserved and must be zero writeBytes(0x00, 0x01, 0x00, 0x00, 0x00, 0x00); writeBytes(8, 8, 8, 0); // Number of bits in component 1, 2, 3 & 4 respectively writeBytes(col.getRed(), col.getGreen(), col.getBlue()); // RGB intensity } commit(chained(SEC)); this.currentColor = col; } /** * Sets the variable space character increment. *

* This is a modal control sequence. * * @param incr The increment to be set (positive integer, 1/1440 inch) * @throws IOException if an I/O error occurs */ public void setVariableSpaceCharacterIncrement(int incr) throws IOException { if (incr == this.currentVariableSpaceCharacterIncrement) { return; } assert incr >= 0 && incr < (1 << 16); newControlSequence(); writeShort(Math.abs(incr)); //Increment commit(chained(SVI)); this.currentVariableSpaceCharacterIncrement = incr; } /** * Sets the intercharacter adjustment (additional increment or decrement between graphic * characters). *

* This is a modal control sequence. * * @param incr The increment to be set (1/1440 inch) * @throws IOException if an I/O error occurs */ public void setInterCharacterAdjustment(int incr) throws IOException { if (incr == this.currentInterCharacterAdjustment) { return; } assert incr >= Short.MIN_VALUE && incr <= Short.MAX_VALUE; newControlSequence(); writeShort(Math.abs(incr)); //Increment writeBytes(incr >= 0 ? 0 : 1); // Direction commit(chained(SIA)); this.currentInterCharacterAdjustment = incr; } /** * A control sequence is a sequence of bytes that specifies a control * function. A control sequence consists of a control sequence introducer * and zero or more parameters. The control sequence can extend multiple * presentation text data objects, but must eventually be terminated. This * method terminates the control sequence (by using a NOP command). * * @throws IOException if an I/O error occurs */ public void endChainedControlSequence() throws IOException { newControlSequence(); commit(NOP); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy