com.adobe.fontengine.font.mac.FontFactory 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
The newest version!
/**
*
*/
package com.adobe.fontengine.font.mac;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.adobe.agl.util.ULocale;
import com.adobe.fontengine.font.Font;
import com.adobe.fontengine.font.FontData;
import com.adobe.fontengine.font.FontImpl;
import com.adobe.fontengine.font.FontLoadingException;
import com.adobe.fontengine.font.InvalidFontException;
import com.adobe.fontengine.font.UnsupportedFontException;
import com.adobe.fontengine.font.mac.FONDResourceHandler.Association;
import com.adobe.fontengine.font.mac.sfntResourceHandler.SfntResource;
import com.adobe.fontengine.fontmanagement.ResourceFont;
import com.adobe.internal.io.ExtendedDataInputStream;
import com.adobe.internal.mac.resource.ResourceParser;
/**
* Factory for building Mac resource fonts from data or resource fork type resources.
*
*/
public class FontFactory
{
private static final String RESOURCE_FORK_EXTENSION = "/..namedfork/rsrc";
private static final String DFONT_SUFFIX = ".dfont";
public static final int UNKNOWN = 0;
public static final int RESOURCE_FORK_FONT = 1;
public static final int DATA_FORK_FONT = 2;
/**
* @param url this is the full URL including any resource fork information
* @param type is this a data or resource fork
* @param fontID the id of the font within the resource
* @param fondID the id of the FOND resource which describes this font
* @return a FontData loaded from the URL given
* @throws InvalidFontException
* @throws UnsupportedFontException
* @throws FontLoadingException
*/
public static FontData load(URL url, int type, int fontID, int fondID)
throws InvalidFontException, UnsupportedFontException, FontLoadingException
{
FontData rsrcFontData = null;
ResourceParser parser = new ResourceParser();
FONDResourceHandler handlerFOND = new FONDResourceHandler();
versResourceHandler handlervers = new versResourceHandler();
sfntResourceHandler handlersfnt = new sfntResourceHandler(fontID);
parser.addHandler(handlerFOND);
parser.addHandler(handlervers);
parser.addHandler(handlersfnt);
try {
parser.setURL(url);
parser.parse();
} catch (IOException e) {
throw new FontLoadingException(e);
}
Map sfntMap = handlersfnt.getResources();
Set associationSet = handlerFOND.getAssociations();
for (Association association : associationSet)
{
if (fondID == association.getFondID() && (fontID == association.getFontID()))
{
SfntResource resource = sfntMap.get(fontID);
if (resource != null)
{
Font font = resource.getFont();
if (font != null)
{
rsrcFontData = new ResourceFontData(
((FontImpl) font).getFontData(), scriptCodeToCharset(resource.getScriptCode()),
association.getName(), resource.getName(), association.isBold(), association.isItalic());
break;
}
}
}
}
return rsrcFontData;
}
/**
* @param url the base URL of the font not including any possible resource fork information
* @param type the type of the resource - data or resource fork
* @return all available fonts from this resource that are of a type understood
* @throws InvalidFontException
* @throws UnsupportedFontException
* @throws FontLoadingException
*/
public static ResourceFont[] load(URL url, int type)
throws InvalidFontException, UnsupportedFontException, FontLoadingException
{
ResourceParser parser = new ResourceParser();
FONDResourceHandler handlerFOND = new FONDResourceHandler();
versResourceHandler handlervers = new versResourceHandler();
sfntResourceHandler handlersfnt = new sfntResourceHandler();
parser.addHandler(handlerFOND);
parser.addHandler(handlervers);
parser.addHandler(handlersfnt);
try {
if (type == RESOURCE_FORK_FONT)
{
url = new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getFile() + RESOURCE_FORK_EXTENSION);
}
parser.setURL(url);
parser.parse();
} catch (IOException e) {
throw new FontLoadingException(e);
}
Map sfntMap = handlersfnt.getResources();
Set associationSet = handlerFOND.getAssociations();
List fonts = new ArrayList();
for (Association association : associationSet)
{
int sfntID = association.getFontID();
SfntResource resource = sfntMap.get(sfntID);
if (resource != null)
{
Font font = resource.getFont();
if (font != null)
{
FontData rsrcFontData = new ResourceFontData(
((FontImpl) font).getFontData(), scriptCodeToCharset(resource.getScriptCode()),
association.getName(), resource.getName(), association.isBold(), association.isItalic());
Font rsrcFont = new ResourceFont(url, type, sfntID, association.getFondID(), rsrcFontData);
fonts.add(rsrcFont);
}
}
}
ResourceFont[] a = new ResourceFont [fonts.size()];
return fonts.toArray(a);
}
public static int getNumBytesNeededToIdentify()
{
// this is the resource file header length
// we can tell if it's not a resource file in that length
// but we can't reliably tell if it is
// combined with the url name though it's a good guess
return 16;
}
public static int isResourceFont(byte[] bytes, URL url)
throws IOException
{
InputStream rsrcStream = null;
int streamType = UNKNOWN;
try
{
rsrcStream = getDataResourceFontStream(url);
if (rsrcStream != null)
{
streamType = DATA_FORK_FONT;
} else {
rsrcStream = getResourceStream(url);
if (rsrcStream != null)
{
streamType = RESOURCE_FORK_FONT;
}
}
if (rsrcStream == null)
{
return UNKNOWN;
}
long dataOffset;
long mapOffset;
long dataLength;
long mapLength;
try {
ExtendedDataInputStream dis = new ExtendedDataInputStream(rsrcStream);
dataOffset = dis.readUnsignedInt();
mapOffset = dis.readUnsignedInt();
dataLength = dis.readUnsignedInt();
mapLength = dis.readUnsignedInt();
} catch (Exception e) {
return UNKNOWN;
}
if (((mapOffset > dataOffset) && (mapOffset < (dataOffset + dataLength)))
|| ((dataOffset > mapOffset) && (dataOffset < (mapOffset + mapLength))))
{
return UNKNOWN;
}
return streamType;
} finally {
if (rsrcStream != null)
{
rsrcStream.close();
}
}
}
private static InputStream getResourceStream(URL url) throws IOException
{
URL rsrcURL = new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getFile() + RESOURCE_FORK_EXTENSION);
InputStream rsrcStream = null;
try {
rsrcStream = rsrcURL.openStream();
} catch (FileNotFoundException e) {
// ignore this - it means that there is no resource fork
}
return rsrcStream;
}
private static InputStream getDataResourceFontStream(URL url)
throws IOException
{
InputStream rsrcStream = null;
String file = url.getFile();
if (file.endsWith(DFONT_SUFFIX))
{
rsrcStream = url.openStream();
}
return rsrcStream;
}
// TODO - this needs to move to the Rideau ScriptUtility class
// but that means that Rideau will require ULocale and ScriptUtility will need to be made public
private static final String[] SCRIPTID_TO_ULOCALE =
{
"en", //smRoman 0 Roman -> English
"ja", //smJapanese 1 Japanese -> Japanese
"zh-Hant", //smTradChinese 2 Traditional Chinese
"ko", //smKorean 3 Korean -> Korean
"ar", //smArabic 4 Arabic -> Arabic
"he", //smHebrew 5 Hebrew -> Hebrew
"el", //smGreek 6 Greek -> Greek
"ru", //smCyrillic 7 Cyrillic -> Russian
"MacSymbol", //smRSymbol 8 Right-to-left symbols
"hi", //smDevanagari 9 Devanagari -> Hindi
"pa", //smGurmukhi 10 Gurmukhi -> Punjabi
"gu", //smGujarati 11 Gujarati -> Gujarati
null, //smOriya 12 Oriya
null, //smBengali 13 Bengali
null, //smTamil 14 Tamil
null, //smTelugu 15 Telugu
null, //smKannada 16 Kannada/Kanarese
null, //smMalayalam 17 Malayalam
null, //smSinhalese 18 Sinhalese
null, //smBurmese 19 Burmese
null, //smKhmer 20 Khmer
"th", //smThai 21 Thai -> Thai
null, //smLaotian 22 Laotian
null, //smGeorgian 23 Georgian
null, //smArmenian 24 Armenian
"zh-Hans", //smSimpChinese 25 Simplified Chinese
null, //smTibetan 26 Tibetan
null, //smMongolian 27 Mongolian
null, //smEthiopic 28 = smGeez and smGeez 28 Geez/Ethiopic
"MacCentralEuropean", //smEastEurRoman 29 Extended Roman for Slavic and Baltic languages
null, //smVietnamese 30 Extended Roman for Vietnamese
null, //smExtArabic 31 Extended Arabic for Sindhi
null, //smUninterp 32 Uninterpreted symbols
};
static final ULocale scriptCodeToCharset(int script)
{
script = Math.min(script, SCRIPTID_TO_ULOCALE.length - 1);
String locale = SCRIPTID_TO_ULOCALE[script];
if (locale == null)
{
locale = SCRIPTID_TO_ULOCALE[0];
}
return new ULocale(locale);
}
}