git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1882341 13f79535-47bb-0310-9956-ffa450edef68tags/fop-2_6
@@ -31,7 +31,12 @@ import java.util.Map.Entry; | |||
import org.apache.fop.fonts.CustomFont; | |||
import org.apache.fop.fonts.Typeface; | |||
import org.apache.fop.fonts.truetype.GlyfTable; | |||
import org.apache.fop.fonts.truetype.OFDirTabEntry; | |||
import org.apache.fop.fonts.truetype.OFMtxEntry; | |||
import org.apache.fop.fonts.truetype.OFTableName; | |||
import org.apache.fop.render.java2d.CustomFontMetricsMapper; | |||
import org.apache.fop.util.CharUtilities; | |||
public class PCLSoftFontManager { | |||
private Map<Typeface, PCLFontReader> fontReaderMap; | |||
@@ -45,11 +50,11 @@ public class PCLSoftFontManager { | |||
} | |||
public ByteArrayOutputStream makeSoftFont(Typeface font, String text) throws IOException { | |||
List<Map<Character, Integer>> mappedGlyphs = mapFontGlyphs(font); | |||
if (!fontReaderMap.containsKey(font)) { | |||
fontReaderMap.put(font, PCLFontReaderFactory.createInstance(font)); | |||
} | |||
fontReader = fontReaderMap.get(font); | |||
List<Map<Character, Integer>> mappedGlyphs = mapFontGlyphs(font); | |||
if (mappedGlyphs.isEmpty()) { | |||
mappedGlyphs.add(new HashMap<Character, Integer>()); | |||
} | |||
@@ -95,7 +100,7 @@ public class PCLSoftFontManager { | |||
return f; | |||
} | |||
private List<Map<Character, Integer>> mapFontGlyphs(Typeface tf) { | |||
private List<Map<Character, Integer>> mapFontGlyphs(Typeface tf) throws IOException { | |||
List<Map<Character, Integer>> mappedGlyphs = new ArrayList<Map<Character, Integer>>(); | |||
if (tf instanceof CustomFontMetricsMapper) { | |||
CustomFontMetricsMapper fontMetrics = (CustomFontMetricsMapper) tf; | |||
@@ -105,10 +110,13 @@ public class PCLSoftFontManager { | |||
return mappedGlyphs; | |||
} | |||
private List<Map<Character, Integer>> mapGlyphs(Map<Integer, Integer> usedGlyphs, CustomFont font) { | |||
private List<Map<Character, Integer>> mapGlyphs(Map<Integer, Integer> usedGlyphs, CustomFont font) | |||
throws IOException { | |||
int charCount = 32; | |||
int charCountComposite = 32; | |||
List<Map<Character, Integer>> mappedGlyphs = new ArrayList<Map<Character, Integer>>(); | |||
Map<Character, Integer> fontGlyphs = new HashMap<Character, Integer>(); | |||
Map<Character, Integer> fontGlyphsComposite = new HashMap<Character, Integer>(); | |||
for (Entry<Integer, Integer> entry : usedGlyphs.entrySet()) { | |||
int glyphID = entry.getKey(); | |||
if (glyphID == 0) { | |||
@@ -120,14 +128,38 @@ public class PCLSoftFontManager { | |||
charCount = 32; | |||
fontGlyphs = new HashMap<Character, Integer>(); | |||
} | |||
fontGlyphs.put(unicode, charCount++); | |||
if (isComposite(font, unicode)) { | |||
fontGlyphsComposite.put(unicode, charCountComposite++); | |||
} else { | |||
fontGlyphs.put(unicode, charCount++); | |||
} | |||
} | |||
if (fontGlyphs.size() > 0) { | |||
mappedGlyphs.add(fontGlyphs); | |||
} | |||
if (fontGlyphsComposite.size() > 0) { | |||
mappedGlyphs.add(fontGlyphsComposite); | |||
} | |||
return mappedGlyphs; | |||
} | |||
private boolean isComposite(CustomFont customFont, int unicode) throws IOException { | |||
OFDirTabEntry glyfTableInfo = fontReader.getFontFile().getDirectoryEntry(OFTableName.GLYF); | |||
if (glyfTableInfo == null) { | |||
return false; | |||
} | |||
List<OFMtxEntry> mtx = fontReader.getFontFile().getMtx(); | |||
Map<Integer, Integer> subsetGlyphs = customFont.getUsedGlyphs(); | |||
GlyfTable glyfTable = new GlyfTable(fontReader.getFontFileReader(), mtx.toArray(new OFMtxEntry[mtx.size()]), | |||
glyfTableInfo, subsetGlyphs); | |||
Map<Integer, Integer> mtxCharacters = fontReader.scanMtxCharacters(); | |||
if (mtxCharacters.containsKey(unicode)) { | |||
int mtxChar = mtxCharacters.get(unicode); | |||
return glyfTable.isComposite(mtxChar); | |||
} | |||
return false; | |||
} | |||
private void writeFontID(int fontID, OutputStream os) throws IOException { | |||
os.write(assignFontID(fontID)); | |||
} | |||
@@ -256,6 +288,9 @@ public class PCLSoftFontManager { | |||
int curFontID = -1; | |||
String current = ""; | |||
for (char ch : text.toCharArray()) { | |||
if (ch == CharUtilities.NBSPACE) { | |||
ch = ' '; | |||
} | |||
for (PCLSoftFont softFont : fonts) { | |||
if (curFontID == -1) { | |||
curFontID = softFont.getFontID(); |
@@ -22,7 +22,6 @@ package org.apache.fop.render.pcl.fonts.truetype; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.UnsupportedEncodingException; | |||
import java.util.ArrayList; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
@@ -553,7 +552,7 @@ public class PCLTTFFontReader extends PCLFontReader { | |||
} | |||
private void writeTrueTypeTable(ByteArrayOutputStream baos, OFTableName table, | |||
List<TableOffset> tableOffsets) throws IOException, UnsupportedEncodingException { | |||
List<TableOffset> tableOffsets) throws IOException { | |||
OFDirTabEntry tabEntry = ttfFont.getDirectoryEntry(table); | |||
if (tabEntry != null) { | |||
baos.write(tabEntry.getTag()); | |||
@@ -566,7 +565,7 @@ public class PCLTTFFontReader extends PCLFontReader { | |||
} | |||
} | |||
private void writeGDIR(ByteArrayOutputStream baos) throws UnsupportedEncodingException, IOException { | |||
private void writeGDIR(ByteArrayOutputStream baos) throws IOException { | |||
baos.write("gdir".getBytes("ISO-8859-1")); | |||
baos.write(PCLByteWriterUtil.unsignedLongInt(0)); // Checksum | |||
baos.write(PCLByteWriterUtil.unsignedLongInt(0)); // Offset | |||
@@ -695,28 +694,24 @@ public class PCLTTFFontReader extends PCLFontReader { | |||
return (int) sum; | |||
} | |||
protected byte[] createHmtx(Map<Character, Integer> mappedGlyphs) throws IOException { | |||
protected byte[] createHmtx(Map<Character, Integer> mappedGlyphs) { | |||
byte[] hmtxTable = new byte[((mappedGlyphs.size() + 32) * 4)]; | |||
OFDirTabEntry entry = ttfFont.getDirectoryEntry(OFTableName.HMTX); | |||
if (entry != null) { | |||
for (Entry<Character, Integer> glyphSubset : mappedGlyphs.entrySet()) { | |||
char unicode = glyphSubset.getKey(); | |||
int originalIndex = 0; | |||
int softFontGlyphIndex = glyphSubset.getValue(); | |||
if (font instanceof MultiByteFont) { | |||
originalIndex = ((MultiByteFont) font).getGIDFromChar(unicode); | |||
writeUShort(hmtxTable, (softFontGlyphIndex) * 4, | |||
int originalIndex = ((MultiByteFont) font).getGIDFromChar(unicode); | |||
writeUShort(hmtxTable, softFontGlyphIndex * 4, | |||
ttfFont.getMtx().get(originalIndex).getWx()); | |||
writeUShort(hmtxTable, (softFontGlyphIndex) * 4 + 2, | |||
writeUShort(hmtxTable, softFontGlyphIndex * 4 + 2, | |||
ttfFont.getMtx().get(originalIndex).getLsb()); | |||
} else { | |||
originalIndex = ((SingleByteFont) font).getGIDFromChar(unicode); | |||
writeUShort(hmtxTable, (softFontGlyphIndex) * 4, | |||
int originalIndex = ((SingleByteFont) font).getGIDFromChar(unicode); | |||
writeUShort(hmtxTable, softFontGlyphIndex * 4, | |||
font.getWidth(originalIndex, 1)); | |||
writeUShort(hmtxTable, (softFontGlyphIndex) * 4 + 2, 0); | |||
writeUShort(hmtxTable, softFontGlyphIndex * 4 + 2, 0); | |||
} | |||
} | |||
} |
@@ -0,0 +1,55 @@ | |||
/* | |||
* 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.render.pcl.fonts; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.File; | |||
import java.net.URI; | |||
import java.util.HashMap; | |||
import org.junit.Assert; | |||
import org.junit.Test; | |||
import org.apache.fop.apps.FOUserAgent; | |||
import org.apache.fop.apps.FopFactory; | |||
import org.apache.fop.fonts.CMapSegment; | |||
import org.apache.fop.fonts.EmbeddingMode; | |||
import org.apache.fop.fonts.FontType; | |||
import org.apache.fop.fonts.MultiByteFont; | |||
import org.apache.fop.render.java2d.CustomFontMetricsMapper; | |||
public class PCLSoftFontManagerTestCase { | |||
@Test | |||
public void testSplitCompositeGlyphs() throws Exception { | |||
FOUserAgent ua = FopFactory.newInstance(new File(".").toURI()).newFOUserAgent(); | |||
PCLSoftFontManager pclSoftFontManager = new PCLSoftFontManager(new HashMap()); | |||
MultiByteFont mbf = new MultiByteFont(ua.getResourceResolver(), EmbeddingMode.SUBSET); | |||
mbf.setEmbedURI(new URI("test/resources/fonts/ttf/DejaVuLGCSerif.ttf")); | |||
mbf.setFontType(FontType.TRUETYPE); | |||
CMapSegment cMapSegment1 = new CMapSegment('a', 'a', 1); | |||
CMapSegment cMapSegment2 = new CMapSegment('\u00E0', '\u00E0', 2); | |||
mbf.setCMap(new CMapSegment[] {cMapSegment1, cMapSegment2}); | |||
mbf.mapChar('a'); | |||
mbf.mapChar('\u00E0'); | |||
CustomFontMetricsMapper font = new CustomFontMetricsMapper(mbf); | |||
ByteArrayOutputStream bos = pclSoftFontManager.makeSoftFont(font, ""); | |||
String[] fontStrings = bos.toString().split("DejaVu changes are in public domain"); | |||
Assert.assertEquals(fontStrings.length, 3); | |||
} | |||
} |