123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- /* ====================================================================
- 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.InputStream;
- import java.io.OutputStream;
- import java.util.ArrayList;
- import java.util.LinkedHashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.function.Predicate;
- import java.util.function.Supplier;
-
- import org.apache.poi.common.usermodel.fonts.FontCharset;
- import org.apache.poi.common.usermodel.fonts.FontHeader;
- import org.apache.poi.common.usermodel.fonts.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;
-
- /**
- * {@code FontCollection} ia a container that holds information
- * about all the fonts in the presentation.
- */
-
- @SuppressWarnings("WeakerAccess")
- public final class FontCollection extends RecordContainer {
- private final Map<Integer,HSLFFontInfo> fonts = new LinkedHashMap<>();
- private byte[] _header;
-
- /* package */ FontCollection(byte[] source, int start, int len) {
- _header = new byte[8];
- System.arraycopy(source,start,_header,0,8);
-
- _children = Record.findChildRecords(source,start+8,len-8);
-
- for (org.apache.poi.hslf.record.Record r : _children){
- if(r instanceof FontEntityAtom) {
- HSLFFontInfo fi = new HSLFFontInfo((FontEntityAtom) r);
- fonts.put(fi.getIndex(), 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());
- }
- }
- }
-
- /**
- * Return the type, which is 2005
- */
- @Override
- public long getRecordType() {
- return RecordTypes.FontCollection.typeID;
- }
-
- /**
- * Write the contents of the record back, so it can be written
- * to disk
- */
- @Override
- public void writeOut(OutputStream out) throws IOException {
- writeOut(_header[0],_header[1],getRecordType(),_children,out);
- }
-
- /**
- * Add font with the given FontInfo configuration to the font collection.
- * The returned FontInfo contains the HSLF specific details and the collection
- * uniquely contains fonts based on their typeface, i.e. calling the method with FontInfo
- * objects having the same name results in the same HSLFFontInfo reference.
- *
- * @param fontInfo the FontInfo configuration, can be a instance of {@link HSLFFontInfo},
- * {@link HSLFFontInfoPredefined} or a custom implementation
- * @return the register HSLFFontInfo object
- */
- public HSLFFontInfo addFont(FontInfo fontInfo) {
- HSLFFontInfo fi = getFontInfo(fontInfo.getTypeface(), fontInfo.getCharset());
- if (fi != null) {
- return fi;
- }
-
- fi = new HSLFFontInfo(fontInfo);
- fi.setIndex(fonts.size());
- fonts.put(fi.getIndex(), fi);
-
- FontEntityAtom fnt = fi.createRecord();
-
- // Append new child to the end
- appendChildRecord(fnt);
-
- // the added font is the last in the list
- 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
- *
- * @param typeface the full font name
- *
- * @return the HSLFFontInfo for the given name or {@code null} if not found
- */
- public HSLFFontInfo getFontInfo(String typeface) {
- return getFontInfo(typeface, null);
- }
-
- /**
- * Lookup a FontInfo object by its typeface
- *
- * @param typeface the full font name
- * @param charset the charset
- *
- * @return the HSLFFontInfo for the given name or {@code null} if not found
- */
- public HSLFFontInfo getFontInfo(String typeface, FontCharset charset) {
- return fonts.values().stream().filter(findFont(typeface, charset)).findFirst().orElse(null);
- }
-
- private static Predicate<HSLFFontInfo> findFont(String typeface, FontCharset charset) {
- return (fi) -> typeface.equals(fi.getTypeface()) && (charset == null || charset.equals(fi.getCharset()));
- }
-
- /**
- * Lookup a FontInfo object by its internal font index
- *
- * @param index the internal font index
- *
- * @return the HSLFFontInfo for the given index or {@code null} if not found
- */
- public HSLFFontInfo getFontInfo(int index) {
- for (HSLFFontInfo fi : fonts.values()) {
- if (fi.getIndex() == index) {
- return fi;
- }
- }
- return null;
- }
-
- /**
- * @return the number of registered fonts
- */
- public int getNumberOfFonts() {
- return fonts.size();
- }
-
- public List<HSLFFontInfo> getFonts() {
- return new ArrayList<>(fonts.values());
- }
-
- @Override
- public Map<String, Supplier<?>> getGenericProperties() {
- return null;
- }
- }
|