Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/FontCollection.java URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/FontCollection.java?rev=1849898&r1=1849897&r2=1849898&view=diff ============================================================================== --- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/FontCollection.java (original) +++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/FontCollection.java Fri Dec 28 23:43:31 2018 @@ -18,13 +18,19 @@ package org.apache.poi.hslf.record; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; +import java.util.ArrayList; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; +import org.apache.poi.common.usermodel.fonts.FontHeader; import org.apache.poi.common.usermodel.fonts.FontInfo; +import org.apache.poi.common.usermodel.fonts.FontPitch; import org.apache.poi.hslf.usermodel.HSLFFontInfo; import org.apache.poi.hslf.usermodel.HSLFFontInfoPredefined; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.POILogger; /** @@ -32,11 +38,12 @@ import org.apache.poi.util.POILogger; * about all the fonts in the presentation. */ +@SuppressWarnings("WeakerAccess") public final class FontCollection extends RecordContainer { private final Map<String,HSLFFontInfo> fonts = new LinkedHashMap<>(); private byte[] _header; - protected FontCollection(byte[] source, int start, int len) { + /* package */ FontCollection(byte[] source, int start, int len) { _header = new byte[8]; System.arraycopy(source,start,_header,0,8); @@ -44,8 +51,13 @@ public final class FontCollection extend for (Record r : _children){ if(r instanceof FontEntityAtom) { - HSLFFontInfo fi = new HSLFFontInfo((FontEntityAtom)r); - fonts.put(fi.getTypeface(), fi); + HSLFFontInfo fi = new HSLFFontInfo((FontEntityAtom) r); + fonts.put(fi.getTypeface(), fi); + } else if (r instanceof FontEmbeddedData) { + FontEmbeddedData fed = (FontEmbeddedData)r; + FontHeader fontHeader = fed.getFontHeader(); + HSLFFontInfo fi = addFont(fontHeader); + fi.addFacet(fed); } else { logger.log(POILogger.WARN, "Warning: FontCollection child wasn't a FontEntityAtom, was " + r.getClass().getSimpleName()); } @@ -88,7 +100,7 @@ public final class FontCollection extend fi = new HSLFFontInfo(fontInfo); fi.setIndex(fonts.size()); fonts.put(fi.getTypeface(), fi); - + FontEntityAtom fnt = fi.createRecord(); // Append new child to the end @@ -98,6 +110,58 @@ public final class FontCollection extend return fi; } + public HSLFFontInfo addFont(InputStream fontData) throws IOException { + FontHeader fontHeader = new FontHeader(); + InputStream is = fontHeader.bufferInit(fontData); + + HSLFFontInfo fi = addFont(fontHeader); + + // always overwrite the font info properties when a font data given + // as the font info properties are assigned generically when only a typeface is given + FontEntityAtom fea = fi.getFontEntityAtom(); + assert (fea != null); + fea.setCharSet(fontHeader.getCharsetByte()); + fea.setPitchAndFamily(FontPitch.getNativeId(fontHeader.getPitch(),fontHeader.getFamily())); + + // always activate subsetting + fea.setFontFlags(1); + // true type font and no font substitution + fea.setFontType(12); + + Record after = fea; + + final int insertIdx = getFacetIndex(fontHeader.isItalic(), fontHeader.isBold()); + + FontEmbeddedData newChild = null; + for (FontEmbeddedData fed : fi.getFacets()) { + FontHeader fh = fed.getFontHeader(); + final int curIdx = getFacetIndex(fh.isItalic(), fh.isBold()); + + if (curIdx == insertIdx) { + newChild = fed; + break; + } else if (curIdx > insertIdx) { + // the new facet needs to be inserted before the current facet + break; + } + + after = fed; + } + + if (newChild == null) { + newChild = new FontEmbeddedData(); + addChildAfter(newChild, after); + fi.addFacet(newChild); + } + + newChild.setFontData(IOUtils.toByteArray(is)); + return fi; + } + + private static int getFacetIndex(boolean isItalic, boolean isBold) { + return (isItalic ? 2 : 0) | (isBold ? 1 : 0); + } + /** * Lookup a FontInfo object by its typeface @@ -132,4 +196,8 @@ public final class FontCollection extend public int getNumberOfFonts() { return fonts.size(); } + + public List<HSLFFontInfo> getFonts() { + return new ArrayList<>(fonts.values()); + } }
Added: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/FontEmbeddedData.java URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/FontEmbeddedData.java?rev=1849898&view=auto ============================================================================== --- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/FontEmbeddedData.java (added) +++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/FontEmbeddedData.java Fri Dec 28 23:43:31 2018 @@ -0,0 +1,116 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.record; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.poi.common.usermodel.fonts.FontFacet; +import org.apache.poi.common.usermodel.fonts.FontHeader; +import org.apache.poi.util.IOUtils; +import org.apache.poi.util.LittleEndian; + +@SuppressWarnings("WeakerAccess") +public class FontEmbeddedData extends RecordAtom implements FontFacet { + //arbitrarily selected; may need to increase + private static final int MAX_RECORD_LENGTH = 1_000_000; + + /** + * Record header. + */ + private byte[] _header; + + /** + * Record data - An EOT Font + */ + private byte[] _data; + + /** + * Constructs a brand new font embedded record. + */ + /* package */ FontEmbeddedData() { + _header = new byte[8]; + _data = new byte[4]; + + LittleEndian.putShort(_header, 2, (short)getRecordType()); + LittleEndian.putInt(_header, 4, _data.length); + } + + /** + * Constructs the font embedded record from its source data. + * + * @param source the source data as a byte array. + * @param start the start offset into the byte array. + * @param len the length of the slice in the byte array. + */ + /* package */ FontEmbeddedData(byte[] source, int start, int len) { + // Get the header. + _header = new byte[8]; + System.arraycopy(source,start,_header,0,8); + + // Get the record data. + _data = IOUtils.safelyAllocate(len-8, MAX_RECORD_LENGTH); + System.arraycopy(source,start+8,_data,0,len-8); + + // Must be at least 4 bytes long + if(_data.length < 4) { + throw new IllegalArgumentException("The length of the data for a ExObjListAtom must be at least 4 bytes, but was only " + _data.length); + } + } + + @Override + public long getRecordType() { + return RecordTypes.FontEmbeddedData.typeID; + } + + @Override + public void writeOut(OutputStream out) throws IOException { + out.write(_header); + out.write(_data); + } + + public void setFontData(byte[] fontData) { + _data = fontData.clone(); + LittleEndian.putInt(_header, 4, _data.length); + } + + public FontHeader getFontHeader() { + FontHeader h = new FontHeader(); + h.init(_data, 0, _data.length); + return h; + } + + @Override + public int getWeight() { + return getFontHeader().getWeight(); + } + + @Override + public boolean isItalic() { + return getFontHeader().isItalic(); + } + + public String getTypeface() { + return getFontHeader().getFamilyName(); + } + + @Override + public Object getFontData() { + return this; + } +} Propchange: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/FontEmbeddedData.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/FontEntityAtom.java URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/FontEntityAtom.java?rev=1849898&r1=1849897&r2=1849898&view=diff ============================================================================== --- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/FontEntityAtom.java (original) +++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/FontEntityAtom.java Fri Dec 28 23:43:31 2018 @@ -43,7 +43,7 @@ public final class FontEntityAtom extend /** * record header */ - private byte[] _header; + private final byte[] _header = new byte[8]; /** * record data @@ -53,9 +53,8 @@ public final class FontEntityAtom extend /** * Build an instance of <code>FontEntityAtom</code> from on-disk data */ - protected FontEntityAtom(byte[] source, int start, int len) { + /* package */ FontEntityAtom(byte[] source, int start, int len) { // Get the header - _header = new byte[8]; System.arraycopy(source,start,_header,0,8); // Grab the record data @@ -69,7 +68,6 @@ public final class FontEntityAtom extend public FontEntityAtom() { _recdata = new byte[68]; - _header = new byte[8]; LittleEndian.putShort(_header, 2, (short)getRecordType()); LittleEndian.putInt(_header, 4, _recdata.length); } @@ -108,7 +106,7 @@ public final class FontEntityAtom extend byte[] bytes = StringUtil.getToUnicodeLE(name); System.arraycopy(bytes, 0, _recdata, 0, bytes.length); // null the remaining bytes - Arrays.fill(_recdata, 64-bytes.length, 64, (byte)0); + Arrays.fill(_recdata, bytes.length, 64, (byte)0); } public void setFontIndex(int idx){ Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java?rev=1849898&r1=1849897&r2=1849898&view=diff ============================================================================== --- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java (original) +++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java Fri Dec 28 23:43:31 2018 @@ -62,7 +62,18 @@ public enum RecordTypes { NamedShow(1041,null), NamedShowSlides(1042,null), SheetProperties(1044,null), - RoundTripCustomTableStyles12Atom(1064,null), + OriginalMainMasterId(1052,null), + CompositeMasterId(1052,null), + RoundTripContentMasterInfo12(1054,null), + RoundTripShapeId12(1055,null), + RoundTripHFPlaceholder12(1056,RoundTripHFPlaceholder12::new), + RoundTripContentMasterId(1058,null), + RoundTripOArtTextStyles12(1059,null), + RoundTripShapeCheckSumForCustomLayouts12(1062,null), + RoundTripNotesMasterTextStyles12(1063,null), + RoundTripCustomTableStyles12(1064,null), + + List(2000,DocInfoListContainer::new), FontCollection(2005,FontCollection::new), BookmarkCollection(2019,null), @@ -92,7 +103,7 @@ public enum RecordTypes { DefaultRulerAtom(4011,null), StyleTextProp9Atom(4012, StyleTextProp9Atom::new), //0x0FAC RT_StyleTextProp9Atom FontEntityAtom(4023,FontEntityAtom::new), - FontEmbeddedData(4024,null), + FontEmbeddedData(4024,FontEmbeddedData::new), CString(4026,CString::new), MetaFile(4033,null), ExOleObjAtom(4035,ExOleObjAtom::new), @@ -159,17 +170,6 @@ public enum RecordTypes { // Records ~12050 seem to be related to Document Encryption DocumentEncryptionAtom(12052,DocumentEncryptionAtom::new), - OriginalMainMasterId(1052,null), - CompositeMasterId(1052,null), - RoundTripContentMasterInfo12(1054,null), - RoundTripShapeId12(1055,null), - RoundTripHFPlaceholder12(1056,RoundTripHFPlaceholder12::new), - RoundTripContentMasterId(1058,null), - RoundTripOArtTextStyles12(1059,null), - RoundTripShapeCheckSumForCustomLayouts12(1062,null), - RoundTripNotesMasterTextStyles12(1063,null), - RoundTripCustomTableStyles12(1064,null), - // records greater then 0xF000 belong to with Microsoft Office Drawing format also known as Escher EscherDggContainer(0xF000,null), EscherDgg(0xf006,null), Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFontInfo.java URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFontInfo.java?rev=1849898&r1=1849897&r2=1849898&view=diff ============================================================================== --- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFontInfo.java (original) +++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFontInfo.java Fri Dec 28 23:43:31 2018 @@ -17,13 +17,18 @@ package org.apache.poi.hslf.usermodel; +import java.util.ArrayList; +import java.util.List; + 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.hslf.record.FontEmbeddedData; import org.apache.poi.hslf.record.FontEntityAtom; import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; +import org.apache.poi.util.Internal; /** * Represents a Font used in a presentation.<p> @@ -32,6 +37,7 @@ import org.apache.poi.util.BitFieldFacto * * @since POI 3.17-beta2 */ +@SuppressWarnings("WeakerAccess") public class HSLFFontInfo implements FontInfo { public enum FontRenderType { @@ -53,6 +59,8 @@ public class HSLFFontInfo implements Fon private FontPitch pitch = FontPitch.VARIABLE; private boolean isSubsetted; private boolean isSubstitutable = true; + private final List<FontEmbeddedData> facets = new ArrayList<>(); + private FontEntityAtom fontEntityAtom; /** * Creates a new instance of HSLFFontInfo with more or sensible defaults.<p> @@ -70,6 +78,7 @@ public class HSLFFontInfo implements Fon * Creates a new instance of HSLFFontInfo and initialize it from the supplied font atom */ public HSLFFontInfo(FontEntityAtom fontAtom){ + fontEntityAtom = fontAtom; setIndex(fontAtom.getFontIndex()); setTypeface(fontAtom.getFontName()); setCharset(FontCharset.valueOf(fontAtom.getCharSet())); @@ -187,7 +196,11 @@ public class HSLFFontInfo implements Fon } public FontEntityAtom createRecord() { + assert(fontEntityAtom == null); + FontEntityAtom fnt = new FontEntityAtom(); + fontEntityAtom = fnt; + fnt.setFontIndex(getIndex() << 4); fnt.setFontName(getTypeface()); fnt.setCharSet(getCharset().getNativeId()); @@ -212,4 +225,18 @@ public class HSLFFontInfo implements Fon fnt.setPitchAndFamily(FontPitch.getNativeId(pitch, family)); return fnt; } + + public void addFacet(FontEmbeddedData facet) { + facets.add(facet); + } + + @Override + public List<FontEmbeddedData> getFacets() { + return facets; + } + + @Internal + public FontEntityAtom getFontEntityAtom() { + return fontEntityAtom; + } } Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFontInfoPredefined.java URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFontInfoPredefined.java?rev=1849898&r1=1849897&r2=1849898&view=diff ============================================================================== --- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFontInfoPredefined.java (original) +++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFontInfoPredefined.java Fri Dec 28 23:43:31 2018 @@ -44,16 +44,6 @@ public enum HSLFFontInfoPredefined imple this.pitch = pitch; this.family = family; } - - @Override - public Integer getIndex() { - return -1; - } - - @Override - public void setIndex(int index) { - throw new UnsupportedOperationException("Predefined enum can't be changed."); - } @Override public String getTypeface() { @@ -61,37 +51,17 @@ public enum HSLFFontInfoPredefined imple } @Override - public void setTypeface(String typeface) { - throw new UnsupportedOperationException("Predefined enum can't be changed."); - } - - @Override public FontCharset getCharset() { return charset; } @Override - public void setCharset(FontCharset charset) { - throw new UnsupportedOperationException("Predefined enum can't be changed."); - } - - @Override public FontFamily getFamily() { return family; } @Override - public void setFamily(FontFamily family) { - throw new UnsupportedOperationException("Predefined enum can't be changed."); - } - - @Override public FontPitch getPitch() { return pitch; } - - @Override - public void setPitch(FontPitch pitch) { - throw new UnsupportedOperationException("Predefined enum can't be changed."); - } } Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java?rev=1849898&r1=1849897&r2=1849898&view=diff ============================================================================== --- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java (original) +++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java Fri Dec 28 23:43:31 2018 @@ -50,7 +50,6 @@ import org.apache.poi.poifs.filesystem.O import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.sl.usermodel.MasterSheet; import org.apache.poi.sl.usermodel.PictureData.PictureType; -import org.apache.poi.sl.usermodel.Resources; import org.apache.poi.sl.usermodel.SlideShow; import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; @@ -892,6 +891,21 @@ public final class HSLFSlideShow impleme } /** + * Add a font in this presentation and also embed its font data + * + * @param fontData the EOT font data as stream + * + * @return the registered HSLFFontInfo - the font info object is unique based on the typeface + * + * @since POI 4.1.0 + */ + public HSLFFontInfo addFont(InputStream fontData) throws IOException { + Document doc = getDocumentRecord(); + doc.getDocumentAtom().setSaveWithFonts(true); + return doc.getEnvironment().getFontCollection().addFont(fontData); + } + + /** * Get a font by index * * @param idx @@ -912,6 +926,11 @@ public final class HSLFSlideShow impleme return getDocumentRecord().getEnvironment().getFontCollection().getNumberOfFonts(); } + @Override + public List<HSLFFontInfo> getFonts() { + return getDocumentRecord().getEnvironment().getFontCollection().getFonts(); + } + /** * Return Header / Footer settings for slides * @@ -1127,12 +1146,6 @@ public final class HSLFSlideShow impleme return null; } - @Override - public Resources getResources() { - // TODO implement or throw exception if not supported - return null; - } - /** * @return the handler class which holds the hslf records */ Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java?rev=1849898&r1=1849897&r2=1849898&view=diff ============================================================================== --- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java (original) +++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java Fri Dec 28 23:43:31 2018 @@ -44,8 +44,9 @@ import org.apache.poi.util.POILogger; * Represents a run of text, all with the same style * */ +@SuppressWarnings({"WeakerAccess", "Duplicates", "unused"}) public final class HSLFTextRun implements TextRun { - protected POILogger logger = POILogFactory.getLogger(this.getClass()); + private static final POILogger logger = POILogFactory.getLogger(HSLFTextRun.class); /** The TextRun we belong to */ private HSLFTextParagraph parentParagraph; @@ -132,17 +133,17 @@ public final class HSLFTextRun implement return getFlag(index); } - protected boolean getFlag(int index) { + boolean getFlag(int index) { BitMaskTextProp prop = (characterStyle == null) ? null : characterStyle.findByName(CharFlagsTextProp.NAME); if (prop == null || !prop.getSubPropMatches()[index]) { - prop = getMasterProp(CharFlagsTextProp.NAME); + prop = getMasterProp(); } - return prop == null ? false : prop.getSubValue(index); + return prop != null && prop.getSubValue(index); } - private <T extends TextProp> T getMasterProp(final String name) { + private <T extends TextProp> T getMasterProp() { final int txtype = parentParagraph.getRunType(); final HSLFSheet sheet = parentParagraph.getSheet(); if (sheet == null) { @@ -155,7 +156,8 @@ public final class HSLFTextRun implement logger.log(POILogger.WARN, "MasterSheet is not available"); return null; } - + + String name = CharFlagsTextProp.NAME; final TextPropCollection col = master.getPropCollection(txtype, parentParagraph.getIndentLevel(), name, true); return (col == null) ? null : col.findByName(name); } @@ -302,7 +304,7 @@ public final class HSLFTextRun implement @Override public void setFontFamily(String typeface) { - setFontInfo(new HSLFFontInfo(typeface), FontGroup.LATIN); + setFontFamily(typeface, FontGroup.LATIN); } @Override @@ -330,7 +332,7 @@ public final class HSLFTextRun implement switch (fg) { default: case LATIN: - propName = "font.index"; + propName = "ansi.font.index"; break; case COMPLEX_SCRIPT: // TODO: implement TextCFException10 structure @@ -350,6 +352,7 @@ public final class HSLFTextRun implement } + setCharTextPropVal("font.index", fontIdx); setCharTextPropVal(propName, fontIdx); } @@ -435,8 +438,8 @@ public final class HSLFTextRun implement setFontColor(rgb); } - protected void setFlag(int index, boolean value) { - BitMaskTextProp prop = (BitMaskTextProp)characterStyle.addWithName(CharFlagsTextProp.NAME); + private void setFlag(int index, boolean value) { + BitMaskTextProp prop = characterStyle.addWithName(CharFlagsTextProp.NAME); prop.setSubValue(value, index); } @@ -469,7 +472,7 @@ public final class HSLFTextRun implement * * @param link the hyperlink */ - protected void setHyperlink(HSLFHyperlink link) { + /* package */ void setHyperlink(HSLFHyperlink link) { this.link = link; } @@ -521,4 +524,9 @@ public final class HSLFTextRun implement private FontGroup safeFontGroup(FontGroup fontGroup) { return (fontGroup != null) ? fontGroup : FontGroup.getFontGroupFirst(getRawText()); } + + @Override + public HSLFTextParagraph getParagraph() { + return parentParagraph; + } } Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFont.java URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFont.java?rev=1849898&r1=1849897&r2=1849898&view=diff ============================================================================== --- poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFont.java (original) +++ poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFont.java Fri Dec 28 23:43:31 2018 @@ -22,6 +22,7 @@ import java.nio.charset.StandardCharsets import org.apache.poi.common.usermodel.fonts.FontCharset; import org.apache.poi.common.usermodel.fonts.FontFamily; +import org.apache.poi.common.usermodel.fonts.FontHeader; import org.apache.poi.common.usermodel.fonts.FontInfo; import org.apache.poi.common.usermodel.fonts.FontPitch; import org.apache.poi.util.BitField; @@ -32,6 +33,7 @@ import org.apache.poi.util.LittleEndianI /** * The Font object specifies the attributes of a logical font */ +@SuppressWarnings({"unused", "Duplicates"}) public class HwmfFont implements FontInfo { /** @@ -289,7 +291,7 @@ public class HwmfFont implements FontInf /** * An 8-bit unsigned integer that defines the character set. - * It SHOULD be set to a value in the {@link WmfCharset} Enumeration. + * It SHOULD be set to a value in the {@link FontCharset} Enumeration. * * The DEFAULT_CHARSET value MAY be used to allow the name and size of a font to fully * describe the logical font. If the specified font name does not exist, a font in another character @@ -373,7 +375,7 @@ public class HwmfFont implements FontInf height = -12; width = 0; escapement = 0; - weight = 400; + weight = FontHeader.REGULAR_WEIGHT; italic = false; underline = false; strikeOut = false; @@ -438,51 +440,21 @@ public class HwmfFont implements FontInf } @Override - public void setFamily(FontFamily family) { - throw new UnsupportedOperationException("setCharset not supported by HwmfFont."); - } - - @Override public FontPitch getPitch() { return FontPitch.valueOf((pitchAndFamily >>> 6) & 3); } @Override - public void setPitch(FontPitch pitch) { - throw new UnsupportedOperationException("setPitch not supported by HwmfFont."); - } - - @Override - public Integer getIndex() { - return null; - } - - @Override - public void setIndex(int index) { - throw new UnsupportedOperationException("setIndex not supported by HwmfFont."); - } - - @Override public String getTypeface() { return facename; } @Override - public void setTypeface(String typeface) { - throw new UnsupportedOperationException("setTypeface not supported by HwmfFont."); - } - - @Override public FontCharset getCharset() { return charSet; } @Override - public void setCharset(FontCharset charset) { - throw new UnsupportedOperationException("setCharset not supported by HwmfFont."); - } - - @Override public String toString() { return "{ height: "+height+ ", width: "+width+ Modified: poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/extractor/TestExtractor.java URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/extractor/TestExtractor.java?rev=1849898&r1=1849897&r2=1849898&view=diff ============================================================================== --- poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/extractor/TestExtractor.java (original) +++ poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/extractor/TestExtractor.java Fri Dec 28 23:43:31 2018 @@ -29,7 +29,9 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.util.BitSet; import java.util.List; +import java.util.stream.Collectors; import org.apache.poi.POIDataSamples; import org.apache.poi.hslf.usermodel.HSLFObjectShape; @@ -52,12 +54,22 @@ public final class TestExtractor { /** * Extractor primed on the 2 page basic test data */ - private static final String expectText = "This is a test title\nThis is a test subtitle\nThis is on page 1\nThis is the title on page 2\nThis is page two\nIt has several blocks of text\nNone of them have formatting\n"; + private static final String EXPECTED_PAGE1 = + "This is a test title\n" + + "This is a test subtitle\n\n" + + "This is on page 1\n"; + + private static final String EXPECTED_PAGE2 = + "This is the title on page 2\n" + + "This is page two\n\n" + + "It has several blocks of text\n\n" + + "None of them have formatting\n"; - /** - * Extractor primed on the 1 page but text-box'd test data - */ - private static final String expectText2 = "Hello, World!!!\nI am just a poor boy\nThis is Times New Roman\nPlain Text \n"; + private static final String NOTES_PAGE1 = + "\nThese are the notes for page 1\n"; + + private static final String NOTES_PAGE2 = + "\nThese are the notes on page two, again lacking formatting\n"; /** * Where our embeded files live @@ -75,9 +87,16 @@ public final class TestExtractor { public void testReadSheetText() throws IOException { // Basic 2 page example try (SlideShowExtractor ppe = openExtractor("basic_test_ppt_file.ppt")) { - assertEquals(expectText, ppe.getText()); + assertEquals(EXPECTED_PAGE1+EXPECTED_PAGE2, ppe.getText()); } + // Extractor primed on the 1 page but text-box'd test data + final String expectText2 = + "Hello, World!!!\n" + + "I am just a poor boy\n" + + "This is Times New Roman\n" + + "Plain Text \n"; + // 1 page example with text boxes try (SlideShowExtractor ppe = openExtractor("with_textbox.ppt")) { assertEquals(expectText2, ppe.getText()); @@ -92,8 +111,7 @@ public final class TestExtractor { ppe.setSlidesByDefault(false); ppe.setMasterByDefault(false); String notesText = ppe.getText(); - String expText = "\nThese are the notes for page 1\n\nThese are the notes on page two, again lacking formatting\n"; - assertEquals(expText, notesText); + assertEquals(NOTES_PAGE1+NOTES_PAGE2, notesText); } // Other one doesn't have notes @@ -109,14 +127,8 @@ public final class TestExtractor { @Test public void testReadBoth() throws IOException { - String[] slText = new String[]{ - "This is a test title\nThis is a test subtitle\nThis is on page 1\n", - "This is the title on page 2\nThis is page two\nIt has several blocks of text\nNone of them have formatting\n" - }; - String[] ntText = new String[]{ - "\nThese are the notes for page 1\n", - "\nThese are the notes on page two, again lacking formatting\n" - }; + String[] slText = { EXPECTED_PAGE1, EXPECTED_PAGE2 }; + String[] ntText = { NOTES_PAGE1, NOTES_PAGE2 }; try (SlideShowExtractor ppe = openExtractor("basic_test_ppt_file.ppt")) { ppe.setSlidesByDefault(true); @@ -165,8 +177,8 @@ public final class TestExtractor { final DirectoryNode root = fs.getRoot(); final String[] TEST_SET = { - "MBD0000A3B6", "Sample PowerPoint file\nThis is the 1st file\nNot much too it\n", - "MBD0000A3B3", "Sample PowerPoint file\nThis is the 2nd file\nNot much too it either\n" + "MBD0000A3B6", "Sample PowerPoint file\nThis is the 1st file\n\nNot much too it\n", + "MBD0000A3B3", "Sample PowerPoint file\nThis is the 2nd file\n\nNot much too it either\n" }; for (int i=0; i<TEST_SET.length; i+=2) { @@ -386,7 +398,7 @@ public final class TestExtractor { // Open directly try (SlideShow<?,?> ppt = SlideShowFactory.create(npoifs.getRoot()); SlideShowExtractor<?,?> extractor = new SlideShowExtractor<>(ppt)) { - assertEquals(expectText, extractor.getText()); + assertEquals(EXPECTED_PAGE1+EXPECTED_PAGE2, extractor.getText()); } } } @@ -457,4 +469,19 @@ public final class TestExtractor { private static int countMatches(final String base, final String find) { return base.split(find).length-1; } + + @Test + public void glyphCounting() throws IOException { + String[] expected = { + "Times New Roman", "\t\n ,-./01234679:ABDEFGILMNOPRSTVWabcdefghijklmnoprstuvwxyz\u00F3\u201C\u201D", + "Arial", " Lacdilnost" + }; + try (SlideShowExtractor ppt = openExtractor("45543.ppt")) { + for (int i=0; i<expected.length; i+=2) { + BitSet l = ppt.getCodepoints(expected[i], null, null); + String s = l.stream().mapToObj(Character::toChars).map(String::valueOf).collect(Collectors.joining()); + assertEquals(expected[i+1], s); + } + } + } } Modified: poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestHSLFSlideShow.java URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestHSLFSlideShow.java?rev=1849898&r1=1849897&r2=1849898&view=diff ============================================================================== --- poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestHSLFSlideShow.java (original) +++ poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestHSLFSlideShow.java Fri Dec 28 23:43:31 2018 @@ -27,7 +27,7 @@ import org.apache.poi.sl.usermodel.BaseT import org.apache.poi.sl.usermodel.SlideShow; import org.junit.Test; -public class TestHSLFSlideShow extends BaseTestSlideShow { +public class TestHSLFSlideShow extends BaseTestSlideShow<HSLFShape,HSLFTextParagraph> { @Override public HSLFSlideShow createSlideShow() { return new HSLFSlideShow(); @@ -39,11 +39,7 @@ public class TestHSLFSlideShow extends B assertNotNull(createSlideShow()); } - public SlideShow<?, ?> reopen(SlideShow<?, ?> show) { - return reopen((HSLFSlideShow)show); - } - - public static HSLFSlideShow reopen(HSLFSlideShow show) { + public HSLFSlideShow reopen(SlideShow<HSLFShape,HSLFTextParagraph> show) { try { BufAccessBAOS bos = new BufAccessBAOS(); show.write(bos); @@ -55,7 +51,7 @@ public class TestHSLFSlideShow extends B } private static class BufAccessBAOS extends ByteArrayOutputStream { - public byte[] getBuf() { + byte[] getBuf() { return buf; } } Modified: poi/trunk/src/testcases/org/apache/poi/sl/usermodel/BaseTestSlideShow.java URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/sl/usermodel/BaseTestSlideShow.java?rev=1849898&r1=1849897&r2=1849898&view=diff ============================================================================== --- poi/trunk/src/testcases/org/apache/poi/sl/usermodel/BaseTestSlideShow.java (original) +++ poi/trunk/src/testcases/org/apache/poi/sl/usermodel/BaseTestSlideShow.java Fri Dec 28 23:43:31 2018 @@ -17,6 +17,7 @@ package org.apache.poi.sl.usermodel; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; @@ -29,20 +30,24 @@ import java.io.InputStream; import java.util.List; import org.apache.poi.POIDataSamples; +import org.apache.poi.common.usermodel.fonts.FontInfo; import org.apache.poi.sl.usermodel.PictureData.PictureType; import org.apache.poi.sl.usermodel.TabStop.TabStopType; import org.junit.Test; -public abstract class BaseTestSlideShow { +public abstract class BaseTestSlideShow< + S extends Shape<S,P>, + P extends TextParagraph<S,P,? extends TextRun> +> { protected static final POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - public abstract SlideShow<?, ?> createSlideShow(); + public abstract SlideShow<S,P> createSlideShow(); - public abstract SlideShow<?, ?> reopen(SlideShow<?, ?> show); + public abstract SlideShow<S,P> reopen(SlideShow<S,P> show); @Test public void addPicture_File() throws IOException { - SlideShow<?,?> show = createSlideShow(); + SlideShow<S,P> show = createSlideShow(); File f = slTests.getFile("clock.jpg"); assertEquals(0, show.getPictureData().size()); @@ -55,26 +60,18 @@ public abstract class BaseTestSlideShow @Test public void addPicture_Stream() throws IOException { - SlideShow<?,?> show = createSlideShow(); - try { - InputStream stream = slTests.openResourceAsStream("clock.jpg"); - try { - assertEquals(0, show.getPictureData().size()); - PictureData picture = show.addPicture(stream, PictureType.JPEG); - assertEquals(1, show.getPictureData().size()); - assertSame(picture, show.getPictureData().get(0)); - - } finally { - stream.close(); - } - } finally { - show.close(); + try (SlideShow<S,P> show = createSlideShow(); + InputStream stream = slTests.openResourceAsStream("clock.jpg")) { + assertEquals(0, show.getPictureData().size()); + PictureData picture = show.addPicture(stream, PictureType.JPEG); + assertEquals(1, show.getPictureData().size()); + assertSame(picture, show.getPictureData().get(0)); } } @Test public void addPicture_ByteArray() throws IOException { - SlideShow<?,?> show = createSlideShow(); + SlideShow<S,P> show = createSlideShow(); byte[] data = slTests.readFile("clock.jpg"); assertEquals(0, show.getPictureData().size()); @@ -87,7 +84,7 @@ public abstract class BaseTestSlideShow @Test public void findPicture() throws IOException { - SlideShow<?,?> show = createSlideShow(); + SlideShow<S,P> show = createSlideShow(); byte[] data = slTests.readFile("clock.jpg"); assertNull(show.findPictureData(data)); @@ -101,11 +98,11 @@ public abstract class BaseTestSlideShow @Test public void addTabStops() throws IOException { - try (final SlideShow<?,?> show1 = createSlideShow()) { + try (final SlideShow<S,P> show1 = createSlideShow()) { // first set the TabStops in the Master sheet - final MasterSheet<?, ?> master1 = show1.getSlideMasters().get(0); - final AutoShape<?, ?> master1_as = (AutoShape<?,?>)master1.getPlaceholder(Placeholder.BODY); - final TextParagraph<?, ?, ? extends TextRun> master1_tp = master1_as.getTextParagraphs().get(0); + final MasterSheet<S,P> master1 = show1.getSlideMasters().get(0); + final AutoShape<S,P> master1_as = (AutoShape<S,P>)master1.getPlaceholder(Placeholder.BODY); + final P master1_tp = master1_as.getTextParagraphs().get(0); master1_tp.clearTabStops(); int i1 = 0; for (final TabStopType tst : TabStopType.values()) { @@ -114,11 +111,11 @@ public abstract class BaseTestSlideShow } // then set it on a normal slide - final Slide<?,?> slide1 = show1.createSlide(); - final AutoShape<?, ?> slide1_as = slide1.createAutoShape(); + final Slide<S,P> slide1 = show1.createSlide(); + final AutoShape<S,P> slide1_as = slide1.createAutoShape(); slide1_as.setText("abc"); slide1_as.setAnchor(new Rectangle2D.Double(100,100,100,100)); - final TextParagraph<?, ?, ? extends TextRun> slide1_tp = slide1_as.getTextParagraphs().get(0); + final P slide1_tp = slide1_as.getTextParagraphs().get(0); slide1_tp.getTextRuns().get(0).setFontColor(new Color(0x563412)); slide1_tp.clearTabStops(); int i2 = 0; @@ -127,10 +124,10 @@ public abstract class BaseTestSlideShow i2++; } - try (final SlideShow<?, ?> show2 = reopen(show1)) { - final MasterSheet<?, ?> master2 = show2.getSlideMasters().get(0); - final AutoShape<?, ?> master2_as = (AutoShape<?,?>)master2.getPlaceholder(Placeholder.BODY); - final TextParagraph<?, ?, ? extends TextRun> master2_tp = master2_as.getTextParagraphs().get(0); + try (final SlideShow<S,P> show2 = reopen(show1)) { + final MasterSheet<S,P> master2 = show2.getSlideMasters().get(0); + final AutoShape<S,P> master2_as = (AutoShape<S,P>)master2.getPlaceholder(Placeholder.BODY); + final P master2_tp = master2_as.getTextParagraphs().get(0); final List<? extends TabStop> master2_tabStops = master2_tp.getTabStops(); assertNotNull(master2_tabStops); int i3 = 0; @@ -142,9 +139,10 @@ public abstract class BaseTestSlideShow } - final Slide<?,?> slide2 = show2.getSlides().get(0); - final AutoShape<?,?> slide2_as = (AutoShape<?,?>)slide2.getShapes().get(0); - final TextParagraph<?, ?, ? extends TextRun> slide2_tp = slide2_as.getTextParagraphs().get(0); + final Slide<S,P> slide2 = show2.getSlides().get(0); + @SuppressWarnings("unchecked") + final AutoShape<S,P> slide2_as = (AutoShape<S,P>)slide2.getShapes().get(0); + final P slide2_tp = slide2_as.getTextParagraphs().get(0); final List<? extends TabStop> slide2_tabStops = slide2_tp.getTabStops(); assertNotNull(slide2_tabStops); int i4 = 0; @@ -162,18 +160,35 @@ public abstract class BaseTestSlideShow public void shapeAndSlideName() throws IOException { final String file = "SampleShow.ppt"+(getClass().getSimpleName().contains("XML")?"x":""); try (final InputStream is = slTests.openResourceAsStream(file); - final SlideShow<? extends Shape, ?> ppt = SlideShowFactory.create(is)) { - final List<? extends Shape> shapes1 = ppt.getSlides().get(0).getShapes(); + final SlideShow<S,P> ppt = SlideShowFactory.create(is)) { + final List<S> shapes1 = ppt.getSlides().get(0).getShapes(); assertEquals("The Title", shapes1.get(0).getShapeName()); assertEquals("Another Subtitle", shapes1.get(1).getShapeName()); - final List<? extends Shape> shapes2 = ppt.getSlides().get(1).getShapes(); + final List<S> shapes2 = ppt.getSlides().get(1).getShapes(); assertEquals("Title 1", shapes2.get(0).getShapeName()); assertEquals("Content Placeholder 2", shapes2.get(1).getShapeName()); - for (final Slide<?,?> slide : ppt.getSlides()) { + for (final Slide<S,P> slide : ppt.getSlides()) { final String expected = slide.getSlideNumber()==1 ? "FirstSlide" : "Slide2"; assertEquals(expected, slide.getSlideName()); } } } + + @Test + public void addFont() throws IOException { + try (SlideShow<S,P> ppt = createSlideShow()) { + ppt.createSlide(); + try (InputStream fontData = slTests.openResourceAsStream("font.fntdata")) { + ppt.addFont(fontData); + } + + try (SlideShow<S, P> ppt2 = reopen(ppt)) { + List<? extends FontInfo> fonts = ppt2.getFonts(); + assertFalse(fonts.isEmpty()); + FontInfo fi = fonts.get(fonts.size()-1); + assertEquals("Harlow Solid Italic", fi.getTypeface()); + } + } + } } Added: poi/trunk/test-data/slideshow/font.fntdata URL: http://svn.apache.org/viewvc/poi/trunk/test-data/slideshow/font.fntdata?rev=1849898&view=auto ============================================================================== Binary file - no diff available. Propchange: poi/trunk/test-data/slideshow/font.fntdata ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
