git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1337142 13f79535-47bb-0310-9956-ffa450edef68tags/fop-1_1rc1old
@@ -105,9 +105,9 @@ public abstract class CharactersetEncoder { | |||
@Override | |||
EncodedChars getEncodedChars(byte[] byteArray, int length) { | |||
if (byteArray[0] == 0x0E && byteArray[length - 1] == 0x0F) { | |||
return new EncodedChars(byteArray, 1, length - 2); | |||
return new EncodedChars(byteArray, 1, length - 2, true); | |||
} | |||
return new EncodedChars(byteArray); | |||
return new EncodedChars(byteArray, true); | |||
} | |||
} | |||
@@ -123,7 +123,7 @@ public abstract class CharactersetEncoder { | |||
@Override | |||
EncodedChars getEncodedChars(byte[] byteArray, int length) { | |||
return new EncodedChars(byteArray); | |||
return new EncodedChars(byteArray, false); | |||
} | |||
} | |||
@@ -145,36 +145,25 @@ public abstract class CharactersetEncoder { | |||
/** | |||
* A container for encoded character bytes | |||
*/ | |||
public static final class EncodedChars { | |||
public static class EncodedChars { | |||
private final byte[] bytes; | |||
private final int offset; | |||
private final int length; | |||
private final boolean isDBCS; | |||
private EncodedChars(byte[] bytes, int offset, int length) { | |||
if (offset < 0) { | |||
throw new IllegalArgumentException(); | |||
} | |||
if (length < 0) { | |||
throw new IllegalArgumentException(); | |||
} | |||
if (offset + length > bytes.length) { | |||
private EncodedChars(byte[] bytes, int offset, int length, boolean isDBCS) { | |||
if (offset < 0 || length < 0 || offset + length > bytes.length) { | |||
throw new IllegalArgumentException(); | |||
} | |||
this.bytes = bytes; | |||
this.offset = offset; | |||
this.length = length; | |||
this.isDBCS = isDBCS; | |||
} | |||
private EncodedChars(byte[] bytes) { | |||
this(bytes, 0, bytes.length); | |||
private EncodedChars(byte[] bytes, boolean isDBCS) { | |||
this(bytes, 0, bytes.length, isDBCS); | |||
} | |||
/** | |||
@@ -186,18 +175,9 @@ public abstract class CharactersetEncoder { | |||
* @throws IOException if an I/O error occurs | |||
*/ | |||
public void writeTo(OutputStream out, int offset, int length) throws IOException { | |||
if (offset < 0) { | |||
if (offset < 0 || length < 0 || offset + length > bytes.length) { | |||
throw new IllegalArgumentException(); | |||
} | |||
if (length < 0) { | |||
throw new IllegalArgumentException(); | |||
} | |||
if (offset + length > this.length) { | |||
throw new IllegalArgumentException(); | |||
} | |||
out.write(bytes, this.offset + offset, length); | |||
} | |||
@@ -210,6 +190,15 @@ public abstract class CharactersetEncoder { | |||
return length; | |||
} | |||
/** | |||
* Indicates whether or not the EncodedChars object wraps double byte characters. | |||
* | |||
* @return true if the wrapped characters are double byte (DBCSs) | |||
*/ | |||
public boolean isDBCS() { | |||
return isDBCS; | |||
} | |||
/** | |||
* The bytes | |||
* |
@@ -0,0 +1,82 @@ | |||
/* | |||
* 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.modca; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
/** | |||
* Represents the 4 bytes that specify the axis-area rotation reference coordinate system | |||
*/ | |||
public enum AxisOrientation { | |||
RIGHT_HANDED_0(Rotation.ROTATION_0, Rotation.ROTATION_90), | |||
RIGHT_HANDED_90(Rotation.ROTATION_90, Rotation.ROTATION_180), | |||
RIGHT_HANDED_180(Rotation.ROTATION_180, Rotation.ROTATION_270), | |||
RIGHT_HANDED_270(Rotation.ROTATION_270, Rotation.ROTATION_0); | |||
/** | |||
* The object area's X-axis rotation from the X axis of the reference coordinate system | |||
*/ | |||
private final Rotation xoaOrent; | |||
/** | |||
* The object area's Y-axis rotation from the Y axis of the reference coordinate system | |||
*/ | |||
private final Rotation yoaOrent; | |||
public void writeTo(byte[] out, int offset) { | |||
xoaOrent.writeTo(out, offset); | |||
yoaOrent.writeTo(out, offset + 2); | |||
} | |||
private AxisOrientation(Rotation xoaOrent, Rotation yoaOrent) { | |||
this.xoaOrent = xoaOrent; | |||
this.yoaOrent = yoaOrent; | |||
} | |||
/** | |||
* Writes the axis orientation area bytes to the output stream. | |||
* | |||
* @param stream the output stream to write to | |||
* @throws IOException if an I/O error occurs | |||
*/ | |||
public void writeTo(OutputStream stream) throws IOException { | |||
byte[] data = new byte[4]; | |||
writeTo(data, 0); | |||
stream.write(data); | |||
} | |||
/** | |||
* Gets the right-handed axis orientation object for a given orientation in degrees. | |||
* | |||
* @param orientation the orientation in degrees | |||
* @return the {@link AxisOrientation} object | |||
*/ | |||
public static AxisOrientation getRightHandedAxisOrientationFor(int orientation) { | |||
switch (orientation) { | |||
case 0: return RIGHT_HANDED_0; | |||
case 90: return RIGHT_HANDED_90; | |||
case 180: return RIGHT_HANDED_180; | |||
case 270: return RIGHT_HANDED_270; | |||
default: throw new IllegalArgumentException( | |||
"The orientation must be one of the values 0, 90, 180, 270"); | |||
} | |||
} | |||
} |
@@ -67,7 +67,7 @@ public class IncludeObject extends AbstractNamedAFPObject { | |||
private int yoaOset = 0; | |||
/** the orientation of the referenced object */ | |||
private ObjectAreaRotation oaOrent = ObjectAreaRotation.RIGHT_HANDED_0; | |||
private AxisOrientation oaOrent = AxisOrientation.RIGHT_HANDED_0; | |||
/** the X-axis origin defined in the object */ | |||
private int xocaOset = -1; | |||
@@ -93,7 +93,7 @@ public class IncludeObject extends AbstractNamedAFPObject { | |||
* The orientation (0,90, 180, 270) | |||
*/ | |||
public void setObjectAreaOrientation(int orientation) { | |||
this.oaOrent = ObjectAreaRotation.objectAreaRotationFor(orientation); | |||
this.oaOrent = AxisOrientation.getRightHandedAxisOrientationFor(orientation); | |||
} | |||
/** | |||
@@ -234,69 +234,4 @@ public class IncludeObject extends AbstractNamedAFPObject { | |||
addTriplet(new MeasurementUnitsTriplet(xRes, xRes)); | |||
} | |||
/** | |||
* Represents the 4 bytes that specify the area rotation reference coordinate system | |||
* | |||
*/ | |||
private enum ObjectAreaRotation { | |||
RIGHT_HANDED_0(Rotation.ROTATION_0, Rotation.ROTATION_90), | |||
RIGHT_HANDED_90(Rotation.ROTATION_90, Rotation.ROTATION_180), | |||
RIGHT_HANDED_180(Rotation.ROTATION_180, Rotation.ROTATION_270), | |||
RIGHT_HANDED_270(Rotation.ROTATION_270, Rotation.ROTATION_0); | |||
/** | |||
* The object area's X-axis rotation from the X axis of the reference coordinate system | |||
*/ | |||
private final Rotation xoaOrent; | |||
/** | |||
* The object area's Y-axis rotation from the Y axis of the reference coordinate system | |||
*/ | |||
private final Rotation yoaOrent; | |||
public void writeTo(byte[] out, int offset) { | |||
xoaOrent.writeTo(out, offset); | |||
yoaOrent.writeTo(out, offset + 2); | |||
} | |||
ObjectAreaRotation(Rotation xoaOrent, Rotation yoaOrent) { | |||
this.xoaOrent = xoaOrent; | |||
this.yoaOrent = yoaOrent; | |||
} | |||
private static ObjectAreaRotation objectAreaRotationFor(int orientation) { | |||
switch (orientation) { | |||
case 0: return RIGHT_HANDED_0; | |||
case 90: return RIGHT_HANDED_90; | |||
case 180: return RIGHT_HANDED_180; | |||
case 270: return RIGHT_HANDED_270; | |||
default: throw new IllegalArgumentException( | |||
"The orientation must be one of the values 0, 90, 180, 270"); | |||
} | |||
} | |||
} | |||
/** | |||
* Represents a rotation value | |||
* | |||
*/ | |||
private enum Rotation { | |||
ROTATION_0(0), | |||
ROTATION_90(0x2D), | |||
ROTATION_180(0x5A), | |||
ROTATION_270(0x87); | |||
private final byte firstByte; | |||
public void writeTo(byte[] out, int offset) { | |||
out[offset] = firstByte; | |||
out[offset + 1] = (byte)0; | |||
} | |||
Rotation(int firstByte) { | |||
this.firstByte = (byte) firstByte; | |||
} | |||
} | |||
} |
@@ -0,0 +1,46 @@ | |||
/* | |||
* 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.modca; | |||
/** | |||
* Represents a rotation value | |||
* | |||
*/ | |||
public enum Rotation { | |||
ROTATION_0(0), | |||
ROTATION_90(0x2D), | |||
ROTATION_180(0x5A), | |||
ROTATION_270(0x87); | |||
private final byte firstByte; | |||
public void writeTo(byte[] out, int offset) { | |||
out[offset] = firstByte; | |||
out[offset + 1] = (byte)0; | |||
} | |||
private Rotation(int firstByte) { | |||
this.firstByte = (byte) firstByte; | |||
} | |||
public byte getByte() { | |||
return firstByte; | |||
} | |||
} |
@@ -31,6 +31,8 @@ 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; | |||
/** | |||
* Generator class for PTOCA data structures. | |||
@@ -87,8 +89,10 @@ public abstract class PtocaBuilder implements PtocaConstants { | |||
baout.writeTo(out); | |||
} | |||
private void writeByte(int data) { | |||
baout.write(data); | |||
private void writeBytes(int... data) { | |||
for (int d : data) { | |||
baout.write(d); | |||
} | |||
} | |||
private void writeShort(int data) { | |||
@@ -123,7 +127,7 @@ public abstract class PtocaBuilder implements PtocaConstants { | |||
} | |||
newControlSequence(); | |||
writeByte(font); | |||
writeBytes(font); | |||
commit(chained(SCFL)); | |||
} | |||
@@ -187,26 +191,11 @@ public abstract class PtocaBuilder implements PtocaConstants { | |||
* @throws IOException if an I/O error occurs | |||
*/ | |||
public void addTransparentData(EncodedChars encodedChars) throws IOException { | |||
// data size greater than TRANSPARENT_MAX_SIZE, so slice | |||
int numTransData = encodedChars.getLength() / TRANSPARENT_DATA_MAX_SIZE; | |||
int currIndex = 0; | |||
for (int transDataCnt = 0; transDataCnt < numTransData; transDataCnt++) { | |||
addTransparentDataChunk(encodedChars, currIndex, TRANSPARENT_DATA_MAX_SIZE); | |||
currIndex += TRANSPARENT_DATA_MAX_SIZE; | |||
for (TransparentData trn : new TransparentDataControlSequence(encodedChars)) { | |||
newControlSequence(); | |||
trn.writeTo(baout); | |||
commit(chained(TRN)); | |||
} | |||
int left = encodedChars.getLength() - currIndex; | |||
addTransparentDataChunk(encodedChars, currIndex, left); | |||
} | |||
private void addTransparentDataChunk(EncodedChars encodedChars, int offset, int length) | |||
throws IOException { | |||
newControlSequence(); | |||
encodedChars.writeTo(baout, offset, length); | |||
commit(chained(TRN)); | |||
} | |||
/** | |||
@@ -222,7 +211,7 @@ public abstract class PtocaBuilder implements PtocaConstants { | |||
newControlSequence(); | |||
writeShort(length); // Rule length | |||
writeShort(width); // Rule width | |||
writeByte(0); // Rule width fraction is always null. enough? | |||
writeBytes(0); // Rule width fraction is always null. enough? | |||
commit(chained(DBR)); | |||
} | |||
@@ -239,7 +228,7 @@ public abstract class PtocaBuilder implements PtocaConstants { | |||
newControlSequence(); | |||
writeShort(length); // Rule length | |||
writeShort(width); // Rule width | |||
writeByte(0); // Rule width fraction is always null. enough? | |||
writeBytes(0); // Rule width fraction is always null. enough? | |||
commit(chained(DIR)); | |||
} | |||
@@ -260,32 +249,7 @@ public abstract class PtocaBuilder implements PtocaConstants { | |||
return; | |||
} | |||
newControlSequence(); | |||
switch (orientation) { | |||
case 90: | |||
writeByte(0x2D); | |||
writeByte(0x00); | |||
writeByte(0x5A); | |||
writeByte(0x00); | |||
break; | |||
case 180: | |||
writeByte(0x5A); | |||
writeByte(0x00); | |||
writeByte(0x87); | |||
writeByte(0x00); | |||
break; | |||
case 270: | |||
writeByte(0x87); | |||
writeByte(0x00); | |||
writeByte(0x00); | |||
writeByte(0x00); | |||
break; | |||
default: | |||
writeByte(0x00); | |||
writeByte(0x00); | |||
writeByte(0x2D); | |||
writeByte(0x00); | |||
break; | |||
} | |||
AxisOrientation.getRightHandedAxisOrientationFor(orientation).writeTo(baout); | |||
commit(chained(STO)); | |||
this.currentOrientation = orientation; | |||
currentX = -1; | |||
@@ -317,55 +281,30 @@ public abstract class PtocaBuilder implements PtocaConstants { | |||
newControlSequence(); | |||
if (col.getColorSpace().getType() == ColorSpace.TYPE_CMYK) { | |||
writeByte(0x00); // Reserved; must be zero | |||
writeByte(0x04); // Color space - 0x04 = CMYK | |||
writeByte(0x00); // Reserved; must be zero | |||
writeByte(0x00); // Reserved; must be zero | |||
writeByte(0x00); // Reserved; must be zero | |||
writeByte(0x00); // Reserved; must be zero | |||
writeByte(8); // Number of bits in component 1 | |||
writeByte(8); // Number of bits in component 2 | |||
writeByte(8); // Number of bits in component 3 | |||
writeByte(8); // Number of bits in component 4 | |||
// 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); | |||
writeByte(component); | |||
writeBytes(component); | |||
} | |||
} else if (cs instanceof CIELabColorSpace) { | |||
writeByte(0x00); // Reserved; must be zero | |||
writeByte(0x08); // Color space - 0x08 = CIELAB | |||
writeByte(0x00); // Reserved; must be zero | |||
writeByte(0x00); // Reserved; must be zero | |||
writeByte(0x00); // Reserved; must be zero | |||
writeByte(0x00); // Reserved; must be zero | |||
writeByte(8); // Number of bits in component 1 | |||
writeByte(8); // Number of bits in component 2 | |||
writeByte(8); // Number of bits in component 3 | |||
writeByte(0); // Number of bits in component 4 | |||
// 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; | |||
writeByte(l); // L* | |||
writeByte(a); // a* | |||
writeByte(b); // b* | |||
writeBytes(l, a, b); // l*, a* and b* | |||
} else { | |||
writeByte(0x00); // Reserved; must be zero | |||
writeByte(0x01); // Color space - 0x01 = RGB | |||
writeByte(0x00); // Reserved; must be zero | |||
writeByte(0x00); // Reserved; must be zero | |||
writeByte(0x00); // Reserved; must be zero | |||
writeByte(0x00); // Reserved; must be zero | |||
writeByte(8); // Number of bits in component 1 | |||
writeByte(8); // Number of bits in component 2 | |||
writeByte(8); // Number of bits in component 3 | |||
writeByte(0); // Number of bits in component 4 | |||
writeByte(col.getRed()); // Red intensity | |||
writeByte(col.getGreen()); // Green intensity | |||
writeByte(col.getBlue()); // Blue intensity | |||
// 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; | |||
@@ -407,7 +346,7 @@ public abstract class PtocaBuilder implements PtocaConstants { | |||
assert incr >= Short.MIN_VALUE && incr <= Short.MAX_VALUE; | |||
newControlSequence(); | |||
writeShort(Math.abs(incr)); //Increment | |||
writeByte(incr >= 0 ? 0 : 1); // Direction | |||
writeBytes(incr >= 0 ? 0 : 1); // Direction | |||
commit(chained(SIA)); | |||
this.currentInterCharacterAdjustment = incr; |
@@ -64,6 +64,6 @@ public interface PtocaConstants { | |||
byte NOP = (byte)0xF8; | |||
/** Maximum size of transparent data chunks */ | |||
int TRANSPARENT_DATA_MAX_SIZE = 253; | |||
int TRANSPARENT_DATA_MAX_SIZE = 253; // max length = 255 (minus the ControlSequence length) | |||
} |
@@ -0,0 +1,89 @@ | |||
/* | |||
* 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.ptoca; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import org.apache.fop.afp.fonts.CharactersetEncoder.EncodedChars; | |||
import org.apache.fop.afp.ptoca.TransparentDataControlSequence.TransparentData; | |||
import static org.apache.fop.afp.ptoca.PtocaConstants.TRANSPARENT_DATA_MAX_SIZE; | |||
/** | |||
* This object represents a series of PTOCA TransparentData (TRN) control sequences. This implements | |||
* {@link Iterable} to enable iteration through the TRNs. | |||
*/ | |||
final class TransparentDataControlSequence implements Iterable<TransparentData> { | |||
private static final int MAX_SBCS_TRN_SIZE = TRANSPARENT_DATA_MAX_SIZE; | |||
// The maximum size of a TRN must be an EVEN number so that we're splitting TRNs on character | |||
// boundaries rather than in the middle of a double-byte character | |||
private static final int MAX_DBCS_TRN_SIZE = MAX_SBCS_TRN_SIZE - 1; | |||
static final class TransparentData { | |||
private final int offset; | |||
private final int length; | |||
private final EncodedChars encodedChars; | |||
private TransparentData(int offset, int length, EncodedChars encChars) { | |||
this.offset = offset; | |||
this.length = length; | |||
this.encodedChars = encChars; | |||
} | |||
void writeTo(OutputStream outStream) throws IOException { | |||
encodedChars.writeTo(outStream, offset, length); | |||
} | |||
} | |||
private final List<TransparentData> trns; | |||
/** | |||
* Converts an encoded String wrapped in an {@link EncodedChars} into a series of | |||
* {@link TransparentData} control sequences. | |||
* | |||
* @param encChars the encoded characters to convert to TRNs | |||
*/ | |||
public TransparentDataControlSequence(EncodedChars encChars) { | |||
int maxTrnLength = encChars.isDBCS() ? MAX_DBCS_TRN_SIZE : MAX_SBCS_TRN_SIZE; | |||
int numTransData = encChars.getLength() / maxTrnLength; | |||
int currIndex = 0; | |||
List<TransparentData> trns = new ArrayList<TransparentData>(); | |||
for (int transDataCnt = 0; transDataCnt < numTransData; transDataCnt++) { | |||
trns.add(new TransparentData(currIndex, maxTrnLength, encChars)); | |||
currIndex += maxTrnLength; | |||
} | |||
int left = encChars.getLength() - currIndex; | |||
trns.add(new TransparentData(currIndex, left, encChars)); | |||
this.trns = Collections.unmodifiableList(trns); | |||
} | |||
/** | |||
* The {@link Iterator} for retrieving the series of TRN control sequences. | |||
*/ | |||
public Iterator<TransparentData> iterator() { | |||
return trns.iterator(); | |||
} | |||
} |
@@ -0,0 +1,73 @@ | |||
/* | |||
* 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.ptoca; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import org.junit.Test; | |||
import org.apache.fop.afp.fonts.CharactersetEncoder.EncodedChars; | |||
import org.apache.fop.afp.ptoca.TransparentDataControlSequence.TransparentData; | |||
import static org.apache.fop.afp.ptoca.PtocaConstants.TRANSPARENT_DATA_MAX_SIZE; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.times; | |||
import static org.mockito.Mockito.verify; | |||
import static org.mockito.Mockito.when; | |||
public class TransparentDataControlSequenceTestCase { | |||
private EncodedChars encodedChars; | |||
private final OutputStream outStream = mock(OutputStream.class); | |||
@Test | |||
public void testSingleByteCharacterSet() throws IOException { | |||
testTRNs(false); | |||
} | |||
@Test | |||
public void testDoubleByteCharacterSets() throws IOException { | |||
testTRNs(true); | |||
} | |||
public void testTRNs(boolean isDBCS) throws IOException { | |||
for (int length = 100; length < 10000; length += 1000) { | |||
createTRNControlSequence(isDBCS, length); | |||
int maxTRNSize = TRANSPARENT_DATA_MAX_SIZE - (isDBCS ? 1 : 0); | |||
int numberOfTRNs = length / maxTRNSize; | |||
for (int i = 0; i < numberOfTRNs; i++) { | |||
verify(encodedChars, times(1)).writeTo(outStream, i * maxTRNSize, maxTRNSize); | |||
} | |||
int lastOffset = numberOfTRNs * maxTRNSize; | |||
verify(encodedChars, times(1)).writeTo(outStream, numberOfTRNs * maxTRNSize, | |||
length - lastOffset); | |||
} | |||
} | |||
private void createTRNControlSequence(boolean isDBCS, int length) throws IOException { | |||
encodedChars = mock(EncodedChars.class); | |||
when(encodedChars.isDBCS()).thenReturn(isDBCS); | |||
when(encodedChars.getLength()).thenReturn(length); | |||
for (TransparentData trn : new TransparentDataControlSequence(encodedChars)) { | |||
trn.writeTo(outStream); | |||
} | |||
} | |||
} |