com.helger.pdflayout.spec.PreloadFont Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ph-pdf-layout Show documentation
Show all versions of ph-pdf-layout Show documentation
Library for creating nicely layouted PDF documents based on PDFBox
/*
* Copyright (C) 2014-2024 Philip Helger (www.helger.com)
* philip[at]helger[dot]com
*
* Licensed 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 com.helger.pdflayout.spec;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import javax.annotation.Nonnull;
import javax.annotation.WillNotClose;
import javax.annotation.concurrent.NotThreadSafe;
import org.apache.fontbox.ttf.OTFParser;
import org.apache.fontbox.ttf.OpenTypeFont;
import org.apache.fontbox.ttf.TTFParser;
import org.apache.fontbox.ttf.TrueTypeFont;
import org.apache.pdfbox.io.RandomAccessReadBuffer;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.font.Standard14Fonts;
import com.helger.commons.ValueEnforcer;
import com.helger.commons.annotation.Nonempty;
import com.helger.commons.annotation.ReturnsMutableCopy;
import com.helger.commons.collection.impl.CommonsLinkedHashMap;
import com.helger.commons.collection.impl.ICommonsOrderedMap;
import com.helger.commons.equals.EqualsHelper;
import com.helger.commons.hashcode.HashCodeGenerator;
import com.helger.commons.id.IHasID;
import com.helger.commons.io.stream.StreamHelper;
import com.helger.commons.string.ToStringGenerator;
import com.helger.font.api.IFontResource;
import com.helger.pdflayout.debug.PLDebugLog;
/**
* Represents an abstract font that is potentially not yet loaded and can be
* used in multiple documents.
* Note: {@link PDFont} is not Serializable.
*
* @author Philip Helger
*/
@NotThreadSafe
public final class PreloadFont implements IHasID , Serializable
{
private static final int DEFAULT_FALLBACK_CODE_POINT = '?';
// Must be defined before the standard fonts are registered
private static final ICommonsOrderedMap STANDARD_14 = new CommonsLinkedHashMap <> ();
private static final ICommonsOrderedMap STANDARD_14_PF = new CommonsLinkedHashMap <> ();
@Nonnull
private static PreloadFont _createPredefined (@Nonnull final Standard14Fonts.FontName eFontName)
{
ValueEnforcer.notNull (eFontName, "Font");
// Symbol fonts needs a different fallback code point!
int nFallbackCodePoint;
if (eFontName == Standard14Fonts.FontName.SYMBOL)
nFallbackCodePoint = '•';
else
if (eFontName == Standard14Fonts.FontName.ZAPF_DINGBATS)
nFallbackCodePoint = '✕';
else
nFallbackCodePoint = DEFAULT_FALLBACK_CODE_POINT;
final PDType1Font aFont = new PDType1Font (eFontName);
final PreloadFont ret = new PreloadFont (aFont, nFallbackCodePoint);
STANDARD_14.put (aFont.getBaseFont (), aFont);
STANDARD_14_PF.put (aFont.getBaseFont (), ret);
return ret;
}
/** PDF built-in font Helvetica regular */
public static final PreloadFont REGULAR = _createPredefined (Standard14Fonts.FontName.HELVETICA);
/** PDF built-in font Helvetica bold */
public static final PreloadFont REGULAR_BOLD = _createPredefined (Standard14Fonts.FontName.HELVETICA_BOLD);
/** PDF built-in font Helvetica italic */
public static final PreloadFont REGULAR_ITALIC = _createPredefined (Standard14Fonts.FontName.HELVETICA_OBLIQUE);
/** PDF built-in font Helvetica bold and italic */
public static final PreloadFont REGULAR_BOLD_ITALIC = _createPredefined (Standard14Fonts.FontName.HELVETICA_BOLD_OBLIQUE);
/** PDF built-in font Courier regular */
public static final PreloadFont MONOSPACE = _createPredefined (Standard14Fonts.FontName.COURIER);
/** PDF built-in font Courier bold */
public static final PreloadFont MONOSPACE_BOLD = _createPredefined (Standard14Fonts.FontName.COURIER_BOLD);
/** PDF built-in font Courier italic */
public static final PreloadFont MONOSPACE_ITALIC = _createPredefined (Standard14Fonts.FontName.COURIER_OBLIQUE);
/** PDF built-in font Courier bold and italic */
public static final PreloadFont MONOSPACE_BOLD_ITALIC = _createPredefined (Standard14Fonts.FontName.COURIER_BOLD_OBLIQUE);
/** PDF built-in font Times Roman regular */
public static final PreloadFont TIMES = _createPredefined (Standard14Fonts.FontName.TIMES_ROMAN);
/** PDF built-in font Times Roman bold */
public static final PreloadFont TIMES_BOLD = _createPredefined (Standard14Fonts.FontName.TIMES_BOLD);
/** PDF built-in font Times Roman italic */
public static final PreloadFont TIMES_ITALIC = _createPredefined (Standard14Fonts.FontName.TIMES_ITALIC);
/** PDF built-in font Times Roman bold italic */
public static final PreloadFont TIMES_BOLD_ITALIC = _createPredefined (Standard14Fonts.FontName.TIMES_BOLD_ITALIC);
/** PDF built-in font Symbol */
public static final PreloadFont SYMBOL = _createPredefined (Standard14Fonts.FontName.SYMBOL);
/** PDF built-in font Zapf Dingbats */
public static final PreloadFont ZAPF_DINGBATS = _createPredefined (Standard14Fonts.FontName.ZAPF_DINGBATS);
private String m_sID;
private PDFont m_aFont;
private IFontResource m_aFontRes;
private boolean m_bEmbed;
private int m_nFallbackCodePoint;
// Status vars
private transient TrueTypeFont m_aTTF;
private transient OpenTypeFont m_aOTF;
private void _parseFontRes () throws IOException
{
if (m_aFontRes != null)
switch (m_aFontRes.getFontType ())
{
case TTF:
if (PLDebugLog.isDebugFont ())
PLDebugLog.debugFont (m_aFontRes.toString (), "Loading TTF font");
m_aTTF = new TTFParser ().parse (new RandomAccessReadBuffer (m_aFontRes.getInputStream ()));
break;
case OTF:
if (PLDebugLog.isDebugFont ())
PLDebugLog.debugFont (m_aFontRes.toString (), "Loading OTF font");
m_aOTF = new OTFParser ().parse (new RandomAccessReadBuffer (m_aFontRes.getInputStream ()));
break;
default:
throw new IllegalArgumentException ("Cannot parse font resources of type " + m_aFontRes.getFontType ());
}
}
private void readObject (@Nonnull @WillNotClose final ObjectInputStream aOIS) throws IOException,
ClassNotFoundException
{
m_sID = StreamHelper.readSafeUTF (aOIS);
final String sBaseFontName = StreamHelper.readSafeUTF (aOIS);
m_aFont = STANDARD_14.get (sBaseFontName);
m_aFontRes = (IFontResource) aOIS.readObject ();
m_bEmbed = aOIS.readBoolean ();
m_nFallbackCodePoint = aOIS.readInt ();
_parseFontRes ();
}
private void writeObject (@Nonnull @WillNotClose final ObjectOutputStream aOOS) throws IOException
{
StreamHelper.writeSafeUTF (aOOS, m_sID);
StreamHelper.writeSafeUTF (aOOS, m_aFont != null ? m_aFont.getName () : null);
aOOS.writeObject (m_aFontRes);
aOOS.writeBoolean (m_bEmbed);
aOOS.writeInt (m_nFallbackCodePoint);
// TTF and OTF are not written
}
private PreloadFont (@Nonnull final PDFont aFont, final int nFallbackCodePoint)
{
ValueEnforcer.notNull (aFont, "Font");
m_sID = aFont.getName ();
m_aFont = aFont;
m_aFontRes = null;
m_bEmbed = false;
m_nFallbackCodePoint = nFallbackCodePoint;
}
private PreloadFont (@Nonnull final IFontResource aFontRes, final boolean bEmbed, final int nFallbackCodePoint)
throws IOException
{
ValueEnforcer.notNull (aFontRes, "FontResource");
m_sID = aFontRes.getID ();
m_aFont = null;
m_aFontRes = aFontRes;
m_bEmbed = bEmbed;
m_nFallbackCodePoint = nFallbackCodePoint;
// Not loaded custom font
_parseFontRes ();
}
@Nonnull
@Nonempty
public String getID ()
{
return m_sID;
}
/**
* Load the {@link PDFont} associated to this preload font. This class uses no
* caching!
*
* @param aDoc
* The {@link PDDocument} to which the font should be attached to. May
* not be null
.
* @return The loaded font.
* @throws IOException
* In case loading the external file fails
*/
@Nonnull
public PDFont loadPDFont (@Nonnull final PDDocument aDoc) throws IOException
{
if (m_aFont != null)
{
// Pre-defined font
return m_aFont;
}
PDFont ret = null;
if (m_aTTF != null)
ret = PDType0Font.load (aDoc, m_aTTF, m_bEmbed);
else
if (m_aOTF != null)
ret = PDType0Font.load (aDoc, m_aOTF, m_bEmbed);
if (ret == null)
throw new IllegalArgumentException ("Cannot load font resources of type " + m_aFontRes.getFontType ());
return ret;
}
/**
* @return The fallback code point to be used if a character is not contained
* in the font. Defaults to '?'.
*/
public int getFallbackCodePoint ()
{
return m_nFallbackCodePoint;
}
@Override
public boolean equals (final Object o)
{
if (o == this)
return true;
if (o == null || !getClass ().equals (o.getClass ()))
return false;
final PreloadFont rhs = (PreloadFont) o;
return EqualsHelper.equals (m_aFont, rhs.m_aFont) &&
EqualsHelper.equals (m_aFontRes, rhs.m_aFontRes) &&
m_bEmbed == rhs.m_bEmbed &&
m_nFallbackCodePoint == rhs.m_nFallbackCodePoint;
}
@Override
public int hashCode ()
{
return new HashCodeGenerator (this).append (m_aFont)
.append (m_aFontRes)
.append (m_bEmbed)
.append (m_nFallbackCodePoint)
.getHashCode ();
}
@Override
public String toString ()
{
return new ToStringGenerator (null).appendIfNotNull ("Font", m_aFont)
.appendIfNotNull ("FontResource", m_aFontRes)
.append ("Embed", m_bEmbed)
.append ("FallbackCodePoint", m_nFallbackCodePoint)
.getToString ();
}
/**
* Create a new {@link PreloadFont} from an existing {@link IFontResource}
* where the subset cannot be embedded into the resulting PDF.
*
* @param aFontRes
* The font resource to include. May not be null
.
* @return Never null
.
* @throws IllegalArgumentException
* If the font could not be loaded.
*/
@Nonnull
public static PreloadFont createNonEmbedding (@Nonnull final IFontResource aFontRes)
{
ValueEnforcer.notNull (aFontRes, "FontRes");
try
{
return new PreloadFont (aFontRes, false, DEFAULT_FALLBACK_CODE_POINT);
}
catch (final IOException ex)
{
throw new IllegalArgumentException ("Cannot use the passed font resource " + aFontRes, ex);
}
}
/**
* Create a new {@link PreloadFont} from an existing {@link IFontResource}
* where the subset can be embedded into the resulting PDF.
*
* @param aFontRes
* The font resource to include. May not be null
.
* @return Never null
.
* @throws IllegalArgumentException
* If the font could not be loaded.
*/
@Nonnull
public static PreloadFont createEmbedding (@Nonnull final IFontResource aFontRes)
{
ValueEnforcer.notNull (aFontRes, "FontRes");
try
{
return new PreloadFont (aFontRes, true, DEFAULT_FALLBACK_CODE_POINT);
}
catch (final IOException ex)
{
throw new IllegalArgumentException ("Cannot use the passed font resource " + aFontRes, ex);
}
}
@Nonnull
@ReturnsMutableCopy
public static ICommonsOrderedMap getAllStandard14Fonts ()
{
return STANDARD_14.getClone ();
}
@Nonnull
@ReturnsMutableCopy
public static ICommonsOrderedMap getAllStandard14PreloadFonts ()
{
return STANDARD_14_PF.getClone ();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy