diff --git a/gfx/thebes/gfxAndroidPlatform.h b/gfx/thebes/gfxAndroidPlatform.h index d33db9cbe51..b705404394b 100644 --- a/gfx/thebes/gfxAndroidPlatform.h +++ b/gfx/thebes/gfxAndroidPlatform.h @@ -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 { diff --git a/gfx/thebes/gfxFT2FontList.cpp b/gfx/thebes/gfxFT2FontList.cpp index ea4d1d71ceb..f6ba35364a5 100644 --- a/gfx/thebes/gfxFT2FontList.cpp +++ b/gfx/thebes/gfxFT2FontList.cpp @@ -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 +#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 #include #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(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(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 (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 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& 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* aFontList) +{ + for (int i = 0, n = mAvailableFonts.Length(); i < n; ++i) { + const FT2FontEntry *fe = + static_cast(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* fontlist = reinterpret_cast*>(aUserArg); - FontFamily *family = static_cast(aFamily.get()); + FT2FontFamily *family = static_cast(aFamily.get()); family->AddFacesToFontList(fontlist); return PL_DHASH_NEXT; @@ -723,7 +1048,7 @@ FindFullName(nsStringHashKey::KeyType aKey, gfxFontEntry* gfxFT2FontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry, - const nsAString& aFontName) + const nsAString& aFontName) { // walk over list of names FullFontNameSearch data(aFontName); @@ -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); } + diff --git a/gfx/thebes/gfxFT2FontList.h b/gfx/thebes/gfxFT2FontList.h index 1d15c0dc98d..7c083d01dd6 100644 --- a/gfx/thebes/gfxFT2FontList.h +++ b/gfx/thebes/gfxFT2FontList.h @@ -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& 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* aFontList); +}; class gfxFT2FontList : public gfxPlatformFontList { diff --git a/gfx/thebes/gfxFT2Fonts.cpp b/gfx/thebes/gfxFT2Fonts.cpp index ce7927e68d8..6f7c6b38697 100644 --- a/gfx/thebes/gfxFT2Fonts.cpp +++ b/gfx/thebes/gfxFT2Fonts.cpp @@ -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 -#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(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(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 (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 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& 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(FindFontForStyle(aFontStyle, needsBold)); -} - -void -FontFamily::AddFacesToFontList(InfallibleTArray* aFontList) -{ - for (int i = 0, n = mAvailableFonts.Length(); i < n; ++i) { - const FontEntry *fe = - static_cast(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 + FT2FontEntry *fe = static_cast (gfxPlatformFontList::PlatformFontList()-> FindFontForFamily(aName, aStyle, aNeedsBold)); #else - FontEntry *fe = static_cast + FT2FontEntry *fe = static_cast (gfxToolkitPlatform::GetPlatform()->FindFontEntry(aName, *aStyle)); #endif if (!fe) { @@ -899,11 +598,12 @@ gfxFT2Font::GetOrMakeFont(const nsAString& aName, const gfxFontStyle *aStyle, } already_AddRefed -gfxFT2Font::GetOrMakeFont(FontEntry *aFontEntry, const gfxFontStyle *aStyle, PRBool aNeedsBold) +gfxFT2Font::GetOrMakeFont(FT2FontEntry *aFontEntry, const gfxFontStyle *aStyle, + PRBool aNeedsBold) { nsRefPtr 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) diff --git a/gfx/thebes/gfxFT2Fonts.h b/gfx/thebes/gfxFT2Fonts.h index f4a02e1fcb8..7a6412fc1b2 100644 --- a/gfx/thebes/gfxFT2Fonts.h +++ b/gfx/thebes/gfxFT2Fonts.h @@ -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* 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& 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 GetOrMakeFont(const nsAString& aName, const gfxFontStyle *aStyle, PRBool aNeedsBold = PR_FALSE); static already_AddRefed - GetOrMakeFont(FontEntry *aFontEntry, const gfxFontStyle *aStyle, + GetOrMakeFont(FT2FontEntry *aFontEntry, const gfxFontStyle *aStyle, PRBool aNeedsBold = PR_FALSE); struct CachedGlyphData {