Java tutorial
/* * 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: ACIUtils.java 1304264 2012-03-23 10:26:13Z vhennebert $ */ package org.apache.fop.svg; import java.awt.font.TextAttribute; import java.text.AttributedCharacterIterator; import java.text.AttributedCharacterIterator.Attribute; import java.text.CharacterIterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.batik.bridge.SVGFontFamily; import org.apache.batik.gvt.font.GVTFont; import org.apache.batik.gvt.font.GVTFontFamily; import org.apache.batik.gvt.text.GVTAttributedCharacterIterator; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontTriplet; /** * Utilities for java.text.AttributedCharacterIterator. */ public final class ACIUtils { /** the logger for this class */ private static final Log LOG = LogFactory.getLog(ACIUtils.class); private ACIUtils() { //This class shouldn't be instantiated. } /** * Tries to find matching fonts in FOP's {@link FontInfo} instance for fonts used by * Apache Batik. The method inspects the various GVT attributes found in the ACI. * @param aci the ACI to find matching fonts for * @param fontInfo the font info instance with FOP's fonts * @return an array of matching fonts */ public static Font[] findFontsForBatikACI(AttributedCharacterIterator aci, FontInfo fontInfo) { List<Font> fonts = new java.util.ArrayList<Font>(); @SuppressWarnings("unchecked") List<GVTFontFamily> gvtFonts = (List<GVTFontFamily>) aci .getAttribute(GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES); Float posture = (Float) aci.getAttribute(TextAttribute.POSTURE); Float taWeight = (Float) aci.getAttribute(TextAttribute.WEIGHT); Float fontSize = (Float) aci.getAttribute(TextAttribute.SIZE); String style = toStyle(posture); int weight = toCSSWeight(taWeight); int fsize = (int) (fontSize.floatValue() * 1000); String firstFontFamily = null; //GVT_FONT can sometimes be different from the fonts in GVT_FONT_FAMILIES //or GVT_FONT_FAMILIES can even be empty and only GVT_FONT is set /* The following code section is not available until Batik 1.7 is released. */ GVTFont gvtFont = (GVTFont) aci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.GVT_FONT); if (gvtFont != null) { String gvtFontFamily = gvtFont.getFamilyName(); if (fontInfo.hasFont(gvtFontFamily, style, weight)) { FontTriplet triplet = fontInfo.fontLookup(gvtFontFamily, style, weight); Font f = fontInfo.getFontInstance(triplet, fsize); if (LOG.isDebugEnabled()) { LOG.debug("Found a font that matches the GVT font: " + gvtFontFamily + ", " + weight + ", " + style + " -> " + f); } fonts.add(f); } firstFontFamily = gvtFontFamily; } if (gvtFonts != null) { boolean haveInstanceOfSVGFontFamily = false; for (GVTFontFamily fam : gvtFonts) { if (fam instanceof SVGFontFamily) { haveInstanceOfSVGFontFamily = true; } String fontFamily = fam.getFamilyName(); if (fontInfo.hasFont(fontFamily, style, weight)) { FontTriplet triplet = fontInfo.fontLookup(fontFamily, style, weight); Font f = fontInfo.getFontInstance(triplet, fsize); if (LOG.isDebugEnabled()) { LOG.debug("Found a font that matches the GVT font family: " + fontFamily + ", " + weight + ", " + style + " -> " + f); } fonts.add(f); } if (firstFontFamily == null) { firstFontFamily = fontFamily; } } // SVG fonts are embedded fonts in the SVG document and are rarely used; however if they // are used but the fonts also exists in the system and are known to FOP then FOP should // use them; then the decision whether Batik should stroke the text should be made after // no matching fonts are found if (fonts.isEmpty() && haveInstanceOfSVGFontFamily) { fontInfo.notifyStrokingSVGTextAsShapes(firstFontFamily); return null; // Let Batik paint this text! } } if (fonts.isEmpty()) { if (firstFontFamily == null) { //This will probably never happen. Just to be on the safe side. firstFontFamily = "any"; } //lookup with fallback possibility (incl. substitution notification) FontTriplet triplet = fontInfo.fontLookup(firstFontFamily, style, weight); Font f = fontInfo.getFontInstance(triplet, fsize); if (LOG.isDebugEnabled()) { LOG.debug("Falling back to adjustable font lookup up for: " + firstFontFamily + ", " + weight + ", " + style + " -> " + f); } fonts.add(f); } return fonts.toArray(new Font[fonts.size()]); } private static int toCSSWeight(Float weight) { if (weight == null) { return 400; } else if (weight <= TextAttribute.WEIGHT_EXTRA_LIGHT.floatValue()) { return 100; } else if (weight <= TextAttribute.WEIGHT_LIGHT.floatValue()) { return 200; } else if (weight <= TextAttribute.WEIGHT_DEMILIGHT.floatValue()) { return 300; } else if (weight <= TextAttribute.WEIGHT_REGULAR.floatValue()) { return 400; } else if (weight <= TextAttribute.WEIGHT_SEMIBOLD.floatValue()) { return 500; } else if (weight < TextAttribute.WEIGHT_BOLD.floatValue()) { return 600; } else if (weight == TextAttribute.WEIGHT_BOLD.floatValue()) { return 700; } else if (weight <= TextAttribute.WEIGHT_HEAVY.floatValue()) { return 800; } else if (weight <= TextAttribute.WEIGHT_EXTRABOLD.floatValue()) { return 900; } else { return 900; } } private static String toStyle(Float posture) { return ((posture != null) && (posture.floatValue() > 0.0)) ? Font.STYLE_ITALIC : Font.STYLE_NORMAL; } /** * Dumps the contents of an ACI to System.out. Used for debugging only. * @param aci the ACI to dump */ public static void dumpAttrs(AttributedCharacterIterator aci) { aci.first(); Set<Entry<Attribute, Object>> entries = aci.getAttributes().entrySet(); for (Map.Entry<Attribute, Object> entry : entries) { if (entry.getValue() != null) { System.out.println(entry.getKey() + ": " + entry.getValue()); } } int start = aci.getBeginIndex(); System.out.print("AttrRuns: "); while (aci.current() != CharacterIterator.DONE) { int end = aci.getRunLimit(); System.out.print("" + (end - start) + ", "); aci.setIndex(end); if (start == end) { break; } start = end; } System.out.println(""); } }