/* * 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.render.pcl.fonts; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class PCLCharacterDefinition { private int charCode; private int charDefinitionSize; private byte[] glyfData; private boolean hasContinuation; private PCLCharacterFormat charFormat; private PCLCharacterClass charClass; private List<PCLCharacterDefinition> composites; private boolean isComposite; public PCLCharacterDefinition(int charCode, PCLCharacterFormat charFormat, PCLCharacterClass charClass, byte[] glyfData, boolean isComposite) { this.charCode = charCode; this.charFormat = charFormat; this.charClass = charClass; this.glyfData = glyfData; this.isComposite = isComposite; // Glyph Data + (Descriptor Size) + (Character Data Size) + (Glyph ID) must // be less than 32767 otherwise it will result in a continuation structure. charDefinitionSize = glyfData.length + 4 + 2 + 2; hasContinuation = charDefinitionSize > 32767; composites = new ArrayList<PCLCharacterDefinition>(); } public byte[] getCharacterCommand() throws IOException { return PCLByteWriterUtil.writeCommand(String.format("*c%dE", (isComposite) ? 65535 : charCode)); } public byte[] getCharacterDefinitionCommand() throws IOException { return PCLByteWriterUtil.writeCommand(String.format("(s%dW", 10 + glyfData.length)); } public byte[] getData() throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); // Write Character Descriptor if (!hasContinuation) { writeCharacterDescriptorHeader(0, baos); baos.write(glyfData); } else { int continuations = glyfData.length / 32767; for (int i = 0; i < continuations; i++) { writeCharacterDescriptorHeader(i == 0 ? 0 : 1, baos); int continuationStart = i * 32767; int continuationLength = continuationStart - glyfData.length < 32767 ? continuationStart - glyfData.length : 32767; baos.write(glyfData, continuationStart, continuationLength); } } baos.write(0); // Reserved byte[] charBytes = baos.toByteArray(); long sum = 0; for (int i = 4; i < charBytes.length; i++) { sum += charBytes[i]; } int remainder = (int) (sum % 256); baos.write(256 - remainder); // Checksum return baos.toByteArray(); } private void writeCharacterDescriptorHeader(int continuation, ByteArrayOutputStream baos) throws IOException { baos.write(PCLByteWriterUtil.unsignedByte(charFormat.getValue())); baos.write(continuation); baos.write(PCLByteWriterUtil.unsignedByte(2)); // Descriptor size (from this byte to character data) baos.write(PCLByteWriterUtil.unsignedByte(charClass.getValue())); baos.write(PCLByteWriterUtil.unsignedInt(glyfData.length + 4)); baos.write(PCLByteWriterUtil.unsignedInt(charCode)); } public void addCompositeGlyph(PCLCharacterDefinition composite) { composites.add(composite); } public List<PCLCharacterDefinition> getCompositeGlyphs() { return composites; } /** * Character Format used in PCL Character Descriptor See Table 11-50 from PCL 5 Specification */ public enum PCLCharacterFormat { LaserJet_Raster(4), Intellifont(10), TrueType(15); private int value; PCLCharacterFormat(int value) { this.value = value; } public int getValue() { return value; } } /** * Character Class used in PCL Character Descriptor See Table 11-51 from PCL 5 Specification */ public enum PCLCharacterClass { Bitmap(1), CompressedBitmap(2), Contour_Intellifont(3), Compound_Contour_Intellifont(4), TrueType(15); private int value; PCLCharacterClass(int value) { this.value = value; } public int getValue() { return value; } } }