Browse Source

FOP-2975: Put composite glyphs to separate font

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1882341 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-2_6
Simon Steiner 3 years ago
parent
commit
bb1feeb8e2

+ 39
- 4
fop-core/src/main/java/org/apache/fop/render/pcl/fonts/PCLSoftFontManager.java View File

@@ -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();

+ 9
- 14
fop-core/src/main/java/org/apache/fop/render/pcl/fonts/truetype/PCLTTFFontReader.java View File

@@ -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);
}
}
}

+ 55
- 0
fop-core/src/test/java/org/apache/fop/render/pcl/fonts/PCLSoftFontManagerTestCase.java View File

@@ -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);
}
}

Loading…
Cancel
Save