Backed out changeset 8284007baae4 (bug 878674) for Android startup java exceptions

This commit is contained in:
Ed Morley 2013-06-25 11:26:00 +01:00
parent b068dae3e8
commit 3b7e3a0a84
8 changed files with 247 additions and 349 deletions

View File

@ -52,7 +52,6 @@
#include "nsAppDirectoryServiceDefs.h"
#include "nsISimpleEnumerator.h"
#include "mozilla/Preferences.h"
#include "mozilla/scache/StartupCache.h"
#include <sys/stat.h>
@ -78,8 +77,6 @@ GetFontInfoLog()
#define LOG(args) PR_LOG(GetFontInfoLog(), PR_LOG_DEBUG, args)
#define LOG_ENABLED() PR_LOG_TEST(GetFontInfoLog(), PR_LOG_DEBUG)
static cairo_user_data_key_t sFTUserFontDataKey;
static __inline void
BuildKeyNameFromFontName(nsAString &aName)
{
@ -95,89 +92,45 @@ BuildKeyNameFromFontName(nsAString &aName)
// This allows us to read font names, tables, etc if necessary
// without permanently instantiating a freetype face and consuming
// memory long-term.
// This may fail (resulting in a null FT_Face), e.g. if it fails to
// allocate memory to uncompress a font from omnijar.
class AutoFTFace {
public:
AutoFTFace(FT2FontEntry* aFontEntry)
: mFace(nullptr), mFontDataBuf(nullptr), mOwnsFace(false)
: mFace(nullptr), mOwnsFace(false)
{
if (aFontEntry->mFTFace) {
mFace = aFontEntry->mFTFace;
return;
}
NS_ASSERTION(!aFontEntry->mFilename.IsEmpty(),
"can't use AutoFTFace for fonts without a filename");
FT_Library ft = gfxToolkitPlatform::GetPlatform()->GetFTLibrary();
// A relative path (no initial "/") means this is a resource in
// omnijar, not an installed font on the device.
// The NS_ASSERTIONs here should never fail, as the resource must have
// been read successfully during font-list initialization or we'd never
// have created the font entry. The only legitimate runtime failure
// here would be memory allocation, in which case mFace remains null.
if (aFontEntry->mFilename[0] != '/') {
nsRefPtr<nsZipArchive> reader =
Omnijar::GetReader(Omnijar::Type::GRE);
nsZipItem *item = reader->GetItem(aFontEntry->mFilename.get());
NS_ASSERTION(item, "failed to find zip entry");
uint32_t bufSize = item->RealSize();
mFontDataBuf = static_cast<uint8_t*>(moz_malloc(bufSize));
if (mFontDataBuf) {
nsZipCursor cursor(item, reader, mFontDataBuf, bufSize);
cursor.Copy(&bufSize);
NS_ASSERTION(bufSize == item->RealSize(),
"error reading bundled font");
if (FT_Err_Ok != FT_New_Memory_Face(ft, mFontDataBuf, bufSize,
aFontEntry->mFTFontIndex,
&mFace)) {
NS_WARNING("failed to create freetype face");
}
}
} else {
NS_ASSERTION(!aFontEntry->mFilename.IsEmpty(),
"can't use AutoFTFace for fonts without a filename");
FT_Library ft = gfxToolkitPlatform::GetPlatform()->GetFTLibrary();
if (FT_Err_Ok != FT_New_Face(ft, aFontEntry->mFilename.get(),
aFontEntry->mFTFontIndex, &mFace)) {
NS_WARNING("failed to create freetype face");
}
if (FT_Err_Ok != FT_Select_Charmap(mFace, FT_ENCODING_UNICODE)) {
NS_WARNING("failed to select Unicode charmap");
}
mOwnsFace = true;
}
if (FT_Err_Ok != FT_Select_Charmap(mFace, FT_ENCODING_UNICODE)) {
NS_WARNING("failed to select Unicode charmap");
}
mOwnsFace = true;
}
~AutoFTFace() {
if (mFace && mOwnsFace) {
FT_Done_Face(mFace);
if (mFontDataBuf) {
moz_free(mFontDataBuf);
}
}
}
operator FT_Face() { return mFace; }
// If we 'forget' the FT_Face (used when ownership is handed over to Cairo),
// we do -not- free the mFontDataBuf (if used); that also becomes the
// responsibility of the new owner of the face.
FT_Face forget() {
NS_ASSERTION(mOwnsFace, "can't forget() when we didn't own the face");
mOwnsFace = false;
return mFace;
}
const uint8_t* FontData() const { return mFontDataBuf; }
private:
FT_Face mFace;
uint8_t* mFontDataBuf; // Uncompressed data (for fonts stored in a JAR),
// or null for fonts instantiated from a file.
// If non-null, this must survive as long as the
// FT_Face.
bool mOwnsFace;
FT_Face mFace;
bool mOwnsFace;
};
/*
@ -193,12 +146,7 @@ private:
cairo_scaled_font_t *
FT2FontEntry::CreateScaledFont(const gfxFontStyle *aStyle)
{
cairo_font_face_t *cairoFace = CairoFontFace();
if (!cairoFace) {
return nullptr;
}
cairo_scaled_font_t *scaledFont = nullptr;
cairo_scaled_font_t *scaledFont = NULL;
cairo_matrix_t sizeMatrix;
cairo_matrix_t identityMatrix;
@ -231,7 +179,7 @@ FT2FontEntry::CreateScaledFont(const gfxFontStyle *aStyle)
cairo_font_options_set_hint_metrics(fontOptions, CAIRO_HINT_METRICS_OFF);
}
scaledFont = cairo_scaled_font_create(cairoFace,
scaledFont = cairo_scaled_font_create(CairoFontFace(),
&sizeMatrix,
&identityMatrix, fontOptions);
cairo_font_options_destroy(fontOptions);
@ -259,9 +207,6 @@ gfxFont*
FT2FontEntry::CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold)
{
cairo_scaled_font_t *scaledFont = CreateScaledFont(aFontStyle);
if (!scaledFont) {
return nullptr;
}
gfxFont *font = new gfxFT2Font(scaledFont, this, aFontStyle, aNeedsBold);
cairo_scaled_font_destroy(scaledFont);
return font;
@ -318,8 +263,6 @@ public:
}
}
const uint8_t *FontData() const { return mFontData; }
private:
FT_Face mFace;
const uint8_t *mFontData;
@ -397,6 +340,8 @@ FT2FontEntry::CreateFontEntry(FT_Face aFace,
const nsAString& aName,
const uint8_t *aFontData)
{
static cairo_user_data_key_t key;
FT2FontEntry *fe = new FT2FontEntry(aName);
fe->mItalic = FTFaceIsItalic(aFace);
fe->mWeight = FTFaceGetWeight(aFace);
@ -410,7 +355,7 @@ FT2FontEntry::CreateFontEntry(FT_Face aFace,
(FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
fe->mFontFace = cairo_ft_font_face_create_for_ft_face(aFace, flags);
FTUserFontData *userFontData = new FTUserFontData(aFace, aFontData);
cairo_font_face_set_user_data(fe->mFontFace, &sFTUserFontDataKey,
cairo_font_face_set_user_data(fe->mFontFace, &key,
userFontData, FTFontDestroyFunc);
}
@ -443,6 +388,8 @@ gfxFT2Font::GetFontEntry()
cairo_font_face_t *
FT2FontEntry::CairoFontFace()
{
static cairo_user_data_key_t key;
if (!mFontFace) {
AutoFTFace face(this);
if (!face) {
@ -453,8 +400,8 @@ FT2FontEntry::CairoFontFace()
FT_LOAD_DEFAULT :
(FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
mFontFace = cairo_ft_font_face_create_for_ft_face(face, flags);
FTUserFontData *userFontData = new FTUserFontData(face, face.FontData());
cairo_font_face_set_user_data(mFontFace, &sFTUserFontDataKey,
FTUserFontData *userFontData = new FTUserFontData(face, nullptr);
cairo_font_face_set_user_data(mFontFace, &key,
userFontData, FTFontDestroyFunc);
}
return mFontFace;
@ -517,24 +464,6 @@ FT2FontEntry::CopyFontTable(uint32_t aTableTag,
return NS_OK;
}
hb_blob_t*
FT2FontEntry::GetFontTable(uint32_t aTableTag)
{
if (mFontFace) {
// if there's a cairo font face, we may be able to return a blob
// that just wraps a range of the attached user font data
FTUserFontData *userFontData = static_cast<FTUserFontData*>(
cairo_font_face_get_user_data(mFontFace, &sFTUserFontDataKey));
if (userFontData && userFontData->FontData()) {
return GetTableFromFontData(userFontData->FontData(), aTableTag);
}
}
// otherwise, use the default method (which in turn will call our
// implementation of CopyFontTable)
return gfxFontEntry::GetFontTable(aTableTag);
}
void
FT2FontEntry::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
FontListSizes* aSizes) const
@ -688,7 +617,7 @@ public:
}
virtual void
GetInfoForFile(const nsCString& aFileName, nsCString& aFaceList,
GetInfoForFile(nsCString& aFileName, nsCString& aFaceList,
uint32_t *aTimestamp, uint32_t *aFilesize)
{
if (!mMap.ops) {
@ -700,7 +629,7 @@ public:
return;
}
FNCMapEntry* entry = static_cast<FNCMapEntry*>(hdr);
if (entry && entry->mFilesize) {
if (entry && entry->mTimestamp && entry->mFilesize) {
*aTimestamp = entry->mTimestamp;
*aFilesize = entry->mFilesize;
aFaceList.Assign(entry->mFaces);
@ -712,7 +641,7 @@ public:
}
virtual void
CacheFileInfo(const nsCString& aFileName, const nsCString& aFaceList,
CacheFileInfo(nsCString& aFileName, nsCString& aFaceList,
uint32_t aTimestamp, uint32_t aFilesize)
{
if (!mMap.ops) {
@ -809,9 +738,9 @@ gfxFT2FontList::gfxFT2FontList()
}
void
gfxFT2FontList::AppendFacesFromCachedFaceList(const nsCString& aFileName,
gfxFT2FontList::AppendFacesFromCachedFaceList(nsCString& aFileName,
bool aStdFile,
const nsCString& aFaceList)
nsCString& aFaceList)
{
const char *beginning = aFaceList.get();
const char *end = strchr(beginning, ',');
@ -904,7 +833,7 @@ FT2FontEntry::CheckForBrokenFont(gfxFontFamily *aFamily)
}
void
gfxFT2FontList::AppendFacesFromFontFile(const nsCString& aFileName,
gfxFT2FontList::AppendFacesFromFontFile(nsCString& aFileName,
bool aStdFile,
FontNameCache *aCache)
{
@ -940,7 +869,44 @@ gfxFT2FontList::AppendFacesFromFontFile(const nsCString& aFileName,
if (FT_Err_Ok != FT_New_Face(ftLibrary, aFileName.get(), i, &face)) {
continue;
}
AddFaceToList(aFileName, i, aStdFile, face, faceList);
if (FT_Err_Ok != FT_Select_Charmap(face, FT_ENCODING_UNICODE)) {
FT_Done_Face(face);
continue;
}
// build the font entry name and create an FT2FontEntry,
// but do -not- keep a reference to the FT_Face
FT2FontEntry* fe =
CreateNamedFontEntry(face, aFileName.get(), i);
if (fe) {
NS_ConvertUTF8toUTF16 name(face->family_name);
BuildKeyNameFromFontName(name);
gfxFontFamily *family = mFontFamilies.GetWeak(name);
if (!family) {
family = new FT2FontFamily(name);
mFontFamilies.Put(name, family);
if (mBadUnderlineFamilyNames.Contains(name)) {
family->SetBadUnderlineFamily();
}
}
fe->mStandardFace = aStdFile;
family->AddFontEntry(fe);
fe->CheckForBrokenFont(family);
AppendToFaceList(faceList, name, fe);
#ifdef PR_LOGGING
if (LOG_ENABLED()) {
LOG(("(fontinit) added (%s) to family (%s)"
" with style: %s weight: %d stretch: %d",
NS_ConvertUTF16toUTF8(fe->Name()).get(),
NS_ConvertUTF16toUTF8(family->Name()).get(),
fe->IsItalic() ? "italic" : "normal",
fe->Weight(), fe->Stretch()));
}
#endif
}
FT_Done_Face(face);
}
FT_Done_Face(dummy);
@ -950,160 +916,6 @@ gfxFT2FontList::AppendFacesFromFontFile(const nsCString& aFileName,
}
}
#define JAR_LAST_MODIFED_TIME "jar-last-modified-time"
void
gfxFT2FontList::FindFontsInOmnijar(FontNameCache *aCache)
{
bool jarChanged = false;
mozilla::scache::StartupCache* cache =
mozilla::scache::StartupCache::GetSingleton();
char *cachedModifiedTimeBuf;
uint32_t longSize;
int64_t jarModifiedTime;
if (cache &&
NS_SUCCEEDED(cache->GetBuffer(JAR_LAST_MODIFED_TIME,
&cachedModifiedTimeBuf,
&longSize)) &&
longSize == sizeof(int64_t))
{
nsCOMPtr<nsIFile> jarFile = Omnijar::GetPath(Omnijar::Type::GRE);
jarFile->GetLastModifiedTime(&jarModifiedTime);
if (jarModifiedTime > *(int64_t*)cachedModifiedTimeBuf) {
jarChanged = true;
}
}
static const char* sJarSearchPaths[] = {
"res/fonts/*.ttf$",
};
nsRefPtr<nsZipArchive> reader = Omnijar::GetReader(Omnijar::Type::GRE);
for (unsigned i = 0; i < ArrayLength(sJarSearchPaths); i++) {
nsZipFind* find;
if (NS_SUCCEEDED(reader->FindInit(sJarSearchPaths[i], &find))) {
const char* path;
uint16_t len;
while (NS_SUCCEEDED(find->FindNext(&path, &len))) {
nsCString entryName(path, len);
AppendFacesFromOmnijarEntry(reader, entryName, aCache,
jarChanged);
}
delete find;
}
}
if (cache) {
cache->PutBuffer(JAR_LAST_MODIFED_TIME, (char*)&jarModifiedTime,
sizeof(jarModifiedTime));
}
}
// Given the freetype face corresponding to an entryName and face index,
// add the face to the available font list and to the faceList string
void
gfxFT2FontList::AddFaceToList(const nsCString& aEntryName, uint32_t aIndex,
bool aStdFile, FT_Face aFace,
nsCString& aFaceList)
{
if (FT_Err_Ok != FT_Select_Charmap(aFace, FT_ENCODING_UNICODE)) {
// ignore faces that don't support a Unicode charmap
return;
}
// build the font entry name and create an FT2FontEntry,
// but do -not- keep a reference to the FT_Face
FT2FontEntry* fe =
CreateNamedFontEntry(aFace, aEntryName.get(), aIndex);
if (fe) {
NS_ConvertUTF8toUTF16 name(aFace->family_name);
BuildKeyNameFromFontName(name);
gfxFontFamily *family = mFontFamilies.GetWeak(name);
if (!family) {
family = new FT2FontFamily(name);
mFontFamilies.Put(name, family);
if (mBadUnderlineFamilyNames.Contains(name)) {
family->SetBadUnderlineFamily();
}
}
fe->mStandardFace = aStdFile;
family->AddFontEntry(fe);
fe->CheckForBrokenFont(family);
AppendToFaceList(aFaceList, name, fe);
#ifdef PR_LOGGING
if (LOG_ENABLED()) {
LOG(("(fontinit) added (%s) to family (%s)"
" with style: %s weight: %d stretch: %d",
NS_ConvertUTF16toUTF8(fe->Name()).get(),
NS_ConvertUTF16toUTF8(family->Name()).get(),
fe->IsItalic() ? "italic" : "normal",
fe->Weight(), fe->Stretch()));
}
#endif
}
}
void
gfxFT2FontList::AppendFacesFromOmnijarEntry(nsZipArchive* aArchive,
const nsCString& aEntryName,
FontNameCache *aCache,
bool aJarChanged)
{
nsCString faceList;
if (aCache && !aJarChanged) {
uint32_t filesize, timestamp;
aCache->GetInfoForFile(aEntryName, faceList, &timestamp, &filesize);
if (faceList.Length() > 0) {
AppendFacesFromCachedFaceList(aEntryName, true, faceList);
return;
}
}
nsZipItem *item = aArchive->GetItem(aEntryName.get());
NS_ASSERTION(item, "failed to find zip entry");
uint32_t bufSize = item->RealSize();
// We use fallible allocation here; if there's not enough RAM, we'll simply
// ignore the bundled fonts and fall back to the device's installed fonts.
nsAutoPtr<uint8_t> buf(static_cast<uint8_t*>(moz_malloc(bufSize)));
if (!buf) {
return;
}
nsZipCursor cursor(item, aArchive, buf, bufSize);
uint8_t* data = cursor.Copy(&bufSize);
NS_ASSERTION(data && bufSize == item->RealSize(),
"error reading bundled font");
if (!data) {
return;
}
FT_Library ftLibrary = gfxAndroidPlatform::GetPlatform()->GetFTLibrary();
FT_Face dummy;
if (FT_Err_Ok != FT_New_Memory_Face(ftLibrary, buf, bufSize, 0, &dummy)) {
return;
}
for (FT_Long i = 0; i < dummy->num_faces; i++) {
FT_Face face;
if (FT_Err_Ok != FT_New_Memory_Face(ftLibrary, buf, bufSize, i, &face)) {
continue;
}
AddFaceToList(aEntryName, i, true, face, faceList);
FT_Done_Face(face);
}
FT_Done_Face(dummy);
if (aCache && !faceList.IsEmpty()) {
aCache->CacheFileInfo(aEntryName, faceList, 0, bufSize);
}
}
// Called on each family after all fonts are added to the list;
// this will sort faces to give priority to "standard" font files
// if aUserArg is non-null (i.e. we're using it as a boolean flag)
@ -1125,6 +937,131 @@ FinalizeFamilyMemberList(nsStringHashKey::KeyType aKey,
return PL_DHASH_NEXT;
}
#ifdef ANDROID
#define JAR_READ_BUFFER_SIZE 1024
nsresult
CopyFromUriToFile(nsCString aSpec, nsIFile* aLocalFile)
{
nsCOMPtr<nsIURI> uri;
nsCOMPtr<nsIInputStream> inputStream;
nsresult rv = NS_NewURI(getter_AddRefs(uri), aSpec);
NS_ENSURE_SUCCESS(rv, rv);
rv = NS_OpenURI(getter_AddRefs(inputStream), uri);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIOutputStream> outputStream;
rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), aLocalFile);
NS_ENSURE_SUCCESS(rv, rv);
char buf[JAR_READ_BUFFER_SIZE];
while (true) {
uint32_t read;
uint32_t written;
rv = inputStream->Read(buf, JAR_READ_BUFFER_SIZE, &read);
NS_ENSURE_SUCCESS(rv, rv);
rv = outputStream->Write(buf, read, &written);
NS_ENSURE_SUCCESS(rv, rv);
if (written != read) {
return NS_ERROR_FAILURE;
}
if (read != JAR_READ_BUFFER_SIZE) {
break;
}
}
return NS_OK;
}
#define JAR_LAST_MODIFED_TIME "jar-last-modified-time"
void ExtractFontsFromJar(nsIFile* aLocalDir)
{
bool exists;
bool allFontsExtracted = true;
nsCString jarPath;
int64_t jarModifiedTime;
uint32_t longSize;
char* cachedModifiedTimeBuf;
nsZipFind* find;
nsRefPtr<nsZipArchive> reader = Omnijar::GetReader(Omnijar::Type::GRE);
nsCOMPtr<nsIFile> jarFile = Omnijar::GetPath(Omnijar::Type::GRE);
Omnijar::GetURIString(Omnijar::Type::GRE, jarPath);
jarFile->GetLastModifiedTime(&jarModifiedTime);
mozilla::scache::StartupCache* cache = mozilla::scache::StartupCache::GetSingleton();
if (cache && NS_SUCCEEDED(cache->GetBuffer(JAR_LAST_MODIFED_TIME, &cachedModifiedTimeBuf, &longSize))
&& longSize == sizeof(int64_t)) {
if (jarModifiedTime < *((int64_t*) cachedModifiedTimeBuf)) {
return;
}
}
aLocalDir->Exists(&exists);
if (!exists) {
aLocalDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
}
static const char* sJarSearchPaths[] = {
"res/fonts/*.ttf$",
};
for (size_t i = 0; i < ArrayLength(sJarSearchPaths); i++) {
reader->FindInit(sJarSearchPaths[i], &find);
while (true) {
const char* tmpPath;
uint16_t len;
find->FindNext(&tmpPath, &len);
if (!tmpPath) {
break;
}
nsCString path(tmpPath, len);
nsCOMPtr<nsIFile> localFile (do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
if (NS_FAILED(localFile->InitWithFile(aLocalDir))) {
allFontsExtracted = false;
continue;
}
int32_t lastSlash = path.RFindChar('/');
nsCString fileName;
if (lastSlash == kNotFound) {
fileName = path;
} else {
fileName = Substring(path, lastSlash + 1);
}
if (NS_FAILED(localFile->AppendNative(fileName))) {
allFontsExtracted = false;
continue;
}
int64_t lastModifiedTime;
localFile->Exists(&exists);
localFile->GetLastModifiedTime(&lastModifiedTime);
if (!exists || lastModifiedTime < jarModifiedTime) {
nsCString spec;
spec.Append(jarPath);
spec.Append(path);
if (NS_FAILED(CopyFromUriToFile(spec, localFile))) {
localFile->Remove(true);
allFontsExtracted = false;
}
}
}
}
if (allFontsExtracted && cache) {
cache->PutBuffer(JAR_LAST_MODIFED_TIME, (char*)&jarModifiedTime, sizeof(int64_t));
}
}
#endif
void
gfxFT2FontList::FindFonts()
{
@ -1217,25 +1154,25 @@ gfxFT2FontList::FindFonts()
// if we can't find/read the font directory, we are doomed!
NS_RUNTIMEABORT("Could not read the system fonts directory");
}
#endif // XP_WIN && ANDROID
// Look for fonts stored in omnijar, unless we're on a low-memory
// device where we don't want to spend the RAM to decompress them.
// (Prefs may disable this, or force-enable it even with low memory.)
bool lowmem;
nsCOMPtr<nsIMemory> mem = nsMemory::GetGlobalMemoryService();
if ((NS_SUCCEEDED(mem->IsLowMemoryPlatform(&lowmem)) && !lowmem &&
Preferences::GetBool("gfx.bundled_fonts.enabled")) ||
Preferences::GetBool("gfx.bundled_fonts.force-enabled")) {
FindFontsInOmnijar(&fnc);
// look for fonts shipped with the product
NS_NAMED_LITERAL_STRING(kFontsDirName, "fonts");
nsCOMPtr<nsIFile> localDir;
nsresult rv = NS_GetSpecialDirectory(NS_APP_RES_DIR,
getter_AddRefs(localDir));
if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(localDir->Append(kFontsDirName))) {
ExtractFontsFromJar(localDir);
nsCString localPath;
rv = localDir->GetNativePath(localPath);
if (NS_SUCCEEDED(rv)) {
FindFontsInDir(localPath, &fnc);
}
}
// look for locally-added fonts in a "fonts" subdir of the profile
nsCOMPtr<nsIFile> localDir;
nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_LOCAL_50_DIR,
getter_AddRefs(localDir));
if (NS_SUCCEEDED(rv) &&
NS_SUCCEEDED(localDir->Append(NS_LITERAL_STRING("fonts")))) {
rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_LOCAL_50_DIR,
getter_AddRefs(localDir));
if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(localDir->Append(kFontsDirName))) {
nsCString localPath;
rv = localDir->GetNativePath(localPath);
if (NS_SUCCEEDED(rv)) {
@ -1247,6 +1184,7 @@ gfxFT2FontList::FindFonts()
// and marking "simple" families.
// Passing non-null userData here says that we want faces to be sorted.
mFontFamilies.Enumerate(FinalizeFamilyMemberList, this);
#endif // XP_WIN && ANDROID
}
#ifdef ANDROID

View File

@ -23,17 +23,16 @@ using mozilla::dom::FontListEntry;
class FontNameCache;
typedef struct FT_FaceRec_* FT_Face;
class nsZipArchive;
class FT2FontEntry : public gfxFontEntry
{
public:
FT2FontEntry(const nsAString& aFaceName) :
gfxFontEntry(aFaceName),
mFTFace(nullptr),
mFontFace(nullptr),
mFTFontIndex(0)
gfxFontEntry(aFaceName)
{
mFTFace = nullptr;
mFontFace = nullptr;
mFTFontIndex = 0;
}
~FT2FontEntry();
@ -54,30 +53,22 @@ public:
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.
// also record the filename and index
// aFontData (if non-NULL) is NS_Malloc'ed data that aFace depends on,
// to be freed after the face is destroyed
static FT2FontEntry*
CreateFontEntry(FT_Face aFace,
const char *aFilename, uint8_t aIndex,
CreateFontEntry(FT_Face aFace, const char *aFilename, uint8_t aIndex,
const nsAString& aName,
const uint8_t *aFontData = nullptr);
virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle,
bool aNeedsBold);
// Create (if necessary) and return the cairo_font_face for this font.
// This may fail and return null, so caller must be prepared to handle this.
cairo_font_face_t *CairoFontFace();
// Create a cairo_scaled_font for this face, with the given style.
// This may fail and return null, so caller must be prepared to handle this.
cairo_scaled_font_t *CreateScaledFont(const gfxFontStyle *aStyle);
nsresult ReadCMAP();
virtual hb_blob_t* GetFontTable(uint32_t aTableTag) MOZ_OVERRIDE;
virtual nsresult CopyFontTable(uint32_t aTableTag,
FallibleTArray<uint8_t>& aBuffer) MOZ_OVERRIDE;
@ -94,7 +85,7 @@ public:
cairo_font_face_t *mFontFace;
nsCString mFilename;
uint8_t mFTFontIndex;
uint8_t mFTFontIndex;
};
class FT2FontFamily : public gfxFontFamily
@ -133,26 +124,16 @@ protected:
void AppendFaceFromFontListEntry(const FontListEntry& aFLE,
bool isStdFile);
void AppendFacesFromFontFile(const nsCString& aFileName,
void AppendFacesFromFontFile(nsCString& aFileName,
bool isStdFile = false,
FontNameCache *aCache = nullptr);
void AppendFacesFromOmnijarEntry(nsZipArchive *aReader,
const nsCString& aEntryName,
FontNameCache *aCache,
bool aJarChanged);
void AppendFacesFromCachedFaceList(const nsCString& aFileName,
void AppendFacesFromCachedFaceList(nsCString& aFileName,
bool isStdFile,
const nsCString& aFaceList);
void AddFaceToList(const nsCString& aEntryName, uint32_t aIndex,
bool aStdFile, FT_Face aFace, nsCString& aFaceList);
nsCString& aFaceList);
void FindFonts();
void FindFontsInOmnijar(FontNameCache *aCache);
#ifdef ANDROID
void FindFontsInDir(const nsCString& aDir, FontNameCache* aFNC);
#endif

View File

@ -557,6 +557,12 @@ gfxFT2Font::~gfxFT2Font()
{
}
cairo_font_face_t *
gfxFT2Font::CairoFontFace()
{
return GetFontEntry()->CairoFontFace();
}
/**
* Look up the font in the gfxFont cache. If we don't find it, create one.
* In either case, add a ref, append it to the aFonts array, and return it ---

View File

@ -25,6 +25,8 @@ public: // new functions
bool aNeedsBold);
virtual ~gfxFT2Font ();
cairo_font_face_t *CairoFontFace();
FT2FontEntry *GetFontEntry();
static already_AddRefed<gfxFT2Font>

View File

@ -442,33 +442,6 @@ gfxFontEntry::ShareFontTableAndGetBlob(uint32_t aTag,
return entry->ShareTableAndGetBlob(*aBuffer, &mFontTableCache);
}
static int
DirEntryCmp(const void* aKey, const void* aItem)
{
int32_t tag = *static_cast<const int32_t*>(aKey);
const TableDirEntry* entry = static_cast<const TableDirEntry*>(aItem);
return tag - int32_t(entry->tag);
}
hb_blob_t*
gfxFontEntry::GetTableFromFontData(const void* aFontData, uint32_t aTableTag)
{
const SFNTHeader* header =
reinterpret_cast<const SFNTHeader*>(aFontData);
const TableDirEntry* dir =
reinterpret_cast<const TableDirEntry*>(header + 1);
dir = static_cast<const TableDirEntry*>
(bsearch(&aTableTag, dir, uint16_t(header->numTables),
sizeof(TableDirEntry), DirEntryCmp));
if (dir) {
return hb_blob_create(reinterpret_cast<const char*>(aFontData) +
dir->offset, dir->length,
HB_MEMORY_MODE_READONLY, nullptr, nullptr);
}
return nullptr;
}
hb_blob_t *
gfxFontEntry::GetFontTable(uint32_t aTag)
{

View File

@ -508,14 +508,7 @@ protected:
return NS_ERROR_FAILURE;
}
// Return a blob that wraps a table found within a buffer of font data.
// The blob does NOT own its data; caller guarantees that the buffer
// will remain valid at least as long as the blob.
// Returns null if the specified table is not found.
// This method assumes aFontData is valid 'sfnt' data; before using this,
// caller is responsible to do any sanitization/validation necessary.
hb_blob_t* GetTableFromFontData(const void* aFontData, uint32_t aTableTag);
protected:
// Shaper-specific face objects, shared by all instantiations of the same
// physical font, regardless of size.
// Usually, only one of these will actually be created for any given font

View File

@ -627,6 +627,14 @@ bool gfxDownloadedFcFontEntry::SetCairoFace(cairo_font_face_t *aFace)
return true;
}
static int
DirEntryCmp(const void* aKey, const void* aItem)
{
int32_t tag = *static_cast<const int32_t*>(aKey);
const TableDirEntry* entry = static_cast<const TableDirEntry*>(aItem);
return tag - int32_t(entry->tag);
}
hb_blob_t *
gfxDownloadedFcFontEntry::GetFontTable(uint32_t aTableTag)
{
@ -634,7 +642,18 @@ gfxDownloadedFcFontEntry::GetFontTable(uint32_t aTableTag)
// so we can just return a blob that "wraps" the appropriate chunk of it.
// The blob should not attempt to free its data, as the entire sfnt data
// will be freed when the font entry is deleted.
return GetTableFromFontData(mFontData, aTableTag);
const SFNTHeader* header = reinterpret_cast<const SFNTHeader*>(mFontData);
const TableDirEntry* dir = reinterpret_cast<const TableDirEntry*>(header + 1);
dir = static_cast<const TableDirEntry*>
(bsearch(&aTableTag, dir, uint16_t(header->numTables),
sizeof(TableDirEntry), DirEntryCmp));
if (dir) {
return hb_blob_create(reinterpret_cast<const char*>(mFontData) +
dir->offset, dir->length,
HB_MEMORY_MODE_READONLY, nullptr, nullptr);
}
return nullptr;
}
/*

View File

@ -253,11 +253,6 @@ pref("gfx.color_management.enablev4", false);
pref("gfx.downloadable_fonts.enabled", true);
pref("gfx.downloadable_fonts.fallback_delay", 3000);
#ifdef ANDROID
pref("gfx.bundled_fonts.enabled", true);
pref("gfx.bundled_fonts.force-enabled", false);
#endif
pref("gfx.filter.nearest.force-enabled", false);
// prefs controlling the font (name/cmap) loader that runs shortly after startup
@ -3326,82 +3321,73 @@ pref("font.name-list.sans-serif.he", "Droid Sans Hebrew, Open Sans, Droid Sans")
pref("font.name.serif.ja", "Charis SIL Compact");
pref("font.name.sans-serif.ja", "Open Sans");
pref("font.name.monospace.ja", "MotoyaLMaru");
pref("font.name-list.serif.ja", "Droid Serif");
pref("font.name-list.sans-serif.ja", "Open Sans, Roboto, Droid Sans, MotoyaLMaru, MotoyaLCedar, Droid Sans Japanese");
pref("font.name-list.monospace.ja", "MotoyaLMaru, MotoyaLCedar, Droid Sans Mono");
pref("font.name.serif.ko", "Charis SIL Compact");
pref("font.name.sans-serif.ko", "Open Sans");
pref("font.name.monospace.ko", "Droid Sans Mono");
pref("font.name-list.serif.ko", "Droid Serif, HYSerif");
pref("font.name-list.serif.ko", "HYSerif");
pref("font.name-list.sans-serif.ko", "SmartGothic, NanumGothic, DroidSansFallback, Droid Sans Fallback");
pref("font.name.serif.th", "Charis SIL Compact");
pref("font.name.sans-serif.th", "Open Sans");
pref("font.name.monospace.th", "Droid Sans Mono");
pref("font.name-list.serif.th", "Droid Serif");
pref("font.name-list.sans-serif.th", "Droid Sans Thai, Open Sans, Droid Sans");
pref("font.name.serif.tr", "Charis SIL Compact");
pref("font.name.sans-serif.tr", "Open Sans");
pref("font.name.monospace.tr", "Droid Sans Mono");
pref("font.name-list.serif.tr", "Droid Serif");
pref("font.name-list.sans-serif.tr", "Open Sans, Roboto, Droid Sans");
pref("font.name.serif.x-baltic", "Charis SIL Compact");
pref("font.name.sans-serif.x-baltic", "Open Sans");
pref("font.name.monospace.x-baltic", "Droid Sans Mono");
pref("font.name-list.serif.x-baltic", "Droid Serif");
pref("font.name-list.sans-serif.x-baltic", "Open Sans, Roboto, Droid Sans");
pref("font.name.serif.x-central-euro", "Charis SIL Compact");
pref("font.name.sans-serif.x-central-euro", "Open Sans");
pref("font.name.monospace.x-central-euro", "Droid Sans Mono");
pref("font.name-list.serif.x-central-euro", "Droid Serif");
pref("font.name-list.sans-serif.x-central-euro", "Open Sans, Roboto, Droid Sans");
pref("font.name.serif.x-cyrillic", "Charis SIL Compact");
pref("font.name.sans-serif.x-cyrillic", "Open Sans");
pref("font.name.monospace.x-cyrillic", "Droid Sans Mono");
pref("font.name-list.serif.x-cyrillic", "Droid Serif");
pref("font.name-list.sans-serif.x-cyrillic", "Open Sans, Roboto, Droid Sans");
pref("font.name.serif.x-unicode", "Charis SIL Compact");
pref("font.name.sans-serif.x-unicode", "Open Sans");
pref("font.name.monospace.x-unicode", "Droid Sans Mono");
pref("font.name-list.serif.x-unicode", "Droid Serif");
pref("font.name-list.sans-serif.x-unicode", "Open Sans, Roboto, Droid Sans");
pref("font.name.serif.x-user-def", "Charis SIL Compact");
pref("font.name.sans-serif.x-user-def", "Open Sans");
pref("font.name.monospace.x-user-def", "Droid Sans Mono");
pref("font.name-list.serif.x-user-def", "Droid Serif");
pref("font.name-list.sans-serif.x-user-def", "Open Sans, Roboto, Droid Sans");
pref("font.name.serif.x-western", "Charis SIL Compact");
pref("font.name.sans-serif.x-western", "Open Sans");
pref("font.name.monospace.x-western", "Droid Sans Mono");
pref("font.name-list.serif.x-western", "Droid Serif");
pref("font.name-list.sans-serif.x-western", "Open Sans, Roboto, Droid Sans");
pref("font.name.serif.zh-CN", "Charis SIL Compact");
pref("font.name.sans-serif.zh-CN", "Open Sans");
pref("font.name.monospace.zh-CN", "Droid Sans Mono");
pref("font.name-list.serif.zh-CN", "Droid Serif, Droid Sans Fallback");
pref("font.name-list.serif.zh-CN", "Droid Sans Fallback");
pref("font.name-list.sans-serif.zh-CN", "Roboto, Droid Sans, Droid Sans Fallback");
pref("font.name-list.monospace.zh-CN", "Droid Sans Fallback");
pref("font.name.serif.zh-HK", "Charis SIL Compact");
pref("font.name.sans-serif.zh-HK", "Open Sans");
pref("font.name.monospace.zh-HK", "Droid Sans Mono");
pref("font.name-list.serif.zh-HK", "Droid Serif, Droid Sans Fallback");
pref("font.name-list.serif.zh-HK", "Droid Sans Fallback");
pref("font.name-list.sans-serif.zh-HK", "Roboto, Droid Sans, Droid Sans Fallback");
pref("font.name-list.monospace.zh-HK", "Droid Sans Fallback");
pref("font.name.serif.zh-TW", "Charis SIL Compact");
pref("font.name.sans-serif.zh-TW", "Open Sans");
pref("font.name.monospace.zh-TW", "Droid Sans Mono");
pref("font.name-list.serif.zh-TW", "Droid Serif, Droid Sans Fallback");
pref("font.name-list.serif.zh-TW", "Droid Sans Fallback");
pref("font.name-list.sans-serif.zh-TW", "Roboto, Droid Sans, Droid Sans Fallback");
pref("font.name-list.monospace.zh-TW", "Droid Sans Fallback");