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.
|
* @param typeface the font family as defined in the .pptx file.
|
||||||
* This can be unknown or missing in the graphic environment.
|
* 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
|
* @return the font to be used to paint text
|
||||||
*/
|
*/
|
||||||
String getRendererableFont(String typeface, int pitchFamily);
|
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;
|
package org.apache.poi.sl.draw;
|
||||||
|
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Font;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Paint;
|
import java.awt.Paint;
|
||||||
import java.awt.font.FontRenderContext;
|
import java.awt.font.FontRenderContext;
|
||||||
@ -500,6 +501,10 @@ public class DrawTextParagraph implements Drawable {
|
|||||||
PlaceableShape<?,?> ps = getParagraphShape();
|
PlaceableShape<?,?> ps = getParagraphShape();
|
||||||
|
|
||||||
DrawFontManager fontHandler = (DrawFontManager)graphics.getRenderingHint(Drawable.FONT_HANDLER);
|
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){
|
for (TextRun run : paragraph){
|
||||||
String runText = getRenderableText(run);
|
String runText = getRenderableText(run);
|
||||||
@ -507,31 +512,48 @@ public class DrawTextParagraph implements Drawable {
|
|||||||
if (runText.isEmpty()) continue;
|
if (runText.isEmpty()) continue;
|
||||||
|
|
||||||
// user can pass an custom object to convert fonts
|
// user can pass an custom object to convert fonts
|
||||||
String fontFamily = run.getFontFamily();
|
String mappedFont = run.getFontFamily();
|
||||||
@SuppressWarnings("unchecked")
|
String fallbackFont = Font.SANS_SERIF;
|
||||||
Map<String,String> fontMap = (Map<String,String>)graphics.getRenderingHint(Drawable.FONT_MAP);
|
|
||||||
if (fontMap != null && fontMap.containsKey(fontFamily)) {
|
|
||||||
fontFamily = fontMap.get(fontFamily);
|
|
||||||
}
|
|
||||||
if(fontHandler != null) {
|
|
||||||
fontFamily = fontHandler.getRendererableFont(fontFamily, run.getPitchAndFamily());
|
|
||||||
}
|
|
||||||
if (fontFamily == null) {
|
|
||||||
fontFamily = paragraph.getDefaultFontFamily();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (mappedFont == null) {
|
||||||
|
mappedFont = paragraph.getDefaultFontFamily();
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
runText = mapFontCharset(runText,mappedFont);
|
||||||
int beginIndex = text.length();
|
int beginIndex = text.length();
|
||||||
text.append(mapFontCharset(runText,fontFamily));
|
text.append(runText);
|
||||||
int endIndex = text.length();
|
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();
|
PaintStyle fgPaintStyle = run.getFontColor();
|
||||||
Paint fgPaint = new DrawPaint(ps).getPaint(graphics, fgPaintStyle);
|
Paint fgPaint = new DrawPaint(ps).getPaint(graphics, fgPaintStyle);
|
||||||
attList.add(new AttributedStringData(TextAttribute.FOREGROUND, fgPaint, beginIndex, endIndex));
|
attList.add(new AttributedStringData(TextAttribute.FOREGROUND, fgPaint, beginIndex, endIndex));
|
||||||
|
|
||||||
Double fontSz = run.getFontSize();
|
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));
|
attList.add(new AttributedStringData(TextAttribute.SIZE, fontSz.floatValue(), beginIndex, endIndex));
|
||||||
|
|
||||||
if(run.isBold()) {
|
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_HREF, hl.getAddress(), beginIndex, endIndex));
|
||||||
attList.add(new AttributedStringData(HYPERLINK_LABEL, hl.getLabel(), 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
|
// ensure that the paragraph contains at least one character
|
||||||
@ -576,7 +625,7 @@ public class DrawTextParagraph implements Drawable {
|
|||||||
|
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isHSLF() {
|
protected boolean isHSLF() {
|
||||||
return paragraph.getClass().getName().contains("HSLF");
|
return paragraph.getClass().getName().contains("HSLF");
|
||||||
}
|
}
|
||||||
|
@ -106,10 +106,25 @@ public interface Drawable {
|
|||||||
int TEXT_AS_SHAPES = 2;
|
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);
|
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);
|
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 FONT_MAP = new DrawableHint(9);
|
||||||
|
|
||||||
DrawableHint GSAVE = new DrawableHint(10);
|
DrawableHint GSAVE = new DrawableHint(10);
|
||||||
|
Loading…
Reference in New Issue
Block a user