Browse Source

FOP-2994: Support OTF/TTF SVG fonts

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1885366 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-2_6
Simon Steiner 3 years ago
parent
commit
a5fa25cf3e
30 changed files with 355 additions and 72 deletions
  1. 1
    1
      fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java
  2. 1
    1
      fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java
  3. 3
    1
      fop-core/src/main/java/org/apache/fop/complexscripts/fonts/OTFAdvancedTypographicTableReader.java
  4. 10
    0
      fop-core/src/main/java/org/apache/fop/fonts/CustomFont.java
  5. 10
    2
      fop-core/src/main/java/org/apache/fop/fonts/DefaultFontConfig.java
  6. 1
    1
      fop-core/src/main/java/org/apache/fop/fonts/DefaultFontConfigurator.java
  7. 8
    2
      fop-core/src/main/java/org/apache/fop/fonts/EmbedFontInfo.java
  8. 2
    2
      fop-core/src/main/java/org/apache/fop/fonts/FontLoader.java
  9. 4
    2
      fop-core/src/main/java/org/apache/fop/fonts/LazyFont.java
  10. 6
    0
      fop-core/src/main/java/org/apache/fop/fonts/MultiByteFont.java
  11. 2
    2
      fop-core/src/main/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java
  12. 11
    6
      fop-core/src/main/java/org/apache/fop/fonts/truetype/OFFontLoader.java
  13. 2
    0
      fop-core/src/main/java/org/apache/fop/fonts/truetype/OFTableName.java
  14. 30
    0
      fop-core/src/main/java/org/apache/fop/fonts/truetype/OpenFont.java
  15. 100
    0
      fop-core/src/main/java/org/apache/fop/fonts/truetype/SVGGlyphData.java
  16. 1
    1
      fop-core/src/main/java/org/apache/fop/render/afp/AFPFontConfig.java
  17. 24
    0
      fop-core/src/main/java/org/apache/fop/render/intermediate/AbstractIFPainter.java
  18. 3
    3
      fop-core/src/main/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java
  19. 6
    2
      fop-core/src/main/java/org/apache/fop/render/pdf/PDFPainter.java
  20. 32
    23
      fop-core/src/main/java/org/apache/fop/render/ps/PSImageHandlerSVG.java
  21. 18
    15
      fop-core/src/main/java/org/apache/fop/render/ps/PSPainter.java
  22. 1
    1
      fop-core/src/test/java/org/apache/fop/fonts/DejaVuLGCSerifTestCase.java
  23. 1
    1
      fop-core/src/test/java/org/apache/fop/fonts/EmbedFontInfoTestCase.java
  24. 1
    1
      fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFToType1TestCase.java
  25. 2
    2
      fop-core/src/test/java/org/apache/fop/fonts/truetype/TTFFontLoaderTestCase.java
  26. 4
    1
      fop-core/src/test/java/org/apache/fop/fonts/type1/Type1FontLoaderTestCase.java
  27. 1
    1
      fop-core/src/test/java/org/apache/fop/pdf/PDFFactoryTestCase.java
  28. 36
    0
      fop-core/src/test/java/org/apache/fop/render/pdf/PDFPainterTestCase.java
  29. 33
    0
      fop-core/src/test/java/org/apache/fop/render/ps/PSPainterTestCase.java
  30. 1
    1
      fop-core/src/test/java/org/apache/fop/svg/font/FontInfoBuilder.java

+ 1
- 1
fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java View File

@@ -413,7 +413,7 @@ public class FOUserAgent {
try {
// Have to do this so we can resolve data URIs
StreamSource src = new StreamSource(resourceResolver.getResource(uri));
src.setSystemId(uri);
src.setSystemId(getResourceResolver().getBaseURI().toASCIIString());
return src;
} catch (URISyntaxException use) {
return null;

+ 1
- 1
fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java View File

@@ -141,7 +141,7 @@ public class FopConfParser {
*/
public FopConfParser(File fopConfFile, ResourceResolver resourceResolver)
throws SAXException, IOException {
this(new FileInputStream(fopConfFile), fopConfFile.toURI(), resourceResolver);
this(new FileInputStream(fopConfFile), fopConfFile.getParentFile().toURI(), resourceResolver);
}

public FopConfParser(InputStream fopConfStream, URI baseURI, EnvironmentProfile enviro)

+ 3
- 1
fop-core/src/main/java/org/apache/fop/complexscripts/fonts/OTFAdvancedTypographicTableReader.java View File

@@ -215,7 +215,9 @@ public final class OTFAdvancedTypographicTableReader {
log.debug(tableTag + " lang sys default: " + dt);
}
}
seScripts.put(scriptTag, new Object[] { dt, ll, seLanguages });
if (seLanguages != null) {
seScripts.put(scriptTag, new Object[]{dt, ll, seLanguages});
}
seLanguages = null;
}


+ 10
- 0
fop-core/src/main/java/org/apache/fop/fonts/CustomFont.java View File

@@ -32,6 +32,7 @@ import java.util.Map;
import java.util.Set;

import org.apache.fop.apps.io.InternalResourceResolver;
import org.apache.fop.fonts.truetype.SVGGlyphData;


/**
@@ -80,6 +81,7 @@ public abstract class CustomFont extends Typeface
private boolean useKerning = true;
/** the character map, mapping Unicode ranges to glyph indices. */
protected List<CMapSegment> cmap = new ArrayList<CMapSegment>();
protected Map<Integer, SVGGlyphData> svgs;
private boolean useAdvanced = true;
private boolean simulateStyle;
protected List<SimpleSingleByteEncoding> additionalEncodings;
@@ -682,4 +684,12 @@ public abstract class CustomFont extends Typeface
}
return 0;
}

public boolean hasSVG() {
return svgs != null;
}

