org.apache.fop.afp.fonts.DoubleByteFont Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fop Show documentation
Show all versions of fop Show documentation
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.
/*
* 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: DoubleByteFont.java 1679676 2015-05-16 02:10:42Z adelmelle $ */
package org.apache.fop.afp.fonts;
import java.awt.Rectangle;
import java.lang.Character.UnicodeBlock;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.afp.AFPEventProducer;
/**
* Implementation of {@link AbstractOutlineFont} that supports double-byte fonts (CID Keyed font (Type 0)).
* The width of characters that are not prescribed a width metrics in the font resource use
* a fallback width. The default width is 1 em. A character can be supplied and queried for the
* fallback width of all non-ideograph characters.
*/
public class DoubleByteFont extends AbstractOutlineFont {
private static final Log log = LogFactory.getLog(DoubleByteFont.class);
private final Set charsProcessed;
//See also http://unicode.org/reports/tr11/ which we've not closely looked at, yet
//TODO the Unicode block listed here is probably not complete (ex. Hiragana, Katakana etc.)
private static final Set IDEOGRAPHIC = new HashSet();
static {
IDEOGRAPHIC.add(Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS);
//IDEOGRAPHIC.add(Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT);//Java 1.5
IDEOGRAPHIC.add(Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS);
IDEOGRAPHIC.add(Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A);
//IDEOGRAPHIC.add(Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B); //Java 1.1
}
/**
* Constructor for an double-byte outline font.
* @param name the name of the font
* @param embeddable whether or not this font is embeddable
* @param charSet the character set
* @param eventProducer Handles any AFP related events
*/
public DoubleByteFont(String name, boolean embeddable, CharacterSet charSet,
AFPEventProducer eventProducer) {
super(name, embeddable, charSet, eventProducer);
charsProcessed = new HashSet();
}
/** {@inheritDoc} */
public int getWidth(int character, int size) {
int charWidth;
try {
charWidth = charSet.getWidth(toUnicodeCodepoint(character), size);
} catch (IllegalArgumentException e) {
if (!charsProcessed.contains(character)) {
charsProcessed.add(character);
getAFPEventProducer().charactersetMissingMetrics(this, (char)character,
charSet.getName().trim());
}
// We shall try and handle characters that have no mapped width metric in font resource
charWidth = -1;
}
if (charWidth == -1) {
charWidth = getDefaultCharacterWidth(character) * size;
}
return charWidth;
}
private int getDefaultCharacterWidth(int character) {
int nominalCharIncrement = charSet.getNominalCharIncrement();
if (nominalCharIncrement > 0) {
return nominalCharIncrement;
} else {
return inferCharWidth(character);
}
}
@Override
public Rectangle getBoundingBox(int character, int size) {
Rectangle characterBox = getBoundingBoxOrNull(character, size);
if (characterBox == null) {
characterBox = getDefaultCharacterBox(character, size);
}
return characterBox;
}
private Rectangle getBoundingBoxOrNull(int character, int size) {
Rectangle characterBox = null;
try {
characterBox = charSet.getCharacterBox(toUnicodeCodepoint(character), size);
} catch (IllegalArgumentException e) {
if (!charsProcessed.contains(character)) {
charsProcessed.add(character);
getAFPEventProducer().charactersetMissingMetrics(this, (char) character,
charSet.getName().trim());
}
}
return characterBox;
}
private Rectangle getDefaultCharacterBox(int character, int size) {
return getBoundingBoxOrNull('-', size);
}
private int inferCharWidth(int character) {
//Is this character an ideograph?
boolean isIdeographic = false;
Character.UnicodeBlock charBlock = Character.UnicodeBlock.of((char)character);
if (charBlock == null) {
isIdeographic = false;
} else if (IDEOGRAPHIC.contains(charBlock)) {
isIdeographic = true;
} else { //default
isIdeographic = false;
}
if (isIdeographic) {
return charSet.getEmSpaceIncrement();
} else {
return charSet.getSpaceIncrement();
}
}
}