bug 684889 pt2 - move and rename FontFamily/Entry classes from gfxFT2Fonts to gfxFT2FontList source file. r=jdaggett

This commit is contained in:
Jonathan Kew 2011-09-23 12:16:13 +01:00
parent 1f9c88fc75
commit 4661532843
5 changed files with 426 additions and 406 deletions

View File

@ -44,6 +44,13 @@
#include "gfxUserFontSet.h"
#include "nsTArray.h"
namespace mozilla {
namespace dom {
class FontListEntry;
};
};
using mozilla::dom::FontListEntry;
typedef struct FT_LibraryRec_ *FT_Library;
class THEBES_API gfxAndroidPlatform : public gfxPlatform {

View File

@ -39,23 +39,39 @@
*
* ***** END LICENSE BLOCK ***** */
#ifdef ANDROID
#if defined(MOZ_WIDGET_GTK2)
#include "gfxPlatformGtk.h"
#define gfxToolkitPlatform gfxPlatformGtk
#elif defined(MOZ_WIDGET_QT)
#include <qfontinfo.h>
#include "gfxQtPlatform.h"
#define gfxToolkitPlatform gfxQtPlatform
#elif defined(XP_WIN)
#include "gfxWindowsPlatform.h"
#define gfxToolkitPlatform gfxWindowsPlatform
#elif defined(ANDROID)
#include "mozilla/dom/ContentChild.h"
#include "nsXULAppAPI.h"
#include "gfxAndroidPlatform.h"
#define gfxToolkitPlatform gfxAndroidPlatform
#endif
#ifdef ANDROID
#include "nsXULAppAPI.h"
#include <dirent.h>
#include <android/log.h>
#define ALOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gecko" , ## args)
#endif
#include "gfxFT2FontList.h"
#include "gfxUserFontSet.h"
#include "gfxFontUtils.h"
#include "ft2build.h"
#include FT_FREETYPE_H
#include FT_TRUETYPE_TAGS_H
#include FT_TRUETYPE_TABLES_H
#include "cairo-ft.h"
#include "gfxFT2FontList.h"
#include "gfxFT2Fonts.h"
#include "gfxUserFontSet.h"
#include "gfxFontUtils.h"
#include "nsServiceManagerUtils.h"
#include "nsTArray.h"
@ -78,6 +94,7 @@
static PRLogModuleInfo *gFontInfoLog = PR_NewLogModule("fontInfoLog");
#endif /* PR_LOGGING */
#undef LOG
#define LOG(args) PR_LOG(gFontInfoLog, PR_LOG_DEBUG, args)
#define LOG_ENABLED() PR_LOG_TEST(gFontInfoLog, PR_LOG_DEBUG)
@ -91,6 +108,318 @@ BuildKeyNameFromFontName(nsAString &aName)
ToLowerCase(aName);
}
/*
* FT2FontEntry
* gfxFontEntry subclass corresponding to a specific face that can be
* rendered by freetype. This is associated with a face index in a
* file (normally a .ttf/.otf file holding a single face, but in principle
* there could be .ttc files with multiple faces).
* The FT2FontEntry can create the necessary FT_Face on demand, and can
* then create a Cairo font_face and scaled_font for drawing.
*/
cairo_scaled_font_t *
FT2FontEntry::CreateScaledFont(const gfxFontStyle *aStyle)
{
cairo_scaled_font_t *scaledFont = NULL;
cairo_matrix_t sizeMatrix;
cairo_matrix_t identityMatrix;
// XXX deal with adjusted size
cairo_matrix_init_scale(&sizeMatrix, aStyle->size, aStyle->size);
cairo_matrix_init_identity(&identityMatrix);
// synthetic oblique by skewing via the font matrix
PRBool needsOblique = !IsItalic() &&
(aStyle->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE));
if (needsOblique) {
const double kSkewFactor = 0.25;
cairo_matrix_t style;
cairo_matrix_init(&style,
1, //xx
0, //yx
-1 * kSkewFactor, //xy
1, //yy
0, //x0
0); //y0
cairo_matrix_multiply(&sizeMatrix, &sizeMatrix, &style);
}
cairo_font_options_t *fontOptions = cairo_font_options_create();
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
cairo_font_options_set_hint_metrics(fontOptions, CAIRO_HINT_METRICS_OFF);
#endif
scaledFont = cairo_scaled_font_create(CairoFontFace(),
&sizeMatrix,
&identityMatrix, fontOptions);
cairo_font_options_destroy(fontOptions);
NS_ASSERTION(cairo_scaled_font_status(scaledFont) == CAIRO_STATUS_SUCCESS,
"Failed to make scaled font");
return scaledFont;
}
FT2FontEntry::~FT2FontEntry()
{
// Do nothing for mFTFace here since FTFontDestroyFunc is called by cairo.
mFTFace = nsnull;
#ifndef ANDROID
if (mFontFace) {
cairo_font_face_destroy(mFontFace);
mFontFace = nsnull;
}
#endif
}
gfxFont*
FT2FontEntry::CreateFontInstance(const gfxFontStyle *aFontStyle, PRBool aNeedsBold)
{
cairo_scaled_font_t *scaledFont = CreateScaledFont(aFontStyle);
gfxFont *font = new gfxFT2Font(scaledFont, this, aFontStyle, aNeedsBold);
cairo_scaled_font_destroy(scaledFont);
return font;
}
/* static */
FT2FontEntry*
FT2FontEntry::CreateFontEntry(const gfxProxyFontEntry &aProxyEntry,
const PRUint8 *aFontData,
PRUint32 aLength)
{
// Ownership of aFontData is passed in here; the fontEntry must
// retain it as long as the FT_Face needs it, and ensure it is
// eventually deleted.
FT_Face face;
FT_Error error =
FT_New_Memory_Face(gfxToolkitPlatform::GetPlatform()->GetFTLibrary(),
aFontData, aLength, 0, &face);
if (error != FT_Err_Ok) {
NS_Free((void*)aFontData);
return nsnull;
}
FT2FontEntry* fe = FT2FontEntry::CreateFontEntry(face, nsnull, 0, aFontData);
if (fe) {
fe->mItalic = aProxyEntry.mItalic;
fe->mWeight = aProxyEntry.mWeight;
fe->mStretch = aProxyEntry.mStretch;
}
return fe;
}
class FTUserFontData {
public:
FTUserFontData(FT_Face aFace, const PRUint8* aData)
: mFace(aFace), mFontData(aData)
{
}
~FTUserFontData()
{
FT_Done_Face(mFace);
if (mFontData) {
NS_Free((void*)mFontData);
}
}
private:
FT_Face mFace;
const PRUint8 *mFontData;
};
static void
FTFontDestroyFunc(void *data)
{
FTUserFontData *userFontData = static_cast<FTUserFontData*>(data);
delete userFontData;
}
/* static */
FT2FontEntry*
FT2FontEntry::CreateFontEntry(const FontListEntry& aFLE)
{
FT2FontEntry *fe = new FT2FontEntry(aFLE.faceName());
fe->mFilename = aFLE.filepath();
fe->mFTFontIndex = aFLE.index();
fe->mWeight = aFLE.weight();
fe->mStretch = aFLE.stretch();
fe->mItalic = aFLE.italic();
return fe;
}
/* static */
FT2FontEntry*
FT2FontEntry::CreateFontEntry(FT_Face aFace,
const char* aFilename, PRUint8 aIndex,
const PRUint8 *aFontData)
{
static cairo_user_data_key_t key;
if (!aFace->family_name) {
FT_Done_Face(aFace);
return nsnull;
}
// Construct font name from family name and style name, regular fonts
// do not have the modifier by convention.
NS_ConvertUTF8toUTF16 fontName(aFace->family_name);
if (aFace->style_name && strcmp("Regular", aFace->style_name)) {
fontName.AppendLiteral(" ");
AppendUTF8toUTF16(aFace->style_name, fontName);
}
FT2FontEntry *fe = new FT2FontEntry(fontName);
fe->mItalic = aFace->style_flags & FT_STYLE_FLAG_ITALIC;
fe->mFTFace = aFace;
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
fe->mFontFace = cairo_ft_font_face_create_for_ft_face(aFace, FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
#else
fe->mFontFace = cairo_ft_font_face_create_for_ft_face(aFace, 0);
#endif
fe->mFilename = aFilename;
fe->mFTFontIndex = aIndex;
FTUserFontData *userFontData = new FTUserFontData(aFace, aFontData);
cairo_font_face_set_user_data(fe->mFontFace, &key,
userFontData, FTFontDestroyFunc);
TT_OS2 *os2 = static_cast<TT_OS2*>(FT_Get_Sfnt_Table(aFace, ft_sfnt_os2));
PRUint16 os2weight = 0;
if (os2 && os2->version != 0xffff) {
// Technically, only 100 to 900 are valid, but some fonts
// have this set wrong -- e.g. "Microsoft Logo Bold Italic" has
// it set to 6 instead of 600. We try to be nice and handle that
// as well.
if (os2->usWeightClass >= 100 && os2->usWeightClass <= 900)
os2weight = os2->usWeightClass;
else if (os2->usWeightClass >= 1 && os2->usWeightClass <= 9)
os2weight = os2->usWeightClass * 100;
}
if (os2weight != 0)
fe->mWeight = os2weight;
else if (aFace->style_flags & FT_STYLE_FLAG_BOLD)
fe->mWeight = 700;
else
fe->mWeight = 400;
NS_ASSERTION(fe->mWeight >= 100 && fe->mWeight <= 900, "Invalid final weight in font!");
return fe;
}
FT2FontEntry*
gfxFT2Font::GetFontEntry()
{
return static_cast<FT2FontEntry*> (mFontEntry.get());
}
cairo_font_face_t *
FT2FontEntry::CairoFontFace()
{
static cairo_user_data_key_t key;
if (!mFontFace) {
FT_Face face;
FT_New_Face(gfxToolkitPlatform::GetPlatform()->GetFTLibrary(), mFilename.get(), mFTFontIndex, &face);
mFTFace = face;
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
mFontFace = cairo_ft_font_face_create_for_ft_face(face, FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
#else
mFontFace = cairo_ft_font_face_create_for_ft_face(face, 0);
#endif
FTUserFontData *userFontData = new FTUserFontData(face, nsnull);
cairo_font_face_set_user_data(mFontFace, &key,
userFontData, FTFontDestroyFunc);
}
return mFontFace;
}
nsresult
FT2FontEntry::ReadCMAP()
{
if (mCmapInitialized) {
return NS_OK;
}
// attempt this once, if errors occur leave a blank cmap
mCmapInitialized = PR_TRUE;
AutoFallibleTArray<PRUint8,16384> buffer;
nsresult rv = GetFontTable(TTAG_cmap, buffer);
if (NS_SUCCEEDED(rv)) {
PRPackedBool unicodeFont;
PRPackedBool symbolFont;
rv = gfxFontUtils::ReadCMAP(buffer.Elements(), buffer.Length(),
mCharacterMap, mUVSOffset,
unicodeFont, symbolFont);
}
mHasCmapTable = NS_SUCCEEDED(rv);
return rv;
}
nsresult
FT2FontEntry::GetFontTable(PRUint32 aTableTag,
FallibleTArray<PRUint8>& aBuffer)
{
// Ensure existence of mFTFace
CairoFontFace();
NS_ENSURE_TRUE(mFTFace, NS_ERROR_FAILURE);
FT_Error status;
FT_ULong len = 0;
status = FT_Load_Sfnt_Table(mFTFace, aTableTag, 0, nsnull, &len);
NS_ENSURE_TRUE(status == 0, NS_ERROR_FAILURE);
NS_ENSURE_TRUE(len != 0, NS_ERROR_FAILURE);
if (!aBuffer.SetLength(len)) {
return NS_ERROR_OUT_OF_MEMORY;
}
PRUint8 *buf = aBuffer.Elements();
status = FT_Load_Sfnt_Table(mFTFace, aTableTag, 0, buf, &len);
NS_ENSURE_TRUE(status == 0, NS_ERROR_FAILURE);
return NS_OK;
}
/*
* FT2FontFamily
* A standard gfxFontFamily; just adds a method used to support sending
* the font list from chrome to content via IPC.
*/
void
FT2FontFamily::AddFacesToFontList(InfallibleTArray<FontListEntry>* aFontList)
{
for (int i = 0, n = mAvailableFonts.Length(); i < n; ++i) {
const FT2FontEntry *fe =
static_cast<const FT2FontEntry*>(mAvailableFonts[i].get());
if (!fe) {
continue;
}
aFontList->AppendElement(FontListEntry(Name(), fe->Name(),
fe->mFilename,
fe->Weight(), fe->Stretch(),
fe->IsItalic(),
fe->mFTFontIndex));
}
}
/*
* Startup cache support for the font list:
* We store the list of families and faces, with their style attributes and the
* corresponding font files, in the startup cache.
* This allows us to recreate the gfxFT2FontList collection of families and
* faces without instantiating Freetype faces for each font file (in order to
* find their attributes), leading to significantly quicker startup.
*/
#define CACHE_KEY "font.cached-list"
class FontNameCache {
@ -309,11 +638,6 @@ private:
// For Mobile, we use gfxFT2Fonts, and we build the font list by directly
// scanning the system's Fonts directory for OpenType and TrueType files.
//
// FontEntry is currently defined in gfxFT2Fonts.h, but should probably be
// moved here for consistency with other platform implementations, and
// because it logically "belongs" to the fontlist that manages the families
// and entries.
gfxFT2FontList::gfxFT2FontList()
{
@ -368,7 +692,7 @@ gfxFT2FontList::AppendFacesFromCachedFaceList(nsCString& aFileName,
static void
AppendToFaceList(nsCString& aFaceList,
nsAString& aFamilyName, FontEntry* aFontEntry)
nsAString& aFamilyName, FT2FontEntry* aFontEntry)
{
aFaceList.Append(NS_ConvertUTF16toUTF8(aFamilyName));
aFaceList.Append(',');
@ -422,13 +746,14 @@ gfxFT2FontList::AppendFacesFromFontFile(nsCString& aFileName,
continue;
}
FontEntry* fe = FontEntry::CreateFontEntry(face, aFileName.get(), i);
FT2FontEntry* fe =
FT2FontEntry::CreateFontEntry(face, aFileName.get(), i);
if (fe) {
NS_ConvertUTF8toUTF16 name(face->family_name);
BuildKeyNameFromFontName(name);
gfxFontFamily *family = mFontFamilies.GetWeak(name);
if (!family) {
family = new gfxFontFamily(name);
family = new FT2FontFamily(name);
mFontFamilies.Put(name, family);
if (mBadUnderlineFamilyNames.Contains(name)) {
family->SetBadUnderlineFamily();
@ -632,13 +957,13 @@ void
gfxFT2FontList::AppendFaceFromFontListEntry(const FontListEntry& aFLE,
PRBool aStdFile)
{
FontEntry* fe = FontEntry::CreateFontEntry(aFLE);
FT2FontEntry* fe = FT2FontEntry::CreateFontEntry(aFLE);
if (fe) {
fe->mStandardFace = aStdFile;
nsAutoString name(aFLE.familyName());
gfxFontFamily *family = mFontFamilies.GetWeak(name);
if (!family) {
family = new gfxFontFamily(name);
family = new FT2FontFamily(name);
mFontFamilies.Put(name, family);
if (mBadUnderlineFamilyNames.Contains(name)) {
family->SetBadUnderlineFamily();
@ -659,7 +984,7 @@ AddFamilyToFontList(nsStringHashKey::KeyType aKey,
InfallibleTArray<FontListEntry>* fontlist =
reinterpret_cast<InfallibleTArray<FontListEntry>*>(aUserArg);
FontFamily *family = static_cast<FontFamily*>(aFamily.get());
FT2FontFamily *family = static_cast<FT2FontFamily*>(aFamily.get());
family->AddFacesToFontList(fontlist);
return PL_DHASH_NEXT;
@ -762,5 +1087,6 @@ gfxFT2FontList::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
// The FT2 font needs the font data to persist, so we do NOT free it here
// but instead pass ownership to the font entry.
// Deallocation will happen later, when the font face is destroyed.
return FontEntry::CreateFontEntry(*aProxyEntry, aFontData, aLength);
return FT2FontEntry::CreateFontEntry(*aProxyEntry, aFontData, aLength);
}

View File

@ -55,6 +55,69 @@ namespace mozilla {
using mozilla::dom::FontListEntry;
class FontNameCache;
typedef struct FT_FaceRec_* FT_Face;
class FT2FontEntry : public gfxFontEntry
{
public:
FT2FontEntry(const nsAString& aFaceName) :
gfxFontEntry(aFaceName)
{
mFTFace = nsnull;
mFontFace = nsnull;
mFTFontIndex = 0;
}
~FT2FontEntry();
const nsString& GetName() const {
return Name();
}
// create a font entry for a downloaded font
static FT2FontEntry*
CreateFontEntry(const gfxProxyFontEntry &aProxyEntry,
const PRUint8 *aFontData, PRUint32 aLength);
// create a font entry representing an installed font, identified by
// a FontListEntry; the freetype and cairo faces will not be instantiated
// until actually needed
static FT2FontEntry*
CreateFontEntry(const FontListEntry& aFLE);
// create a font entry for a given freetype face; if it is an installed font,
// also record the filename and index
static FT2FontEntry*
CreateFontEntry(FT_Face aFace, const char *aFilename, PRUint8 aIndex,
const PRUint8 *aFontData = nsnull);
// aFontData is NS_Malloc'ed data that aFace depends on, to be freed
// after the face is destroyed; null if there is no such buffer
virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle,
PRBool aNeedsBold);
cairo_font_face_t *CairoFontFace();
cairo_scaled_font_t *CreateScaledFont(const gfxFontStyle *aStyle);
nsresult ReadCMAP();
nsresult GetFontTable(PRUint32 aTableTag, FallibleTArray<PRUint8>& aBuffer);
FT_Face mFTFace;
cairo_font_face_t *mFontFace;
nsCString mFilename;
PRUint8 mFTFontIndex;
};
class FT2FontFamily : public gfxFontFamily
{
public:
FT2FontFamily(const nsAString& aName) :
gfxFontFamily(aName) { }
// Append this family's faces to the IPC fontlist
void AddFacesToFontList(InfallibleTArray<FontListEntry>* aFontList);
};
class gfxFT2FontList : public gfxPlatformFontList
{

View File

@ -45,7 +45,6 @@
#include "gfxWindowsPlatform.h"
#define gfxToolkitPlatform gfxWindowsPlatform
#elif defined(ANDROID)
#include "mozilla/dom/ContentChild.h"
#include "gfxAndroidPlatform.h"
#define gfxToolkitPlatform gfxAndroidPlatform
#endif
@ -56,10 +55,6 @@
#include "gfxFT2Utils.h"
#include "gfxFT2FontList.h"
#include <locale.h>
#include "cairo-ft.h"
#include FT_TRUETYPE_TAGS_H
#include FT_TRUETYPE_TABLES_H
#include "gfxFontUtils.h"
#include "gfxHarfBuzzShaper.h"
#include "gfxUnicodeProperties.h"
#include "gfxAtoms.h"
@ -82,302 +77,6 @@ static PRLogModuleInfo *gFontLog = PR_NewLogModule("ft2fonts");
#define CONVERT_DESIGN_UNITS_TO_PIXELS(v, s) \
MOZ_FT_TRUNC(MOZ_FT_ROUND(FT_MulFix((v) , (s))))
static cairo_scaled_font_t *
CreateScaledFont(FontEntry *aFontEntry, const gfxFontStyle *aStyle)
{
cairo_scaled_font_t *scaledFont = NULL;
cairo_matrix_t sizeMatrix;
cairo_matrix_t identityMatrix;
// XXX deal with adjusted size
cairo_matrix_init_scale(&sizeMatrix, aStyle->size, aStyle->size);
cairo_matrix_init_identity(&identityMatrix);
// synthetic oblique by skewing via the font matrix
PRBool needsOblique =
!aFontEntry->mItalic &&
(aStyle->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE));
if (needsOblique) {
const double kSkewFactor = 0.25;
cairo_matrix_t style;
cairo_matrix_init(&style,
1, //xx
0, //yx
-1 * kSkewFactor, //xy
1, //yy
0, //x0
0); //y0
cairo_matrix_multiply(&sizeMatrix, &sizeMatrix, &style);
}
cairo_font_options_t *fontOptions = cairo_font_options_create();
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
cairo_font_options_set_hint_metrics(fontOptions, CAIRO_HINT_METRICS_OFF);
#endif
scaledFont = cairo_scaled_font_create(aFontEntry->CairoFontFace(),
&sizeMatrix,
&identityMatrix, fontOptions);
cairo_font_options_destroy(fontOptions);
NS_ASSERTION(cairo_scaled_font_status(scaledFont) == CAIRO_STATUS_SUCCESS,
"Failed to make scaled font");
return scaledFont;
}
/**
* FontEntry
*/
FontEntry::~FontEntry()
{
// Do nothing for mFTFace here since FTFontDestroyFunc is called by cairo.
mFTFace = nsnull;
#ifndef ANDROID
if (mFontFace) {
cairo_font_face_destroy(mFontFace);
mFontFace = nsnull;
}
#endif
}
gfxFont*
FontEntry::CreateFontInstance(const gfxFontStyle *aFontStyle, PRBool aNeedsBold)
{
cairo_scaled_font_t *scaledFont = CreateScaledFont(this, aFontStyle);
gfxFont *font = new gfxFT2Font(scaledFont, this, aFontStyle, aNeedsBold);
cairo_scaled_font_destroy(scaledFont);
return font;
}
/* static */
FontEntry*
FontEntry::CreateFontEntry(const gfxProxyFontEntry &aProxyEntry,
const PRUint8 *aFontData,
PRUint32 aLength)
{
// Ownership of aFontData is passed in here; the fontEntry must
// retain it as long as the FT_Face needs it, and ensure it is
// eventually deleted.
FT_Face face;
FT_Error error =
FT_New_Memory_Face(gfxToolkitPlatform::GetPlatform()->GetFTLibrary(),
aFontData, aLength, 0, &face);
if (error != FT_Err_Ok) {
NS_Free((void*)aFontData);
return nsnull;
}
FontEntry* fe = FontEntry::CreateFontEntry(face, nsnull, 0, aFontData);
if (fe) {
fe->mItalic = aProxyEntry.mItalic;
fe->mWeight = aProxyEntry.mWeight;
fe->mStretch = aProxyEntry.mStretch;
}
return fe;
}
class FTUserFontData {
public:
FTUserFontData(FT_Face aFace, const PRUint8* aData)
: mFace(aFace), mFontData(aData)
{
}
~FTUserFontData()
{
FT_Done_Face(mFace);
if (mFontData) {
NS_Free((void*)mFontData);
}
}
private:
FT_Face mFace;
const PRUint8 *mFontData;
};
static void
FTFontDestroyFunc(void *data)
{
FTUserFontData *userFontData = static_cast<FTUserFontData*>(data);
delete userFontData;
}
/* static */ FontEntry*
FontEntry::CreateFontEntry(const FontListEntry& aFLE)
{
FontEntry *fe = new FontEntry(aFLE.faceName());
fe->mFilename = aFLE.filepath();
fe->mFTFontIndex = aFLE.index();
fe->mWeight = aFLE.weight();
fe->mStretch = aFLE.stretch();
fe->mItalic = aFLE.italic();
return fe;
}
/* static */ FontEntry*
FontEntry::CreateFontEntry(FT_Face aFace,
const char* aFilename, PRUint8 aIndex,
const PRUint8 *aFontData)
{
static cairo_user_data_key_t key;
if (!aFace->family_name) {
FT_Done_Face(aFace);
return nsnull;
}
// Construct font name from family name and style name, regular fonts
// do not have the modifier by convention.
NS_ConvertUTF8toUTF16 fontName(aFace->family_name);
if (aFace->style_name && strcmp("Regular", aFace->style_name)) {
fontName.AppendLiteral(" ");
AppendUTF8toUTF16(aFace->style_name, fontName);
}
FontEntry *fe = new FontEntry(fontName);
fe->mItalic = aFace->style_flags & FT_STYLE_FLAG_ITALIC;
fe->mFTFace = aFace;
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
fe->mFontFace = cairo_ft_font_face_create_for_ft_face(aFace, FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
#else
fe->mFontFace = cairo_ft_font_face_create_for_ft_face(aFace, 0);
#endif
fe->mFilename = aFilename;
fe->mFTFontIndex = aIndex;
FTUserFontData *userFontData = new FTUserFontData(aFace, aFontData);
cairo_font_face_set_user_data(fe->mFontFace, &key,
userFontData, FTFontDestroyFunc);
TT_OS2 *os2 = static_cast<TT_OS2*>(FT_Get_Sfnt_Table(aFace, ft_sfnt_os2));
PRUint16 os2weight = 0;
if (os2 && os2->version != 0xffff) {
// Technically, only 100 to 900 are valid, but some fonts
// have this set wrong -- e.g. "Microsoft Logo Bold Italic" has
// it set to 6 instead of 600. We try to be nice and handle that
// as well.
if (os2->usWeightClass >= 100 && os2->usWeightClass <= 900)
os2weight = os2->usWeightClass;
else if (os2->usWeightClass >= 1 && os2->usWeightClass <= 9)
os2weight = os2->usWeightClass * 100;
}
if (os2weight != 0)
fe->mWeight = os2weight;
else if (aFace->style_flags & FT_STYLE_FLAG_BOLD)
fe->mWeight = 700;
else
fe->mWeight = 400;
NS_ASSERTION(fe->mWeight >= 100 && fe->mWeight <= 900, "Invalid final weight in font!");
return fe;
}
FontEntry*
gfxFT2Font::GetFontEntry()
{
return static_cast<FontEntry*> (mFontEntry.get());
}
cairo_font_face_t *
FontEntry::CairoFontFace()
{
static cairo_user_data_key_t key;
if (!mFontFace) {
FT_Face face;
FT_New_Face(gfxToolkitPlatform::GetPlatform()->GetFTLibrary(), mFilename.get(), mFTFontIndex, &face);
mFTFace = face;
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
mFontFace = cairo_ft_font_face_create_for_ft_face(face, FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
#else
mFontFace = cairo_ft_font_face_create_for_ft_face(face, 0);
#endif
FTUserFontData *userFontData = new FTUserFontData(face, nsnull);
cairo_font_face_set_user_data(mFontFace, &key,
userFontData, FTFontDestroyFunc);
}
return mFontFace;
}
nsresult
FontEntry::ReadCMAP()
{
if (mCmapInitialized) {
return NS_OK;
}
// attempt this once, if errors occur leave a blank cmap
mCmapInitialized = PR_TRUE;
AutoFallibleTArray<PRUint8,16384> buffer;
nsresult rv = GetFontTable(TTAG_cmap, buffer);
if (NS_SUCCEEDED(rv)) {
PRPackedBool unicodeFont;
PRPackedBool symbolFont;
rv = gfxFontUtils::ReadCMAP(buffer.Elements(), buffer.Length(),
mCharacterMap, mUVSOffset,
unicodeFont, symbolFont);
}
mHasCmapTable = NS_SUCCEEDED(rv);
return rv;
}
nsresult
FontEntry::GetFontTable(PRUint32 aTableTag, FallibleTArray<PRUint8>& aBuffer)
{
// Ensure existence of mFTFace
CairoFontFace();
NS_ENSURE_TRUE(mFTFace, NS_ERROR_FAILURE);
FT_Error status;
FT_ULong len = 0;
status = FT_Load_Sfnt_Table(mFTFace, aTableTag, 0, nsnull, &len);
NS_ENSURE_TRUE(status == 0, NS_ERROR_FAILURE);
NS_ENSURE_TRUE(len != 0, NS_ERROR_FAILURE);
if (!aBuffer.SetLength(len)) {
return NS_ERROR_OUT_OF_MEMORY;
}
PRUint8 *buf = aBuffer.Elements();
status = FT_Load_Sfnt_Table(mFTFace, aTableTag, 0, buf, &len);
NS_ENSURE_TRUE(status == 0, NS_ERROR_FAILURE);
return NS_OK;
}
FontEntry *
FontFamily::FindFontEntry(const gfxFontStyle& aFontStyle)
{
PRBool needsBold = PR_FALSE;
return static_cast<FontEntry*>(FindFontForStyle(aFontStyle, needsBold));
}
void
FontFamily::AddFacesToFontList(InfallibleTArray<FontListEntry>* aFontList)
{
for (int i = 0, n = mAvailableFonts.Length(); i < n; ++i) {
const FontEntry *fe =
static_cast<const FontEntry*>(mAvailableFonts[i].get());
if (!fe) {
continue;
}
aFontList->AppendElement(FontListEntry(Name(), fe->Name(),
fe->mFilename,
fe->Weight(), fe->Stretch(),
fe->IsItalic(),
fe->mFTFontIndex));
}
}
#ifndef ANDROID // not needed on Android, we use the generic gfxFontGroup
/**
* gfxFT2FontGroup
@ -852,7 +551,7 @@ gfxFT2Font::AddRange(gfxTextRun *aTextRun, const PRUnichar *str, PRUint32 offset
}
gfxFT2Font::gfxFT2Font(cairo_scaled_font_t *aCairoFont,
FontEntry *aFontEntry,
FT2FontEntry *aFontEntry,
const gfxFontStyle *aFontStyle,
PRBool aNeedsBold)
: gfxFT2FontBase(aCairoFont, aFontEntry, aFontStyle)
@ -882,11 +581,11 @@ gfxFT2Font::GetOrMakeFont(const nsAString& aName, const gfxFontStyle *aStyle,
PRBool aNeedsBold)
{
#ifdef ANDROID
FontEntry *fe = static_cast<FontEntry*>
FT2FontEntry *fe = static_cast<FT2FontEntry*>
(gfxPlatformFontList::PlatformFontList()->
FindFontForFamily(aName, aStyle, aNeedsBold));
#else
FontEntry *fe = static_cast<FontEntry*>
FT2FontEntry *fe = static_cast<FT2FontEntry*>
(gfxToolkitPlatform::GetPlatform()->FindFontEntry(aName, *aStyle));
#endif
if (!fe) {
@ -899,11 +598,12 @@ gfxFT2Font::GetOrMakeFont(const nsAString& aName, const gfxFontStyle *aStyle,
}
already_AddRefed<gfxFT2Font>
gfxFT2Font::GetOrMakeFont(FontEntry *aFontEntry, const gfxFontStyle *aStyle, PRBool aNeedsBold)
gfxFT2Font::GetOrMakeFont(FT2FontEntry *aFontEntry, const gfxFontStyle *aStyle,
PRBool aNeedsBold)
{
nsRefPtr<gfxFont> font = gfxFontCache::GetCache()->Lookup(aFontEntry, aStyle);
if (!font) {
cairo_scaled_font_t *scaledFont = CreateScaledFont(aFontEntry, aStyle);
cairo_scaled_font_t *scaledFont = aFontEntry->CreateScaledFont(aStyle);
font = new gfxFT2Font(scaledFont, aFontEntry, aStyle, aNeedsBold);
cairo_scaled_font_destroy(scaledFont);
if (!font)

View File

@ -47,102 +47,26 @@
#include "gfxFontUtils.h"
#include "gfxUserFontSet.h"
namespace mozilla {
namespace dom {
class FontListEntry;
};
};
using mozilla::dom::FontListEntry;
typedef struct FT_FaceRec_* FT_Face;
/**
* FontFamily is a class that describes one of the fonts on the users system. It holds
* each FontEntry (maps more directly to a font face) which holds font type, charset info
* and character map info.
*/
class FontEntry;
class FontFamily : public gfxFontFamily
{
public:
FontFamily(const nsAString& aName) :
gfxFontFamily(aName) { }
FontEntry *FindFontEntry(const gfxFontStyle& aFontStyle);
// Append this family's faces to the IPC fontlist
void AddFacesToFontList(InfallibleTArray<FontListEntry>* aFontList);
};
class FontEntry : public gfxFontEntry
{
public:
FontEntry(const nsAString& aFaceName) :
gfxFontEntry(aFaceName)
{
mFTFace = nsnull;
mFontFace = nsnull;
mFTFontIndex = 0;
}
~FontEntry();
const nsString& GetName() const {
return Name();
}
// create a font entry for a downloaded font
static FontEntry*
CreateFontEntry(const gfxProxyFontEntry &aProxyEntry,
const PRUint8 *aFontData, PRUint32 aLength);
// create a font entry representing an installed font, identified by
// a FontListEntry; the freetype and cairo faces will not be instantiated
// until actually needed
static FontEntry*
CreateFontEntry(const FontListEntry& aFLE);
// create a font entry for a given freetype face; if it is an installed font,
// also record the filename and index
static FontEntry*
CreateFontEntry(FT_Face aFace, const char *aFilename, PRUint8 aIndex,
const PRUint8 *aFontData = nsnull);
// aFontData is NS_Malloc'ed data that aFace depends on, to be freed
// after the face is destroyed; null if there is no such buffer
virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, PRBool aNeedsBold);
cairo_font_face_t *CairoFontFace();
nsresult ReadCMAP();
nsresult GetFontTable(PRUint32 aTableTag, FallibleTArray<PRUint8>& aBuffer);
FT_Face mFTFace;
cairo_font_face_t *mFontFace;
nsCString mFilename;
PRUint8 mFTFontIndex;
};
class FT2FontEntry;
class gfxFT2Font : public gfxFT2FontBase {
public: // new functions
gfxFT2Font(cairo_scaled_font_t *aCairoFont,
FontEntry *aFontEntry,
FT2FontEntry *aFontEntry,
const gfxFontStyle *aFontStyle,
PRBool aNeedsBold);
virtual ~gfxFT2Font ();
cairo_font_face_t *CairoFontFace();
FontEntry *GetFontEntry();
FT2FontEntry *GetFontEntry();
static already_AddRefed<gfxFT2Font>
GetOrMakeFont(const nsAString& aName, const gfxFontStyle *aStyle,
PRBool aNeedsBold = PR_FALSE);
static already_AddRefed<gfxFT2Font>
GetOrMakeFont(FontEntry *aFontEntry, const gfxFontStyle *aStyle,
GetOrMakeFont(FT2FontEntry *aFontEntry, const gfxFontStyle *aStyle,
PRBool aNeedsBold = PR_FALSE);
struct CachedGlyphData {