/*
 * 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: MapCodedFont.java 1762060 2016-09-23 12:57:46Z ssteiner $ */

package org.apache.fop.afp.modca;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.List;

import org.apache.fop.afp.AFPConstants;
import org.apache.fop.afp.fonts.AFPFont;
import org.apache.fop.afp.fonts.CharacterSet;
import org.apache.fop.afp.fonts.DoubleByteFont;
import org.apache.fop.afp.fonts.FontRuntimeException;
import org.apache.fop.afp.fonts.OutlineFont;
import org.apache.fop.afp.fonts.RasterFont;
import org.apache.fop.afp.util.BinaryUtils;

The Map Coded Font structured field maps a unique coded font resource local ID, which may be embedded one or more times within an object's data and descriptor, to the identifier of a coded font resource object. Additionally, the Map Coded Font structured field specifies a set of resource attributes for the coded font.
/** * The Map Coded Font structured field maps a unique coded font resource local * ID, which may be embedded one or more times within an object's data and * descriptor, to the identifier of a coded font resource object. Additionally, * the Map Coded Font structured field specifies a set of resource attributes * for the coded font. */
public class MapCodedFont extends AbstractStructuredObject {
the collection of map coded fonts (maximum of 254)
/** the collection of map coded fonts (maximum of 254) */
private final List<FontDefinition> fontList = new java.util.ArrayList<FontDefinition>();
Main constructor
/** * Main constructor */
public MapCodedFont() { }
{@inheritDoc}
/** {@inheritDoc} */
public void writeToStream(OutputStream os) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] startData = new byte[9]; copySF(startData, Type.MAP, Category.CODED_FONT); baos.write(startData); for (Object aFontList : fontList) { FontDefinition fd = (FontDefinition) aFontList; // Start of repeating groups (occurs 1 to 254) baos.write(0x00); if (fd.scale == 0) { // Raster Font baos.write(0x22); // Length of 34 } else { // Outline Font baos.write(0x3A); // Length of 58 } // Font Character Set Name Reference baos.write(0x0C); //TODO Relax requirement for 8 chars in the name baos.write(0x02); baos.write((byte) 0x86); baos.write(0x00); baos.write(fd.characterSet); // Font Code Page Name Reference baos.write(0x0C); //TODO Relax requirement for 8 chars in the name baos.write(0x02); baos.write((byte) 0x85); baos.write(0x00); baos.write(fd.codePage); //TODO idea: for CIDKeyed fonts, maybe hint at Unicode encoding with X'50' triplet //to allow font substitution. // Character Rotation baos.write(0x04); baos.write(0x26); baos.write(fd.orientation); baos.write(0x00); // Resource Local Identifier baos.write(0x04); baos.write(0x24); baos.write(0x05); baos.write(fd.fontReferenceKey); if (fd.scale != 0) { // Outline Font (triplet '1F') baos.write(0x14); baos.write(0x1F); baos.write(0x00); baos.write(0x00); baos.write(BinaryUtils.convert(fd.scale, 2)); // Height baos.write(new byte[]{0x00, 0x00}); // Width baos.write(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); baos.write(0x60); // Outline Font (triplet '5D') baos.write(0x04); baos.write(0x5D); baos.write(BinaryUtils.convert(fd.scale, 2)); } } byte[] data = baos.toByteArray(); // Set the total record length byte[] rl1 = BinaryUtils.convert(data.length - 1, 2); data[1] = rl1[0]; data[2] = rl1[1]; os.write(data); }
Add a font definition on the the map coded font object.
Params:
  • fontReference – the font number used as the resource identifier
  • font – the font
  • size – the size of the font
  • orientation – the orientation of the font
Throws:
/** * Add a font definition on the the map coded font object. * * @param fontReference * the font number used as the resource identifier * @param font * the font * @param size * the size of the font * @param orientation * the orientation of the font * @throws MaximumSizeExceededException if the maximum number of fonts have been exceeded */
public void addFont(int fontReference, AFPFont font, int size, int orientation) throws MaximumSizeExceededException { FontDefinition fontDefinition = new FontDefinition(); fontDefinition.fontReferenceKey = BinaryUtils.convert(fontReference)[0]; switch (orientation) { case 90: fontDefinition.orientation = 0x2D; break; case 180: fontDefinition.orientation = 0x5A; break; case 270: fontDefinition.orientation = (byte) 0x87; break; default: fontDefinition.orientation = 0x00; break; } try { if (font instanceof RasterFont) { RasterFont raster = (RasterFont) font; CharacterSet cs = raster.getCharacterSet(size); if (cs == null) { String msg = "Character set not found for font " + font.getFontName() + " with point size " + size; LOG.error(msg); throw new FontRuntimeException(msg); } fontDefinition.characterSet = cs.getNameBytes(); if (fontDefinition.characterSet.length != 8) { throw new IllegalArgumentException("The character set " + new String(fontDefinition.characterSet, AFPConstants.EBCIDIC_ENCODING) + " must have a fixed length of 8 characters."); } fontDefinition.codePage = cs.getCodePage().getBytes( AFPConstants.EBCIDIC_ENCODING); if (fontDefinition.codePage.length != 8) { throw new IllegalArgumentException("The code page " + new String(fontDefinition.codePage, AFPConstants.EBCIDIC_ENCODING) + " must have a fixed length of 8 characters."); } } else if (font instanceof OutlineFont) { OutlineFont outline = (OutlineFont) font; CharacterSet cs = outline.getCharacterSet(); fontDefinition.characterSet = cs.getNameBytes(); // There are approximately 72 points to 1 inch or 20 1440ths per point. fontDefinition.scale = 20 * size / 1000; fontDefinition.codePage = cs.getCodePage().getBytes( AFPConstants.EBCIDIC_ENCODING); if (fontDefinition.codePage.length != 8) { throw new IllegalArgumentException("The code page " + new String(fontDefinition.codePage, AFPConstants.EBCIDIC_ENCODING) + " must have a fixed length of 8 characters."); } } else if (font instanceof DoubleByteFont) { DoubleByteFont outline = (DoubleByteFont) font; CharacterSet cs = outline.getCharacterSet(); fontDefinition.characterSet = cs.getNameBytes(); // There are approximately 72 points to 1 inch or 20 1440ths per point. fontDefinition.scale = 20 * size / 1000; fontDefinition.codePage = cs.getCodePage().getBytes( AFPConstants.EBCIDIC_ENCODING); //TODO Relax requirement for 8 characters if (fontDefinition.codePage.length != 8) { throw new IllegalArgumentException("The code page " + new String(fontDefinition.codePage, AFPConstants.EBCIDIC_ENCODING) + " must have a fixed length of 8 characters."); } } else { String msg = "Font of type " + font.getClass().getName() + " not recognized."; LOG.error(msg); throw new FontRuntimeException(msg); } if (fontList.size() > 253) { // Throw an exception if the size is exceeded throw new MaximumSizeExceededException(); } else { fontList.add(fontDefinition); } } catch (UnsupportedEncodingException ex) { throw new FontRuntimeException("Failed to create font " + " due to a UnsupportedEncodingException", ex); } }
Private utility class used as a container for font attributes
/** * Private utility class used as a container for font attributes */
private static final class FontDefinition { private FontDefinition() { }
The code page of the font
/** * The code page of the font */
private byte[] codePage;
The character set of the font
/** * The character set of the font */
private byte[] characterSet;
The font reference key
/** * The font reference key */
private byte fontReferenceKey;
The orientation of the font
/** * The orientation of the font */
private byte orientation;
The scale (only specified for outline fonts)
/** * The scale (only specified for outline fonts) */
private int scale; } }