public void setSVG(Map<Integer, SVGGlyphData> svgs) {
this.svgs = svgs;
}
}

+ 10
- 2
fop-core/src/main/java/org/apache/fop/fonts/DefaultFontConfig.java View File

@@ -132,7 +132,8 @@ public final class DefaultFontConfig implements FontConfig {
fontCfg.getAttribute("encoding-mode", EncodingMode.AUTO.getName()),
fontCfg.getAttribute("embedding-mode", EncodingMode.AUTO.getName()),
fontCfg.getAttributeAsBoolean("simulate-style", false),
fontCfg.getAttributeAsBoolean("embed-as-type1", false));
fontCfg.getAttributeAsBoolean("embed-as-type1", false),
fontCfg.getAttributeAsBoolean("svg", true));
instance.fonts.add(font);
boolean hasTriplets = false;
for (Configuration tripletCfg : fontCfg.getChildren("font-triplet")) {
@@ -322,6 +323,8 @@ public final class DefaultFontConfig implements FontConfig {
private final boolean embedAsType1;
private final boolean simulateStyle;

private final boolean useSVG;

private final List<FontTriplet> tripletList = new ArrayList<FontTriplet>();

public List<FontTriplet> getTripletList() {
@@ -330,7 +333,7 @@ public final class DefaultFontConfig implements FontConfig {

private Font(String metrics, String embed, String afm, String pfm, String subFont, boolean kerning,
boolean advanced, String encodingMode, String embeddingMode, boolean simulateStyle,
boolean embedAsType1) {
boolean embedAsType1, boolean useSVG) {
this.metrics = metrics;
this.embedUri = embed;
this.afm = afm;
@@ -342,6 +345,7 @@ public final class DefaultFontConfig implements FontConfig {
this.embeddingMode = embeddingMode;
this.simulateStyle = simulateStyle;
this.embedAsType1 = embedAsType1;
this.useSVG = useSVG;
}

/**
@@ -399,5 +403,9 @@ public final class DefaultFontConfig implements FontConfig {
public boolean getEmbedAsType1() {
return embedAsType1;
}

public boolean getUseSVG() {
return useSVG;
}
}
}

+ 1
- 1
fop-core/src/main/java/org/apache/fop/fonts/DefaultFontConfigurator.java View File

@@ -168,7 +168,7 @@ public class DefaultFontConfigurator implements FontConfigurator<EmbedFontInfo>
EmbeddingMode embeddingMode = EmbeddingMode.getValue(font.getEmbeddingMode());
EmbedFontInfo embedFontInfo = new EmbedFontInfo(fontUris, font.isKerning(),
font.isAdvanced(), tripletList, subFont, encodingMode, embeddingMode,
font.getSimulateStyle(), font.getEmbedAsType1());
font.getSimulateStyle(), font.getEmbedAsType1(), font.getUseSVG());
if (fontCache != null) {
if (!fontCache.containsFont(embedFontInfo)) {
fontCache.addFont(embedFontInfo, resourceResolver);

+ 8
- 2
fop-core/src/main/java/org/apache/fop/fonts/EmbedFontInfo.java View File

@@ -45,6 +45,7 @@ public class EmbedFontInfo implements Serializable {
/** simulates bold or italic on a regular font */
private final boolean simulateStyle;
private final boolean embedAsType1;
private final boolean useSVG;

/** the PostScript name of the font */
protected String postScriptName;
@@ -69,7 +70,7 @@ public class EmbedFontInfo implements Serializable {
*/
public EmbedFontInfo(FontUris fontUris, boolean kerning, boolean advanced,
List<FontTriplet> fontTriplets, String subFontName, EncodingMode encodingMode,
EmbeddingMode embeddingMode, boolean simulateStyle, boolean embedAsType1) {
EmbeddingMode embeddingMode, boolean simulateStyle, boolean embedAsType1, boolean useSVG) {
this.kerning = kerning;
this.advanced = advanced;
this.fontTriplets = fontTriplets;
@@ -79,6 +80,7 @@ public class EmbedFontInfo implements Serializable {
this.fontUris = fontUris;
this.simulateStyle = simulateStyle;
this.embedAsType1 = embedAsType1;
this.useSVG = useSVG;
}

/**
@@ -91,7 +93,7 @@ public class EmbedFontInfo implements Serializable {
public EmbedFontInfo(FontUris fontUris, boolean kerning, boolean advanced,
List<FontTriplet> fontTriplets, String subFontName) {
this(fontUris, kerning, advanced, fontTriplets, subFontName, EncodingMode.AUTO,
EmbeddingMode.AUTO, false, false);
EmbeddingMode.AUTO, false, false, true);
}

/**
@@ -209,6 +211,10 @@ public class EmbedFontInfo implements Serializable {
return embedAsType1;
}

public boolean getUseSVG() {
return useSVG;
}

private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException {
in.defaultReadObject();

+ 2
- 2
fop-core/src/main/java/org/apache/fop/fonts/FontLoader.java View File

@@ -93,7 +93,7 @@ public abstract class FontLoader {
public static CustomFont loadFont(FontUris fontUris, String subFontName,
boolean embedded, EmbeddingMode embeddingMode, EncodingMode encodingMode,
boolean useKerning, boolean useAdvanced, InternalResourceResolver resourceResolver,
boolean simulateStyle, boolean embedAsType1) throws IOException {
boolean simulateStyle, boolean embedAsType1, boolean useSVG) throws IOException {
boolean type1 = isType1(fontUris);
FontLoader loader;
if (type1) {
@@ -105,7 +105,7 @@ public abstract class FontLoader {
resourceResolver);
} else {
loader = new OFFontLoader(fontUris.getEmbed(), subFontName, embedded, embeddingMode,
encodingMode, useKerning, useAdvanced, resourceResolver, simulateStyle, embedAsType1);
encodingMode, useKerning, useAdvanced, resourceResolver, simulateStyle, embedAsType1, useSVG);
}
return loader.getFont();
}

+ 4
- 2
fop-core/src/main/java/org/apache/fop/fonts/LazyFont.java View File

@@ -47,6 +47,7 @@ public class LazyFont extends Typeface implements FontDescriptor, Substitutable,
private final boolean useAdvanced;
private boolean simulateStyle;
private boolean embedAsType1;
private boolean useSVG;
private final EncodingMode encodingMode;
private final EmbeddingMode embeddingMode;
private final String subFontName;
@@ -74,6 +75,7 @@ public class LazyFont extends Typeface implements FontDescriptor, Substitutable,
}
this.simulateStyle = fontInfo.getSimulateStyle();
this.embedAsType1 = fontInfo.getEmbedAsType1();
useSVG = fontInfo.getUseSVG();
this.encodingMode = fontInfo.getEncodingMode() != null ? fontInfo.getEncodingMode()
: EncodingMode.AUTO;
this.embeddingMode = fontInfo.getEmbeddingMode() != null ? fontInfo.getEmbeddingMode()
@@ -116,8 +118,8 @@ public class LazyFont extends Typeface implements FontDescriptor, Substitutable,
if (fontUris.getEmbed() == null) {
throw new RuntimeException("Cannot load font. No font URIs available.");
}
realFont = FontLoader.loadFont(fontUris, subFontName, embedded, embeddingMode,
encodingMode, useKerning, useAdvanced, resourceResolver, simulateStyle, embedAsType1);
realFont = FontLoader.loadFont(fontUris, subFontName, embedded, embeddingMode, encodingMode,
useKerning, useAdvanced, resourceResolver, simulateStyle, embedAsType1, useSVG);
}
if (realFont instanceof FontDescriptor) {
realFontDescriptor = (FontDescriptor) realFont;

+ 6
- 0
fop-core/src/main/java/org/apache/fop/fonts/MultiByteFont.java View File

@@ -42,6 +42,7 @@ import org.apache.fop.complexscripts.fonts.Substitutable;
import org.apache.fop.complexscripts.util.CharAssociation;
import org.apache.fop.complexscripts.util.CharNormalize;
import org.apache.fop.complexscripts.util.GlyphSequence;
import org.apache.fop.fonts.truetype.SVGGlyphData;
import org.apache.fop.util.CharUtilities;

/**
@@ -857,5 +858,10 @@ public class MultiByteFont extends CIDFont implements Substitutable, Positionabl
public InputStream getCmapStream() {
return null;
}

public SVGGlyphData getSVG(char c) {
int gid = findGlyphIndex(c);
return svgs.get(gid);
}
}


+ 2
- 2
fop-core/src/main/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java View File

@@ -223,7 +223,7 @@ public class FontInfoFinder {
try {
OFFontLoader ttfLoader = new OFFontLoader(fontURI, fontName, true,
EmbeddingMode.AUTO, EncodingMode.AUTO, useKerning, useAdvanced,
resourceResolver, false, false);
resourceResolver, false, false, true);
customFont = ttfLoader.getFont();
if (this.eventListener != null) {
customFont.setEventListener(this.eventListener);
@@ -251,7 +251,7 @@ public class FontInfoFinder {
try {
FontUris fontUris = new FontUris(fontURI, null);
customFont = FontLoader.loadFont(fontUris, null, true, EmbeddingMode.AUTO, EncodingMode.AUTO,
useKerning, useAdvanced, resourceResolver, false, false);
useKerning, useAdvanced, resourceResolver, false, false, true);
if (this.eventListener != null) {
customFont.setEventListener(this.eventListener);
}

+ 11
- 6
fop-core/src/main/java/org/apache/fop/fonts/truetype/OFFontLoader.java View File

@@ -55,6 +55,7 @@ public class OFFontLoader extends FontLoader {
private EmbeddingMode embeddingMode;
private boolean simulateStyle;
private boolean embedAsType1;
private boolean useSVG;

/**
* Default constructor
@@ -63,7 +64,7 @@ public class OFFontLoader extends FontLoader {
*/
public OFFontLoader(URI fontFileURI, InternalResourceResolver resourceResolver) {
this(fontFileURI, null, true, EmbeddingMode.AUTO, EncodingMode.AUTO, true, true, resourceResolver, false,
false);
false, true);
}

/**
@@ -79,15 +80,16 @@ public class OFFontLoader extends FontLoader {
* @param resolver the FontResolver for font URI resolution
* @param simulateStyle Determines whether to simulate font styles if a font does not support those by default.
*/
public OFFontLoader(URI fontFileURI, String subFontName, boolean embedded,
EmbeddingMode embeddingMode, EncodingMode encodingMode, boolean useKerning,
boolean useAdvanced, InternalResourceResolver resolver, boolean simulateStyle, boolean embedAsType1) {
public OFFontLoader(URI fontFileURI, String subFontName, boolean embedded, EmbeddingMode embeddingMode,
EncodingMode encodingMode, boolean useKerning, boolean useAdvanced, InternalResourceResolver resolver,
boolean simulateStyle, boolean embedAsType1, boolean useSVG) {
super(fontFileURI, embedded, useKerning, useAdvanced, resolver);
this.subFontName = subFontName;
this.encodingMode = encodingMode;
this.embeddingMode = embeddingMode;
this.simulateStyle = simulateStyle;
this.embedAsType1 = embedAsType1;
this.useSVG = useSVG;
if (this.encodingMode == EncodingMode.AUTO) {
this.encodingMode = EncodingMode.CID; //Default to CID mode for TrueType
}
@@ -118,7 +120,7 @@ public class OFFontLoader extends FontLoader {
if (!supported) {
throw new IOException("The font does not have a Unicode cmap table: " + fontFileURI);
}
buildFont(otf, ttcFontName, embedAsType1);
buildFont(otf, ttcFontName);
loaded = true;
} finally {
IOUtils.closeQuietly(in);
@@ -133,7 +135,7 @@ public class OFFontLoader extends FontLoader {
return null;
}

private void buildFont(OpenFont otf, String ttcFontName, boolean embedAsType1) {
private void buildFont(OpenFont otf, String ttcFontName) {
boolean isCid = this.embedded;
if (this.encodingMode == EncodingMode.SINGLE_BYTE) {
isCid = false;
@@ -201,6 +203,9 @@ public class OFFontLoader extends FontLoader {
copyGlyphMetricsSingleByte(otf);
}
returnFont.setCMap(getCMap(otf));
if (useSVG) {
returnFont.setSVG(otf.svgs);
}

if (otf.getKerning() != null && useKerning) {
copyKerning(otf, isCid);

+ 2
- 0
fop-core/src/main/java/org/apache/fop/fonts/truetype/OFTableName.java View File

@@ -119,6 +119,8 @@ public final class OFTableName {
/** Vertical Metrics. */
public static final OFTableName VMTX = new OFTableName("vmtx");

public static final OFTableName SVG = new OFTableName("SVG ");

private final String name;

private OFTableName(String name) {

+ 30
- 0
fop-core/src/main/java/org/apache/fop/fonts/truetype/OpenFont.java View File

@@ -31,6 +31,7 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -219,6 +220,7 @@ public abstract class OpenFont {

private int[] ansiWidth;
private Map<Integer, List<Integer>> ansiIndex;
protected Map<Integer, SVGGlyphData> svgs;

// internal mapping of glyph indexes to unicode indexes
// used for quick mappings in this class
@@ -839,6 +841,7 @@ public abstract class OpenFont {
readPostScript();
readOS2();
determineAscDesc();
readSVG();

readName();
boolean pcltFound = readPCLT();
@@ -1329,6 +1332,33 @@ public abstract class OpenFont {
}
}

private void readSVG() throws IOException {
OFDirTabEntry dirTab = dirTabs.get(OFTableName.SVG);
if (dirTab != null) {
svgs = new LinkedHashMap<>();
fontFile.seekSet(dirTab.getOffset());
fontFile.readTTFUShort(); //version
fontFile.readTTFULong(); //svgDocumentListOffset
fontFile.readTTFULong(); //reserved
int numEntries = fontFile.readTTFUShort();
for (int i = 0; i < numEntries; i++) {
int startGlyphID = fontFile.readTTFUShort();
fontFile.readTTFUShort(); //endGlyphID
SVGGlyphData svgGlyph = new SVGGlyphData();
svgGlyph.svgDocOffset = fontFile.readTTFULong();
svgGlyph.svgDocLength = fontFile.readTTFULong();
svgs.put(startGlyphID, svgGlyph);
}
for (SVGGlyphData entry : svgs.values()) {
seekTab(fontFile, OFTableName.SVG, entry.svgDocOffset);
fontFile.readTTFUShort(); //version
fontFile.readTTFULong(); //svgDocumentListOffset
fontFile.readTTFULong(); //reserved
entry.setSVG(fontFile.readTTFString((int) entry.svgDocLength));
}
}
}

/**
* Read "hmtx" table and put the horizontal metrics
* in the mtxTab array. If the number of metrics is less

+ 100
- 0
fop-core/src/main/java/org/apache/fop/fonts/truetype/SVGGlyphData.java View File

@@ -0,0 +1,100 @@
/*
* 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.fonts.truetype;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import org.apache.xmlgraphics.util.uri.DataURLUtil;

public class SVGGlyphData {
protected long svgDocOffset;
protected long svgDocLength;
private String svg;
public float scale = 1;

public void setSVG(String svg) {
this.svg = svg;
}

public String getDataURL(int height) {
try {
String modifiedSVG = updateTransform(svg, height);
return DataURLUtil.createDataURL(new ByteArrayInputStream(modifiedSVG.getBytes("UTF-8")), "image/svg");
} catch (IOException | TransformerException | SAXException | ParserConfigurationException e) {
throw new RuntimeException(e);
}
}

private String updateTransform(String svg, int height)
throws IOException, ParserConfigurationException, SAXException, TransformerException {
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
InputSource inputSource = new InputSource();
inputSource.setCharacterStream(new StringReader(svg));
Document doc = documentBuilder.parse(inputSource);
NodeList nodes = doc.getElementsByTagName("g");
Element gElement = (Element) nodes.item(0);
if (gElement != null) {
String transform = gElement.getAttribute("transform");
if (transform.contains("scale(")) {
String scaleStr = transform.split("scale\\(")[1].split("\\)")[0].trim();
scale = Float.parseFloat(scaleStr);
gElement.removeAttribute("transform");
} else {
gElement.setAttribute("transform", "translate(0," + height + ")");
}
} else {
Element svgElement = (Element) doc.getElementsByTagName("svg").item(0);
svgElement.setAttribute("viewBox", "0 0 1000 " + height);
gElement = doc.createElement("g");
gElement.setAttribute("transform", "translate(0," + height + ")");
NodeList paths = doc.getElementsByTagName("path");
for (int i = 0; i < paths.getLength(); i++) {
Node path = paths.item(i);
if (i == 0) {
path.getParentNode().insertBefore(gElement, path);
}
gElement.appendChild(path);
}
}
Transformer transformer = TransformerFactory.newInstance().newTransformer();
StreamResult result = new StreamResult(new StringWriter());
DOMSource source = new DOMSource(doc);
transformer.transform(source, result);
return result.getWriter().toString();
}
}

+ 1
- 1
fop-core/src/main/java/org/apache/fop/render/afp/AFPFontConfig.java View File

@@ -384,7 +384,7 @@ public final class AFPFontConfig implements FontConfig {
try {
FontUris fontUris = new FontUris(new URI(fontUri), null);
EmbedFontInfo embedFontInfo = new EmbedFontInfo(fontUris, false, true, null, subfont, EncodingMode.AUTO,
EmbeddingMode.FULL, false, false);
EmbeddingMode.FULL, false, false, true);
Typeface tf = new LazyFont(embedFontInfo, resourceResolver, false).getRealFont();
AFPResourceAccessor accessor = getAccessor(resourceResolver);
CharacterSet characterSet = CharacterSetBuilder.getDoubleByteInstance().build(characterset,

+ 24
- 0
fop-core/src/main/java/org/apache/fop/render/intermediate/AbstractIFPainter.java View File

@@ -46,8 +46,11 @@ import org.apache.xmlgraphics.image.loader.util.ImageUtil;
import org.apache.fop.ResourceEventProducer;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fo.Constants;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.MultiByteFont;
import org.apache.fop.fonts.truetype.SVGGlyphData;
import org.apache.fop.render.ImageHandler;
import org.apache.fop.render.ImageHandlerRegistry;
import org.apache.fop.render.ImageHandlerUtil;
@@ -469,4 +472,25 @@ public abstract class AbstractIFPainter<T extends IFDocumentHandler> implements
int[][] dp, String text, boolean nextIsSpace) throws IFException {
drawText(x, y, letterSpacing, wordSpacing, dp, text);
}

protected void drawSVGText(MultiByteFont multiByteFont, FontTriplet triplet, int x, int y, String text,
IFState state) throws IFException {
int sizeMillipoints = state.getFontSize();
Font font = getFontInfo().getFontInstance(triplet, sizeMillipoints);
int newx = x;
for (char c : text.toCharArray()) {
SVGGlyphData svg = multiByteFont.getSVG(c);
if (svg != null) {
int codePoint = font.mapCodePoint(c);
String dataURL = svg.getDataURL(multiByteFont.getCapHeight());
Rectangle boundingBox = multiByteFont.getBoundingBox(codePoint, (int) (sizeMillipoints / 1000f));
boundingBox.y = y - boundingBox.height - boundingBox.y;
boundingBox.x = newx;
boundingBox.width = (int) (sizeMillipoints * svg.scale);
boundingBox.height = (int) (sizeMillipoints * svg.scale);
drawImage(dataURL, boundingBox);
}
newx += font.getCharWidth(c);
}
}
}

+ 3
- 3
fop-core/src/main/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java View File

@@ -83,11 +83,11 @@ public class ConfiguredFontCollection implements FontCollection {
font = new CustomFontMetricsMapper(fontMetrics, fontSource);
} else {
FontUris fontUris = configFontInfo.getFontUris();
CustomFont fontMetrics = FontLoader.loadFont(fontUris,
configFontInfo.getSubFontName(), true,
CustomFont fontMetrics = FontLoader.loadFont(fontUris, configFontInfo.getSubFontName(), true,
configFontInfo.getEmbeddingMode(), configFontInfo.getEncodingMode(),
configFontInfo.getKerning(), configFontInfo.getAdvanced(), resourceResolver,
configFontInfo.getSimulateStyle(), configFontInfo.getEmbedAsType1());
configFontInfo.getSimulateStyle(), configFontInfo.getEmbedAsType1(),
configFontInfo.getUseSVG());
font = new CustomFontMetricsMapper(fontMetrics);
}


+ 6
- 2
fop-core/src/main/java/org/apache/fop/render/pdf/PDFPainter.java View File

@@ -43,6 +43,7 @@ import org.apache.fop.fonts.CustomFont;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.LazyFont;
import org.apache.fop.fonts.MultiByteFont;
import org.apache.fop.fonts.SingleByteFont;
import org.apache.fop.fonts.Typeface;
import org.apache.fop.pdf.PDFArray;
@@ -431,8 +432,11 @@ public class PDFPainter extends AbstractIFPainter<PDFDocumentHandler> {

FontTriplet triplet = new FontTriplet(
state.getFontFamily(), state.getFontStyle(), state.getFontWeight());

if ((dp == null) || IFUtil.isDPOnlyDX(dp)) {
String fontKey = getFontInfo().getInternalFontKey(triplet);
Typeface typeface = getTypeface(fontKey);
if (typeface instanceof MultiByteFont && ((MultiByteFont) typeface).hasSVG()) {
drawSVGText((MultiByteFont) typeface, triplet, x, y, text, state);
} else if ((dp == null) || IFUtil.isDPOnlyDX(dp)) {
drawTextWithDX(x, y, text, triplet, letterSpacing,
wordSpacing, IFUtil.convertDPToDX(dp));
} else {

+ 32
- 23
fop-core/src/main/java/org/apache/fop/render/ps/PSImageHandlerSVG.java View File

@@ -21,6 +21,7 @@ package org.apache.fop.render.ps;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
@@ -43,14 +44,11 @@ import org.w3c.dom.NodeList;
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.transcoder.SVGAbstractTranscoder;
import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.PNGTranscoder;

import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageException;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D;
import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
import org.apache.xmlgraphics.ps.ImageEncoder;
import org.apache.xmlgraphics.ps.ImageEncodingHelper;
@@ -58,6 +56,7 @@ import org.apache.xmlgraphics.ps.PSGenerator;

import org.apache.fop.image.loader.batik.BatikImageFlavors;
import org.apache.fop.image.loader.batik.BatikUtil;
import org.apache.fop.image.loader.batik.ImageConverterSVG2G2D;
import org.apache.fop.render.ImageHandler;
import org.apache.fop.render.RenderingContext;
import org.apache.fop.render.ps.svg.PSSVGGraphics2D;
@@ -85,7 +84,7 @@ public class PSImageHandlerSVG implements ImageHandler {
ImageXMLDOM imageSVG = (ImageXMLDOM)image;

if (shouldRaster(imageSVG)) {
InputStream is = renderSVGToInputStream(context, imageSVG);
InputStream is = renderSVGToInputStream(imageSVG, pos);

float x = (float) pos.getX() / 1000f;
float y = (float) pos.getY() / 1000f;
@@ -175,25 +174,35 @@ public class PSImageHandlerSVG implements ImageHandler {
}
}

private InputStream renderSVGToInputStream(RenderingContext context, ImageXMLDOM imageSVG) throws IOException {
PNGTranscoder png = new PNGTranscoder();
Float width = getDimension(imageSVG.getDocument(), "width") * 8;
png.addTranscodingHint(SVGAbstractTranscoder.KEY_WIDTH, width);
Float height = getDimension(imageSVG.getDocument(), "height") * 8;
png.addTranscodingHint(SVGAbstractTranscoder.KEY_HEIGHT, height);
TranscoderInput input = new TranscoderInput(imageSVG.getDocument());
ByteArrayOutputStream os = new ByteArrayOutputStream();
TranscoderOutput output = new TranscoderOutput(os);
private InputStream renderSVGToInputStream(ImageXMLDOM imageSVG, Rectangle destinationRect)
throws IOException {
Rectangle rectangle;
int width;
int height;
Float widthSVG = getDimension(imageSVG.getDocument(), "width");
Float heightSVG = getDimension(imageSVG.getDocument(), "height");
if (widthSVG != null && heightSVG != null) {
width = (int) (widthSVG * 8);
height = (int) (heightSVG * 8);
rectangle = new Rectangle(0, 0, width, height);
} else {
int scale = 10;
width = destinationRect.width / scale;
height = destinationRect.height / scale;
rectangle = new Rectangle(0, 0, destinationRect.width / 100, destinationRect.height / 100);
destinationRect.width *= scale;
destinationRect.height *= scale;
}
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics2D = image.createGraphics();
try {
png.transcode(input, output);
} catch (TranscoderException ex) {
SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
context.getUserAgent().getEventBroadcaster());
eventProducer.svgRenderingError(this, ex, imageSVG.getInfo().getOriginalURI());
} finally {
os.flush();
os.close();
ImageGraphics2D img = (ImageGraphics2D) new ImageConverterSVG2G2D().convert(imageSVG, new HashMap());
img.getGraphics2DImagePainter().paint(graphics2D, rectangle);
} catch (ImageException e) {
throw new IOException(e);
}
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(image, "png", os);
return new ByteArrayInputStream(os.toByteArray());
}


+ 18
- 15
fop-core/src/main/java/org/apache/fop/render/ps/PSPainter.java View File

@@ -359,25 +359,28 @@ public class PSPainter extends AbstractIFPainter<PSDocumentHandler> {
}
PSGenerator generator = getGenerator();
generator.useColor(state.getTextColor());
FontTriplet triplet = new FontTriplet(state.getFontFamily(), state.getFontStyle(), state.getFontWeight());
String fontKey = getFontKey(triplet);
Typeface typeface = getTypeface(fontKey);
if (typeface instanceof MultiByteFont && ((MultiByteFont) typeface).hasSVG()) {
drawSVGText((MultiByteFont) typeface, triplet, x, y, text, state);
return;
}
beginTextObject();
FontTriplet triplet = new FontTriplet(
state.getFontFamily(), state.getFontStyle(), state.getFontWeight());
//TODO Ignored: state.getFontVariant()
//TODO Opportunity for font caching if font state is more heavily used
String fontKey = getFontKey(triplet);
int sizeMillipoints = state.getFontSize();

// This assumes that *all* CIDFonts use a /ToUnicode mapping
Typeface tf = getTypeface(fontKey);
SingleByteFont singleByteFont = null;
if (tf instanceof SingleByteFont) {
singleByteFont = (SingleByteFont)tf;
if (typeface instanceof SingleByteFont) {
singleByteFont = (SingleByteFont)typeface;
}
Font font = getFontInfo().getFontInstance(triplet, sizeMillipoints);

PSFontResource res = getDocumentHandler().getPSResourceForFontKey(fontKey);
boolean otf = tf instanceof MultiByteFont && ((MultiByteFont)tf).isOTFFile();
useFont(fontKey, sizeMillipoints, otf);
boolean isOpenTypeFont = typeface instanceof MultiByteFont && ((MultiByteFont)typeface).isOTFFile();
useFont(fontKey, sizeMillipoints, isOpenTypeFont);

if (dp != null && dp[0] != null) {
x += dp[0][0];
@@ -393,12 +396,12 @@ public class PSPainter extends AbstractIFPainter<PSDocumentHandler> {
int currentEncoding = -1;
for (int i = 0; i < textLen; i++) {
char c = text.charAt(i);
char mapped = tf.mapChar(c);
char mapped = typeface.mapChar(c);
int encoding = mapped / 256;
if (currentEncoding != encoding) {
if (i > 0) {
writeText(text, start, i - start,
letterSpacing, wordSpacing, dp, font, tf, false);
letterSpacing, wordSpacing, dp, font, typeface, false);
}
if (encoding == 0) {
useFont(fontKey, sizeMillipoints, false);
@@ -410,20 +413,20 @@ public class PSPainter extends AbstractIFPainter<PSDocumentHandler> {
}
}
} else {
if (tf instanceof MultiByteFont && ((MultiByteFont)tf).isOTFFile()) {
if (typeface instanceof MultiByteFont && ((MultiByteFont)typeface).isOTFFile()) {
//Analyze string and split up in order to paint in different sub-fonts/encodings
int curEncoding = 0;
for (int i = start; i < textLen; i++) {
char orgChar = text.charAt(i);

MultiByteFont mbFont = (MultiByteFont)tf;
MultiByteFont mbFont = (MultiByteFont)typeface;
mbFont.mapChar(orgChar);
int origGlyphIdx = mbFont.findGlyphIndex(orgChar);
int newGlyphIdx = mbFont.getUsedGlyphs().get(origGlyphIdx);
int encoding = newGlyphIdx / 256;
if (encoding != curEncoding) {
if (i != 0) {
writeText(text, start, i - start, letterSpacing, wordSpacing, dp, font, tf,
writeText(text, start, i - start, letterSpacing, wordSpacing, dp, font, typeface,
true);
start = i;
}
@@ -435,8 +438,8 @@ public class PSPainter extends AbstractIFPainter<PSDocumentHandler> {
useFont(fontKey, sizeMillipoints, false);
}
}
writeText(text, start, textLen - start, letterSpacing, wordSpacing, dp, font, tf,
tf instanceof MultiByteFont);
writeText(text, start, textLen - start, letterSpacing, wordSpacing, dp, font, typeface,
typeface instanceof MultiByteFont);
} catch (IOException ioe) {
throw new IFException("I/O error in drawText()", ioe);
}

+ 1
- 1
fop-core/src/test/java/org/apache/fop/fonts/DejaVuLGCSerifTestCase.java View File

@@ -49,7 +49,7 @@ public class DejaVuLGCSerifTestCase {
File file = new File("test/resources/fonts/ttf/DejaVuLGCSerif.ttf");
FontUris fontUris = new FontUris(file.toURI(), null);
font = FontLoader.loadFont(fontUris, "", true, EmbeddingMode.AUTO, EncodingMode.AUTO,
false, false, resolver, false, false);
false, false, resolver, false, false, true);
}

/**

+ 1
- 1
fop-core/src/test/java/org/apache/fop/fonts/EmbedFontInfoTestCase.java View File

@@ -54,7 +54,7 @@ public class EmbedFontInfoTestCase {
triplets.add(triplet);
FontUris fontUris = new FontUris(embedURI, metricsURI);
sut = new EmbedFontInfo(fontUris, kerning, useAdvanced, triplets, subFontName, encMode,
embedMode, false, false);
embedMode, false, false, true);
}

@Test

+ 1
- 1
fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFToType1TestCase.java View File

@@ -78,7 +78,7 @@ public class OTFToType1TestCase {
InternalResourceResolver rr = ResourceResolverFactory.createDefaultInternalResourceResolver(
new File(".").toURI());
CustomFont realFont = FontLoader.loadFont(new FontUris(new File(s).toURI(), null), null, true,
EmbeddingMode.SUBSET, EncodingMode.AUTO, true, true, rr, false, true);
EmbeddingMode.SUBSET, EncodingMode.AUTO, true, true, rr, false, true, true);
realFont.mapChar('d');
return realFont;
}

+ 2
- 2
fop-core/src/test/java/org/apache/fop/fonts/truetype/TTFFontLoaderTestCase.java View File

@@ -51,12 +51,12 @@ public class TTFFontLoaderTestCase {

OFFontLoader fontLoader = new OFFontLoader(absoluteFilePath, fontName, embedded,
EmbeddingMode.AUTO, EncodingMode.AUTO, useKerning, useComplexScriptFeatures,
resourceResolver, false, false);
resourceResolver, false, false, true);
assertTrue(fontLoader.getFont().hasKerningInfo());
useKerning = false;

fontLoader = new OFFontLoader(absoluteFilePath, fontName, embedded, EmbeddingMode.AUTO,
EncodingMode.AUTO, useKerning, useComplexScriptFeatures, resourceResolver, false, false);
EncodingMode.AUTO, useKerning, useComplexScriptFeatures, resourceResolver, false, false, true);
assertFalse(fontLoader.getFont().hasKerningInfo());
}
}

+ 4
- 1
fop-core/src/test/java/org/apache/fop/fonts/type1/Type1FontLoaderTestCase.java View File

@@ -29,6 +29,7 @@ import org.junit.Test;

import org.apache.commons.io.IOUtils;

import org.apache.fop.apps.io.InternalResourceResolver;
import org.apache.fop.apps.io.ResourceResolverFactory;
import org.apache.fop.fonts.CustomFont;
import org.apache.fop.fonts.EmbeddingMode;
@@ -50,8 +51,10 @@ public class Type1FontLoaderTestCase {
fos.close();

FontUris fontUris = new FontUris(pfbNoAFM.toURI(), null, null, pfm.toURI());
InternalResourceResolver resourceResolver =
ResourceResolverFactory.createDefaultInternalResourceResolver(new File(".").toURI());
CustomFont x = FontLoader.loadFont(fontUris, null, true, EmbeddingMode.AUTO, EncodingMode.AUTO, true, true,
ResourceResolverFactory.createDefaultInternalResourceResolver(new File(".").toURI()), false, false);
resourceResolver, false, false, true);
Assert.assertEquals(x.getBoundingBox(0, 12).getBounds(), new Rectangle(-240, -60, 0, 60));
} finally {
pfbNoAFM.delete();

+ 1
- 1
fop-core/src/test/java/org/apache/fop/pdf/PDFFactoryTestCase.java View File

@@ -144,7 +144,7 @@ public class PDFFactoryTestCase {
PDFFactory pdfFactory = new PDFFactory(doc);
URI uri = new File("test/resources/fonts/otf/SourceSansProBold.otf").toURI();
CustomFont sb = OFFontLoader.loadFont(new FontUris(uri, null),
null, true, EmbeddingMode.SUBSET, null, false, false, rr, false, false);
null, true, EmbeddingMode.SUBSET, null, false, false, rr, false, false, true);
for (char c = 0; c < 512; c++) {
sb.mapChar(c);
}

+ 36
- 0
fop-core/src/test/java/org/apache/fop/render/pdf/PDFPainterTestCase.java View File

@@ -25,7 +25,9 @@ import java.awt.Rectangle;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.xml.transform.stream.StreamResult;

@@ -49,6 +51,7 @@ import org.apache.fop.fo.Constants;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.MultiByteFont;
import org.apache.fop.fonts.truetype.SVGGlyphData;
import org.apache.fop.pdf.PDFDocument;
import org.apache.fop.pdf.PDFFilterList;
import org.apache.fop.pdf.PDFPage;
@@ -305,4 +308,37 @@ public class PDFPainterTestCase {
+ "\n"
+ "endstream");
}

@Test
public void testSVGFont() throws IFException, IOException {
FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
foUserAgent = fopFactory.newFOUserAgent();
PDFDocumentHandler pdfDocumentHandler = new PDFDocumentHandler(new IFContext(foUserAgent));
pdfDocumentHandler.setResult(new StreamResult(new ByteArrayOutputStream()));
pdfDocumentHandler.startDocument();
pdfDocumentHandler.startPage(0, "", "", new Dimension());
FontInfo fi = new FontInfo();
fi.addFontProperties("f1", new FontTriplet("a", "normal", 400));
MultiByteFont font = new MultiByteFont(null, null);
font.setWidthArray(new int[1]);
Map<Integer, SVGGlyphData> svgs = new HashMap<>();
SVGGlyphData svgGlyph = new SVGGlyphData();
svgGlyph.setSVG("<svg xmlns=\"http://www.w3.org/2000/svg\">\n"
+ "<circle cx=\"50\" cy=\"50\" r=\"40\" stroke=\"black\" stroke-width=\"3\" fill=\"red\" />\n"
+ "</svg>");
svgs.put(0, svgGlyph);
font.setSVG(svgs);
font.setBBoxArray(new Rectangle[] {new Rectangle()});
fi.addMetrics("f1", font);
pdfDocumentHandler.setFontInfo(fi);
PDFPainter pdfPainter = new PDFPainter(pdfDocumentHandler, null);
pdfPainter.setFont("a", "normal", 400, null, 12, null);
pdfPainter.drawText(0, 0, 0, 0, null, "test");
PDFFilterList filters = pdfPainter.generator.getStream().getFilterList();
filters.setDisableAllFilters(true);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
pdfPainter.generator.getStream().output(bos);
Assert.assertTrue(bos.toString().contains("0.00012 0 0 0.00012 0 0 cm"));
Assert.assertTrue(bos.toString().contains("1 0 0 rg"));
}
}

+ 33
- 0
fop-core/src/test/java/org/apache/fop/render/ps/PSPainterTestCase.java View File

@@ -17,6 +17,7 @@
package org.apache.fop.render.ps;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -54,6 +55,7 @@ import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.MultiByteFont;
import org.apache.fop.fonts.Typeface;
import org.apache.fop.fonts.truetype.SVGGlyphData;
import org.apache.fop.render.intermediate.IFContext;
import org.apache.fop.render.intermediate.IFException;
import org.apache.fop.render.intermediate.IFState;
@@ -242,4 +244,35 @@ public class PSPainterTestCase {
mbf.setIsOTFFile(otf);
fi.addMetrics(name, mbf);
}

@Test
public void testSVGFont() throws IFException {
FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
PSDocumentHandler psDocumentHandler = new PSDocumentHandler(new IFContext(foUserAgent));
ByteArrayOutputStream bos = new ByteArrayOutputStream();
psDocumentHandler.setResult(new StreamResult(bos));
psDocumentHandler.startDocument();
psDocumentHandler.startPage(0, "", "", new Dimension());
FontInfo fi = new FontInfo();
fi.addFontProperties("f1", new FontTriplet("a", "normal", 400));
MultiByteFont font = new MultiByteFont(null, null);
font.setWidthArray(new int[1]);
Map<Integer, SVGGlyphData> svgs = new HashMap<>();
SVGGlyphData svgGlyph = new SVGGlyphData();
svgGlyph.setSVG("<svg xmlns=\"http://www.w3.org/2000/svg\">\n"
+ "<circle cx=\"50\" cy=\"50\" r=\"40\" stroke=\"black\" stroke-width=\"3\" fill=\"red\" />\n"
+ "</svg>");
svgs.put(0, svgGlyph);
font.setSVG(svgs);
font.setBBoxArray(new Rectangle[] {new Rectangle()});
fi.addMetrics("f1", font);
psDocumentHandler.setFontInfo(fi);
PSPainter psPainter = new PSPainter(psDocumentHandler);
psPainter.setFont("a", "normal", 400, null, 12, Color.black);
psPainter.drawText(0, 0, 0, 0, null, "test");
Assert.assertTrue(bos.toString().contains("%FOPBeginSVG"));
Assert.assertTrue(bos.toString().contains("[0.00012 0 0 0.00012 0 0] CT"));
Assert.assertTrue(bos.toString().contains("1 0 0 RC"));
}
}

+ 1
- 1
fop-core/src/test/java/org/apache/fop/svg/font/FontInfoBuilder.java View File

@@ -83,7 +83,7 @@ class FontInfoBuilder {
URI baseURI = new File("test/resources/fonts/ttf").toURI();
InternalResourceResolver resolver = ResourceResolverFactory.createDefaultInternalResourceResolver(baseURI);
OFFontLoader fontLoader = new OFFontLoader(new URI(filename), null, true,
EmbeddingMode.AUTO, EncodingMode.AUTO, true, useAdvanced, resolver, false, false);
EmbeddingMode.AUTO, EncodingMode.AUTO, true, useAdvanced, resolver, false, false, true);
FontMetrics font = fontLoader.getFont();
registerFont(font, "F" + fontKey++, fontName);
return this;

Loading…
Cancel
Save