aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache/fop/afp/goca/GraphicsData.java
blob: aa64c23c4c3c2e8a3f1727e401c4a31d4434a7ab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*
 * 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$ */

package org.apache.fop.afp.goca;

import java.io.IOException;
import java.io.OutputStream;

import org.apache.fop.afp.StructuredData;
import org.apache.fop.afp.util.BinaryUtils;
import org.apache.fop.afp.util.StringUtils;

/**
 * A GOCA graphics data
 */
public final class GraphicsData extends AbstractGraphicsDrawingOrderContainer {

    /** the maximum graphics data length */
    public static final int MAX_DATA_LEN = GraphicsChainedSegment.MAX_DATA_LEN + 16;
    //+16 to avoid unnecessary, practically empty GraphicsData instances.

    /** the graphics segment */
    private GraphicsChainedSegment currentSegment = null;

    private boolean segmentedData;

    /**
     * Main constructor
     */
    public GraphicsData() {
    }

    /** {@inheritDoc} */
    @Override
    public int getDataLength() {
        return 8 + super.getDataLength();
    }

    /**
     * Sets the indicator that this instance is a part of a series of segmented data chunks.
     * This indirectly sets the SegFlag on the SFI header.
     * @param segmented true if this data object is not the last of the series
     */
    public void setSegmentedData(boolean segmented) {
        this.segmentedData = segmented;
    }

    /**
     * Returns a new segment name
     *
     * @return a new segment name
     */
    public String createSegmentName() {
        return StringUtils.lpad(String.valueOf(
                (super.objects != null ? super.objects.size() : 0) + 1),
            '0', 4);
    }

    /**
     * Creates a new graphics segment.
     *
     * @return a newly created graphics segment
     */
    public GraphicsChainedSegment newSegment() {
        return newSegment(false, false);
    }

    /**
     * Creates a new graphics segment.
     * @param appended true if this segment is appended to the previous one
     * @param prologPresent true if started with a prolog
     * @return a newly created graphics segment
     */
    public GraphicsChainedSegment newSegment(boolean appended, boolean prologPresent) {
        String segmentName = createSegmentName();
        if (currentSegment == null) {
            currentSegment = new GraphicsChainedSegment(segmentName);
        } else {
            currentSegment.setComplete(true);
            currentSegment = new GraphicsChainedSegment(segmentName,
                    currentSegment.getNameBytes(), appended, prologPresent);
        }
        super.addObject(currentSegment);
        return currentSegment;
    }

    /** {@inheritDoc} */
    @Override
    public void addObject(StructuredData object) {
        if (currentSegment == null
                || (currentSegment.getDataLength() + object.getDataLength())
                >= GraphicsChainedSegment.MAX_DATA_LEN) {
            newSegment(true, false);
        }
        currentSegment.addObject(object);
    }

    /**
     * Removes the current segment from this graphics data
     *
     * @return the current segment from this graphics data
     */
    public StructuredData removeCurrentSegment() {
        this.currentSegment = null;
        return super.removeLast();
    }

    /** {@inheritDoc} */
    @Override
    public void writeToStream(OutputStream os) throws IOException {
        byte[] data = new byte[9];
        copySF(data, SF_CLASS, Type.DATA, Category.GRAPHICS);
        int dataLength = getDataLength();
        byte[] len = BinaryUtils.convert(dataLength, 2);
        data[1] = len[0]; // Length byte 1
        data[2] = len[1]; // Length byte 2
        if (this.segmentedData) {
            data[6] |= 32; //Data is segmented
        }
        os.write(data);

        writeObjects(objects, os);
    }

    /** {@inheritDoc} */
    @Override
    public String toString() {
        return "GraphicsData(len: " + getDataLength() + ")";
    }

    /**
     * Adds the given segment to this graphics data
     *
     * @param segment a graphics chained segment
     */
    public void addSegment(GraphicsChainedSegment segment) {
        currentSegment = segment;
        super.addObject(currentSegment);
    }
}