git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1745490 13f79535-47bb-0310-9956-ffa450edef68pull/3/head
import java.io.ByteArrayOutputStream; | import java.io.ByteArrayOutputStream; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.io.InputStream; | import java.io.InputStream; | ||||
import java.util.ArrayList; | |||||
import java.util.HashMap; | |||||
import java.util.List; | |||||
import java.util.Map; | |||||
import org.apache.commons.io.IOUtils; | import org.apache.commons.io.IOUtils; | ||||
import org.apache.fontbox.cff.CFFFont; | import org.apache.fontbox.cff.CFFFont; | ||||
} | } | ||||
public InputStream getInputStream() throws IOException { | public InputStream getInputStream() throws IOException { | ||||
return null; | |||||
} | |||||
public List<InputStream> getInputStreams() throws IOException { | |||||
InputStream cff = super.getInputStream(); | InputStream cff = super.getInputStream(); | ||||
return convertOTFToType1(cff); | return convertOTFToType1(cff); | ||||
} | } | ||||
private InputStream convertOTFToType1(InputStream in) throws IOException { | |||||
private List<InputStream> convertOTFToType1(InputStream in) throws IOException { | |||||
CFFFont f = new CFFParser().parse(IOUtils.toByteArray(in)).get(0); | CFFFont f = new CFFParser().parse(IOUtils.toByteArray(in)).get(0); | ||||
if (!(f instanceof CFFType1Font)) { | if (!(f instanceof CFFType1Font)) { | ||||
throw new IOException(getEmbedFileURI() + ": only OTF CFF Type1 font can be converted to Type1"); | throw new IOException(getEmbedFileURI() + ": only OTF CFF Type1 font can be converted to Type1"); | ||||
} | } | ||||
byte[] t1 = new Type1FontFormatter(cidSet.getGlyphs(), eventListener).format((CFFType1Font) f); | |||||
List<InputStream> fonts = new ArrayList<InputStream>(); | |||||
Map<Integer, Integer> glyphs = cidSet.getGlyphs(); | |||||
int i = 0; | |||||
for (Map<Integer, Integer> x : splitGlyphs(glyphs)) { | |||||
String iStr = "." + i; | |||||
fonts.add(convertOTFToType1(x, f, iStr)); | |||||
i++; | |||||
} | |||||
return fonts; | |||||
} | |||||
private List<Map<Integer, Integer>> splitGlyphs(Map<Integer, Integer> glyphs) { | |||||
List<Map<Integer, Integer>> allGlyphs = new ArrayList<Map<Integer, Integer>>(); | |||||
for (Map.Entry<Integer, Integer> x : glyphs.entrySet()) { | |||||
int k = x.getKey(); | |||||
int v = x.getValue(); | |||||
int pot = v / 256; | |||||
v = v % 256; | |||||
while (allGlyphs.size() < pot + 1) { | |||||
Map<Integer, Integer> glyphsPerFont = new HashMap<Integer, Integer>(); | |||||
glyphsPerFont.put(0, 0); | |||||
allGlyphs.add(glyphsPerFont); | |||||
} | |||||
allGlyphs.get(pot).put(k, v); | |||||
} | |||||
return allGlyphs; | |||||
} | |||||
private InputStream convertOTFToType1(Map<Integer, Integer> glyphs, CFFFont f, String i) throws IOException { | |||||
byte[] t1 = new Type1FontFormatter(glyphs).format((CFFType1Font) f, i); | |||||
PFBData pfb = new PFBParser().parsePFB(new ByteArrayInputStream(t1)); | PFBData pfb = new PFBParser().parsePFB(new ByteArrayInputStream(t1)); | ||||
ByteArrayOutputStream s1 = new ByteArrayOutputStream(); | ByteArrayOutputStream s1 = new ByteArrayOutputStream(); | ||||
s1.write(pfb.getHeaderSegment()); | s1.write(pfb.getHeaderSegment()); |
getEventProducer().fontDirectoryNotFound(source, dir); | getEventProducer().fontDirectoryNotFound(source, dir); | ||||
} | } | ||||
public void fontType1MaxGlyphs(Object source, String fontName) { | |||||
getEventProducer().fontType1MaxGlyphs(source, fontName); | |||||
} | |||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public void svgTextStrokedAsShapes(Object source, String fontFamily) { | public void svgTextStrokedAsShapes(Object source, String fontFamily) { | ||||
getEventProducer().svgTextStrokedAsShapes(source, fontFamily); | getEventProducer().svgTextStrokedAsShapes(source, fontFamily); |
* @param fontFamily the family name of the font that is being stroked | * @param fontFamily the family name of the font that is being stroked | ||||
*/ | */ | ||||
void svgTextStrokedAsShapes(Object source, String fontFamily); | void svgTextStrokedAsShapes(Object source, String fontFamily); | ||||
void fontType1MaxGlyphs(Object source, String fontName); | |||||
} | } |
*/ | */ | ||||
void svgTextStrokedAsShapes(Object source, String fontFamily); | void svgTextStrokedAsShapes(Object source, String fontFamily); | ||||
/** | |||||
* A method to warn the user that the font has too many glyphs | |||||
* @param source | |||||
* @param fontName | |||||
* @event.severity ERROR | |||||
*/ | |||||
void fontType1MaxGlyphs(Object source, String fontName); | |||||
} | } |
multiFont = new CFFToType1Font(resourceResolver, embeddingMode); | multiFont = new CFFToType1Font(resourceResolver, embeddingMode); | ||||
} else { | } else { | ||||
multiFont = new MultiByteFont(resourceResolver, embeddingMode); | multiFont = new MultiByteFont(resourceResolver, embeddingMode); | ||||
multiFont.setIsOTFFile(otf instanceof OTFFile); | |||||
} | } | ||||
multiFont.setIsOTFFile(otf instanceof OTFFile); | |||||
returnFont = multiFont; | returnFont = multiFont; | ||||
multiFont.setTTCName(ttcFontName); | multiFont.setTTCName(ttcFontName); | ||||
} else { | } else { |
import java.io.ByteArrayInputStream; | import java.io.ByteArrayInputStream; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.io.InputStream; | import java.io.InputStream; | ||||
import java.util.ArrayList; | |||||
import java.util.HashMap; | import java.util.HashMap; | ||||
import java.util.HashSet; | import java.util.HashSet; | ||||
import java.util.List; | |||||
import java.util.Locale; | import java.util.Locale; | ||||
import java.util.Map; | import java.util.Map; | ||||
import java.util.Set; | import java.util.Set; | ||||
import org.apache.xmlgraphics.ps.dsc.ResourceTracker; | import org.apache.xmlgraphics.ps.dsc.ResourceTracker; | ||||
import org.apache.fop.fonts.Base14Font; | import org.apache.fop.fonts.Base14Font; | ||||
import org.apache.fop.fonts.CFFToType1Font; | |||||
import org.apache.fop.fonts.CIDFontType; | import org.apache.fop.fonts.CIDFontType; | ||||
import org.apache.fop.fonts.CIDSet; | import org.apache.fop.fonts.CIDSet; | ||||
import org.apache.fop.fonts.CMapSegment; | import org.apache.fop.fonts.CMapSegment; | ||||
Map fontResources = new HashMap(); | Map fontResources = new HashMap(); | ||||
for (String key : fonts.keySet()) { | for (String key : fonts.keySet()) { | ||||
Typeface tf = getTypeFace(fontInfo, fonts, key); | Typeface tf = getTypeFace(fontInfo, fonts, key); | ||||
PSResource fontRes = new PSResource(PSResource.TYPE_FONT, tf.getEmbedFontName()); | |||||
PSFontResource fontResource = embedFont(gen, tf, fontRes, eventProducer); | |||||
PSFontResource fontResource = embedFont(gen, tf, eventProducer); | |||||
fontResources.put(key, fontResource); | fontResources.put(key, fontResource); | ||||
if (tf instanceof SingleByteFont) { | if (tf instanceof SingleByteFont) { | ||||
return tf; | return tf; | ||||
} | } | ||||
private static PSFontResource embedFont(PSGenerator gen, Typeface tf, PSResource fontRes, | |||||
PSEventProducer eventProducer) throws IOException { | |||||
private static PSFontResource embedFont(PSGenerator gen, Typeface tf, PSEventProducer eventProducer) | |||||
throws IOException { | |||||
boolean embeddedFont = false; | boolean embeddedFont = false; | ||||
FontType fontType = tf.getFontType(); | FontType fontType = tf.getFontType(); | ||||
PSFontResource fontResource = null; | PSFontResource fontResource = null; | ||||
PSResource fontRes = new PSResource(PSResource.TYPE_FONT, tf.getEmbedFontName()); | |||||
if (!(fontType == FontType.TYPE1 || fontType == FontType.TRUETYPE | if (!(fontType == FontType.TYPE1 || fontType == FontType.TRUETYPE | ||||
|| fontType == FontType.TYPE0) || !(tf instanceof CustomFont)) { | || fontType == FontType.TYPE0) || !(tf instanceof CustomFont)) { | ||||
gen.writeDSCComment(DSCConstants.INCLUDE_RESOURCE, fontRes); | gen.writeDSCComment(DSCConstants.INCLUDE_RESOURCE, fontRes); | ||||
} | } | ||||
CustomFont cf = (CustomFont)tf; | CustomFont cf = (CustomFont)tf; | ||||
if (isEmbeddable(cf)) { | if (isEmbeddable(cf)) { | ||||
InputStream in = getInputStreamOnFont(gen, cf); | |||||
if (in != null) { | |||||
if (fontType == FontType.TYPE0) { | |||||
if (((MultiByteFont)tf).isOTFFile()) { | |||||
checkPostScriptLevel3(gen, eventProducer, "OpenType CFF"); | |||||
embedType2CFF(gen, (MultiByteFont) tf, in); | |||||
} else { | |||||
if (gen.embedIdentityH()) { | |||||
checkPostScriptLevel3(gen, eventProducer, "TrueType"); | |||||
List<InputStream> ins = getInputStreamOnFont(gen, cf); | |||||
if (ins != null) { | |||||
int i = 0; | |||||
for (InputStream in : ins) { | |||||
if (i > 0) { | |||||
fontRes = new PSResource(PSResource.TYPE_FONT, tf.getEmbedFontName() + "." + i); | |||||
} | |||||
if (fontType == FontType.TYPE0) { | |||||
if (((MultiByteFont) tf).isOTFFile()) { | |||||
checkPostScriptLevel3(gen, eventProducer, "OpenType CFF"); | |||||
embedType2CFF(gen, (MultiByteFont) tf, in); | |||||
} else { | |||||
if (gen.embedIdentityH()) { | |||||
checkPostScriptLevel3(gen, eventProducer, "TrueType"); | |||||
/* | /* | ||||
* First CID-keyed font to be embedded; add | * First CID-keyed font to be embedded; add | ||||
* %%IncludeResource: comment for ProcSet CIDInit. | * %%IncludeResource: comment for ProcSet CIDInit. | ||||
*/ | */ | ||||
gen.includeProcsetCIDInitResource(); | |||||
gen.includeProcsetCIDInitResource(); | |||||
} | |||||
PSResource cidFontResource; | |||||
cidFontResource = embedType2CIDFont(gen, | |||||
(MultiByteFont) tf, in); | |||||
fontResource = PSFontResource.createFontResource(fontRes, | |||||
gen.getProcsetCIDInitResource(), gen.getIdentityHCMapResource(), | |||||
cidFontResource); | |||||
} | } | ||||
PSResource cidFontResource; | |||||
cidFontResource = embedType2CIDFont(gen, | |||||
(MultiByteFont) tf, in); | |||||
fontResource = PSFontResource.createFontResource(fontRes, | |||||
gen.getProcsetCIDInitResource(), gen.getIdentityHCMapResource(), | |||||
cidFontResource); | |||||
} | } | ||||
gen.writeDSCComment(DSCConstants.BEGIN_RESOURCE, fontRes); | |||||
if (fontType == FontType.TYPE1) { | |||||
embedType1Font(gen, (CustomFont) tf, in); | |||||
if (fontResource == null) { | |||||
fontResource = PSFontResource.createFontResource(fontRes); | |||||
} | |||||
} else if (fontType == FontType.TRUETYPE) { | |||||
embedTrueTypeFont(gen, (SingleByteFont) tf, in); | |||||
fontResource = PSFontResource.createFontResource(fontRes); | |||||
} else if (!((MultiByteFont) tf).isOTFFile()) { | |||||
composeType0Font(gen, (MultiByteFont) tf); | |||||
} | |||||
gen.writeDSCComment(DSCConstants.END_RESOURCE); | |||||
gen.getResourceTracker().registerSuppliedResource(fontRes); | |||||
embeddedFont = true; | |||||
i++; | |||||
} | } | ||||
gen.writeDSCComment(DSCConstants.BEGIN_RESOURCE, fontRes); | |||||
if (fontType == FontType.TYPE1) { | |||||
embedType1Font(gen, (CustomFont) tf, in); | |||||
fontResource = PSFontResource.createFontResource(fontRes); | |||||
} else if (fontType == FontType.TRUETYPE) { | |||||
embedTrueTypeFont(gen, (SingleByteFont) tf, in); | |||||
fontResource = PSFontResource.createFontResource(fontRes); | |||||
} else { | |||||
composeType0Font(gen, (MultiByteFont) tf, in); | |||||
} | |||||
gen.writeDSCComment(DSCConstants.END_RESOURCE); | |||||
gen.getResourceTracker().registerSuppliedResource(fontRes); | |||||
embeddedFont = true; | |||||
} else { | } else { | ||||
gen.commentln("%WARNING: Could not embed font: " + cf.getEmbedFontName()); | gen.commentln("%WARNING: Could not embed font: " + cf.getEmbedFontName()); | ||||
log.warn("Font " + cf.getEmbedFontName() + " is marked as supplied in the" | log.warn("Font " + cf.getEmbedFontName() + " is marked as supplied in the" | ||||
if (!embeddedFont) { | if (!embeddedFont) { | ||||
gen.writeDSCComment(DSCConstants.INCLUDE_RESOURCE, fontRes); | gen.writeDSCComment(DSCConstants.INCLUDE_RESOURCE, fontRes); | ||||
fontResource = PSFontResource.createFontResource(fontRes); | fontResource = PSFontResource.createFontResource(fontRes); | ||||
return fontResource; | |||||
} | } | ||||
return fontResource; | return fontResource; | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
private static void composeType0Font(PSGenerator gen, MultiByteFont font, | |||||
InputStream fontStream) throws IOException { | |||||
private static void composeType0Font(PSGenerator gen, MultiByteFont font) throws IOException { | |||||
String psName = font.getEmbedFontName(); | String psName = font.getEmbedFontName(); | ||||
gen.write("/"); | gen.write("/"); | ||||
gen.write(psName); | gen.write(psName); | ||||
return font.isEmbeddable(); | return font.isEmbeddable(); | ||||
} | } | ||||
private static InputStream getInputStreamOnFont(PSGenerator gen, CustomFont font) | |||||
private static List<InputStream> getInputStreamOnFont(PSGenerator gen, CustomFont font) | |||||
throws IOException { | throws IOException { | ||||
if (isEmbeddable(font)) { | if (isEmbeddable(font)) { | ||||
List<InputStream> fonts = new ArrayList<InputStream>(); | |||||
InputStream in = font.getInputStream(); | InputStream in = font.getInputStream(); | ||||
if (in == null) { | if (in == null) { | ||||
if (font instanceof CFFToType1Font) { | |||||
return ((CFFToType1Font) font).getInputStreams(); | |||||
} | |||||
return null; | return null; | ||||
} | } | ||||
//Make sure the InputStream is decorated with a BufferedInputStream | //Make sure the InputStream is decorated with a BufferedInputStream | ||||
if (!(in instanceof java.io.BufferedInputStream)) { | if (!(in instanceof java.io.BufferedInputStream)) { | ||||
in = new java.io.BufferedInputStream(in); | in = new java.io.BufferedInputStream(in); | ||||
} | } | ||||
return in; | |||||
fonts.add(in); | |||||
return fonts; | |||||
} else { | } else { | ||||
return null; | return null; | ||||
} | } |
import org.apache.xmlgraphics.ps.PSGenerator; | import org.apache.xmlgraphics.ps.PSGenerator; | ||||
import org.apache.xmlgraphics.ps.PSResource; | import org.apache.xmlgraphics.ps.PSResource; | ||||
import org.apache.fop.fonts.CFFToType1Font; | |||||
import org.apache.fop.fonts.EmbeddingMode; | import org.apache.fop.fonts.EmbeddingMode; | ||||
import org.apache.fop.fonts.Font; | import org.apache.fop.fonts.Font; | ||||
import org.apache.fop.fonts.FontTriplet; | import org.apache.fop.fonts.FontTriplet; | ||||
true); | true); | ||||
start = i; | start = i; | ||||
} | } | ||||
generator.writeln("/" + res.getName() + "." + encoding + " " | |||||
+ generator.formatDouble(sizeMillipoints / 1000f) + " F"); | |||||
generator.useFont("/" + res.getName() + "." + encoding, sizeMillipoints / 1000f); | |||||
curEncoding = encoding; | curEncoding = encoding; | ||||
} | } | ||||
} | } | ||||
int lineStart = 0; | int lineStart = 0; | ||||
StringBuffer accText = new StringBuffer(initialSize); | StringBuffer accText = new StringBuffer(initialSize); | ||||
StringBuffer sb = new StringBuffer(initialSize); | StringBuffer sb = new StringBuffer(initialSize); | ||||
boolean isOTF = multiByte && ((MultiByteFont)tf).isOTFFile() || tf instanceof CFFToType1Font; | |||||
boolean isOTF = multiByte && ((MultiByteFont)tf).isOTFFile(); | |||||
for (int i = start; i < end; i++) { | for (int i = start; i < end; i++) { | ||||
char orgChar = text.charAt(i); | char orgChar = text.charAt(i); | ||||
char ch; | char ch; | ||||
private void useFont(String key, int size, boolean otf) throws IOException { | private void useFont(String key, int size, boolean otf) throws IOException { | ||||
PSFontResource res = getDocumentHandler().getPSResourceForFontKey(key); | PSFontResource res = getDocumentHandler().getPSResourceForFontKey(key); | ||||
PSGenerator generator = getGenerator(); | PSGenerator generator = getGenerator(); | ||||
String name = "/" + res.getName(); | |||||
if (otf) { | if (otf) { | ||||
String name = "/" + res.getName() + ".0"; | |||||
generator.getCurrentState().useFont(name, size); | |||||
generator.writeln(name + ' ' + generator.formatDouble(size / 1000f) + " F"); | |||||
} else { | |||||
generator.useFont("/" + res.getName(), size / 1000f); | |||||
name += ".0"; | |||||
} | } | ||||
generator.useFont(name, size / 1000f); | |||||
res.notifyResourceUsageOnPage(generator.getResourceTracker()); | res.notifyResourceUsageOnPage(generator.getResourceTracker()); | ||||
} | } | ||||
} | } |
import org.apache.fontbox.cff.DataOutput; | import org.apache.fontbox.cff.DataOutput; | ||||
import org.apache.fontbox.cff.Type1FontUtil; | import org.apache.fontbox.cff.Type1FontUtil; | ||||
import org.apache.fop.fonts.FontEventListener; | |||||
/** | /** | ||||
* This class represents a formatter for a given Type1 font. | * This class represents a formatter for a given Type1 font. | ||||
* author Villu Ruusmann | * author Villu Ruusmann | ||||
*/ | */ | ||||
public final class Type1FontFormatter { | public final class Type1FontFormatter { | ||||
private Map<Integer, Integer> gids; | private Map<Integer, Integer> gids; | ||||
private FontEventListener eventListener; | |||||
public Type1FontFormatter(Map<Integer, Integer> gids, FontEventListener eventListener) { | |||||
public Type1FontFormatter(Map<Integer, Integer> gids) { | |||||
this.gids = gids; | this.gids = gids; | ||||
this.eventListener = eventListener; | |||||
} | } | ||||
/** | /** | ||||
* Read and convert a given CFFFont. | * Read and convert a given CFFFont. | ||||
* @param font the given CFFFont | * @param font the given CFFFont | ||||
* @param i | |||||
* @return the Type1 font | * @return the Type1 font | ||||
* @throws IOException if an error occurs during reading the given font | * @throws IOException if an error occurs during reading the given font | ||||
*/ | */ | ||||
public byte[] format(CFFType1Font font) throws IOException { | |||||
public byte[] format(CFFType1Font font, String i) throws IOException { | |||||
DataOutput output = new DataOutput(); | DataOutput output = new DataOutput(); | ||||
printFont(font, output); | |||||
printFont(font, output, i); | |||||
return output.getBytes(); | return output.getBytes(); | ||||
} | } | ||||
private void printFont(CFFType1Font font, DataOutput output) | |||||
private void printFont(CFFType1Font font, DataOutput output, String iStr) | |||||
throws IOException { | throws IOException { | ||||
output.println("%!FontType1-1.0 " + font.getName() + " " | |||||
output.println("%!FontType1-1.0 " + font.getName() + iStr + " " | |||||
+ font.getTopDict().get("version")); | + font.getTopDict().get("version")); | ||||
printFontDictionary(font, output); | |||||
printFontDictionary(font, output, iStr); | |||||
for (int i = 0; i < 8; i++) { | for (int i = 0; i < 8; i++) { | ||||
StringBuilder sb = new StringBuilder(); | StringBuilder sb = new StringBuilder(); | ||||
output.println("cleartomark"); | output.println("cleartomark"); | ||||
} | } | ||||
private void printFontDictionary(CFFType1Font font, DataOutput output) | |||||
private void printFontDictionary(CFFType1Font font, DataOutput output, String iStr) | |||||
throws IOException { | throws IOException { | ||||
output.println("10 dict begin"); | output.println("10 dict begin"); | ||||
output.println("/FontInfo 10 dict dup begin"); | output.println("/FontInfo 10 dict dup begin"); | ||||
output.println("/UnderlineThickness " | output.println("/UnderlineThickness " | ||||
+ font.getTopDict().get("UnderlineThickness") + " def"); | + font.getTopDict().get("UnderlineThickness") + " def"); | ||||
output.println("end readonly def"); | output.println("end readonly def"); | ||||
output.println("/FontName /" + font.getName() + " def"); | |||||
output.println("/FontName /" + font.getName() + iStr + " def"); | |||||
output.println("/PaintType " + font.getTopDict().get("PaintType") + " def"); | output.println("/PaintType " + font.getTopDict().get("PaintType") + " def"); | ||||
output.println("/FontType 1 def"); | output.println("/FontType 1 def"); | ||||
NumberFormat matrixFormat = new DecimalFormat("0.########", new DecimalFormatSymbols(Locale.US)); | NumberFormat matrixFormat = new DecimalFormat("0.########", new DecimalFormatSymbols(Locale.US)); | ||||
sb.append(String.format("dup %d /%s put", gid.getValue(), name)).append('\n'); | sb.append(String.format("dup %d /%s put", gid.getValue(), name)).append('\n'); | ||||
max = Math.max(max, gid.getValue()); | max = Math.max(max, gid.getValue()); | ||||
} | } | ||||
if (max > 255) { | |||||
eventListener.fontType1MaxGlyphs(this, font.getName()); | |||||
} | |||||
output.println("/Encoding " + (max + 1) + " array"); | output.println("/Encoding " + (max + 1) + " array"); | ||||
output.println("0 1 " + max + " {1 index exch /.notdef put} for"); | output.println("0 1 " + max + " {1 index exch /.notdef put} for"); | ||||
output.print(sb.toString()); | output.print(sb.toString()); |
public void svgTextStrokedAsShapes(Object source, String fontFamily) { | public void svgTextStrokedAsShapes(Object source, String fontFamily) { | ||||
// ignore | // ignore | ||||
} | } | ||||
public void fontType1MaxGlyphs(Object source, String fontName) { | |||||
//ignore | |||||
} | |||||
}; | }; | ||||
FontListGenerator listGenerator = new FontListGenerator(); | FontListGenerator listGenerator = new FontListGenerator(); |
<message key="glyphNotAvailable">Glyph "{ch}" (0x{ch,hex}[, {ch,glyph-name}]) not available in font "{fontName}".</message> | <message key="glyphNotAvailable">Glyph "{ch}" (0x{ch,hex}[, {ch,glyph-name}]) not available in font "{fontName}".</message> | ||||
<message key="fontDirectoryNotFound">The font directory {dir} could not be found.</message> | <message key="fontDirectoryNotFound">The font directory {dir} could not be found.</message> | ||||
<message key="svgTextStrokedAsShapes">The SVG text for font {fontFamily} will be stroked as shapes.</message> | <message key="svgTextStrokedAsShapes">The SVG text for font {fontFamily} will be stroked as shapes.</message> | ||||
<message key="fontType1MaxGlyphs">Font "{fontName}" encoding has more than 256 glyphs may cause wrong output, enable font subsetting or disable 'embed-as-type1'.</message> | |||||
</catalogue> | </catalogue> |
import org.apache.fop.apps.io.InternalResourceResolver; | import org.apache.fop.apps.io.InternalResourceResolver; | ||||
import org.apache.fop.apps.io.ResourceResolverFactory; | import org.apache.fop.apps.io.ResourceResolverFactory; | ||||
import org.apache.fop.fonts.CFFToType1Font; | |||||
import org.apache.fop.fonts.CustomFont; | import org.apache.fop.fonts.CustomFont; | ||||
import org.apache.fop.fonts.EmbeddingMode; | import org.apache.fop.fonts.EmbeddingMode; | ||||
import org.apache.fop.fonts.EncodingMode; | import org.apache.fop.fonts.EncodingMode; | ||||
@Test | @Test | ||||
public void testFont() throws IOException { | public void testFont() throws IOException { | ||||
Type1Font t1 = getFont("test/resources/fonts/otf/SourceSansProBold.otf"); | Type1Font t1 = getFont("test/resources/fonts/otf/SourceSansProBold.otf"); | ||||
Assert.assertEquals(t1.getFontName(), "SourceSansPro-Bold"); | |||||
Assert.assertEquals(t1.getFontName(), "SourceSansPro-Bold.0"); | |||||
Assert.assertEquals(t1.getCharStringsDict().keySet().toString(), "[.notdef, d]"); | Assert.assertEquals(t1.getCharStringsDict().keySet().toString(), "[.notdef, d]"); | ||||
t1 = getFont("test/resources/fonts/otf/AlexBrushRegular.otf"); | t1 = getFont("test/resources/fonts/otf/AlexBrushRegular.otf"); | ||||
Assert.assertEquals(t1.getFontName(), "AlexBrush-Regular"); | |||||
Assert.assertEquals(t1.getFontName(), "AlexBrush-Regular.0"); | |||||
} | } | ||||
private Type1Font getFont(String s) throws IOException { | private Type1Font getFont(String s) throws IOException { | ||||
CustomFont realFont = FontLoader.loadFont(new FontUris(new File(s).toURI(), null), null, true, | CustomFont realFont = FontLoader.loadFont(new FontUris(new File(s).toURI(), null), null, true, | ||||
EmbeddingMode.SUBSET, EncodingMode.AUTO, true, true, rr, true); | EmbeddingMode.SUBSET, EncodingMode.AUTO, true, true, rr, true); | ||||
realFont.mapChar('d'); | realFont.mapChar('d'); | ||||
InputStream is = realFont.getInputStream(); | |||||
InputStream is = ((CFFToType1Font)realFont).getInputStreams().get(0); | |||||
return Type1Font.createWithPFB(is); | return Type1Font.createWithPFB(is); | ||||
} | } | ||||
} | } |
+ "/OTFFont.0 0.01 F\n" | + "/OTFFont.0 0.01 F\n" | ||||
+ "1 0 0 -1 0 0 Tm\n" | + "1 0 0 -1 0 0 Tm\n" | ||||
+ "<FFFFFFFFFF> t\n" | + "<FFFFFFFFFF> t\n" | ||||
+ "/OTFFont.0 0.01 F\n" | |||||
+ "1 0 0 -1 0 0 Tm\n" | + "1 0 0 -1 0 0 Tm\n" | ||||
+ "<FFFFFFFFFF> t\n" | + "<FFFFFFFFFF> t\n" | ||||
+ "/TTFFont 0.01 F\n" | + "/TTFFont 0.01 F\n" |