com.adobe.fontengine.font.cff.CFFFont Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
/*
*
* File: CFFFont.java
*
*
* ADOBE CONFIDENTIAL
* ___________________
*
* Copyright 2004-2006 Adobe Systems Incorporated
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains the property of
* Adobe Systems Incorporated and its suppliers, if any. The intellectual
* and technical concepts contained herein are proprietary to Adobe Systems
* Incorporated and its suppliers and may be covered by U.S. and Foreign
* Patents, patents in process, and are protected by trade secret or
* copyright law. Dissemination of this information or reproduction of this
* material is strictly forbidden unless prior written permission is obtained
* from Adobe Systems Incorporated.
*
*/
/*
* Adobe Patent and/or Adobe Patent Pending invention included within this file:
*
* Adobe patent application tracking # P376,
* entitled 'Method for calculating CJK emboxes in fonts',
* invented by Nathaniel McCully
* Issued US Patent 7,071,941 on July 4, 2006.
*
* Adobe patent application tracking # P376,
* entitled 'A LINE COMPOSITION CONTROLLABLE DTP SYSTEM, A LINE
* COMPOSITION CONTROLLING METHOD, A LINE COMPOSITION CONTROL
* PROGRAM AND A RECORDING MEDIUM STORING THE SAME',
* invented by Nathaniel McCully
* Issued Japanese Patent 3708828 on August 12, 2005.
*
* Adobe patent application tracking # P377,
* entitled 'LINE PREEMPT CONTROLLABLE DTP SYSTEM, A LINE
* PREEMPT CONTROL METHOD, A LINE PREEMPT CONTROL PROGRAM
* AND A RECORDING MEDIUM STORING THE SAME'
* invented by Nathaniel McCully
* Issued Japanese Patent 3598070 on September 17, 2004.
*/
package com.adobe.fontengine.font.cff;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.Set;
import com.adobe.agl.util.ULocale;
import com.adobe.fontengine.font.CScan;
import com.adobe.fontengine.font.CatalogDescription;
import com.adobe.fontengine.font.CodePage;
import com.adobe.fontengine.font.CoolTypeScript;
import com.adobe.fontengine.font.EmbeddingPermission;
import com.adobe.fontengine.font.InvalidFontException;
import com.adobe.fontengine.font.LineMetrics;
import com.adobe.fontengine.font.Matrix;
import com.adobe.fontengine.font.OrigFontType;
import com.adobe.fontengine.font.OutlineConsumer;
import com.adobe.fontengine.font.Permission;
import com.adobe.fontengine.font.ROS;
import com.adobe.fontengine.font.Rect;
import com.adobe.fontengine.font.SWFFont4Description;
import com.adobe.fontengine.font.SWFFontDescription;
import com.adobe.fontengine.font.Scaler;
import com.adobe.fontengine.font.ScanConverter;
import com.adobe.fontengine.font.Subset;
import com.adobe.fontengine.font.UnderlineMetrics;
import com.adobe.fontengine.font.UnsupportedFontException;
import com.adobe.fontengine.font.XDCFontDescription;
import com.adobe.fontengine.font.postscript.NameHeuristics;
import com.adobe.fontengine.fontmanagement.CacheSupportInfo;
import com.adobe.fontengine.fontmanagement.Platform;
import com.adobe.fontengine.fontmanagement.fxg.FXGFontDescription;
import com.adobe.fontengine.fontmanagement.platform.PlatformFontDescription;
import com.adobe.fontengine.fontmanagement.postscript.PostscriptFontDescription;
import com.adobe.fontengine.inlineformatting.css20.CSS20Attribute.CSSStretchValue;
abstract public class CFFFont extends com.adobe.fontengine.font.FontData {
//---------------------------------------------------------------- members ---
/** Our FontSet
. */
protected final StringIndex stringIndex;
protected final CharStrings globalSubrs;
protected final String name;
/** Our top Dict
. */
protected final Dict topDict;
//----------------------------------------------------------- constructors ---
CFFFont (StringIndex stringIndex, CharStrings globalSubrs, Dict topDict,
String name, byte[] digest)
throws UnsupportedFontException, InvalidFontException {
super (digest);
this.stringIndex = stringIndex;
this.globalSubrs = globalSubrs;
this.topDict = topDict;
this.name = name;
}
public String getName () {
return name;
}
//--------------------------------------------------------- general access ---
//------------------------------------------------------------- unitsPerEm ---
abstract public Matrix getFontMatrix ();
// see Type1 for this choice
public double getUnitsPerEmX ()
throws UnsupportedFontException, InvalidFontException {
//FOR NOW
// return 1000.0d;
return 1.0d / getFontMatrix ().a;
}
public double getUnitsPerEmY ()
throws UnsupportedFontException, InvalidFontException {
// return 1000.0d;
//FOR NOW
return 1.0d / getFontMatrix ().d;
}
public boolean getCoolTypeProportionalRomanFromFontProperties() throws InvalidFontException
{
return !isFixedPitch();
}
//----------------------------------------------------------------- bboxes ---
//----------------------------------------------------------------- script ---
public CoolTypeScript getCoolTypeScript ()
throws UnsupportedFontException {
CoolTypeScript ctScript;
ROS ros = getROS ();
if ((ctScript = CoolTypeScript.fromWellKnownROS (ros)) != null) {
return ctScript; }
if ((ctScript = CoolTypeScript.fromAnyROS (ros)) != null) {
return ctScript; }
return CoolTypeScript.ROMAN;
}
//-------------------------------------------------------------- capHeight ---
//-------------------------------------------------------------- ideoEmBox ---
/** Compute the IdeoEmBox from the CapHeight.
*/
private Rect getCoolTypeIdeoEmBoxFromCapHeight ()
throws InvalidFontException, UnsupportedFontException {
double capHeight = getCoolTypeCapHeight ();
if (Double.isNaN (capHeight)) {
return null; }
double unitsPerEmX = getUnitsPerEmX ();
double unitsPerEmY = getUnitsPerEmY ();
double ymin = - (unitsPerEmY - capHeight) / 2.0d;
return new Rect (0, ymin, unitsPerEmX, ymin + unitsPerEmY);
}
public Rect getCoolTypeIdeoEmBox ()
throws InvalidFontException, UnsupportedFontException {
Rect r;
if (useCoolTypeCJKHeuristics ()) {
if ((r = getCoolTypeIdeoEmBoxFromFullBoxCharacter ()) != null) {
return r; }
if ((r = getCoolTypeIdeoEmBoxFromTypicalCharacter ()) != null) {
return r; }}
else {
if ((r = getCoolTypeIdeoEmBoxFromCapHeight ()) != null) {
return r; }}
double unitsPerEmX = getUnitsPerEmX ();
double unitsPerEmY = getUnitsPerEmY ();
return new Rect (0, -.120 * unitsPerEmY, unitsPerEmX, 0.880 * unitsPerEmY);
}
//----------------------------------------------------------------- icfBox ---
/** Compute the IcfBox.
* Various heuristics are applied until the IcfBox can be determined.
*/
public Rect getCoolTypeIcfBox ()
throws InvalidFontException, UnsupportedFontException {
Rect ideoEmBox = getCoolTypeIdeoEmBox ();
Rect r;
if ((r = getCoolTypeIcfBoxFromTypicalCharacter (ideoEmBox)) != null) {
return r; }
return getCoolTypeIcfBoxFromIdeoEmBox (ideoEmBox);
}
//----------------------------------------------------------- line metrics ---
//------------------------------------------------------ underline metrics ---
public UnderlineMetrics getCoolTypeUnderlineMetrics ()
throws UnsupportedFontException, InvalidFontException {
return getCoolTypeUnderlineMetrics (getCoolTypeUnitsPerEm (), getUnitsPerEmY ());
}
public UnderlineMetrics getCoolTypeUnderlineMetrics (double coolTypeUnitsPerEm, double unitsPerEmY)
throws UnsupportedFontException, InvalidFontException {
double position = topDict.get (Dict.NumbersKey.UnderlinePosition, true).getFirstValueAsDouble ();
double thickness = topDict.get (Dict.NumbersKey.UnderlineThickness, true).getFirstValueAsDouble ();
return new UnderlineMetrics (
position * unitsPerEmY / coolTypeUnitsPerEm,
thickness * unitsPerEmY / coolTypeUnitsPerEm);
}
//------------------------------------------------------------------- cmap ---
/** {@inheritDoc} */
abstract public int getGlyphForChar (int usv)
throws InvalidFontException, UnsupportedFontException;
//-------------------------------------------------- individual glyph data ---
abstract public double getHorizontalAdvance (int gid)
throws InvalidFontException, UnsupportedFontException;
abstract public String getGlyphName (int gid)
throws InvalidFontException, UnsupportedFontException;
abstract public void getGlyphOutline (int gid, OutlineConsumer consumer)
throws InvalidFontException, UnsupportedFontException;
abstract public void getOutline (int gid, Type2OutlineParser parser,
OutlineConsumer consumer)
throws InvalidFontException, UnsupportedFontException;
/** Get the bounding box for a glyph, in metric space. */
public Rect getGlyphBBox (int gid)
throws UnsupportedFontException, InvalidFontException {
Matrix m = new Matrix (getUnitsPerEmX (), 0, 0, getUnitsPerEmY (), 0, 0);
return new Type2GlyphBBoxCalculator (m).calculateBBox (this, gid);
}
/** Get the CID associated with glyph glyphID
.
* Returns -1 if getROS() returns null.
* @return the CID in the ROS associated with the font.
*/
abstract public int getGlyphCid(int glyphID)
throws InvalidFontException, UnsupportedFontException;
//----------------------------------------------------------------------------
public Scaler getScaler (ScanConverter c)
throws InvalidFontException, UnsupportedFontException {
if (c == null) {
c = new CScan (false, 1.0d, true); }
return new CFFScaler (this, c);
}
//----------------------------------------------------------------------------
abstract public double getStemVForGlyph(int gid)
throws InvalidFontException;
abstract double getItalicAngle();
abstract Rect getRawFontBBox ();
abstract int[] getXUID();
abstract String getNotice();
abstract String getCopyright();
abstract String getFullName();
abstract Integer getFSType();
abstract int getFirstChar() throws InvalidFontException, UnsupportedFontException;
abstract int getLastChar() throws InvalidFontException, UnsupportedFontException;
abstract OrigFontType getOrigFontType();
Permission getEmbeddingPermissionGivenFT(boolean wasEmbedded, OrigFontType thisFontType) {
Integer fsType = getFSType();
if (fsType != null) {
return EmbeddingPermission.interpretFSType(fsType.intValue()); }
OrigFontType oft = getOrigFontType();
if (oft == OrigFontType.kTYPE1 || (oft == null && thisFontType == OrigFontType.kTYPE1)) {
return EmbeddingPermission.getType1DefaultPermission (getNotice(), getName()); }
else if (wasEmbedded) {
return EmbeddingPermission.getDefaultWasEmbeddedPermission (); }
else if (oft == OrigFontType.kCID || (oft == null && thisFontType == OrigFontType.kCID)) {
return EmbeddingPermission.getCIDDefaultPermission (getXUID()); }
else if (oft == OrigFontType.kTRUETYPE) {
return EmbeddingPermission.getTrueTypeDefaultPermission (); }
else {
// oft == ocf
return EmbeddingPermission.getOCFDefaultPermission (); }
}
//--------------------------------------------------------- CSS properties ---
/** Return the set of CSS font-family names that this font matches. */
public Set /**/ getCSSFamilyNames () {
Set s = new HashSet ();
String n = getPreferredCSSFamilyName();
if (n != null) {
s.add (n); }
return s;
}
/** Return the preferred CSS font-family name. */
public String getPreferredCSSFamilyName() {
Dict.StringValue v = topDict.get (Dict.StringKey.FamilyName, false);
return (v != null) ? v.value : name;
}
/** Tell if the font matches the CSS font-style normal. */
public boolean isCSSStyleNormal () {
return ! isCSSStyleItalic ();
}
public boolean isFixedPitch() {
Dict.NumbersValue v = topDict.get (Dict.NumbersKey.isFixedPitch, true);
return v != null && v.getFirstValueAsDouble () != 0.0;
}
/** Tell if the font matches the CSS font-style italic. */
public boolean isCSSStyleItalic () {
Dict.NumbersValue v = topDict.get (Dict.NumbersKey.ItalicAngle, true);
return v != null && v.getFirstValueAsDouble () != 0.0;
}
/** Tell if the font matches the CSS font-style oblique. */
public boolean isCSSStyleOblique () {
return isCSSStyleItalic ();
}
/** Tell if the font matches the CSS font-variant normal. */
public boolean isCSSVariantNormal () {
return ! isCSSVariantSmallCaps ();
}
/** Tell if the font matches the CSS font-variant small-caps. */
public boolean isCSSVariantSmallCaps () {
Dict.StringValue v = topDict.get (Dict.StringKey.FullName, true);
String n = (v != null) ? v.value : name;
if (n == null) {
return false; }
else {
return NameHeuristics.fullNameIndicatesSmallCaps (n); }
}
/** Return the CSS weight of this font. */
public int getCSSWeight () {
Dict.StringValue v = topDict.get (Dict.StringKey.Weight, true);
if (v != null) {
return NameHeuristics.weightNameToWeight (v.value); }
v = topDict.get (Dict.StringKey.FullName, true);
String n = (v != null) ? v.value : name;
if (n != null) {
return NameHeuristics.fullNameToWeight (n); }
else {
return 400; }
}
/** {@inheritDoc} */
public CSSStretchValue getCSSStretchValue () {
Dict.StringValue fullName = topDict.get (Dict.StringKey.FullName, true);
String n = (fullName != null) ? fullName.value : name;
Dict.StringValue familyName = topDict.get (Dict.StringKey.FamilyName, true);
if (n != null) {
return NameHeuristics.fullNameToWidth
(n, familyName != null ? familyName.value : null); }
else {
return CSSStretchValue.NORMAL; }
}
public CacheSupportInfo getCacheSupportInfo()
throws InvalidFontException, UnsupportedFontException
{
return new CacheSupportInfo(getClass().getSimpleName(), getNumGlyphs(), true);
}
//----------------------------------------------------------------------------
public PostscriptFontDescription[] getPostscriptFontDescription () {
String fontName = getName();
if (name != null) {
return new PostscriptFontDescription[] {new PostscriptFontDescription (fontName)}; }
else {
return new PostscriptFontDescription[0]; }
}
//---------------------------------------------------------- FXG Properties ---
public FXGFontDescription[] getFXGFontDescription(Platform platform, ULocale locale)
throws InvalidFontException, UnsupportedFontException
{
return new FXGFontDescription[0];
}
//---------------------------------------------------------- Platform Properties ---
public PlatformFontDescription[] getPlatformFontDescription(Platform platform, ULocale locale)
throws InvalidFontException, UnsupportedFontException
{
return new PlatformFontDescription[0];
}
//----------------------------------------------------------------------------
/** Get the ROS associated with this font.
* If the font does not have an ROS, return null.
*/
abstract public ROS getROS();
private class CFFSWFFont3Description
implements com.adobe.fontengine.font.SWFFontDescription
{
private final boolean wasEmbedded;
private final LineMetrics metrics;
CFFSWFFont3Description(boolean wasEmbedded) throws UnsupportedFontException, InvalidFontException
{
this.wasEmbedded = wasEmbedded;
metrics = CFFFont.this.getCoolTypeLineMetrics();
}
public boolean canDisplay(char c) throws UnsupportedFontException, InvalidFontException {
return getGlyphForChar(c) != 0;
}
public double getHorizontalAdvance(char ccode) throws UnsupportedFontException, InvalidFontException {
int gid = getGlyphForChar(ccode);
return CFFFont.this.getHorizontalAdvance(gid);
}
public void getOutline(char ccode, OutlineConsumer consumer) throws UnsupportedFontException, InvalidFontException {
int gid = getGlyphForChar(ccode);
getGlyphOutline(gid, consumer);
}
public double getEmScale() throws InvalidFontException, UnsupportedFontException {
return getUnitsPerEmX();
}
public double getAscent() throws InvalidFontException, UnsupportedFontException {
return metrics.ascender * getUnitsPerEmX() / getUnitsPerEmY();
}
public double getDescent() throws InvalidFontException, UnsupportedFontException {
return -metrics.descender * getUnitsPerEmX() / getUnitsPerEmY();
}
public double getLineGap() throws InvalidFontException, UnsupportedFontException {
return metrics.linegap * getUnitsPerEmX() / getUnitsPerEmY();
}
public String getCopyright() throws InvalidFontException, UnsupportedFontException {
return CFFFont.this.getCopyright();
}
public String getPostscriptName() throws InvalidFontException, UnsupportedFontException {
return getName();
}
public String getTrademark() throws InvalidFontException, UnsupportedFontException {
return getNotice();
}
public String getFamily() throws InvalidFontException, UnsupportedFontException {
return getPreferredCSSFamilyName();
}
public String getFullName() throws InvalidFontException, UnsupportedFontException {
return CFFFont.this.getFullName();
}
public int getNumGlyphs() throws InvalidFontException, UnsupportedFontException {
return CFFFont.this.getNumGlyphs();
}
public Permission getPermissions() throws InvalidFontException, UnsupportedFontException {
Permission perm = getEmbeddingPermission(wasEmbedded);
if (perm.equals(Permission.ILLEGAL_VALUE))
return Permission.EDITABLE;
return perm;
}
public boolean isBold() throws InvalidFontException, UnsupportedFontException {
return getCSSWeight() >= 700;
}
public boolean isItalic() throws InvalidFontException, UnsupportedFontException {
return isCSSStyleItalic();
}
public int getFirstChar() throws InvalidFontException, UnsupportedFontException {
return CFFFont.this.getFirstChar();
}
public int getLastChar() throws InvalidFontException, UnsupportedFontException {
return CFFFont.this.getLastChar();
}
public String getSubFamily() throws InvalidFontException, UnsupportedFontException {
return null;
}
}
protected abstract class CFFFontXDCFontDescription extends XDCFontDescription {
public ROS getROS()
throws UnsupportedFontException, InvalidFontException {
return CFFFont.this.getROS();
}
public boolean pdfFontIsTrueType() {
return false;
}
public String getPostscriptName()
throws InvalidFontException, UnsupportedFontException {
return getName();
}
public String getFontFamily()
throws InvalidFontException, UnsupportedFontException {
java.util.Set s = getCSSFamilyNames();
if (!s.isEmpty()) {
return (String)s.iterator().next(); }
return null;
}
public int getNumGlyphs ()
throws UnsupportedFontException, InvalidFontException {
return CFFFont.this.getNumGlyphs ();
}
public int getGlyphCid(int glyphID)
throws UnsupportedFontException, InvalidFontException {
return CFFFont.this.getGlyphCid(glyphID);
}
public String getGlyphName(int gid)
throws InvalidFontException, UnsupportedFontException {
return CFFFont.this.getGlyphName(gid);
}
public double getStemV()
throws UnsupportedFontException, InvalidFontException {
int glyphID = getGlyphForChar('l');
if (glyphID == 0) {
glyphID = getGlyphForChar('I'); }
if (glyphID == 0) {
return 0; }
return getStemVForGlyph(glyphID) * 1000.0d / getUnitsPerEmX ();
}
public Rect getFontBBox() throws InvalidFontException, UnsupportedFontException {
Rect bbox = CFFFont.this.getRawFontBBox ();
if (bbox == null) {
return null; }
return bbox.applyMatrix (getFontMatrix ().multiply (1000.0d));
}
public double getCapHeight () throws UnsupportedFontException, InvalidFontException {
double capHeight = getCoolTypeCapHeight ();
if (Double.isNaN (capHeight)) {
return 0; }
else {
return capHeight * (1000.0d / getUnitsPerEmY ()); }
}
public double getXHeight() throws UnsupportedFontException,InvalidFontException {
double xHeight = getCoolTypeXHeight();
if (Double.isNaN(xHeight)) {
return 0;
} else
{
return xHeight * (1000.0d / getUnitsPerEmY());
}
}
public double getItalicAngle() throws InvalidFontException, UnsupportedFontException {
return CFFFont.this.getItalicAngle();
}
public double getAdvance(int glyphID) throws InvalidFontException,
UnsupportedFontException {
return getHorizontalAdvance (glyphID) * 1000.0d / getUnitsPerEmX ();
}
public String getBase14Name() {
return null; }
public boolean isSerifFont() throws InvalidFontException, UnsupportedFontException {
int gid1, gid2;
gid1 = CFFFont.this.getGlyphForChar('l');
gid2 = CFFFont.this.getGlyphForChar('I');
return CFFFont.this.isSerifFont(gid1, gid2, getItalicAngle());
}
public boolean isSmallCapFont()
throws InvalidFontException, UnsupportedFontException {
if (!isAllCapFont()) {
int gid1 = CFFFont.this.getGlyphForChar('h');
int gid2 = CFFFont.this.getGlyphForChar('x');
if (gid2 != 0) {
Rect bbox = CFFFont.this.getGlyphBBox(gid2);
return CFFFont.this.isSmallCapFont(gid1, bbox.ymax);
}
}
return false;
}
public boolean isAllCapFont()
throws InvalidFontException, UnsupportedFontException {
int gid1 = CFFFont.this.getGlyphForChar('K');
int gid2 = CFFFont.this.getGlyphForChar('k');
return CFFFont.this.isAllCapFont(gid1, gid2);
}
abstract public CodePage[] getXDCCodePages()
throws InvalidFontException, UnsupportedFontException;
}
public SWFFontDescription getSWFFontDescription(boolean wasEmbedded) throws UnsupportedFontException, InvalidFontException
{
return new CFFSWFFont3Description(wasEmbedded);
}
public void subsetAndStream (Subset subset, OutputStream os, boolean preserveROS)
throws InvalidFontException, UnsupportedFontException, IOException {
subsetAndStream(subset, os, preserveROS, null);
}
abstract public void stream(OutputStream out, Integer fsType)
throws InvalidFontException, UnsupportedFontException, IOException;
/**
* A version of subsetAndStream that can take an fsType value to be added to the
* fonts postscript string.
* @param fsType if non-null an integer as described in technote 5147
* http://partners.adobe.com/public/developer/en/acrobat/sdk/FontPolicies.pdf
* "Font Embedding Guidelines for Adobe Third-party Developers".
*/
abstract public void subsetAndStream (Subset subset, OutputStream os,
boolean preserveROS, Integer fsType)
throws InvalidFontException, UnsupportedFontException, IOException;
/** Return the charstring index for a given font. */
abstract CharStrings getCharStrings();
/** Return the local subrs associated with a given font dictionary. */
abstract CharStrings getLocalSubrsForFD(int fd);
/** Return the number of font dictionaries in a given font. */
abstract int getNumFDs();
/** Return the default width associated with a given font dictionary. */
abstract double getDefaultWidthForFD(int fd);
/** Return the nominal width associated with a given font dictionary */
abstract double getNominalWidthForFD(int fd);
/** Return the index of the font dictionary associated with a given glyph. */
abstract int getFDForGlyph(int fullGid) throws InvalidFontException;
/** Create a new CharString index that only contains the glyphs in a given subset. */
CharStrings createSubsetCharstringIndex(Subset subset, boolean willSubrize)
throws InvalidFontException, UnsupportedFontException {
Type2CStringGenerator generator = new Type2CStringGenerator(subset.getNumGlyphs(), getNumFDs(), willSubrize);
Type2OutlineParser parser = new Type2OutlineParser(true);
for (int i = 0; i < subset.getNumGlyphs(); i++) {
int fullGid = subset.getFullGid(i);
int fd = getFDForGlyph(fullGid);
generator.newGlyph(i, fd, getDefaultWidthForFD(fd), getNominalWidthForFD(fd));
parser.parse(getCharStrings(), fullGid,
getLocalSubrsForFD(fd), globalSubrs,
generator, Matrix.IDENTITY_MATRIX,
(this instanceof NameKeyedFont)? (NameKeyedFont)this: null); }
return generator.getCharstringIndex();
}
//----------------------------------------------------------------------------
public CatalogDescription getSelectionDescription ()
throws InvalidFontException, UnsupportedFontException {
return null;
}
public SWFFont4Description getSWFFont4Description(boolean wasEmbedded) throws UnsupportedFontException, InvalidFontException {
return null;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy