#63818 - Allow multiple charsets for same font typeface

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1868358 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2019-10-12 17:55:50 +00:00
parent 69f493ee3a
commit ba25ff3684
3 changed files with 57 additions and 25 deletions

View File

@ -84,7 +84,9 @@ public enum ClassIDPredefined {
/** AcroExch.Document */ /** AcroExch.Document */
PDF ("{B801CA65-A1FC-11D0-85AD-444553540000}", ".pdf", "application/pdf"), PDF ("{B801CA65-A1FC-11D0-85AD-444553540000}", ".pdf", "application/pdf"),
/** Plain Text Persistent Handler **/ /** Plain Text Persistent Handler **/
TXT_ONLY ("{5e941d80-bf96-11cd-b579-08002b30bfeb}", ".txt", "text/plain") TXT_ONLY ("{5e941d80-bf96-11cd-b579-08002b30bfeb}", ".txt", "text/plain"),
/** Microsoft Paint **/
PAINT ("{0003000A-0000-0000-C000-000000000046}", null, null)
; ;
private static final Map<String,ClassIDPredefined> LOOKUP = new HashMap<>(); private static final Map<String,ClassIDPredefined> LOOKUP = new HashMap<>();

View File

@ -24,8 +24,10 @@ import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Predicate;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.apache.poi.common.usermodel.fonts.FontCharset;
import org.apache.poi.common.usermodel.fonts.FontHeader; import org.apache.poi.common.usermodel.fonts.FontHeader;
import org.apache.poi.common.usermodel.fonts.FontInfo; import org.apache.poi.common.usermodel.fonts.FontInfo;
import org.apache.poi.common.usermodel.fonts.FontPitch; import org.apache.poi.common.usermodel.fonts.FontPitch;
@ -41,7 +43,7 @@ import org.apache.poi.util.POILogger;
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
public final class FontCollection extends RecordContainer { public final class FontCollection extends RecordContainer {
private final Map<String,HSLFFontInfo> fonts = new LinkedHashMap<>(); private final Map<Integer,HSLFFontInfo> fonts = new LinkedHashMap<>();
private byte[] _header; private byte[] _header;
/* package */ FontCollection(byte[] source, int start, int len) { /* package */ FontCollection(byte[] source, int start, int len) {
@ -53,7 +55,7 @@ public final class FontCollection extends RecordContainer {
for (Record r : _children){ for (Record r : _children){
if(r instanceof FontEntityAtom) { if(r instanceof FontEntityAtom) {
HSLFFontInfo fi = new HSLFFontInfo((FontEntityAtom) r); HSLFFontInfo fi = new HSLFFontInfo((FontEntityAtom) r);
fonts.put(fi.getTypeface(), fi); fonts.put(fi.getIndex(), fi);
} else if (r instanceof FontEmbeddedData) { } else if (r instanceof FontEmbeddedData) {
FontEmbeddedData fed = (FontEmbeddedData)r; FontEmbeddedData fed = (FontEmbeddedData)r;
FontHeader fontHeader = fed.getFontHeader(); FontHeader fontHeader = fed.getFontHeader();
@ -93,14 +95,14 @@ public final class FontCollection extends RecordContainer {
* @return the register HSLFFontInfo object * @return the register HSLFFontInfo object
*/ */
public HSLFFontInfo addFont(FontInfo fontInfo) { public HSLFFontInfo addFont(FontInfo fontInfo) {
HSLFFontInfo fi = getFontInfo(fontInfo.getTypeface()); HSLFFontInfo fi = getFontInfo(fontInfo.getTypeface(), fontInfo.getCharset());
if (fi != null) { if (fi != null) {
return fi; return fi;
} }
fi = new HSLFFontInfo(fontInfo); fi = new HSLFFontInfo(fontInfo);
fi.setIndex(fonts.size()); fi.setIndex(fonts.size());
fonts.put(fi.getTypeface(), fi); fonts.put(fi.getIndex(), fi);
FontEntityAtom fnt = fi.createRecord(); FontEntityAtom fnt = fi.createRecord();
@ -172,7 +174,23 @@ public final class FontCollection extends RecordContainer {
* @return the HSLFFontInfo for the given name or {@code null} if not found * @return the HSLFFontInfo for the given name or {@code null} if not found
*/ */
public HSLFFontInfo getFontInfo(String typeface) { public HSLFFontInfo getFontInfo(String typeface) {
return fonts.get(typeface); return getFontInfo(typeface, null);
}
/**
* Lookup a FontInfo object by its typeface
*
* @param typeface the full font name
* @param charset the charset
*
* @return the HSLFFontInfo for the given name or {@code null} if not found
*/
public HSLFFontInfo getFontInfo(String typeface, FontCharset charset) {
return fonts.values().stream().filter(findFont(typeface, charset)).findFirst().orElse(null);
}
private static Predicate<HSLFFontInfo> findFont(String typeface, FontCharset charset) {
return (fi) -> typeface.equals(fi.getTypeface()) && (charset == null || charset.equals(fi.getCharset()));
} }
/** /**

View File

@ -89,38 +89,50 @@ public final class HSLFSlideMaster extends HSLFMasterSheet {
*/ */
@Override @Override
public TextPropCollection getPropCollection(final int txtype, final int level, final String name, final boolean isCharacter) { public TextPropCollection getPropCollection(final int txtype, final int level, final String name, final boolean isCharacter) {
if (txtype < _txmaster.length) { TextPropCollection tpc = getPropHelper(txtype, level, name, isCharacter);
final TxMasterStyleAtom t = _txmaster[txtype]; if (tpc != null) {
final List<TextPropCollection> styles = isCharacter ? t.getCharacterStyles() : t.getParagraphStyles(); return tpc;
// TODO: what is the reaction for readOnly=false and styles.isEmpty()?
final int minLevel = Math.min(level, styles.size()-1);
if ("*".equals(name)) {
return styles.get(minLevel);
}
for (int i=minLevel; i >= 0; i--) {
final TextPropCollection col = styles.get(i);
final TextProp tp = col.findByName(name);
if (tp != null) {
return col;
}
}
} }
switch (TextPlaceholder.fromNativeId(txtype)) { TextPlaceholder tp = TextPlaceholder.fromNativeId(txtype);
switch (tp == null ? TextPlaceholder.BODY : tp) {
case BODY: case BODY:
case CENTER_BODY: case CENTER_BODY:
case HALF_BODY: case HALF_BODY:
case QUARTER_BODY: case QUARTER_BODY:
return getPropCollection(TextPlaceholder.BODY.nativeId, level, name, isCharacter); return getPropHelper(TextPlaceholder.BODY.nativeId, level, name, isCharacter);
case TITLE: case TITLE:
case CENTER_TITLE: case CENTER_TITLE:
return getPropCollection(TextPlaceholder.TITLE.nativeId, level, name, isCharacter); return getPropHelper(TextPlaceholder.TITLE.nativeId, level, name, isCharacter);
default: default:
return null; return null;
} }
} }
private TextPropCollection getPropHelper(final int txtype, final int level, final String name, final boolean isCharacter) {
if (txtype >= _txmaster.length) {
return null;
}
final TxMasterStyleAtom t = _txmaster[txtype];
final List<TextPropCollection> styles = isCharacter ? t.getCharacterStyles() : t.getParagraphStyles();
// TODO: what is the reaction for readOnly=false and styles.isEmpty()?
final int minLevel = Math.min(level, styles.size()-1);
if ("*".equals(name)) {
return styles.get(minLevel);
}
for (int i=minLevel; i >= 0; i--) {
final TextPropCollection col = styles.get(i);
final TextProp tp = col.findByName(name);
if (tp != null) {
return col;
}
}
return null;
}
/** /**
* Assign SlideShow for this slide master. * Assign SlideShow for this slide master.
*/ */