Author: kiwiwings
Date: Sun Jul 23 22:45:47 2017
New Revision: 1802741
URL: http://svn.apache.org/viewvc?rev=1802741&view=rev
Log:
Bug 61331 - Font group handling / common font interface
Added:
poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/
poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontCharset.java
(with props)
poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontFamily.java
(with props)
poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontGroup.java
(with props)
poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontInfo.java
(with props)
poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontPitch.java
(with props)
poi/trunk/src/java/org/apache/poi/sl/draw/DrawFontInfo.java (with props)
poi/trunk/src/java/org/apache/poi/sl/draw/DrawFontManagerDefault.java
(with props)
poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFontInfo.java
- copied, changed from r1802740,
poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/PPFont.java
poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFontInfoPredefined.java
(with props)
Removed:
poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/PPFont.java
Modified:
poi/site/src/documentation/content/xdocs/status.xml
poi/trunk/src/java/org/apache/poi/sl/draw/DrawFactory.java
poi/trunk/src/java/org/apache/poi/sl/draw/DrawFontManager.java
poi/trunk/src/java/org/apache/poi/sl/draw/DrawTextFragment.java
poi/trunk/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java
poi/trunk/src/java/org/apache/poi/sl/usermodel/TextRun.java
poi/trunk/src/java/org/apache/poi/ss/usermodel/FontCharset.java
poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java
poi/trunk/src/ooxml/testcases/org/apache/poi/sl/TestFonts.java
poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/textproperties/CharFlagsTextProp.java
poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/FontCollection.java
poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/FontEntityAtom.java
poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/RecordContainer.java
poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java
poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java
poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java
poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfGraphics.java
poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFont.java
poi/trunk/src/scratchpad/src/org/apache/poi/hwpf/HWPFOldDocument.java
poi/trunk/src/scratchpad/src/org/apache/poi/hwpf/model/OldFfn.java
poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestPPFont.java
poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestSlideMaster.java
poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/record/TestFontCollection.java
poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java
poi/trunk/src/scratchpad/testcases/org/apache/poi/hwmf/TestHwmfParsing.java
poi/trunk/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestHWPFOldDocument.java
Modified: poi/site/src/documentation/content/xdocs/status.xml
URL:
http://svn.apache.org/viewvc/poi/site/src/documentation/content/xdocs/status.xml?rev=1802741&r1=1802740&r2=1802741&view=diff
==============================================================================
--- poi/site/src/documentation/content/xdocs/status.xml (original)
+++ poi/site/src/documentation/content/xdocs/status.xml Sun Jul 23 22:45:47 2017
@@ -58,6 +58,7 @@
<release version="3.17-beta2" date="2017-09-??">
<actions>
+ <action dev="PD" type="add" fixes-bug="61331" module="SL Common">Font
group handling / common font interface</action>
<action dev="PD" type="fix" fixes-bug="61300" module="POIFS">Avoid
infinite loop with corrupt file.</action>
<action dev="PD" type="fix" fixes-bug="61286,61287"
module="HSSF">Handle zero-length headerfooter and 2 byte
WriteProtectRecord</action>
<action dev="PD" type="fix" fixes-bug="github-43" module="SS
Common">RoundUp and RoundDown functions round incorrectly in some
scenarios</action>
Added: poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontCharset.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontCharset.java?rev=1802741&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontCharset.java
(added)
+++ poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontCharset.java
Sun Jul 23 22:45:47 2017
@@ -0,0 +1,124 @@
+/* ====================================================================
+ 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.common.usermodel.fonts;
+
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
+
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+
+/**
+ * Charset represents the basic set of characters associated with a font (that
it can display), and
+ * corresponds to the ANSI codepage (8-bit or DBCS) of that character set used
by a given language.
+ *
+ * @since POI 3.17-beta2
+ */
+public enum FontCharset {
+ /** Specifies the English character set. */
+ ANSI(0x00000000, "Cp1252"),
+ /**
+ * Specifies a character set based on the current system locale;
+ * for example, when the system locale is United States English,
+ * the default character set is ANSI_CHARSET.
+ */
+ DEFAULT(0x00000001, "Cp1252"),
+ /** Specifies a character set of symbols. */
+ SYMBOL(0x00000002, ""),
+ /** Specifies the Apple Macintosh character set. */
+ MAC(0x0000004D, "MacRoman"),
+ /** Specifies the Japanese character set. */
+ SHIFTJIS(0x00000080, "Shift_JIS"),
+ /** Also spelled "Hangeul". Specifies the Hangul Korean character set. */
+ HANGUL(0x00000081, "cp949"),
+ /** Also spelled "Johap". Specifies the Johab Korean character set. */
+ JOHAB(0x00000082, "x-Johab"),
+ /** Specifies the "simplified" Chinese character set for People's Republic
of China. */
+ GB2312(0x00000086, "GB2312"),
+ /**
+ * Specifies the "traditional" Chinese character set, used mostly in
+ * Taiwan and in the Hong Kong and Macao Special Administrative Regions.
+ */
+ CHINESEBIG5(0x00000088, "Big5"),
+ /** Specifies the Greek character set. */
+ GREEK(0x000000A1, "Cp1253"),
+ /** Specifies the Turkish character set. */
+ TURKISH(0x000000A2, "Cp1254"),
+ /** Specifies the Vietnamese character set. */
+ VIETNAMESE(0x000000A3, "Cp1258"),
+ /** Specifies the Hebrew character set. */
+ HEBREW(0x000000B1, "Cp1255"),
+ /** Specifies the Arabic character set. */
+ ARABIC(0x000000B2, "Cp1256"),
+ /** Specifies the Baltic (Northeastern European) character set. */
+ BALTIC(0x000000BA, "Cp1257"),
+ /** Specifies the Russian Cyrillic character set. */
+ RUSSIAN(0x000000CC, "Cp1251"),
+ /** Specifies the Thai character set. */
+ THAI_(0x000000DE, "x-windows-874"),
+ /** Specifies a Eastern European character set. */
+ EASTEUROPE(0x000000EE, "Cp1250"),
+ /**
+ * Specifies a mapping to one of the OEM code pages,
+ * according to the current system locale setting.
+ */
+ OEM(0x000000FF, "Cp1252");
+
+ private static FontCharset[] _table = new FontCharset[256];
+
+ private int nativeId;
+ private Charset charset;
+
+
+ static {
+ for (FontCharset c : values()) {
+ _table[c.getNativeId()] = c;
+ }
+ }
+
+ FontCharset(int flag, String javaCharsetName) {
+ this.nativeId = flag;
+ if (javaCharsetName.length() > 0) {
+ try {
+ charset = Charset.forName(javaCharsetName);
+ return;
+ } catch (UnsupportedCharsetException e) {
+ POILogger logger = POILogFactory.getLogger(FontCharset.class);
+ logger.log(POILogger.WARN, "Unsupported charset:
"+javaCharsetName);
+ }
+ }
+ charset = null;
+ }
+
+ /**
+ *
+ * @return charset for the font or <code>null</code> if there is no
matching charset or
+ * if the charset is a "default"
+ */
+ public Charset getCharset() {
+ return charset;
+ }
+
+ public int getNativeId() {
+ return nativeId;
+ }
+
+ public static FontCharset valueOf(int value){
+ return (value < 0 || value >= _table.length) ? null :_table[value];
+ }
+}
\ No newline at end of file
Propchange:
poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontCharset.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontFamily.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontFamily.java?rev=1802741&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontFamily.java
(added)
+++ poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontFamily.java
Sun Jul 23 22:45:47 2017
@@ -0,0 +1,80 @@
+/* ====================================================================
+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.common.usermodel.fonts;
+
+/**
+ * A property of a font that describes its general appearance.
+ *
+ * @since POI 3.17-beta2
+ */
+public enum FontFamily {
+ /**
+ * The default font is specified, which is implementation-dependent.
+ */
+ FF_DONTCARE (0x00),
+ /**
+ * Fonts with variable stroke widths, which are proportional to the actual
widths of
+ * the glyphs, and which have serifs. "MS Serif" is an example.
+ */
+ FF_ROMAN (0x01),
+ /**
+ * Fonts with variable stroke widths, which are proportional to the actual
widths of the
+ * glyphs, and which do not have serifs. "MS Sans Serif" is an example.
+ */
+ FF_SWISS (0x02),
+ /**
+ * Fonts with constant stroke width, with or without serifs. Fixed-width
fonts are
+ * usually modern. "Pica", "Elite", and "Courier New" are examples.
+ */
+ FF_MODERN (0x03),
+ /**
+ * Fonts designed to look like handwriting. "Script" and "Cursive" are
examples.
+ */
+ FF_SCRIPT (0x04),
+ /**
+ * Novelty fonts. "Old English" is an example.
+ */
+ FF_DECORATIVE (0x05);
+
+ private int nativeId;
+ private FontFamily(int nativeId) {
+ this.nativeId = nativeId;
+ }
+
+ public int getFlag() {
+ return nativeId;
+ }
+
+ public static FontFamily valueOf(int nativeId) {
+ for (FontFamily ff : values()) {
+ if (ff.nativeId == nativeId) {
+ return ff;
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * Get FontFamily from combined native id
+ */
+ public static FontFamily valueOfPitchFamily(byte pitchAndFamily) {
+ return valueOf(pitchAndFamily >>> 4);
+ }
+
+}
\ No newline at end of file
Propchange:
poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontFamily.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontGroup.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontGroup.java?rev=1802741&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontGroup.java
(added)
+++ poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontGroup.java Sun
Jul 23 22:45:47 2017
@@ -0,0 +1,149 @@
+/* ====================================================================
+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.common.usermodel.fonts;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.NavigableMap;
+import java.util.TreeMap;
+
+/**
+ * Text runs can contain characters which will be handled (if configured) by a
different font,
+ * because the default font (latin) doesn't contain corresponding glyphs.
+ *
+ * @since POI 3.17-beta2
+ *
+ * @see <a
href="https://blogs.msdn.microsoft.com/officeinteroperability/2013/04/22/office-open-xml-themes-schemes-and-fonts/">Office
Open XML Themes, Schemes, and Fonts</a>
+ */
+public enum FontGroup {
+ /** type for latin charset (default) - also used for unicode fonts like MS
Arial Unicode */
+ LATIN,
+ /** type for east asian charsets - usually set as fallback for the latin
font, e.g. something like MS Gothic or MS Mincho */
+ EAST_ASIAN,
+ /** type for symbol fonts */
+ SYMBOL,
+ /** type for complex scripts - see
https://msdn.microsoft.com/en-us/library/windows/desktop/dd317698 */
+ COMPLEX_SCRIPT
+ ;
+
+
+ public static class FontGroupRange {
+ private int len;
+ private FontGroup fontGroup;
+ public int getLength() {
+ return len;
+ }
+ public FontGroup getFontGroup( ) {
+ return fontGroup;
+ }
+ }
+
+ private static class Range {
+ int upper;
+ FontGroup fontGroup;
+ Range(int upper, FontGroup fontGroup) {
+ this.upper = upper;
+ this.fontGroup = fontGroup;
+ }
+ }
+
+ private static NavigableMap<Integer,Range> UCS_RANGES;
+
+ static {
+ UCS_RANGES = new TreeMap<Integer,Range>();
+ UCS_RANGES.put(0x0000, new Range(0x007F, LATIN));
+ UCS_RANGES.put(0x0080, new Range(0x00A6, LATIN));
+ UCS_RANGES.put(0x00A9, new Range(0x00AF, LATIN));
+ UCS_RANGES.put(0x00B2, new Range(0x00B3, LATIN));
+ UCS_RANGES.put(0x00B5, new Range(0x00D6, LATIN));
+ UCS_RANGES.put(0x00D8, new Range(0x00F6, LATIN));
+ UCS_RANGES.put(0x00F8, new Range(0x058F, LATIN));
+ UCS_RANGES.put(0x0590, new Range(0x074F, COMPLEX_SCRIPT));
+ UCS_RANGES.put(0x0780, new Range(0x07BF, COMPLEX_SCRIPT));
+ UCS_RANGES.put(0x0900, new Range(0x109F, COMPLEX_SCRIPT));
+ UCS_RANGES.put(0x10A0, new Range(0x10FF, LATIN));
+ UCS_RANGES.put(0x1200, new Range(0x137F, LATIN));
+ UCS_RANGES.put(0x13A0, new Range(0x177F, LATIN));
+ UCS_RANGES.put(0x1D00, new Range(0x1D7F, LATIN));
+ UCS_RANGES.put(0x1E00, new Range(0x1FFF, LATIN));
+ UCS_RANGES.put(0x1780, new Range(0x18AF, COMPLEX_SCRIPT));
+ UCS_RANGES.put(0x2000, new Range(0x200B, LATIN));
+ UCS_RANGES.put(0x200C, new Range(0x200F, COMPLEX_SCRIPT));
+ // For the quote characters in the range U+2018 - U+201E, use the East
Asian font
+ // if the text has one of the following language identifiers:
+ // ii-CN, ja-JP, ko-KR, zh-CN,zh-HK, zh-MO, zh-SG, zh-TW
+ UCS_RANGES.put(0x2010, new Range(0x2029, LATIN));
+ UCS_RANGES.put(0x202A, new Range(0x202F, COMPLEX_SCRIPT));
+ UCS_RANGES.put(0x2030, new Range(0x2046, LATIN));
+ UCS_RANGES.put(0x204A, new Range(0x245F, LATIN));
+ UCS_RANGES.put(0x2670, new Range(0x2671, COMPLEX_SCRIPT));
+ UCS_RANGES.put(0x27C0, new Range(0x2BFF, LATIN));
+ UCS_RANGES.put(0x3099, new Range(0x309A, EAST_ASIAN));
+ UCS_RANGES.put(0xD835, new Range(0xD835, LATIN));
+ UCS_RANGES.put(0xF000, new Range(0xF0FF, SYMBOL));
+ UCS_RANGES.put(0xFB00, new Range(0xFB17, LATIN));
+ UCS_RANGES.put(0xFB1D, new Range(0xFB4F, COMPLEX_SCRIPT));
+ UCS_RANGES.put(0xFE50, new Range(0xFE6F, LATIN));
+ // All others EAST_ASIAN
+ };
+
+
+ /**
+ * Try to guess the font group based on the codepoint
+ *
+ * @param runText the text which font groups are to be analyzed
+ * @return the FontGroup
+ */
+ public static List<FontGroupRange> getFontGroupRanges(String runText) {
+ List<FontGroupRange> ttrList = new ArrayList<FontGroupRange>();
+ FontGroupRange ttrLast = null;
+ final int rlen = (runText != null) ? runText.length() : 0;
+ for(int cp, i = 0, charCount; i < rlen; i += charCount) {
+ cp = runText.codePointAt(i);
+ charCount = Character.charCount(cp);
+
+ // don't switch the font group for a few default characters
supposedly available in all fonts
+ FontGroup tt;
+ if (ttrLast != null && " \n\r".indexOf(cp) > -1) {
+ tt = ttrLast.fontGroup;
+ } else {
+ tt = lookup(cp);
+ }
+
+ if (ttrLast == null || ttrLast.fontGroup != tt) {
+ ttrLast = new FontGroupRange();
+ ttrLast.fontGroup = tt;
+ ttrList.add(ttrLast);
+ }
+ ttrLast.len += charCount;
+ }
+ return ttrList;
+ }
+
+ public static FontGroup getFontGroupFirst(String runText) {
+ return (runText == null || runText.isEmpty()) ? LATIN :
lookup(runText.codePointAt(0));
+ }
+
+ private static FontGroup lookup(int codepoint) {
+ // Do a lookup for a match in UCS_RANGES
+ Map.Entry<Integer,Range> entry = UCS_RANGES.floorEntry(codepoint);
+ Range range = (entry != null) ? entry.getValue() : null;
+ return (range != null && codepoint <= range.upper) ? range.fontGroup :
EAST_ASIAN;
+ }
+}
\ No newline at end of file
Propchange:
poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontGroup.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontInfo.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontInfo.java?rev=1802741&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontInfo.java
(added)
+++ poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontInfo.java Sun
Jul 23 22:45:47 2017
@@ -0,0 +1,102 @@
+/* ====================================================================
+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.common.usermodel.fonts;
+
+/**
+ * A FontInfo object holds information about a font configuration.
+ * It is roughly an equivalent to the LOGFONT structure in Windows GDI.<p>
+ *
+ * If an implementation doesn't provide a property, the getter will return
{@code null} -
+ * if the value is unset, a default value will be returned.<p>
+ *
+ * Setting a unsupported property results in an {@link
UnsupportedOperationException}.
+ *
+ * @since POI 3.17-beta2
+ *
+ * @see <a
href="https://msdn.microsoft.com/en-us/library/dd145037.aspx">LOGFONT
structure</a>
+ */
+public interface FontInfo {
+
+ /**
+ * Get the index within the collection of Font objects
+ * @return unique index number of the underlying record this Font
represents
+ * (probably you don't care unless you're comparing which one is which)
+ */
+ Integer getIndex();
+
+ /**
+ * Sets the index within the collection of Font objects
+ *
+ * @param index the index within the collection of Font objects
+ *
+ * @throws UnsupportedOperationException if unsupported
+ */
+ void setIndex(int index);
+
+
+ /**
+ * @return the full name of the font, i.e. font family + type face
+ */
+ String getTypeface();
+
+ /**
+ * Sets the font name
+ *
+ * @param typeface the full name of the font, when {@code null} removes
the font definition -
+ * removal is implementation specific
+ */
+ void setTypeface(String typeface);
+
+ /**
+ * @return the font charset
+ */
+ FontCharset getCharset();
+
+ /**
+ * Sets the charset
+ *
+ * @param charset the charset
+ */
+ void setCharset(FontCharset charset);
+
+ /**
+ * @return the family class
+ */
+ FontFamily getFamily();
+
+ /**
+ * Sets the font family class
+ *
+ * @param family the font family class
+ */
+ void setFamily(FontFamily family);
+
+ /**
+ * @return the font pitch or {@code null} if unsupported
+ */
+ FontPitch getPitch();
+
+ /**
+ * Set the font pitch
+ *
+ * @param pitch the font pitch
+ *
+ * @throws UnsupportedOperationException if unsupported
+ */
+ void setPitch(FontPitch pitch);
+}
\ No newline at end of file
Propchange:
poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontInfo.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontPitch.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontPitch.java?rev=1802741&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontPitch.java
(added)
+++ poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontPitch.java Sun
Jul 23 22:45:47 2017
@@ -0,0 +1,74 @@
+/* ====================================================================
+ 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.common.usermodel.fonts;
+
+/**
+ * A property of a font that describes the pitch, of the characters.
+ *
+ * @since POI 3.17-beta2
+ */
+public enum FontPitch {
+ /**
+ * The default pitch, which is implementation-dependent.
+ */
+ DEFAULT (0x00),
+ /**
+ * A fixed pitch, which means that all the characters in the font occupy
the same
+ * width when output in a string.
+ */
+ FIXED (0x01),
+ /**
+ * A variable pitch, which means that the characters in the font occupy
widths
+ * that are proportional to the actual widths of the glyphs when output in
a string. For example,
+ * the "i" and space characters usually have much smaller widths than a
"W" or "O" character.
+ */
+ VARIABLE (0x02);
+
+ private int nativeId;
+ FontPitch(int nativeId) {
+ this.nativeId = nativeId;
+ }
+
+ public int getNativeId() {
+ return nativeId;
+ }
+
+ public static FontPitch valueOf(int flag) {
+ for (FontPitch fp : values()) {
+ if (fp.nativeId == flag) return fp;
+ }
+ return null;
+ }
+
+ /**
+ * Combine pitch and family to native id
+ *
+ * @see <a
href="https://msdn.microsoft.com/en-us/library/dd145037.aspx">LOGFONT
structure</a>
+ */
+ public static byte getNativeId(FontPitch pitch, FontFamily family) {
+ return (byte)(pitch.getNativeId() | (family.getFlag() << 4));
+ }
+
+ /**
+ * Get FontPitch from native id
+ */
+ public static FontPitch valueOfPitchFamily(byte pitchAndFamily) {
+ return valueOf(pitchAndFamily & 0x3);
+ }
+}
+
Propchange:
poi/trunk/src/java/org/apache/poi/common/usermodel/fonts/FontPitch.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: poi/trunk/src/java/org/apache/poi/sl/draw/DrawFactory.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/DrawFactory.java?rev=1802741&r1=1802740&r2=1802741&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/DrawFactory.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/DrawFactory.java Sun Jul 23
22:45:47 2017
@@ -236,4 +236,15 @@ public class DrawFactory {
}
}
}
+
+ /**
+ * Return a FontManager, either registered beforehand or a default
implementation
+ *
+ * @param graphics the graphics context holding potentially a font manager
+ * @return the font manager
+ */
+ public DrawFontManager getFontManager(Graphics2D graphics) {
+ DrawFontManager fontHandler =
(DrawFontManager)graphics.getRenderingHint(Drawable.FONT_HANDLER);
+ return (fontHandler != null) ? fontHandler : new
DrawFontManagerDefault();
+ }
}
\ No newline at end of file
Added: poi/trunk/src/java/org/apache/poi/sl/draw/DrawFontInfo.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/DrawFontInfo.java?rev=1802741&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/DrawFontInfo.java (added)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/DrawFontInfo.java Sun Jul 23
22:45:47 2017
@@ -0,0 +1,89 @@
+/*
+ * ====================================================================
+ * 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.sl.draw;
+
+import org.apache.poi.common.usermodel.fonts.FontCharset;
+import org.apache.poi.common.usermodel.fonts.FontFamily;
+import org.apache.poi.common.usermodel.fonts.FontInfo;
+import org.apache.poi.common.usermodel.fonts.FontPitch;
+import org.apache.poi.util.Internal;
+
+/**
+ * Convenience class to handle FontInfo mappings
+ */
+@Internal
+/* package */ class DrawFontInfo implements FontInfo {
+
+ private final String typeface;
+
+ DrawFontInfo(String typeface) {
+ this.typeface = typeface;
+ }
+
+ @Override
+ public Integer getIndex() {
+ return null;
+ }
+
+ @Override
+ public void setIndex(int index) {
+ throw new UnsupportedOperationException("DrawFontManagers FontInfo
can't be changed.");
+ }
+
+ @Override
+ public String getTypeface() {
+ return typeface;
+ }
+
+ @Override
+ public void setTypeface(String typeface) {
+ throw new UnsupportedOperationException("DrawFontManagers FontInfo
can't be changed.");
+ }
+
+ @Override
+ public FontCharset getCharset() {
+ return FontCharset.ANSI;
+ }
+
+ @Override
+ public void setCharset(FontCharset charset) {
+ throw new UnsupportedOperationException("DrawFontManagers FontInfo
can't be changed.");
+ }
+
+ @Override
+ public FontFamily getFamily() {
+ return FontFamily.FF_SWISS;
+ }
+
+ @Override
+ public void setFamily(FontFamily family) {
+ throw new UnsupportedOperationException("DrawFontManagers FontInfo
can't be changed.");
+ }
+
+ @Override
+ public FontPitch getPitch() {
+ return FontPitch.VARIABLE;
+ }
+
+ @Override
+ public void setPitch(FontPitch pitch) {
+ throw new UnsupportedOperationException("DrawFontManagers FontInfo
can't be changed.");
+ }
+}
Propchange: poi/trunk/src/java/org/apache/poi/sl/draw/DrawFontInfo.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: poi/trunk/src/java/org/apache/poi/sl/draw/DrawFontManager.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/DrawFontManager.java?rev=1802741&r1=1802740&r2=1802741&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/DrawFontManager.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/DrawFontManager.java Sun Jul 23
22:45:47 2017
@@ -19,6 +19,12 @@
package org.apache.poi.sl.draw;
+import java.awt.Font;
+import java.awt.Graphics2D;
+
+import org.apache.poi.common.usermodel.fonts.FontInfo;
+import org.apache.poi.util.StringUtil;
+
/**
* Manages fonts when rendering slides.
*
@@ -29,28 +35,50 @@ public interface DrawFontManager {
/**
* select a font to be used to paint text
*
- * @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
+ * @param graphics the graphics context to request additional rendering
hints
+ * @param fontInfo the font info object corresponding to the text run font
*
* @return the font to be used to paint text
*/
- String getRendererableFont(String typeface, int pitchFamily);
+ FontInfo getMappedFont(Graphics2D graphics, FontInfo fontInfo);
/**
* 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
+ * @param graphics the graphics context to request additional rendering
hints
+ * @param fontInfo the font info object corresponding to the text run font
*
* @return the font to be used as a fallback for the original typeface
*/
- String getFallbackFont(String typeface, int pitchFamily);
+ FontInfo getFallbackFont(Graphics2D graphics, FontInfo fontInfo);
+
+ /**
+ * Map text charset depending on font family.<p>
+ *
+ * Currently this only maps for wingdings font (into unicode private use
area)
+ *
+ * @param graphics the graphics context to request additional rendering
hints
+ * @param fontInfo the font info object corresponding to the text run font
+ * @param text the raw text
+ *
+ * @return String with mapped codepoints
+ *
+ * @see <a href="http://stackoverflow.com/questions/8692095">Drawing
exotic fonts in a java applet</a>
+ * @see StringUtil#mapMsCodepointString(String)
+ */
+ String mapFontCharset(Graphics2D graphics, FontInfo fontInfo, String text);
+
+ /**
+ * Create an AWT font object with the given attributes
+ *
+ * @param graphics the graphics context to request additional rendering
hints
+ * @param fontInfo the font info object corresponding to the text run font
+ * @param size the font size in points
+ * @param bold {@code true} if the font is bold
+ * @param italic {@code true} if the font is italic
+ *
+ * @return the AWT font object
+ */
+ Font createAWTFont(Graphics2D graphics, FontInfo fontInfo, double size,
boolean bold, boolean italic);
}
Added: poi/trunk/src/java/org/apache/poi/sl/draw/DrawFontManagerDefault.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/DrawFontManagerDefault.java?rev=1802741&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/DrawFontManagerDefault.java
(added)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/DrawFontManagerDefault.java Sun
Jul 23 22:45:47 2017
@@ -0,0 +1,101 @@
+/*
+ * ====================================================================
+ * 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.sl.draw;
+
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.util.Map;
+
+import org.apache.poi.common.usermodel.fonts.FontInfo;
+import org.apache.poi.sl.draw.Drawable.DrawableHint;
+
+/**
+ * Manages fonts when rendering slides.
+ *
+ * Use this class to handle unknown / missing fonts or to substitute fonts
+ */
+public class DrawFontManagerDefault implements DrawFontManager {
+
+ @Override
+ public FontInfo getMappedFont(Graphics2D graphics, FontInfo fontInfo) {
+ return getFontWithFallback(graphics, Drawable.FONT_MAP, fontInfo);
+ }
+
+ @Override
+ public FontInfo getFallbackFont(Graphics2D graphics, FontInfo fontInfo) {
+ FontInfo fi = getFontWithFallback(graphics, Drawable.FONT_FALLBACK,
fontInfo);
+ if (fi == null) {
+ fi = new DrawFontInfo(Font.SANS_SERIF);
+ }
+ return fi;
+ }
+
+ public String mapFontCharset(Graphics2D graphics, FontInfo fontInfo,
String text) {
+ // TODO: find a real charset mapping solution instead of hard coding
for Wingdings
+ String attStr = text;
+ if (fontInfo != null &&
"Wingdings".equalsIgnoreCase(fontInfo.getTypeface())) {
+ // wingdings doesn't contain high-surrogates, so chars are ok
+ boolean changed = false;
+ char chrs[] = attStr.toCharArray();
+ for (int i=0; i<chrs.length; i++) {
+ // only change valid chars
+ if ((0x20 <= chrs[i] && chrs[i] <= 0x7f) ||
+ (0xa0 <= chrs[i] && chrs[i] <= 0xff)) {
+ chrs[i] |= 0xf000;
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ attStr = new String(chrs);
+ }
+ }
+ return attStr;
+ }
+
+ @Override
+ public Font createAWTFont(Graphics2D graphics, FontInfo fontInfo, double
fontSize, boolean bold, boolean italic) {
+ int style = (bold ? Font.BOLD : 0) | (italic ? Font.ITALIC : 0);
+ Font font = new Font(fontInfo.getTypeface(), style, 12);
+ if (Font.DIALOG.equals(font.getFamily())) {
+ // SansSerif is a better choice than Dialog
+ font = new Font(Font.SANS_SERIF, style, 12);
+ }
+ return font.deriveFont((float)fontSize);
+ }
+
+ private FontInfo getFontWithFallback(Graphics2D graphics, DrawableHint
hint, FontInfo fontInfo) {
+ @SuppressWarnings("unchecked")
+ Map<String,String> fontMap =
(Map<String,String>)graphics.getRenderingHint(hint);
+ if (fontMap == null) {
+ return fontInfo;
+ }
+
+ String f = (fontInfo != null) ? fontInfo.getTypeface() : null;
+ String mappedTypeface = null;
+ if (fontMap.containsKey(f)) {
+ mappedTypeface = fontMap.get(f);
+ } else if (fontMap.containsKey("*")) {
+ mappedTypeface = fontMap.get("*");
+ }
+
+ return (mappedTypeface != null) ? new DrawFontInfo(mappedTypeface) :
fontInfo;
+ }
+}
Propchange:
poi/trunk/src/java/org/apache/poi/sl/draw/DrawFontManagerDefault.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: poi/trunk/src/java/org/apache/poi/sl/draw/DrawTextFragment.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/DrawTextFragment.java?rev=1802741&r1=1802740&r2=1802741&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/DrawTextFragment.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/DrawTextFragment.java Sun Jul 23
22:45:47 2017
@@ -70,7 +70,7 @@ public class DrawTextFragment implements
* @return full height of this text run which is sum of ascent, descent
and leading
*/
public float getHeight(){
- double h = Math.ceil(layout.getAscent()) +
Math.ceil(layout.getDescent()) + getLeading();
+ double h = layout.getAscent() + layout.getDescent() + getLeading();
return (float)h;
}
@@ -78,9 +78,14 @@ public class DrawTextFragment implements
* @return the leading height before/after a text line
*/
public float getLeading() {
- // fix invalid leadings (leading == 0) by fallback to descent
+ // fix invalid leadings (leading == 0)
double l = layout.getLeading();
- return (float)(l == 0 ? layout.getDescent() : l);
+ if (l == 0) {
+ // see https://stackoverflow.com/questions/925147
+ // we use a 115% value instead of the 120% proposed one, as this
seems to be closer to LO/OO
+ l = (layout.getAscent()+layout.getDescent())*0.15;
+ }
+ return (float)l;
}
/**
Modified: poi/trunk/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java?rev=1802741&r1=1802740&r2=1802741&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java Sun Jul 23
22:45:47 2017
@@ -32,8 +32,11 @@ import java.text.AttributedCharacterIter
import java.text.AttributedString;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
+import java.util.Locale;
+import org.apache.poi.common.usermodel.fonts.FontGroup;
+import org.apache.poi.common.usermodel.fonts.FontGroup.FontGroupRange;
+import org.apache.poi.common.usermodel.fonts.FontInfo;
import org.apache.poi.sl.usermodel.AutoNumberingScheme;
import org.apache.poi.sl.usermodel.Hyperlink;
import org.apache.poi.sl.usermodel.Insets2D;
@@ -50,11 +53,14 @@ import org.apache.poi.sl.usermodel.TextR
import org.apache.poi.sl.usermodel.TextRun.TextCap;
import org.apache.poi.sl.usermodel.TextShape;
import org.apache.poi.sl.usermodel.TextShape.TextDirection;
-import org.apache.poi.util.StringUtil;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
import org.apache.poi.util.Units;
public class DrawTextParagraph implements Drawable {
+ private static final POILogger LOG =
POILogFactory.getLogger(DrawTextParagraph.class);
+
/** Keys for passing hyperlinks to the graphics context */
public static final XlinkAttribute HYPERLINK_HREF = new
XlinkAttribute("href");
public static final XlinkAttribute HYPERLINK_LABEL = new
XlinkAttribute("label");
@@ -200,7 +206,7 @@ public class DrawTextParagraph implement
line.setPosition(penX, penY);
line.draw(graphics);
-
+
if(spacing > 0) {
// If linespacing >= 0, then linespacing is a percentage of
normal line height.
penY += spacing*0.01* line.getHeight();
@@ -325,12 +331,6 @@ public class DrawTextParagraph implement
return null;
}
- String buFont = bulletStyle.getBulletFont();
- if (buFont == null) {
- buFont = paragraph.getDefaultFontFamily();
- }
- assert(buFont != null);
-
PlaceableShape<?,?> ps = getParagraphShape();
PaintStyle fgPaintStyle = bulletStyle.getBulletFontColor();
Paint fgPaint;
@@ -351,10 +351,21 @@ public class DrawTextParagraph implement
fontSize = (float)-buSz;
}
+ String buFontStr = bulletStyle.getBulletFont();
+ if (buFontStr == null) {
+ buFontStr = paragraph.getDefaultFontFamily();
+ }
+ assert(buFontStr != null);
+ FontInfo buFont = new DrawFontInfo(buFontStr);
+
+
+ DrawFontManager dfm =
DrawFactory.getInstance(graphics).getFontManager(graphics);
+ // TODO: check font group defaulting to Symbol
+ buFont = dfm.getMappedFont(graphics, buFont);
- AttributedString str = new
AttributedString(mapFontCharset(buCharacter,buFont));
+ AttributedString str = new
AttributedString(dfm.mapFontCharset(graphics,buFont,buCharacter));
str.addAttribute(TextAttribute.FOREGROUND, fgPaint);
- str.addAttribute(TextAttribute.FAMILY, buFont);
+ str.addAttribute(TextAttribute.FAMILY, buFont.getTypeface());
str.addAttribute(TextAttribute.SIZE, fontSize);
TextLayout layout = new TextLayout(str.getIterator(),
graphics.getFontRenderContext());
@@ -365,7 +376,7 @@ public class DrawTextParagraph implement
protected String getRenderableText(Graphics2D graphics, TextRun tr) {
if (tr.getFieldType() == FieldType.SLIDE_NUMBER) {
Slide<?,?> slide =
(Slide<?,?>)graphics.getRenderingHint(Drawable.CURRENT_SLIDE);
- return (slide == null) ? "" :
Integer.toString(slide.getSlideNumber());
+ return (slide == null) ? "" :
Integer.toString(slide.getSlideNumber());
}
StringBuilder buf = new StringBuilder();
TextCap cap = tr.getTextCap();
@@ -557,11 +568,8 @@ public class DrawTextParagraph implement
}
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);
+ DrawFontManager dfm =
DrawFactory.getInstance(graphics).getFontManager(graphics);
+ assert(dfm != null);
for (TextRun run : paragraph){
String runText = getRenderableText(graphics, run);
@@ -571,36 +579,12 @@ public class DrawTextParagraph implement
}
// user can pass an custom object to convert fonts
- String mappedFont = run.getFontFamily();
- String fallbackFont = Font.SANS_SERIF;
- 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 {
- mappedFont = getFontWithFallback(fontMap, mappedFont);
- fallbackFont = getFontWithFallback(fallbackMap, mappedFont);
- }
-
- runText = mapFontCharset(runText,mappedFont);
+ runText = dfm.mapFontCharset(graphics, run.getFontInfo(null),
runText);
int beginIndex = text.length();
text.append(runText);
int endIndex = text.length();
- 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));
@@ -630,39 +614,14 @@ public class DrawTextParagraph implement
if(run.isSuperscript()) {
attList.add(new
AttributedStringData(TextAttribute.SUPERSCRIPT,
TextAttribute.SUPERSCRIPT_SUPER, beginIndex, endIndex));
}
-
+
Hyperlink<?,?> hl = run.getHyperlink();
if (hl != null) {
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 = canDisplayUpTo(f, textChr, 0, textChr.length);
- int last = nextEnd;
- boolean isNextValid = (nextEnd == 0);
- while ( nextEnd != -1 && nextEnd <= textChr.length ) {
- if (isNextValid) {
- nextEnd = canDisplayUpTo(f, 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);
- }
- }
- }
+
+ processGlyphs(graphics, dfm, attList, beginIndex, run, runText);
}
// ensure that the paragraph contains at least one character
@@ -681,94 +640,97 @@ public class DrawTextParagraph implement
return string;
}
- private String getFontWithFallback(Map<String, String> fontMap, String
mappedFont) {
- if (fontMap != null) {
- if (fontMap.containsKey(mappedFont)) {
- mappedFont = fontMap.get(mappedFont);
- } else if (fontMap.containsKey("*")) {
- mappedFont = fontMap.get("*");
- }
- }
- return mappedFont;
- }
-
/**
- * @return {@code true} if the HSLF implementation is used
- */
- protected boolean isHSLF() {
- return DrawShape.isHSLF(paragraph.getParentShape());
- }
-
- /**
- * Map text charset depending on font family.
- * Currently this only maps for wingdings font (into unicode private use
area)
+ * Processing the glyphs is done in two steps.
+ * <li>determine the font group - a text run can have different font
groups. Depending on the chars,
+ * the correct font group needs to be used
*
- * @param text the raw text
- * @param fontFamily the font family
- * @return AttributedString with mapped codepoints
+ * @param graphics
+ * @param dfm
+ * @param attList
+ * @param beginIndex
+ * @param run
+ * @param runText
*
- * @see <a href="http://stackoverflow.com/questions/8692095">Drawing
exotic fonts in a java applet</a>
- * @see StringUtil#mapMsCodepointString(String)
+ * @see <a
href="https://blogs.msdn.microsoft.com/officeinteroperability/2013/04/22/office-open-xml-themes-schemes-and-fonts/">Office
Open XML Themes, Schemes, and Fonts</a>
*/
- protected String mapFontCharset(String text, String fontFamily) {
- // TODO: find a real charset mapping solution instead of hard coding
for Wingdings
- String attStr = text;
- if ("Wingdings".equalsIgnoreCase(fontFamily)) {
- // wingdings doesn't contain high-surrogates, so chars are ok
- boolean changed = false;
- char chrs[] = attStr.toCharArray();
- for (int i=0; i<chrs.length; i++) {
- // only change valid chars
- if ((0x20 <= chrs[i] && chrs[i] <= 0x7f) ||
- (0xa0 <= chrs[i] && chrs[i] <= 0xff)) {
- chrs[i] |= 0xf000;
- changed = true;
- }
+ private void processGlyphs(Graphics2D graphics, DrawFontManager dfm,
List<AttributedStringData> attList, final int beginIndex, TextRun run, String
runText) {
+ // determine font group ranges of the textrun to focus the fallback
handling only on that font group
+ List<FontGroupRange> ttrList = FontGroup.getFontGroupRanges(runText);
+ int rangeBegin = 0;
+ for (FontGroupRange ttr : ttrList) {
+ FontInfo fiRun = run.getFontInfo(ttr.getFontGroup());
+ if (fiRun == null) {
+ // if the font group specific font wasn't defined, fallback to
LATIN
+ fiRun = run.getFontInfo(FontGroup.LATIN);
+ }
+ FontInfo fiMapped = dfm.getMappedFont(graphics, fiRun);
+ FontInfo fiFallback = dfm.getFallbackFont(graphics, fiRun);
+ assert(fiFallback != null);
+ if (fiMapped == null) {
+ fiMapped = dfm.getMappedFont(graphics, new
DrawFontInfo(paragraph.getDefaultFontFamily()));
}
+ if (fiMapped == null) {
+ fiMapped = fiFallback;
+ }
+
+ Font fontMapped = dfm.createAWTFont(graphics, fiMapped, 10,
run.isBold(), run.isItalic());
+ Font fontFallback = dfm.createAWTFont(graphics, fiFallback, 10,
run.isBold(), run.isItalic());
- if (changed) {
- attStr = new String(chrs);
+ // check for unsupported characters and add a fallback font for
these
+ final int rangeLen = ttr.getLength();
+ int partEnd = rangeBegin;
+ while (partEnd<rangeBegin+rangeLen) {
+ // start with the assumption that the font is able to display
the chars
+ int partBegin = partEnd;
+ partEnd = nextPart(fontMapped, runText, partBegin,
rangeBegin+rangeLen, true);
+
+ // Now we have 3 cases:
+ // (a) the first part couldn't be displayed,
+ // (b) only part of the text run could be displayed
+ // (c) or all chars can be displayed (default)
+
+ if (partBegin < partEnd) {
+ // handle (b) and (c)
+ attList.add(new AttributedStringData(TextAttribute.FAMILY,
fontMapped.getFontName(Locale.ROOT), beginIndex+partBegin, beginIndex+partEnd));
+ if (LOG.check(POILogger.DEBUG)) {
+ LOG.log(POILogger.DEBUG, "mapped:
",fontMapped.getFontName(Locale.ROOT)," ",(beginIndex+partBegin),"
",(beginIndex+partEnd)," - ",runText.substring(beginIndex+partBegin,
beginIndex+partEnd));
+ }
+ }
+
+ // fallback for unsupported glyphs
+ partBegin = partEnd;
+ partEnd = nextPart(fontMapped, runText, partBegin,
rangeBegin+rangeLen, false);
+
+ if (partBegin < partEnd) {
+ // handle (a) and (b)
+ attList.add(new AttributedStringData(TextAttribute.FAMILY,
fontFallback.getFontName(Locale.ROOT), beginIndex+partBegin,
beginIndex+partEnd));
+ if (LOG.check(POILogger.DEBUG)) {
+ LOG.log(POILogger.DEBUG, "fallback:
",fontFallback.getFontName(Locale.ROOT)," ",(beginIndex+partBegin),"
",(beginIndex+partEnd)," - ",runText.substring(beginIndex+partBegin,
beginIndex+partEnd));
+ }
+ }
}
+
+ rangeBegin += rangeLen;
}
- return attStr;
}
- /**
- * Indicates whether or not this {@code Font} can display the characters
in the specified {@code text}
- * starting at {@code start} and ending at {@code limit}.<p>
- *
- * This is a workaround for the Java 6 implementation of {@link
Font#canDisplayUpTo(char[], int, int)}
- *
- * @param font the font to inspect
- * @param text the specified array of {@code char} values
- * @param start the specified starting offset (in
- * {@code char}s) into the specified array of
- * {@code char} values
- * @param limit the specified ending offset (in
- * {@code char}s) into the specified array of
- * {@code char} values
- * @return an offset into {@code text} that points
- * to the first character in {@code text} that this
- * {@code Font} cannot display; or {@code -1} if
- * this {@code Font} can display all characters in
- * {@code text}.
- *
- * @see <a
href="https://bugs.openjdk.java.net/browse/JDK-6623219">Font.canDisplayUpTo
does not work with supplementary characters</a>
- */
- protected static int canDisplayUpTo(Font font, char[] text, int start, int
limit) {
- for (int i = start; i < limit; i++) {
- char c = text[i];
- if (font.canDisplay(c)) {
- continue;
- }
- if (!Character.isHighSurrogate(c)) {
- return i;
- }
- if (!font.canDisplay(Character.codePointAt(text, i, limit))) {
- return i;
+ private static int nextPart(Font fontMapped, String runText, int
beginPart, int endPart, boolean isDisplayed) {
+ int rIdx = beginPart;
+ while (rIdx < endPart) {
+ int codepoint = runText.codePointAt(rIdx);
+ if (fontMapped.canDisplay(codepoint) != isDisplayed) {
+ break;
}
- i++;
+ rIdx += Character.charCount(codepoint);
}
- return -1;
+ return rIdx;
+ }
+
+ /**
+ * @return {@code true} if the HSLF implementation is used
+ */
+ protected boolean isHSLF() {
+ return DrawShape.isHSLF(paragraph.getParentShape());
}
}
Modified: poi/trunk/src/java/org/apache/poi/sl/usermodel/TextRun.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/usermodel/TextRun.java?rev=1802741&r1=1802740&r2=1802741&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/usermodel/TextRun.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/usermodel/TextRun.java Sun Jul 23
22:45:47 2017
@@ -19,6 +19,8 @@ package org.apache.poi.sl.usermodel;
import java.awt.Color;
+import org.apache.poi.common.usermodel.fonts.FontGroup;
+import org.apache.poi.common.usermodel.fonts.FontInfo;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
import org.apache.poi.util.Internal;
@@ -26,12 +28,18 @@ import org.apache.poi.util.Internal;
* Some text.
*/
public interface TextRun {
+ /**
+ * Type of text capitals
+ */
enum TextCap {
NONE,
SMALL,
ALL
}
+ /**
+ * Type of placeholder fields
+ */
enum FieldType {
SLIDE_NUMBER, DATE_TIME
}
@@ -87,19 +95,65 @@ public interface TextRun {
void setFontSize(Double fontSize);
/**
+ * Get the font family - convenience method for {@link
#getFontInfo(FontGroup)}
+ *
* @return font family or null if not set
*/
String getFontFamily();
/**
- * Specifies the typeface, or name of the font that is to be used for this
text run.
+ * Get the font family - convenience method for {@link
#getFontInfo(FontGroup)}
+ *
+ * @param fontGroup the font group, i.e. the range of glpyhs to be covered.
+ * if {@code null}, the font group matching the first character will be
returned
+ *
+ * @return font family or null if not set
+ */
+ String getFontFamily(FontGroup fontGroup);
+
+ /**
+ * Specifies the typeface, or name of the font that is to be used for this
text run -
+ * convenience method for calling {@link #setFontInfo(FontInfo,
FontGroup)} with just a font name
*
* @param typeface the font to apply to this text run.
- * The value of <code>null</code> unsets the Typeface attrubute from the
underlying xml.
+ * The value of {@code null} removes the run specific font setting,
so the default setting is activated again.
*/
void setFontFamily(String typeface);
/**
+ * Specifies the typeface, or name of the font that is to be used for this
text run -
+ * convenience method for calling {@link #setFontInfo(FontInfo,
FontGroup)} with just a font name
+ *
+ * @param typeface the font to apply to this text run.
+ * The value of {@code null} removes the run specific font setting,
so the default setting is activated again.
+ * @param fontGroup the font group, i.e. the range of glpyhs to be covered.
+ * if {@code null}, the font group matching the first character will be
returned
+ */
+ void setFontFamily(String typeface, FontGroup fontGroup);
+
+ /**
+ * Get the font info for the given font group
+ *
+ * @param fontGroup the font group, i.e. the range of glpyhs to be covered.
+ * if {@code null}, the font group matching the first character will be
returned
+ * @return font info or {@code null} if not set
+ *
+ * @since POI 3.17-beta2
+ */
+ FontInfo getFontInfo(FontGroup fontGroup);
+
+ /**
+ * Specifies the font to be used for this text run.
+ *
+ * @param fontInfo the font to apply to this text run.
+ * The value of {@code null} removes the run specific font setting,
so the default setting is activated again.
+ * @param fontGroup the font group, i.e. the range of glpyhs to be
covered. defaults to latin, if {@code null}.
+ *
+ * @since POI 3.17-beta2
+ */
+ void setFontInfo(FontInfo fontInfo, FontGroup fontGroup);
+
+ /**
* @return true, if text is bold
*/
boolean isBold();
Modified: poi/trunk/src/java/org/apache/poi/ss/usermodel/FontCharset.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/usermodel/FontCharset.java?rev=1802741&r1=1802740&r2=1802741&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/usermodel/FontCharset.java (original)
+++ poi/trunk/src/java/org/apache/poi/ss/usermodel/FontCharset.java Sun Jul 23
22:45:47 2017
@@ -17,13 +17,16 @@
package org.apache.poi.ss.usermodel;
+import org.apache.poi.util.Removal;
/**
* Charset represents the basic set of characters associated with a font (that
it can display), and
* corresponds to the ANSI codepage (8-bit or DBCS) of that character set used
by a given language.
*
- * @author Gisella Bronzetti
+ * @deprecated enum will be replaced by common version
org.apache.poi.common.usermodel.FontCharset
*/
+@Removal(version="4.0")
+@Deprecated
public enum FontCharset {
ANSI(0),
Modified:
poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java?rev=1802741&r1=1802740&r2=1802741&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java
(original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java Sun
Jul 23 22:45:47 2017
@@ -18,6 +18,11 @@ package org.apache.poi.xslf.usermodel;
import java.awt.Color;
+import org.apache.poi.common.usermodel.fonts.FontCharset;
+import org.apache.poi.common.usermodel.fonts.FontFamily;
+import org.apache.poi.common.usermodel.fonts.FontGroup;
+import org.apache.poi.common.usermodel.fonts.FontInfo;
+import org.apache.poi.common.usermodel.fonts.FontPitch;
import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.sl.draw.DrawPaint;
@@ -28,6 +33,8 @@ import org.apache.poi.util.Beta;
import org.apache.poi.xslf.model.CharacterPropertyFetcher;
import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFFillProperties;
import org.apache.xmlbeans.XmlObject;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTFontCollection;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTFontScheme;
import org.openxmlformats.schemas.drawingml.x2006.main.CTHyperlink;
import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
@@ -85,8 +92,8 @@ public class XSLFTextRun implements Text
} else if (_r instanceof CTTextLineBreak) {
return "\n";
}
-
-
+
+
String txt = ((CTRegularTextRun)_r).getT();
TextCap cap = getTextCap();
StringBuffer buf = new StringBuffer();
@@ -139,7 +146,7 @@ public class XSLFTextRun implements Text
public void setFontColor(Color color) {
setFontColor(DrawPaint.createSolidPaint(color));
}
-
+
@Override
public void setFontColor(PaintStyle color) {
if (!(color instanceof SolidPaint)) {
@@ -147,10 +154,10 @@ public class XSLFTextRun implements Text
}
SolidPaint sp = (SolidPaint)color;
Color c = DrawPaint.applyColorTransform(sp.getSolidColor());
-
+
CTTextCharacterProperties rPr = getRPr(true);
CTSolidColorFillProperties fill = rPr.isSetSolidFill() ?
rPr.getSolidFill() : rPr.addNewSolidFill();
-
+
XSLFColor col = new XSLFColor(fill,
getParentParagraph().getParentShape().getSheet().getTheme(),
fill.getSchemeClr());
col.setColor(c);
}
@@ -164,7 +171,7 @@ public class XSLFTextRun implements Text
if (props == null) {
return false;
}
-
+
XSLFShape shape = _p.getParentShape();
CTShapeStyle style = shape.getSpStyle();
CTSchemeColor phClr = null;
@@ -177,12 +184,12 @@ public class XSLFTextRun implements Text
PackagePart pp = sheet.getPackagePart();
XSLFTheme theme = sheet.getTheme();
PaintStyle ps = XSLFShape.selectPaint(fp, phClr, pp, theme,
hasPlaceholder);
-
+
if (ps != null) {
setValue(ps);
return true;
}
-
+
return false;
}
};
@@ -270,88 +277,51 @@ public class XSLFTextRun implements Text
}
@Override
- public void setFontFamily(String typeface){
- setFontFamily(typeface, (byte)-1, (byte)-1, false);
+ public void setFontFamily(String typeface) {
+ FontGroup fg = FontGroup.getFontGroupFirst(getRawText());
+ new XSLFFontInfo(fg).setTypeface(typeface);
}
- public void setFontFamily(String typeface, byte charset, byte
pictAndFamily, boolean isSymbol){
- CTTextCharacterProperties rPr = getRPr(true);
+ @Override
+ public void setFontFamily(String typeface, FontGroup fontGroup) {
+ new XSLFFontInfo(fontGroup).setTypeface(typeface);
+ }
- if(typeface == null){
- if(rPr.isSetLatin()) {
- rPr.unsetLatin();
- }
- if(rPr.isSetCs()) {
- rPr.unsetCs();
- }
- if(rPr.isSetSym()) {
- rPr.unsetSym();
- }
- } else {
- if(isSymbol){
- CTTextFont font = rPr.isSetSym() ? rPr.getSym() :
rPr.addNewSym();
- font.setTypeface(typeface);
- } else {
- CTTextFont latin = rPr.isSetLatin() ? rPr.getLatin() :
rPr.addNewLatin();
- latin.setTypeface(typeface);
- if(charset != -1) {
- latin.setCharset(charset);
- }
- if(pictAndFamily != -1) {
- latin.setPitchFamily(pictAndFamily);
- }
- }
- }
+ @Override
+ public void setFontInfo(FontInfo fontInfo, FontGroup fontGroup) {
+ new XSLFFontInfo(fontGroup).copyFrom(fontInfo);
}
@Override
- public String getFontFamily(){
- final XSLFTheme theme = _p.getParentShape().getSheet().getTheme();
+ public String getFontFamily() {
+ FontGroup fg = FontGroup.getFontGroupFirst(getRawText());
+ return new XSLFFontInfo(fg).getTypeface();
+ }
- CharacterPropertyFetcher<String> visitor = new
CharacterPropertyFetcher<String>(_p.getIndentLevel()){
- @Override
- public boolean fetch(CTTextCharacterProperties props){
- if (props != null) {
- CTTextFont font = props.getLatin();
- if (font != null) {
- String typeface = font.getTypeface();
- if("+mj-lt".equals(typeface)) {
- typeface = theme.getMajorFont();
- } else if ("+mn-lt".equals(typeface)){
- typeface = theme.getMinorFont();
- }
- setValue(typeface);
- return true;
- }
- }
- return false;
- }
- };
- fetchCharacterProperty(visitor);
+ @Override
+ public String getFontFamily(FontGroup fontGroup) {
+ return new XSLFFontInfo(fontGroup).getTypeface();
+ }
- return visitor.getValue();
+ @Override
+ public FontInfo getFontInfo(FontGroup fontGroup) {
+ XSLFFontInfo fontInfo = new XSLFFontInfo(fontGroup);
+ return (fontInfo.getTypeface() != null) ? fontInfo : null;
}
@Override
public byte getPitchAndFamily(){
- // final XSLFTheme theme = _p.getParentShape().getSheet().getTheme();
-
- CharacterPropertyFetcher<Byte> visitor = new
CharacterPropertyFetcher<Byte>(_p.getIndentLevel()){
- @Override
- public boolean fetch(CTTextCharacterProperties props){
- if (props != null) {
- CTTextFont font = props.getLatin();
- if (font != null) {
- setValue(font.getPitchFamily());
- return true;
- }
- }
- return false;
- }
- };
- fetchCharacterProperty(visitor);
-
- return visitor.getValue() == null ? 0 : visitor.getValue();
+ FontGroup fg = FontGroup.getFontGroupFirst(getRawText());
+ XSLFFontInfo fontInfo = new XSLFFontInfo(fg);
+ FontPitch pitch = fontInfo.getPitch();
+ if (pitch == null) {
+ pitch = FontPitch.VARIABLE;
+ }
+ FontFamily family = fontInfo.getFamily();
+ if (family == null) {
+ family = FontFamily.FF_SWISS;
+ }
+ return FontPitch.getNativeId(pitch, family);
}
@Override
@@ -574,7 +544,7 @@ public class XSLFTextRun implements Text
@Override
public XSLFHyperlink getHyperlink(){
CTTextCharacterProperties rPr = getRPr(false);
- if (rPr == null) {
+ if (rPr == null) {
return null;
}
CTHyperlink hl = rPr.getHlinkClick();
@@ -592,11 +562,11 @@ public class XSLFTextRun implements Text
if (rPr != null && fetcher.fetch(rPr)) {
return true;
}
-
+
if (shape.fetchShapeProperty(fetcher)) {
return true;
}
-
+
CTPlaceholder ph = shape.getCTPlaceholder();
if (ph == null){
// if it is a plain text box then take defaults from
presentation.xml
@@ -654,8 +624,8 @@ public class XSLFTextRun implements Text
setStrikethrough(strike);
}
}
-
-
+
+
@Override
public FieldType getFieldType() {
if (_r instanceof CTTextField) {
@@ -666,4 +636,224 @@ public class XSLFTextRun implements Text
}
return null;
}
+
+
+ private class XSLFFontInfo implements FontInfo {
+ private final FontGroup fontGroup;
+
+ private XSLFFontInfo(FontGroup fontGroup) {
+ this.fontGroup = (fontGroup != null) ? fontGroup :
FontGroup.getFontGroupFirst(getRawText());
+ }
+
+ public void copyFrom(FontInfo fontInfo) {
+ CTTextFont tf = getXmlObject(true);
+ setTypeface(fontInfo.getTypeface());
+ setCharset(fontInfo.getCharset());
+ FontPitch pitch = fontInfo.getPitch();
+ FontFamily family = fontInfo.getFamily();
+ if (pitch == null && family == null) {
+ if (tf.isSetPitchFamily()) {
+ tf.unsetPitchFamily();
+ }
+ } else {
+ setPitch(pitch);
+ setFamily(family);
+ }
+ }
+
+ @Override
+ public Integer getIndex() {
+ return null;
+ }
+
+ @Override
+ public void setIndex(int index) {
+ throw new UnsupportedOperationException("setIndex not supported by
XSLFFontInfo.");
+ }
+
+ @Override
+ public String getTypeface() {
+ CTTextFont tf = getXmlObject(false);
+ return (tf != null && tf.isSetTypeface()) ? tf.getTypeface() :
null;
+ }
+
+ @Override
+ public void setTypeface(String typeface) {
+ if (typeface != null) {
+ getXmlObject(true).setTypeface(typeface);
+ return;
+ }
+
+ CTTextCharacterProperties props = getRPr(false);
+ if (props == null) {
+ return;
+ }
+ FontGroup fg = FontGroup.getFontGroupFirst(getRawText());
+ switch (fg) {
+ default:
+ case LATIN:
+ if (props.isSetLatin()) {
+ props.unsetLatin();
+ }
+ break;
+ case EAST_ASIAN:
+ if (props.isSetEa()) {
+ props.unsetEa();
+ }
+ break;
+ case COMPLEX_SCRIPT:
+ if (props.isSetCs()) {
+ props.unsetCs();
+ }
+ break;
+ case SYMBOL:
+ if (props.isSetSym()) {
+ props.unsetSym();
+ }
+ break;
+ }
+ }
+
+ @Override
+ public FontCharset getCharset() {
+ CTTextFont tf = getXmlObject(false);
+ return (tf != null && tf.isSetCharset()) ?
FontCharset.valueOf(tf.getCharset()&0xFF) : null;
+ }
+
+ @Override
+ public void setCharset(FontCharset charset) {
+ CTTextFont tf = getXmlObject(true);
+ if (charset != null) {
+ tf.setCharset((byte)charset.getNativeId());
+ } else {
+ if (tf.isSetCharset()) {
+ tf.unsetCharset();
+ }
+ }
+ }
+
+ @Override
+ public FontFamily getFamily() {
+ CTTextFont tf = getXmlObject(false);
+ return (tf != null && tf.isSetPitchFamily()) ?
FontFamily.valueOfPitchFamily(tf.getPitchFamily()) : null;
+ }
+
+ @Override
+ public void setFamily(FontFamily family) {
+ CTTextFont tf = getXmlObject(true);
+ if (family == null && !tf.isSetPitchFamily()) {
+ return;
+ }
+ FontPitch pitch = (tf.isSetPitchFamily())
+ ? FontPitch.valueOfPitchFamily(tf.getPitchFamily())
+ : FontPitch.VARIABLE;
+ byte pitchFamily = FontPitch.getNativeId(pitch, family != null ?
family : FontFamily.FF_SWISS);
+ tf.setPitchFamily(pitchFamily);
+ }
+
+ @Override
+ public FontPitch getPitch() {
+ CTTextFont tf = getXmlObject(false);
+ return (tf != null && tf.isSetPitchFamily()) ?
FontPitch.valueOfPitchFamily(tf.getPitchFamily()) : null;
+ }
+
+ @Override
+ public void setPitch(FontPitch pitch) {
+ CTTextFont tf = getXmlObject(true);
+ if (pitch == null && !tf.isSetPitchFamily()) {
+ return;
+ }
+ FontFamily family = (tf.isSetPitchFamily())
+ ? FontFamily.valueOfPitchFamily(tf.getPitchFamily())
+ : FontFamily.FF_SWISS;
+ byte pitchFamily = FontPitch.getNativeId(pitch != null ? pitch :
FontPitch.VARIABLE, family);
+ tf.setPitchFamily(pitchFamily);
+ }
+
+ private CTTextFont getXmlObject(boolean create) {
+ if (create) {
+ return getCTTextFont(getRPr(true), true);
+ }
+
+ CharacterPropertyFetcher<CTTextFont> visitor = new
CharacterPropertyFetcher<CTTextFont>(_p.getIndentLevel()){
+ @Override
+ public boolean fetch(CTTextCharacterProperties props){
+ CTTextFont font = getCTTextFont(props, false);
+ if (font == null) {
+ return false;
+ }
+ setValue(font);
+ return true;
+ }
+ };
+ fetchCharacterProperty(visitor);
+
+ return visitor.getValue();
+ }
+
+ private CTTextFont getCTTextFont(CTTextCharacterProperties props,
boolean create) {
+ if (props == null) {
+ return null;
+ }
+
+ CTTextFont font;
+ switch (fontGroup) {
+ default:
+ case LATIN:
+ font = props.getLatin();
+ if (font == null && create) {
+ font = props.addNewLatin();
+ }
+ break;
+ case EAST_ASIAN:
+ font = props.getEa();
+ if (font == null && create) {
+ font = props.addNewEa();
+ }
+ break;
+ case COMPLEX_SCRIPT:
+ font = props.getCs();
+ if (font == null && create) {
+ font = props.addNewCs();
+ }
+ break;
+ case SYMBOL:
+ font = props.getSym();
+ if (font == null && create) {
+ font = props.addNewSym();
+ }
+ break;
+ }
+
+ if (font == null) {
+ return null;
+ }
+
+ String typeface = font.isSetTypeface() ? font.getTypeface() : "";
+ if (typeface.startsWith("+mj-") || typeface.startsWith("+mn-")) {
+ // "+mj-lt".equals(typeface) || "+mn-lt".equals(typeface)
+ final XSLFTheme theme =
_p.getParentShape().getSheet().getTheme();
+ CTFontScheme fontTheme =
theme.getXmlObject().getThemeElements().getFontScheme();
+ CTFontCollection coll = typeface.startsWith("+mj-")
+ ? fontTheme.getMajorFont() : fontTheme.getMinorFont();
+ // TODO: handle LCID codes
+ // see
https://blogs.msdn.microsoft.com/officeinteroperability/2013/04/22/office-open-xml-themes-schemes-and-fonts/
+ String fgStr = typeface.substring(4);
+ if ("ea".equals(fgStr)) {
+ font = coll.getEa();
+ } else if ("cs".equals(fgStr)) {
+ font = coll.getCs();
+ } else {
+ font = coll.getLatin();
+ }
+ // SYMBOL is missing
+
+ if (font != null || !font.isSetTypeface() ||
"".equals(font.getTypeface())) {
+ font = coll.getLatin();
+ }
+ }
+
+ return font;
+ }
+ }
}
Modified: poi/trunk/src/ooxml/testcases/org/apache/poi/sl/TestFonts.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/sl/TestFonts.java?rev=1802741&r1=1802740&r2=1802741&view=diff
==============================================================================
--- poi/trunk/src/ooxml/testcases/org/apache/poi/sl/TestFonts.java (original)
+++ poi/trunk/src/ooxml/testcases/org/apache/poi/sl/TestFonts.java Sun Jul 23
22:45:47 2017
@@ -37,6 +37,7 @@ import java.util.HashMap;
import java.util.Map;
import org.apache.poi.POIDataSamples;
+import org.apache.poi.common.usermodel.fonts.FontGroup;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
import org.apache.poi.sl.draw.DrawFactory;
import org.apache.poi.sl.draw.Drawable;
@@ -47,10 +48,8 @@ import org.apache.poi.sl.usermodel.TextB
import org.apache.poi.sl.usermodel.TextParagraph;
import org.apache.poi.sl.usermodel.TextRun;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
-import org.apache.poi.xslf.usermodel.XSLFTextRun;
import org.junit.BeforeClass;
import org.junit.Test;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
/**
@@ -71,14 +70,14 @@ public class TestFonts {
"\u9451\u3092\u4E00\u7DD2\u306B\u898B\u3066\u305F\u306E\u601D\u3044\u51FA\u3059\u301C\u3068\u3044";
private static final String INIT_FONTS[] = { "mona.ttf" };
-
+
// currently linux and mac return quite different values
private static final int[] expected_sizes = { 311, 312, 313,
362, // Windows 10, 13.3" 1080p high-dpi
398, 399,
406 // Ubuntu Trusty, 15", 1680x1050
};
-
+
@BeforeClass
public static void initGE() throws FontFormatException, IOException {
GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();
@@ -87,83 +86,65 @@ public class TestFonts {
ge.registerFont(font);
}
}
-
+
@Test
public void resizeToFitTextHSLF() throws IOException {
assumeFalse(xslfOnly());
SlideShow<?,?> ppt = new HSLFSlideShow();
- TextBox<?,?> tb = resizeToFitText(ppt);
- Rectangle2D anc = tb.getAnchor();
- // ignore font metrics differences on windows / linux (... hopefully
...)
- boolean found = Arrays.binarySearch(expected_sizes,
(int)anc.getHeight()) > -1;
- assertTrue("Did not find height " + anc.getHeight() + " in expected
sizes: " + Arrays.toString(expected_sizes),
- found);
-// setFont(tb, "Mona");
-// FileOutputStream fos = new FileOutputStream("bla-hslf.ppt");
-// ppt.write(fos);
-// fos.close();
+ resizeToFitText(ppt);
ppt.close();
}
@Test
public void resizeToFitTextXSLF() throws IOException {
SlideShow<?,?> ppt = new XMLSlideShow();
- TextBox<?,?> tb = resizeToFitText(ppt);
- Rectangle2D anc = tb.getAnchor();
- // ignore font metrics differences on windows / linux (... hopefully
...)
- boolean found = Arrays.binarySearch(expected_sizes,
(int)anc.getHeight()) > -1;
- assertTrue("Did not find height " + anc.getHeight() + " in expected
sizes: " + Arrays.toString(expected_sizes),
- found);
-// setFont(tb, "Mona");
-// FileOutputStream fos = new FileOutputStream("bla-xslf.ppt");
-// ppt.write(fos);
-// fos.close();
+ resizeToFitText(ppt);
ppt.close();
}
- private TextBox<?,?> resizeToFitText(SlideShow<?,?> slideshow) throws
IOException {
+ private void resizeToFitText(SlideShow<?,?> slideshow) throws IOException {
Slide<?,?> sld = slideshow.createSlide();
TextBox<?,?> tb = sld.createTextBox();
tb.setAnchor(new Rectangle(50, 50, 200, 50));
tb.setStrokeStyle(Color.black, LineDash.SOLID, 3);
tb.setText(JPTEXT);
-
- setFont(tb, "NoSuchFont");
+
+ setFont(tb, "NoSuchFont", FontGroup.LATIN);
Dimension pgsize = slideshow.getPageSize();
int width = (int)pgsize.getWidth();
int height = (int)pgsize.getHeight();
-
+
BufferedImage img = new BufferedImage(width, height,
BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = img.createGraphics();
Map<String,String> fallbackMap = new HashMap<String,String>();
fallbackMap.put("NoSuchFont", "Mona");
+ // in XSLF the fonts default to the theme fonts (Calibri), if the font
group is not overridden
+ // see XSLFTextRun.XSLFTextInfo.getCTTextFont
+ fallbackMap.put("Calibri", "Mona");
graphics.setRenderingHint(Drawable.FONT_FALLBACK, fallbackMap);
graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
-
+
DrawFactory.getInstance(graphics).fixFonts(graphics);
-
+
tb.resizeToFitText(graphics);
graphics.dispose();
-
- return tb;
+
+ Rectangle2D anc = tb.getAnchor();
+ // ignore font metrics differences on windows / linux (... hopefully
...)
+ int tbHeight = (int)anc.getHeight();
+ boolean found = Arrays.binarySearch(expected_sizes, tbHeight) > -1;
+ assertTrue(tbHeight+" wasn't within the expected sizes:
"+Arrays.toString(expected_sizes), found);
}
-
- private void setFont(TextBox<?,?> tb, String fontFamily) {
+
+ private void setFont(TextBox<?,?> tb, String fontFamily, FontGroup
fontGroup) {
// TODO: set east asian font family - MS Office uses "MS Mincho" or
"MS Gothic" as a fallback
// see https://stackoverflow.com/questions/26063828 for good
explanation about the font metrics
// differences on different environments
for (TextParagraph<?,?,?> p : tb.getTextParagraphs()) {
for (TextRun r : p.getTextRuns()) {
- r.setFontFamily(fontFamily);
- if (r instanceof XSLFTextRun) {
- // TODO: provide API for HSLF
- XSLFTextRun xr = (XSLFTextRun)r;
- CTRegularTextRun tr = (CTRegularTextRun)xr.getXmlObject();
- tr.getRPr().addNewEa().setTypeface(fontFamily);
-
- }
+ r.setFontFamily(fontFamily, fontGroup);
}
}
}
Modified:
poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/textproperties/CharFlagsTextProp.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/textproperties/CharFlagsTextProp.java?rev=1802741&r1=1802740&r2=1802741&view=diff
==============================================================================
---
poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/textproperties/CharFlagsTextProp.java
(original)
+++
poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/textproperties/CharFlagsTextProp.java
Sun Jul 23 22:45:47 2017
@@ -43,7 +43,7 @@ public class CharFlagsTextProp extends B
"fehint", // 0x0020 A bit that specifies
whether characters originated from double-byte input.
"unused2", // 0x0040 Undefined and MUST
be ignored.
"kumi", // 0x0080 A bit that specifies
whether Kumimoji are used for vertical text.
- "strikethrough", // 0x0100 Undefined and MUST
be ignored.
+ "strikethrough", // 0x0100 aka "unused3" -
sometimes contains the strikethrough flag
"emboss", // 0x0200 A bit that specifies
whether the characters are embossed.
"pp9rt_1", // 0x0400 An unsigned integer that
specifies the run grouping of additional text properties in StyleTextProp9Atom
record.
"pp9rt_2", // 0x0800
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]