mirror of https://github.com/apache/poi.git
Bug 55902 - Mixed fonts issue with Chinese characters (unable to form images from ppt)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1567455 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
4b9d47af5a
commit
fc697f0e60
25
build.xml
25
build.xml
|
@ -834,7 +834,7 @@ under the License.
|
||||||
</uptodate>
|
</uptodate>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="test-scratchpad" depends="compile-main,compile-scratchpad,-test-scratchpad-check,jacocotask"
|
<target name="test-scratchpad" depends="compile-main,compile-scratchpad,-test-scratchpad-check,jacocotask,test-scratchpad-download-resources"
|
||||||
unless="scratchpad.test.notRequired" xmlns:jacoco="antlib:org.jacoco.ant">
|
unless="scratchpad.test.notRequired" xmlns:jacoco="antlib:org.jacoco.ant">
|
||||||
<jacoco:coverage enabled="${coverage.enabled}" excludes="${coverage.excludes}" destfile="build/jacoco-scratchpad.exec">
|
<jacoco:coverage enabled="${coverage.enabled}" excludes="${coverage.excludes}" destfile="build/jacoco-scratchpad.exec">
|
||||||
<junit printsummary="yes" fork="yes" forkmode="once" haltonfailure="${halt.on.test.failure}"
|
<junit printsummary="yes" fork="yes" forkmode="once" haltonfailure="${halt.on.test.failure}"
|
||||||
|
@ -1383,7 +1383,6 @@ under the License.
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="findbugs"><!-- depends="assemble" -->
|
<target name="findbugs"><!-- depends="assemble" -->
|
||||||
|
|
||||||
<antcall target="downloadfile">
|
<antcall target="downloadfile">
|
||||||
<param name="sourcefile" value="http://prdownloads.sourceforge.net/findbugs/findbugs-noUpdateChecks-2.0.3.zip?download"/>
|
<param name="sourcefile" value="http://prdownloads.sourceforge.net/findbugs/findbugs-noUpdateChecks-2.0.3.zip?download"/>
|
||||||
<param name="destfile" value="${main.lib}/findbugs-noUpdateChecks-2.0.3.zip"/>
|
<param name="destfile" value="${main.lib}/findbugs-noUpdateChecks-2.0.3.zip"/>
|
||||||
|
@ -1425,4 +1424,26 @@ under the License.
|
||||||
<sourcePath path="src/scratchpad/src" />
|
<sourcePath path="src/scratchpad/src" />
|
||||||
</findbugs>
|
</findbugs>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
<target name="test-scratchpad-download-resources">
|
||||||
|
<mkdir dir="build/scratchpad-test-resources"/>
|
||||||
|
|
||||||
|
<antcall target="downloadfile">
|
||||||
|
<param name="sourcefile" value="http://sourceforge.net/projects/monafont/files/monafont/monafont-2.90/monafont-ttf-2.90.zip/download"/>
|
||||||
|
<param name="destfile" value="build/scratchpad-test-resources/monafont-ttf-2.90.zip"/>
|
||||||
|
</antcall>
|
||||||
|
|
||||||
|
<unzip src="build/scratchpad-test-resources/monafont-ttf-2.90.zip"
|
||||||
|
dest="build/scratchpad-test-resources">
|
||||||
|
<patternset>
|
||||||
|
<include name="mona.ttf"/>
|
||||||
|
</patternset>
|
||||||
|
</unzip>
|
||||||
|
|
||||||
|
<antcall target="downloadfile">
|
||||||
|
<param name="sourcefile" value="https://googlefontdirectory.googlecode.com/hg-history/c5955de4df3e40f6ab705bbccbd1f5ad93998287/cabin/Cabin-Regular.ttf"/>
|
||||||
|
<param name="destfile" value="build/scratchpad-test-resources/Cabin-Regular.ttf"/>
|
||||||
|
</antcall>
|
||||||
|
</target>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -20,6 +20,7 @@ package org.apache.poi.hslf.model;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
import java.awt.font.FontRenderContext;
|
import java.awt.font.FontRenderContext;
|
||||||
import java.awt.font.LineBreakMeasurer;
|
import java.awt.font.LineBreakMeasurer;
|
||||||
import java.awt.font.TextAttribute;
|
import java.awt.font.TextAttribute;
|
||||||
|
@ -31,6 +32,7 @@ import java.text.AttributedCharacterIterator;
|
||||||
import java.text.AttributedString;
|
import java.text.AttributedString;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.poi.hslf.record.TextRulerAtom;
|
import org.apache.poi.hslf.record.TextRulerAtom;
|
||||||
import org.apache.poi.hslf.usermodel.RichTextRun;
|
import org.apache.poi.hslf.usermodel.RichTextRun;
|
||||||
|
@ -43,6 +45,9 @@ import org.apache.poi.util.POILogger;
|
||||||
* @author Yegor Kozlov
|
* @author Yegor Kozlov
|
||||||
*/
|
*/
|
||||||
public final class TextPainter {
|
public final class TextPainter {
|
||||||
|
public static final Key KEY_FONTFALLBACK = new Key(50, "Font fallback map");
|
||||||
|
public static final Key KEY_FONTMAP = new Key(51, "Font map");
|
||||||
|
|
||||||
protected POILogger logger = POILogFactory.getLogger(this.getClass());
|
protected POILogger logger = POILogFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,10 +63,14 @@ public final class TextPainter {
|
||||||
_shape = shape;
|
_shape = shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AttributedString getAttributedString(TextRun txrun) {
|
||||||
|
return getAttributedString(txrun, null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the underlying set of rich text runs into java.text.AttributedString
|
* Convert the underlying set of rich text runs into java.text.AttributedString
|
||||||
*/
|
*/
|
||||||
public AttributedString getAttributedString(TextRun txrun){
|
public AttributedString getAttributedString(TextRun txrun, Graphics2D graphics){
|
||||||
String text = txrun.getText();
|
String text = txrun.getText();
|
||||||
//TODO: properly process tabs
|
//TODO: properly process tabs
|
||||||
text = text.replace('\t', ' ');
|
text = text.replace('\t', ' ');
|
||||||
|
@ -77,7 +86,22 @@ public final class TextPainter {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
at.addAttribute(TextAttribute.FAMILY, rt[i].getFontName(), start, end);
|
String mappedFont = rt[i].getFontName();
|
||||||
|
String fallbackFont = Font.SANS_SERIF;
|
||||||
|
if (graphics != null) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String,String> fontMap = (Map<String,String>)graphics.getRenderingHint(KEY_FONTMAP);
|
||||||
|
if (fontMap != null && fontMap.containsKey(mappedFont)) {
|
||||||
|
mappedFont = fontMap.get(mappedFont);
|
||||||
|
}
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String,String> fallbackMap = (Map<String,String>)graphics.getRenderingHint(KEY_FONTFALLBACK);
|
||||||
|
if (fallbackMap != null && fallbackMap.containsKey(mappedFont)) {
|
||||||
|
fallbackFont = fallbackMap.get(mappedFont);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
at.addAttribute(TextAttribute.FAMILY, mappedFont, start, end);
|
||||||
at.addAttribute(TextAttribute.SIZE, new Float(rt[i].getFontSize()), start, end);
|
at.addAttribute(TextAttribute.SIZE, new Float(rt[i].getFontSize()), start, end);
|
||||||
at.addAttribute(TextAttribute.FOREGROUND, rt[i].getFontColor(), start, end);
|
at.addAttribute(TextAttribute.FOREGROUND, rt[i].getFontColor(), start, end);
|
||||||
if(rt[i].isBold()) at.addAttribute(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD, start, end);
|
if(rt[i].isBold()) at.addAttribute(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD, start, end);
|
||||||
|
@ -89,7 +113,31 @@ public final class TextPainter {
|
||||||
if(rt[i].isStrikethrough()) at.addAttribute(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON, start, end);
|
if(rt[i].isStrikethrough()) at.addAttribute(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON, start, end);
|
||||||
int superScript = rt[i].getSuperscript();
|
int superScript = rt[i].getSuperscript();
|
||||||
if(superScript != 0) at.addAttribute(TextAttribute.SUPERSCRIPT, superScript > 0 ? TextAttribute.SUPERSCRIPT_SUPER : TextAttribute.SUPERSCRIPT_SUB, start, end);
|
if(superScript != 0) at.addAttribute(TextAttribute.SUPERSCRIPT, superScript > 0 ? TextAttribute.SUPERSCRIPT_SUPER : TextAttribute.SUPERSCRIPT_SUB, start, end);
|
||||||
|
|
||||||
|
|
||||||
|
int style = (rt[i].isBold() ? Font.BOLD : 0) | (rt[i].isItalic() ? Font.ITALIC : 0);
|
||||||
|
Font f = new Font(mappedFont, style, rt[i].getFontSize());
|
||||||
|
|
||||||
|
// check for unsupported characters and add a fallback font for these
|
||||||
|
char textChr[] = text.toCharArray();
|
||||||
|
int nextEnd = f.canDisplayUpTo(textChr, start, end);
|
||||||
|
boolean isNextValid = nextEnd == start;
|
||||||
|
for (int last = start; nextEnd != -1 && nextEnd <= end; ) {
|
||||||
|
if (isNextValid) {
|
||||||
|
nextEnd = f.canDisplayUpTo(textChr, nextEnd, end);
|
||||||
|
isNextValid = false;
|
||||||
|
} else {
|
||||||
|
if (nextEnd >= end || f.canDisplay(Character.codePointAt(textChr, nextEnd, end)) ) {
|
||||||
|
at.addAttribute(TextAttribute.FAMILY, fallbackFont, last, Math.min(nextEnd,end));
|
||||||
|
if (nextEnd >= end) break;
|
||||||
|
last = nextEnd;
|
||||||
|
isNextValid = true;
|
||||||
|
} else {
|
||||||
|
boolean isHS = Character.isHighSurrogate(textChr[nextEnd]);
|
||||||
|
nextEnd+=(isHS?2:1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return at;
|
return at;
|
||||||
}
|
}
|
||||||
|
@ -98,7 +146,7 @@ public final class TextPainter {
|
||||||
AffineTransform tx = graphics.getTransform();
|
AffineTransform tx = graphics.getTransform();
|
||||||
|
|
||||||
Rectangle2D anchor = _shape.getLogicalAnchor2D();
|
Rectangle2D anchor = _shape.getLogicalAnchor2D();
|
||||||
TextElement[] elem = getTextElements((float)anchor.getWidth(), graphics.getFontRenderContext());
|
TextElement[] elem = getTextElements((float)anchor.getWidth(), graphics.getFontRenderContext(), graphics);
|
||||||
if(elem == null) return;
|
if(elem == null) return;
|
||||||
|
|
||||||
float textHeight = 0;
|
float textHeight = 0;
|
||||||
|
@ -183,13 +231,17 @@ public final class TextPainter {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextElement[] getTextElements(float textWidth, FontRenderContext frc){
|
public TextElement[] getTextElements(float textWidth, FontRenderContext frc){
|
||||||
|
return getTextElements(textWidth, frc, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextElement[] getTextElements(float textWidth, FontRenderContext frc, Graphics2D graphics){
|
||||||
TextRun run = _shape.getTextRun();
|
TextRun run = _shape.getTextRun();
|
||||||
if (run == null) return null;
|
if (run == null) return null;
|
||||||
|
|
||||||
String text = run.getText();
|
String text = run.getText();
|
||||||
if (text == null || text.equals("")) return null;
|
if (text == null || text.equals("")) return null;
|
||||||
|
|
||||||
AttributedString at = getAttributedString(run);
|
AttributedString at = getAttributedString(run, graphics);
|
||||||
|
|
||||||
AttributedCharacterIterator it = at.getIterator();
|
AttributedCharacterIterator it = at.getIterator();
|
||||||
int paragraphStart = it.getBeginIndex();
|
int paragraphStart = it.getBeginIndex();
|
||||||
|
@ -342,4 +394,25 @@ public final class TextPainter {
|
||||||
public float advance;
|
public float advance;
|
||||||
public int textStartIndex, textEndIndex;
|
public int textStartIndex, textEndIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Key extends RenderingHints.Key {
|
||||||
|
String description;
|
||||||
|
|
||||||
|
public Key(int paramInt, String paramString) {
|
||||||
|
super(paramInt);
|
||||||
|
this.description = paramString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int getIndex() {
|
||||||
|
return intKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String toString() {
|
||||||
|
return this.description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCompatibleValue(Object paramObject) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,35 +17,30 @@
|
||||||
|
|
||||||
package org.apache.poi.hslf;
|
package org.apache.poi.hslf;
|
||||||
|
|
||||||
import junit.framework.Test;
|
|
||||||
import junit.framework.TestSuite;
|
|
||||||
|
|
||||||
import org.apache.poi.hslf.extractor.TestCruddyExtractor;
|
import org.apache.poi.hslf.extractor.TestCruddyExtractor;
|
||||||
import org.apache.poi.hslf.extractor.TestExtractor;
|
import org.apache.poi.hslf.extractor.TestExtractor;
|
||||||
import org.apache.poi.hslf.model.AllHSLFModelTests;
|
import org.apache.poi.hslf.model.AllHSLFModelTests;
|
||||||
import org.apache.poi.hslf.record.AllHSLFRecordTests;
|
import org.apache.poi.hslf.record.AllHSLFRecordTests;
|
||||||
import org.apache.poi.hslf.usermodel.AllHSLFUserModelTests;
|
import org.apache.poi.hslf.usermodel.AllHSLFUserModelTests;
|
||||||
import org.apache.poi.hslf.util.TestSystemTimeUtils;
|
import org.apache.poi.hslf.util.TestSystemTimeUtils;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.Suite;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collects all tests from the package <tt>org.apache.poi.hslf</tt> and all sub-packages.
|
* Collects all tests from the package <tt>org.apache.poi.hslf</tt> and all sub-packages.
|
||||||
*
|
|
||||||
* @author Josh Micich
|
|
||||||
*/
|
*/
|
||||||
|
@RunWith(Suite.class)
|
||||||
|
@Suite.SuiteClasses({
|
||||||
|
TestEncryptedFile.class,
|
||||||
|
TestRecordCounts.class,
|
||||||
|
TestReWrite.class,
|
||||||
|
TestReWriteSanity.class,
|
||||||
|
TestCruddyExtractor.class,
|
||||||
|
TestExtractor.class,
|
||||||
|
AllHSLFModelTests.class,
|
||||||
|
AllHSLFRecordTests.class,
|
||||||
|
AllHSLFUserModelTests.class,
|
||||||
|
TestSystemTimeUtils.class
|
||||||
|
})
|
||||||
public class AllHSLFTests {
|
public class AllHSLFTests {
|
||||||
|
|
||||||
public static Test suite() {
|
|
||||||
TestSuite result = new TestSuite(AllHSLFTests.class.getName());
|
|
||||||
result.addTestSuite(TestEncryptedFile.class);
|
|
||||||
result.addTestSuite(TestRecordCounts.class);
|
|
||||||
result.addTestSuite(TestReWrite.class);
|
|
||||||
result.addTestSuite(TestReWriteSanity.class);
|
|
||||||
result.addTestSuite(TestCruddyExtractor.class);
|
|
||||||
result.addTestSuite(TestExtractor.class);
|
|
||||||
result.addTest(AllHSLFModelTests.suite());
|
|
||||||
result.addTest(AllHSLFRecordTests.suite());
|
|
||||||
result.addTest(AllHSLFUserModelTests.suite());
|
|
||||||
result.addTestSuite(TestSystemTimeUtils.class);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,30 +17,27 @@
|
||||||
|
|
||||||
package org.apache.poi.hslf.usermodel;
|
package org.apache.poi.hslf.usermodel;
|
||||||
|
|
||||||
import junit.framework.Test;
|
import org.junit.runner.RunWith;
|
||||||
import junit.framework.TestSuite;
|
import org.junit.runners.Suite;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collects all tests from the package <tt>org.apache.poi.hslf.usermodel</tt>.
|
* Collects all tests from the package <tt>org.apache.poi.hslf.usermodel</tt>.
|
||||||
*
|
|
||||||
* @author Josh Micich
|
|
||||||
*/
|
*/
|
||||||
|
@RunWith(Suite.class)
|
||||||
|
@Suite.SuiteClasses({
|
||||||
|
TestAddingSlides.class,
|
||||||
|
TestBugs.class,
|
||||||
|
TestCounts.class,
|
||||||
|
TestMostRecentRecords.class,
|
||||||
|
TestNotesText.class,
|
||||||
|
TestPictures.class,
|
||||||
|
TestReOrderingSlides.class,
|
||||||
|
TestRecordSetup.class,
|
||||||
|
TestRichTextRun.class,
|
||||||
|
TestSheetText.class,
|
||||||
|
TestSlideOrdering.class,
|
||||||
|
TestSoundData.class,
|
||||||
|
TestFontRendering.class
|
||||||
|
})
|
||||||
public class AllHSLFUserModelTests {
|
public class AllHSLFUserModelTests {
|
||||||
|
|
||||||
public static Test suite() {
|
|
||||||
TestSuite result = new TestSuite(AllHSLFUserModelTests.class.getName());
|
|
||||||
result.addTestSuite(TestAddingSlides.class);
|
|
||||||
result.addTestSuite(TestBugs.class);
|
|
||||||
result.addTestSuite(TestCounts.class);
|
|
||||||
result.addTestSuite(TestMostRecentRecords.class);
|
|
||||||
result.addTestSuite(TestNotesText.class);
|
|
||||||
result.addTestSuite(TestPictures.class);
|
|
||||||
result.addTestSuite(TestReOrderingSlides.class);
|
|
||||||
result.addTestSuite(TestRecordSetup.class);
|
|
||||||
result.addTestSuite(TestRichTextRun.class);
|
|
||||||
result.addTestSuite(TestSheetText.class);
|
|
||||||
result.addTestSuite(TestSlideOrdering.class);
|
|
||||||
result.addTestSuite(TestSoundData.class);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
/* ====================================================================
|
||||||
|
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.
|
||||||
|
==================================================================== */
|
||||||
|
|
||||||
|
package org.apache.poi.hslf.usermodel;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assume.assumeTrue;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.GraphicsEnvironment;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.AffineTransform;
|
||||||
|
import java.awt.geom.Rectangle2D;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.awt.image.DataBufferByte;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
|
import org.apache.poi.POIDataSamples;
|
||||||
|
import org.apache.poi.hslf.model.Slide;
|
||||||
|
import org.apache.poi.hslf.model.TextPainter;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test font rendering of alternative and fallback fonts
|
||||||
|
*/
|
||||||
|
public class TestFontRendering {
|
||||||
|
private static POIDataSamples slTests = POIDataSamples.getSlideShowInstance();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void bug55902mixedFontWithChineseCharacters() throws Exception {
|
||||||
|
// font files need to be downloaded first via
|
||||||
|
// ant test-scratchpad-download-resources
|
||||||
|
String fontFiles[][] = {
|
||||||
|
// Calibri is not available on *nix systems, so we need to use another similar free font
|
||||||
|
{ "build/scratchpad-test-resources/Cabin-Regular.ttf", "mapped", "Calibri" },
|
||||||
|
|
||||||
|
// use "MS PGothic" if available (Windows only) ...
|
||||||
|
// for the junit test not all chars are rendered
|
||||||
|
{ "build/scratchpad-test-resources/mona.ttf", "fallback", "Cabin" }
|
||||||
|
};
|
||||||
|
|
||||||
|
// setup fonts (especially needed, when run under *nix systems)
|
||||||
|
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||||
|
Map<String,String> fontMap = new HashMap<String,String>();
|
||||||
|
Map<String,String> fallbackMap = new HashMap<String,String>();
|
||||||
|
|
||||||
|
for (String fontFile[] : fontFiles) {
|
||||||
|
File f = new File(fontFile[0]);
|
||||||
|
assumeTrue("necessary font file "+f.getName()+" not downloaded.", f.exists());
|
||||||
|
|
||||||
|
Font font = Font.createFont(Font.TRUETYPE_FONT, f);
|
||||||
|
ge.registerFont(font);
|
||||||
|
|
||||||
|
Map<String,String> map = ("mapped".equals(fontFile[1]) ? fontMap : fallbackMap);
|
||||||
|
map.put(fontFile[2], font.getFamily());
|
||||||
|
}
|
||||||
|
|
||||||
|
InputStream is = slTests.openResourceAsStream("bug55902-mixedFontChineseCharacters.ppt");
|
||||||
|
SlideShow ss = new SlideShow(is);
|
||||||
|
is.close();
|
||||||
|
|
||||||
|
Dimension pgsize = ss.getPageSize();
|
||||||
|
|
||||||
|
Slide slide = ss.getSlides()[0];
|
||||||
|
|
||||||
|
// render it
|
||||||
|
double zoom = 1;
|
||||||
|
AffineTransform at = new AffineTransform();
|
||||||
|
at.setToScale(zoom, zoom);
|
||||||
|
|
||||||
|
BufferedImage imgActual = new BufferedImage((int)Math.ceil(pgsize.width*zoom), (int)Math.ceil(pgsize.height*zoom), BufferedImage.TYPE_3BYTE_BGR);
|
||||||
|
Graphics2D graphics = imgActual.createGraphics();
|
||||||
|
graphics.setRenderingHint(TextPainter.KEY_FONTFALLBACK, fallbackMap);
|
||||||
|
graphics.setRenderingHint(TextPainter.KEY_FONTMAP, fontMap);
|
||||||
|
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
|
||||||
|
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
|
||||||
|
graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
|
||||||
|
graphics.setTransform(at);
|
||||||
|
graphics.setPaint(Color.white);
|
||||||
|
graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width, pgsize.height));
|
||||||
|
slide.draw(graphics);
|
||||||
|
|
||||||
|
BufferedImage imgExpected = ImageIO.read(slTests.getFile("bug55902-mixedChars.png"));
|
||||||
|
DataBufferByte expectedDB = (DataBufferByte)imgExpected.getRaster().getDataBuffer();
|
||||||
|
DataBufferByte actualDB = (DataBufferByte)imgActual.getRaster().getDataBuffer();
|
||||||
|
assertTrue(Arrays.equals(expectedDB.getData(0), actualDB.getData(0)));
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 8.9 KiB |
Binary file not shown.
Loading…
Reference in New Issue