| /* | |
| * 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.pdfbox.pdmodel.font; | |
| import java.io.IOException; | |
| import java.io.InputStream; | |
| import java.util.ArrayList; | |
| import java.util.List; | |
| import org.apache.fontbox.afm.FontMetrics; | |
| import org.apache.fontbox.encoding.BuiltInEncoding; | |
| import org.apache.fontbox.pfb.PfbParser; | |
| import org.apache.fontbox.type1.Type1Font; | |
| import org.apache.fontbox.util.BoundingBox; | |
| import org.apache.pdfbox.cos.COSArray; | |
| import org.apache.pdfbox.cos.COSDictionary; | |
| import org.apache.pdfbox.cos.COSName; | |
| import org.apache.pdfbox.pdmodel.PDDocument; | |
| import org.apache.pdfbox.pdmodel.common.PDRectangle; | |
| import org.apache.pdfbox.pdmodel.common.PDStream; | |
| import org.apache.pdfbox.pdmodel.font.encoding.Encoding; | |
| import org.apache.pdfbox.pdmodel.font.encoding.GlyphList; | |
| import org.apache.pdfbox.pdmodel.font.encoding.Type1Encoding; | |
| /** | |
| * Embedded PDType1Font builder. Helper class to populate a PDType1Font from a PFB and AFM. | |
| * | |
| * @author Michael Niedermair | |
| */ | |
| class PDType1FontEmbedder | |
| { | |
| private final Encoding fontEncoding; | |
| private final Type1Font type1; | |
| /** | |
| * This will load a PFB to be embedded into a document. | |
| * | |
| * @param doc The PDF document that will hold the embedded font. | |
| * @param dict The Font dictionary to write to. | |
| * @param pfbStream The pfb input. | |
| * @throws IOException If there is an error loading the data. | |
| */ | |
| PDType1FontEmbedder(PDDocument doc, COSDictionary dict, InputStream pfbStream, | |
| Encoding encoding) throws IOException | |
| { | |
| dict.setItem(COSName.SUBTYPE, COSName.TYPE1); | |
| // read the pfb | |
| byte[] pfbBytes = pfbStream.readAllBytes(); | |
| PfbParser pfbParser = new PfbParser(pfbBytes); | |
| type1 = Type1Font.createWithPFB(pfbBytes); | |
| if (encoding == null) | |
| { | |
| fontEncoding = Type1Encoding.fromFontBox(type1.getEncoding()); | |
| } | |
| else | |
| { | |
| fontEncoding = encoding; | |
| } | |
| // build font descriptor | |
| PDFontDescriptor fd = buildFontDescriptor(type1); | |
| PDStream fontStream = new PDStream(doc, pfbParser.getInputStream(), COSName.FLATE_DECODE); | |
| fontStream.getCOSObject().setInt("Length", pfbParser.size()); | |
| for (int i = 0; i < pfbParser.getLengths().length; i++) | |
| { | |
| fontStream.getCOSObject().setInt("Length" + (i + 1), pfbParser.getLengths()[i]); | |
| } | |
| fd.setFontFile(fontStream); | |
| // set the values | |
| dict.setItem(COSName.FONT_DESC, fd); | |
| dict.setName(COSName.BASE_FONT, type1.getName()); | |
| // widths | |
| List<Integer> widths = new ArrayList<>(256); | |
| for (int code = 0; code <= 255; code++) | |
| { | |
| String name = fontEncoding.getName(code); | |
| int width = Math.round(type1.getWidth(name)); | |
| widths.add(width); | |
| } | |
| dict.setInt(COSName.FIRST_CHAR, 0); | |
| dict.setInt(COSName.LAST_CHAR, 255); | |
| dict.setItem(COSName.WIDTHS, COSArray.ofCOSIntegers(widths)); | |
| dict.setItem(COSName.ENCODING, encoding); | |
| } | |
| /** | |
| * Returns a PDFontDescriptor for the given PFB. | |
| * | |
| * @throws IOException if the font bounding box isn't available | |
| */ | |
| static PDFontDescriptor buildFontDescriptor(Type1Font type1) throws IOException | |
| { | |
| boolean isSymbolic = type1.getEncoding() instanceof BuiltInEncoding; | |
| BoundingBox bbox = type1.getFontBBox(); | |
| PDFontDescriptor fd = new PDFontDescriptor(); | |
| fd.setFontName(type1.getName()); | |
| fd.setFontFamily(type1.getFamilyName()); | |
| fd.setNonSymbolic(!isSymbolic); | |
| fd.setSymbolic(isSymbolic); | |
| fd.setFontBoundingBox(new PDRectangle(bbox)); | |
| fd.setItalicAngle(type1.getItalicAngle()); | |
| fd.setAscent(bbox.getUpperRightY()); | |
| fd.setDescent(bbox.getLowerLeftY()); | |
| fd.setCapHeight(type1.getBlueValues().get(2).floatValue()); | |
| fd.setStemV(0); // for PDF/A | |
| return fd; | |
| } | |
| /** | |
| * Returns a PDFontDescriptor for the given AFM. Used only for Standard 14 fonts. | |
| * | |
| * @param metrics AFM | |
| */ | |
| static PDFontDescriptor buildFontDescriptor(FontMetrics metrics) | |
| { | |
| boolean isSymbolic = metrics.getEncodingScheme().equals("FontSpecific"); | |
| PDFontDescriptor fd = new PDFontDescriptor(); | |
| fd.setFontName(metrics.getFontName()); | |
| fd.setFontFamily(metrics.getFamilyName()); | |
| fd.setNonSymbolic(!isSymbolic); | |
| fd.setSymbolic(isSymbolic); | |
| fd.setFontBoundingBox(new PDRectangle(metrics.getFontBBox())); | |
| fd.setItalicAngle(metrics.getItalicAngle()); | |
| fd.setAscent(metrics.getAscender()); | |
| fd.setDescent(metrics.getDescender()); | |
| fd.setCapHeight(metrics.getCapHeight()); | |
| fd.setXHeight(metrics.getXHeight()); | |
| fd.setAverageWidth(metrics.getAverageCharacterWidth()); | |
| fd.setCharacterSet(metrics.getCharacterSet()); | |
| fd.setStemV(0); // for PDF/A | |
| return fd; | |
| } | |
| /** | |
| * Returns the font's encoding. | |
| */ | |
| public Encoding getFontEncoding() | |
| { | |
| return fontEncoding; | |
| } | |
| /** | |
| * Returns the font's glyph list. | |
| */ | |
| public GlyphList getGlyphList() | |
| { | |
| return GlyphList.getAdobeGlyphList(); | |
| } | |
| /** | |
| * Returns the Type 1 font. | |
| */ | |
| public Type1Font getType1Font() | |
| { | |
| return type1; | |
| } | |
| } |