regression #55902 - Mixed fonts issue with Chinese characters (unable to form images from ppt)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1772485 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
610ce0bb98
commit
dcd8a53c64
@ -31,8 +31,26 @@ public interface DrawFontManager {
|
||||
*
|
||||
* @param typeface the font family as defined in the .pptx file.
|
||||
* This can be unknown or missing in the graphic environment.
|
||||
* @param pitchFamily a pitch-and-family,
|
||||
* see {@link org.apache.poi.hwmf.record.HwmfFont#getFamily()} and
|
||||
* {@link org.apache.poi.hwmf.record.HwmfFont#getPitch()}
|
||||
* for how to calculate those (ancient) values
|
||||
*
|
||||
* @return the font to be used to paint text
|
||||
*/
|
||||
String getRendererableFont(String typeface, int pitchFamily);
|
||||
|
||||
/**
|
||||
* In case the original font doesn't contain a glyph, use the
|
||||
* returned fallback font as an alternative
|
||||
*
|
||||
* @param typeface the font family as defined in the .pptx file.
|
||||
* @param pitchFamily a pitch-and-family,
|
||||
* see {@link org.apache.poi.hwmf.record.HwmfFont#getFamily()} and
|
||||
* {@link org.apache.poi.hwmf.record.HwmfFont#getPitch()}
|
||||
* for how to calculate those (ancient) values
|
||||
*
|
||||
* @return the font to be used as a fallback for the original typeface
|
||||
*/
|
||||
String getFallbackFont(String typeface, int pitchFamily);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
package org.apache.poi.sl.draw;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Paint;
|
||||
import java.awt.font.FontRenderContext;
|
||||
@ -500,6 +501,10 @@ public class DrawTextParagraph implements Drawable {
|
||||
PlaceableShape<?,?> ps = getParagraphShape();
|
||||
|
||||
DrawFontManager fontHandler = (DrawFontManager)graphics.getRenderingHint(Drawable.FONT_HANDLER);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String,String> fontMap = (Map<String,String>)graphics.getRenderingHint(Drawable.FONT_MAP);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String,String> fallbackMap = (Map<String,String>)graphics.getRenderingHint(Drawable.FONT_FALLBACK);
|
||||
|
||||
for (TextRun run : paragraph){
|
||||
String runText = getRenderableText(run);
|
||||
@ -507,31 +512,48 @@ public class DrawTextParagraph implements Drawable {
|
||||
if (runText.isEmpty()) continue;
|
||||
|
||||
// user can pass an custom object to convert fonts
|
||||
String fontFamily = run.getFontFamily();
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String,String> fontMap = (Map<String,String>)graphics.getRenderingHint(Drawable.FONT_MAP);
|
||||
if (fontMap != null && fontMap.containsKey(fontFamily)) {
|
||||
fontFamily = fontMap.get(fontFamily);
|
||||
String mappedFont = run.getFontFamily();
|
||||
String fallbackFont = Font.SANS_SERIF;
|
||||
|
||||
if (mappedFont == null) {
|
||||
mappedFont = paragraph.getDefaultFontFamily();
|
||||
}
|
||||
if(fontHandler != null) {
|
||||
fontFamily = fontHandler.getRendererableFont(fontFamily, run.getPitchAndFamily());
|
||||
if (mappedFont == null) {
|
||||
mappedFont = Font.SANS_SERIF;
|
||||
}
|
||||
if (fontHandler != null) {
|
||||
String font = fontHandler.getRendererableFont(mappedFont, run.getPitchAndFamily());
|
||||
if (font != null) {
|
||||
mappedFont = font;
|
||||
}
|
||||
font = fontHandler.getFallbackFont(mappedFont, run.getPitchAndFamily());
|
||||
if (font != null) {
|
||||
fallbackFont = font;
|
||||
}
|
||||
} else {
|
||||
if (fontMap != null && fontMap.containsKey(mappedFont)) {
|
||||
mappedFont = fontMap.get(mappedFont);
|
||||
}
|
||||
if (fallbackMap != null && fallbackMap.containsKey(mappedFont)) {
|
||||
fallbackFont = fallbackMap.get(mappedFont);
|
||||
}
|
||||
if (fontFamily == null) {
|
||||
fontFamily = paragraph.getDefaultFontFamily();
|
||||
}
|
||||
|
||||
runText = mapFontCharset(runText,mappedFont);
|
||||
int beginIndex = text.length();
|
||||
text.append(mapFontCharset(runText,fontFamily));
|
||||
text.append(runText);
|
||||
int endIndex = text.length();
|
||||
|
||||
attList.add(new AttributedStringData(TextAttribute.FAMILY, fontFamily, beginIndex, endIndex));
|
||||
attList.add(new AttributedStringData(TextAttribute.FAMILY, mappedFont, beginIndex, endIndex));
|
||||
|
||||
PaintStyle fgPaintStyle = run.getFontColor();
|
||||
Paint fgPaint = new DrawPaint(ps).getPaint(graphics, fgPaintStyle);
|
||||
attList.add(new AttributedStringData(TextAttribute.FOREGROUND, fgPaint, beginIndex, endIndex));
|
||||
|
||||
Double fontSz = run.getFontSize();
|
||||
if (fontSz == null) fontSz = paragraph.getDefaultFontSize();
|
||||
if (fontSz == null) {
|
||||
fontSz = paragraph.getDefaultFontSize();
|
||||
}
|
||||
attList.add(new AttributedStringData(TextAttribute.SIZE, fontSz.floatValue(), beginIndex, endIndex));
|
||||
|
||||
if(run.isBold()) {
|
||||
@ -559,6 +581,33 @@ public class DrawTextParagraph implements Drawable {
|
||||
attList.add(new AttributedStringData(HYPERLINK_HREF, hl.getAddress(), beginIndex, endIndex));
|
||||
attList.add(new AttributedStringData(HYPERLINK_LABEL, hl.getLabel(), beginIndex, endIndex));
|
||||
}
|
||||
|
||||
int style = (run.isBold() ? Font.BOLD : 0) | (run.isItalic() ? Font.ITALIC : 0);
|
||||
Font f = new Font(mappedFont, style, (int)Math.rint(fontSz));
|
||||
|
||||
// check for unsupported characters and add a fallback font for these
|
||||
char textChr[] = runText.toCharArray();
|
||||
int nextEnd = f.canDisplayUpTo(textChr, 0, textChr.length);
|
||||
int last = nextEnd;
|
||||
boolean isNextValid = (nextEnd == 0);
|
||||
while ( nextEnd != -1 && nextEnd <= textChr.length ) {
|
||||
if (isNextValid) {
|
||||
nextEnd = f.canDisplayUpTo(textChr, nextEnd, textChr.length);
|
||||
isNextValid = false;
|
||||
} else {
|
||||
if (nextEnd >= textChr.length || f.canDisplay(Character.codePointAt(textChr, nextEnd, textChr.length)) ) {
|
||||
attList.add(new AttributedStringData(TextAttribute.FAMILY, fallbackFont, beginIndex+last, beginIndex+Math.min(nextEnd,textChr.length)));
|
||||
if (nextEnd >= textChr.length) {
|
||||
break;
|
||||
}
|
||||
last = nextEnd;
|
||||
isNextValid = true;
|
||||
} else {
|
||||
boolean isHS = Character.isHighSurrogate(textChr[nextEnd]);
|
||||
nextEnd+=(isHS?2:1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ensure that the paragraph contains at least one character
|
||||
|
@ -106,10 +106,25 @@ public interface Drawable {
|
||||
int TEXT_AS_SHAPES = 2;
|
||||
|
||||
/**
|
||||
* Use this object to resolve unknown / missing fonts when rendering slides
|
||||
* Use this object to resolve unknown / missing fonts when rendering slides.
|
||||
* The font handler must be of type {@link DrawFontManager}.<p>
|
||||
*
|
||||
* In case a {@code FONT_HANDLER} is register, {@code FONT_FALLBACK} and {@code FONT_MAP} are ignored
|
||||
*/
|
||||
DrawableHint FONT_HANDLER = new DrawableHint(7);
|
||||
|
||||
/**
|
||||
* Key for a font fallback map of type {@code Map<String,String>} which maps
|
||||
* the original font family (key) to the fallback font family (value).
|
||||
* In case there is also a {@code FONT_MAP} registered, the original font
|
||||
* is first mapped via the font_map and then the fallback font is determined
|
||||
*/
|
||||
DrawableHint FONT_FALLBACK = new DrawableHint(8);
|
||||
|
||||
/**
|
||||
* Key for a font map of type {@code Map<String,String>} which maps
|
||||
* the original font family (key) to the mapped font family (value)
|
||||
*/
|
||||
DrawableHint FONT_MAP = new DrawableHint(9);
|
||||
|
||||
DrawableHint GSAVE = new DrawableHint(10);
|
||||
|
Loading…
Reference in New Issue
Block a user