| /* ==================================================================== |
| 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.hwpf.model; |
| |
| import java.nio.charset.Charset; |
| |
| import org.apache.logging.log4j.LogManager; |
| import org.apache.logging.log4j.Logger; |
| import org.apache.poi.common.usermodel.fonts.FontCharset; |
| import org.apache.poi.util.Internal; |
| import org.apache.poi.util.LittleEndianConsts; |
| import org.apache.poi.util.StringUtil; |
| |
| import static org.apache.logging.log4j.util.Unbox.box; |
| |
| /** |
| * Word 6.0 Font information |
| */ |
| @Internal |
| public final class OldFfn { |
| |
| private static final Logger LOG = LogManager.getLogger(OldFfn.class); |
| |
| private final byte _chs;// character set identifier |
| |
| private final String fontName; |
| private final String altFontName; |
| |
| private final int length; //length in bytes for this record |
| |
| /** |
| * try to read an OldFfn starting at offset; read no farther than end |
| * |
| * @param buf buffer from which to read |
| * @param offset offset at which to start |
| * @param fontTableEnd read no farther than this |
| * @return an OldFfn or null if asked to read beyond end |
| */ |
| static OldFfn build(byte[] buf, int offset, int fontTableEnd) { |
| int start = offset; |
| //preliminary bytes |
| if (offset + 6 > fontTableEnd) { |
| return null; |
| } |
| //first byte |
| short fontDescriptionLength = buf[offset]; |
| offset += 1; |
| if (offset + fontDescriptionLength > fontTableEnd) { |
| LOG.atWarn().log("Asked to read beyond font table end. Skipping font"); |
| return null; |
| } |
| |
| //no idea what these 3 bytes do |
| offset += 3; |
| byte chs = buf[offset]; |
| Charset charset = null; |
| FontCharset wmfCharset = FontCharset.valueOf(chs & 0xff); |
| if (wmfCharset == null) { |
| LOG.atWarn().log("Couldn't find font for type: {}", box((chs & 0xff))); |
| } else { |
| charset = wmfCharset.getCharset(); |
| } |
| charset = charset == null ? StringUtil.WIN_1252 : charset; |
| offset += LittleEndianConsts.BYTE_SIZE; |
| //if this byte here == 7, it _may_ signify existence of |
| //an altername font name |
| |
| //not sure what the byte after the _chs does |
| offset += LittleEndianConsts.BYTE_SIZE; |
| int fontNameLength = -1; |
| for (int i = offset; i < fontTableEnd; i++) { |
| if (buf[i] == 0) { |
| fontNameLength = i - offset; |
| break; |
| } |
| } |
| if (fontNameLength == -1) { |
| LOG.atWarn().log("Couldn't find the zero-byte delimited font name length"); |
| return null; |
| } |
| String fontName = new String(buf, offset, fontNameLength, charset); |
| String altFontName = null; |
| int altFontNameLength = -1; |
| offset += fontNameLength + 1; |
| if (offset - start < fontDescriptionLength) { |
| for (int i = offset; i <= start + fontDescriptionLength; i++) { |
| if (buf[i] == 0) { |
| altFontNameLength = i - offset; |
| break; |
| } |
| } |
| if (altFontNameLength > -1) { |
| altFontName = new String(buf, offset, altFontNameLength, charset); |
| } |
| } |
| //reset to 0 for length calculation |
| altFontNameLength = (altFontNameLength < 0) ? 0 : altFontNameLength + 1;//add one for zero byte |
| |
| int len = LittleEndianConsts.INT_SIZE + LittleEndianConsts.BYTE_SIZE + LittleEndianConsts.BYTE_SIZE +//6 starting bytes |
| fontNameLength + altFontNameLength + 1;//+1 is for the zero byte |
| //this len should == fontDescriptionLength |
| |
| return new OldFfn(chs, fontName, altFontName, len); |
| |
| } |
| |
| public OldFfn(byte charsetIdentifier, String fontName, String altFontName, int length) { |
| this._chs = charsetIdentifier; |
| this.fontName = fontName; |
| this.altFontName = altFontName; |
| this.length = length; |
| } |
| |
| public byte getChs() { |
| return _chs; |
| } |
| |
| public String getMainFontName() { |
| return fontName; |
| } |
| |
| /** |
| * @return altFontName if it exists, null otherwise |
| */ |
| public String getAltFontName() { |
| return altFontName; |
| } |
| |
| |
| /** |
| * @return length in bytes for this record |
| */ |
| public int getLength() { |
| return length; |
| } |
| |
| @Override |
| public String toString() { |
| return "OldFfn{" + |
| "_chs=" + (_chs & 0xff) + |
| ", fontName='" + fontName + '\'' + |
| ", altFontName='" + altFontName + '\'' + |
| ", length=" + length + |
| '}'; |
| } |
| } |
| |
| |