mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 21:35:39 +00:00
Bug 490267 - implement pref font and system font fallback for gfxFT2Fonts. r=jtd,jfkthame sr=roc
This commit is contained in:
parent
54ee98bc91
commit
8ffb33380a
@ -65,9 +65,6 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual PRBool FindWeightsForStyle(gfxFontEntry* aFontsForWeights[],
|
virtual PRBool FindWeightsForStyle(gfxFontEntry* aFontsForWeights[],
|
||||||
PRBool anItalic, PRInt16 aStretch);
|
PRBool anItalic, PRInt16 aStretch);
|
||||||
|
|
||||||
public:
|
|
||||||
nsString mName;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FontEntry : public gfxFontEntry
|
class FontEntry : public gfxFontEntry
|
||||||
@ -76,6 +73,7 @@ public:
|
|||||||
FontEntry(const nsAString& aFaceName) :
|
FontEntry(const nsAString& aFaceName) :
|
||||||
gfxFontEntry(aFaceName)
|
gfxFontEntry(aFaceName)
|
||||||
{
|
{
|
||||||
|
mFTFace = nsnull;
|
||||||
mFontFace = nsnull;
|
mFontFace = nsnull;
|
||||||
mFTFontIndex = 0;
|
mFTFontIndex = 0;
|
||||||
}
|
}
|
||||||
@ -95,7 +93,9 @@ public:
|
|||||||
CreateFontEntryFromFace(FT_Face aFace);
|
CreateFontEntryFromFace(FT_Face aFace);
|
||||||
|
|
||||||
cairo_font_face_t *CairoFontFace();
|
cairo_font_face_t *CairoFontFace();
|
||||||
|
nsresult ReadCMAP();
|
||||||
|
|
||||||
|
FT_Face mFTFace;
|
||||||
cairo_font_face_t *mFontFace;
|
cairo_font_face_t *mFontFace;
|
||||||
|
|
||||||
nsString mFaceName;
|
nsString mFaceName;
|
||||||
@ -124,6 +124,8 @@ public: // new functions
|
|||||||
|
|
||||||
static already_AddRefed<gfxFT2Font>
|
static already_AddRefed<gfxFT2Font>
|
||||||
GetOrMakeFont(const nsAString& aName, const gfxFontStyle *aStyle);
|
GetOrMakeFont(const nsAString& aName, const gfxFontStyle *aStyle);
|
||||||
|
static already_AddRefed<gfxFT2Font>
|
||||||
|
GetOrMakeFont(FontEntry *aFontEntry, const gfxFontStyle *aStyle);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cairo_scaled_font_t *mScaledFont;
|
cairo_scaled_font_t *mScaledFont;
|
||||||
@ -180,17 +182,18 @@ protected: // new functions
|
|||||||
void *closure);
|
void *closure);
|
||||||
PRBool mEnableKerning;
|
PRBool mEnableKerning;
|
||||||
|
|
||||||
gfxFT2Font *FindFontForChar(PRUint32 ch, PRUint32 prevCh, PRUint32 nextCh, gfxFT2Font *aFont);
|
void GetPrefFonts(const char *aLangGroup,
|
||||||
PRUint32 ComputeRanges();
|
nsTArray<nsRefPtr<FontEntry> >& aFontEntryList);
|
||||||
|
void GetCJKPrefFonts(nsTArray<nsRefPtr<FontEntry> >& aFontEntryList);
|
||||||
|
void FamilyListToArrayList(const nsString& aFamilies,
|
||||||
|
const nsCString& aLangGroup,
|
||||||
|
nsTArray<nsRefPtr<FontEntry> > *aFontEntryList);
|
||||||
|
already_AddRefed<gfxFT2Font> WhichFontSupportsChar(const nsTArray<nsRefPtr<FontEntry> >& aFontEntryList,
|
||||||
|
PRUint32 aCh);
|
||||||
|
already_AddRefed<gfxFont> WhichPrefFontSupportsChar(PRUint32 aCh);
|
||||||
|
already_AddRefed<gfxFont> WhichSystemFontSupportsChar(PRUint32 aCh);
|
||||||
|
|
||||||
struct TextRange {
|
nsTArray<gfxTextRange> mRanges;
|
||||||
TextRange(PRUint32 aStart, PRUint32 aEnd) : start(aStart), end(aEnd) { }
|
|
||||||
PRUint32 Length() const { return end - start; }
|
|
||||||
nsRefPtr<gfxFT2Font> font;
|
|
||||||
PRUint32 start, end;
|
|
||||||
};
|
|
||||||
|
|
||||||
nsTArray<TextRange> mRanges;
|
|
||||||
nsString mString;
|
nsString mString;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -117,6 +117,9 @@ public:
|
|||||||
#ifndef MOZ_PANGO
|
#ifndef MOZ_PANGO
|
||||||
FontFamily *FindFontFamily(const nsAString& aName);
|
FontFamily *FindFontFamily(const nsAString& aName);
|
||||||
FontEntry *FindFontEntry(const nsAString& aFamilyName, const gfxFontStyle& aFontStyle);
|
FontEntry *FindFontEntry(const nsAString& aFamilyName, const gfxFontStyle& aFontStyle);
|
||||||
|
already_AddRefed<gfxFont> FindFontForChar(PRUint32 aCh, gfxFont *aFont);
|
||||||
|
PRBool GetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<FontEntry> > *aFontEntryList);
|
||||||
|
void SetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<FontEntry> >& aFontEntryList);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static double DPI() {
|
static double DPI() {
|
||||||
|
@ -79,6 +79,9 @@ public:
|
|||||||
|
|
||||||
FontFamily *FindFontFamily(const nsAString& aName);
|
FontFamily *FindFontFamily(const nsAString& aName);
|
||||||
FontEntry *FindFontEntry(const nsAString& aFamilyName, const gfxFontStyle& aFontStyle);
|
FontEntry *FindFontEntry(const nsAString& aFamilyName, const gfxFontStyle& aFontStyle);
|
||||||
|
already_AddRefed<gfxFont> FindFontForChar(PRUint32 aCh, gfxFont *aFont);
|
||||||
|
PRBool GetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<FontEntry> > *aFontEntryList);
|
||||||
|
void SetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<FontEntry> >& aFontEntryList);
|
||||||
|
|
||||||
static PRInt32 DPI() {
|
static PRInt32 DPI() {
|
||||||
if (sDPI == -1) {
|
if (sDPI == -1) {
|
||||||
|
@ -52,9 +52,34 @@
|
|||||||
#include "gfxFT2Fonts.h"
|
#include "gfxFT2Fonts.h"
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include "cairo-ft.h"
|
#include "cairo-ft.h"
|
||||||
#include <freetype/tttables.h>
|
#include FT_TRUETYPE_TAGS_H
|
||||||
|
#include FT_TRUETYPE_TABLES_H
|
||||||
#include "gfxFontUtils.h"
|
#include "gfxFontUtils.h"
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
|
#include "nsUnicodeRange.h"
|
||||||
|
#include "nsIPrefService.h"
|
||||||
|
#include "nsIPrefLocalizedString.h"
|
||||||
|
#include "nsServiceManagerUtils.h"
|
||||||
|
#include "nsCRT.h"
|
||||||
|
|
||||||
|
#include "prlog.h"
|
||||||
|
#include "prinit.h"
|
||||||
|
static PRLogModuleInfo *gFontLog = PR_NewLogModule("ft2fonts");
|
||||||
|
|
||||||
|
static const char *sCJKLangGroup[] = {
|
||||||
|
"ja",
|
||||||
|
"ko",
|
||||||
|
"zh-CN",
|
||||||
|
"zh-HK",
|
||||||
|
"zh-TW"
|
||||||
|
};
|
||||||
|
|
||||||
|
#define COUNT_OF_CJK_LANG_GROUP 5
|
||||||
|
#define CJK_LANG_JA sCJKLangGroup[0]
|
||||||
|
#define CJK_LANG_KO sCJKLangGroup[1]
|
||||||
|
#define CJK_LANG_ZH_CN sCJKLangGroup[2]
|
||||||
|
#define CJK_LANG_ZH_HK sCJKLangGroup[3]
|
||||||
|
#define CJK_LANG_ZH_TW sCJKLangGroup[4]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FontEntry
|
* FontEntry
|
||||||
@ -63,6 +88,7 @@
|
|||||||
FontEntry::FontEntry(const FontEntry& aFontEntry) :
|
FontEntry::FontEntry(const FontEntry& aFontEntry) :
|
||||||
gfxFontEntry(aFontEntry)
|
gfxFontEntry(aFontEntry)
|
||||||
{
|
{
|
||||||
|
mFTFace = aFontEntry.mFTFace;
|
||||||
if (aFontEntry.mFontFace)
|
if (aFontEntry.mFontFace)
|
||||||
mFontFace = cairo_font_face_reference(aFontEntry.mFontFace);
|
mFontFace = cairo_font_face_reference(aFontEntry.mFontFace);
|
||||||
else
|
else
|
||||||
@ -71,6 +97,9 @@ FontEntry::FontEntry(const FontEntry& aFontEntry) :
|
|||||||
|
|
||||||
FontEntry::~FontEntry()
|
FontEntry::~FontEntry()
|
||||||
{
|
{
|
||||||
|
// Do nothing for mFTFace here since FTFontDestroyFunc is called by cairo.
|
||||||
|
mFTFace = nsnull;
|
||||||
|
|
||||||
if (mFontFace) {
|
if (mFontFace) {
|
||||||
cairo_font_face_destroy(mFontFace);
|
cairo_font_face_destroy(mFontFace);
|
||||||
mFontFace = nsnull;
|
mFontFace = nsnull;
|
||||||
@ -122,6 +151,7 @@ FontEntry::CreateFontEntryFromFace(FT_Face aFace) {
|
|||||||
}
|
}
|
||||||
FontEntry *fe = new FontEntry(fontName);
|
FontEntry *fe = new FontEntry(fontName);
|
||||||
fe->mItalic = aFace->style_flags & FT_STYLE_FLAG_ITALIC;
|
fe->mItalic = aFace->style_flags & FT_STYLE_FLAG_ITALIC;
|
||||||
|
fe->mFTFace = aFace;
|
||||||
fe->mFontFace = cairo_ft_font_face_create_for_ft_face(aFace, 0);
|
fe->mFontFace = cairo_ft_font_face_create_for_ft_face(aFace, 0);
|
||||||
cairo_font_face_set_user_data(fe->mFontFace, &key,
|
cairo_font_face_set_user_data(fe->mFontFace, &key,
|
||||||
aFace, FTFontDestroyFunc);
|
aFace, FTFontDestroyFunc);
|
||||||
@ -165,12 +195,45 @@ FontEntry::CairoFontFace()
|
|||||||
if (!mFontFace) {
|
if (!mFontFace) {
|
||||||
FT_Face face;
|
FT_Face face;
|
||||||
FT_New_Face(gfxToolkitPlatform::GetPlatform()->GetFTLibrary(), mFilename.get(), mFTFontIndex, &face);
|
FT_New_Face(gfxToolkitPlatform::GetPlatform()->GetFTLibrary(), mFilename.get(), mFTFontIndex, &face);
|
||||||
|
mFTFace = face;
|
||||||
mFontFace = cairo_ft_font_face_create_for_ft_face(face, 0);
|
mFontFace = cairo_ft_font_face_create_for_ft_face(face, 0);
|
||||||
cairo_font_face_set_user_data(mFontFace, &key, face, FTFontDestroyFunc);
|
cairo_font_face_set_user_data(mFontFace, &key, face, FTFontDestroyFunc);
|
||||||
}
|
}
|
||||||
return mFontFace;
|
return mFontFace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
FontEntry::ReadCMAP()
|
||||||
|
{
|
||||||
|
if (mCmapInitialized) return NS_OK;
|
||||||
|
|
||||||
|
// attempt this once, if errors occur leave a blank cmap
|
||||||
|
mCmapInitialized = PR_TRUE;
|
||||||
|
|
||||||
|
// 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, TTAG_cmap, 0, nsnull, &len);
|
||||||
|
NS_ENSURE_TRUE(status == 0, NS_ERROR_FAILURE);
|
||||||
|
NS_ENSURE_TRUE(len != 0, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
nsAutoTArray<PRUint8,16384> buffer;
|
||||||
|
if (!buffer.AppendElements(len))
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
PRUint8 *buf = buffer.Elements();
|
||||||
|
|
||||||
|
status = FT_Load_Sfnt_Table(mFTFace, TTAG_cmap, 0, buf, &len);
|
||||||
|
NS_ENSURE_TRUE(status == 0, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
PRPackedBool unicodeFont;
|
||||||
|
PRPackedBool symbolFont;
|
||||||
|
return gfxFontUtils::ReadCMAP(buf, len, mCharacterMap,
|
||||||
|
unicodeFont, symbolFont);
|
||||||
|
}
|
||||||
|
|
||||||
FontEntry *
|
FontEntry *
|
||||||
FontFamily::FindFontEntry(const gfxFontStyle& aFontStyle)
|
FontFamily::FindFontEntry(const gfxFontStyle& aFontStyle)
|
||||||
{
|
{
|
||||||
@ -367,184 +430,240 @@ PRUint32 getUTF8CharAndNext(const PRUint8 *aString, PRUint8 *aLength)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PRBool
|
||||||
|
AddFontNameToArray(const nsAString& aName,
|
||||||
|
const nsACString& aGenericName,
|
||||||
|
void *aClosure)
|
||||||
|
|
||||||
|
|
||||||
PRBool
|
|
||||||
HasCharacter(gfxFT2Font *aFont, PRUint32 ch)
|
|
||||||
{
|
{
|
||||||
if (aFont->GetFontEntry()->mCharacterMap.test(ch))
|
if (!aName.IsEmpty()) {
|
||||||
return PR_TRUE;
|
nsTArray<nsString> *list = static_cast<nsTArray<nsString> *>(aClosure);
|
||||||
|
|
||||||
// XXX move this lock way way out
|
if (list->IndexOf(aName) == list->NoIndex)
|
||||||
FT_Face face = cairo_ft_scaled_font_lock_face(aFont->CairoScaledFont());
|
list->AppendElement(aName);
|
||||||
FT_UInt gid = FT_Get_Char_Index(face, ch);
|
}
|
||||||
cairo_ft_scaled_font_unlock_face(aFont->CairoScaledFont());
|
|
||||||
|
return PR_TRUE;
|
||||||
if (gid != 0) {
|
}
|
||||||
aFont->GetFontEntry()->mCharacterMap.set(ch);
|
|
||||||
return PR_TRUE;
|
void
|
||||||
|
gfxFT2FontGroup::FamilyListToArrayList(const nsString& aFamilies,
|
||||||
|
const nsCString& aLangGroup,
|
||||||
|
nsTArray<nsRefPtr<FontEntry> > *aFontEntryList)
|
||||||
|
{
|
||||||
|
nsAutoTArray<nsString, 15> fonts;
|
||||||
|
ForEachFont(aFamilies, aLangGroup, AddFontNameToArray, &fonts);
|
||||||
|
|
||||||
|
PRUint32 len = fonts.Length();
|
||||||
|
for (PRUint32 i = 0; i < len; ++i) {
|
||||||
|
const nsString& str = fonts[i];
|
||||||
|
nsRefPtr<FontEntry> fe = gfxToolkitPlatform::GetPlatform()->FindFontEntry(str, mStyle);
|
||||||
|
aFontEntryList->AppendElement(fe);
|
||||||
}
|
}
|
||||||
return PR_FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
void gfxFT2FontGroup::GetPrefFonts(const char *aLangGroup, nsTArray<nsRefPtr<FontEntry> >& aFontEntryList) {
|
||||||
inline FontEntry *
|
NS_ASSERTION(aLangGroup, "aLangGroup is null");
|
||||||
gfxFT2FontGroup::WhichFontSupportsChar(const nsTArray<>& foo, PRUint32 ch)
|
gfxToolkitPlatform *platform = gfxToolkitPlatform::GetPlatform();
|
||||||
{
|
nsAutoTArray<nsRefPtr<FontEntry>, 5> fonts;
|
||||||
for (int i = 0; i < aGroup->FontListLength(); i++) {
|
/* this lookup has to depend on weight and style */
|
||||||
nsRefPtr<gfxFT2Font> font = aGroup->GetFontAt(i);
|
nsCAutoString key(aLangGroup);
|
||||||
if (HasCharacter(font, ch))
|
key.Append("-");
|
||||||
return font;
|
key.AppendInt(GetStyle()->style);
|
||||||
|
key.Append("-");
|
||||||
|
key.AppendInt(GetStyle()->weight);
|
||||||
|
if (!platform->GetPrefFontEntries(key, &fonts)) {
|
||||||
|
nsString fontString;
|
||||||
|
platform->GetPrefFonts(aLangGroup, fontString);
|
||||||
|
if (fontString.IsEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
FamilyListToArrayList(fontString, nsDependentCString(aLangGroup),
|
||||||
|
&fonts);
|
||||||
|
|
||||||
|
platform->SetPrefFontEntries(key, fonts);
|
||||||
}
|
}
|
||||||
return nsnull;
|
aFontEntryList.AppendElements(fonts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PRInt32 GetCJKLangGroupIndex(const char *aLangGroup) {
|
||||||
|
PRInt32 i;
|
||||||
|
for (i = 0; i < COUNT_OF_CJK_LANG_GROUP; i++) {
|
||||||
|
if (!PL_strcasecmp(aLangGroup, sCJKLangGroup[i]))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this function assigns to the array passed in.
|
||||||
|
void gfxFT2FontGroup::GetCJKPrefFonts(nsTArray<nsRefPtr<FontEntry> >& aFontEntryList) {
|
||||||
|
gfxToolkitPlatform *platform = gfxToolkitPlatform::GetPlatform();
|
||||||
|
|
||||||
|
nsCAutoString key("x-internal-cjk-");
|
||||||
|
key.AppendInt(mStyle.style);
|
||||||
|
key.Append("-");
|
||||||
|
key.AppendInt(mStyle.weight);
|
||||||
|
|
||||||
|
if (!platform->GetPrefFontEntries(key, &aFontEntryList)) {
|
||||||
|
nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||||
|
if (!prefs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPrefBranch> prefBranch;
|
||||||
|
prefs->GetBranch(0, getter_AddRefs(prefBranch));
|
||||||
|
if (!prefBranch)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Add the CJK pref fonts from accept languages, the order should be same order
|
||||||
|
nsCAutoString list;
|
||||||
|
nsCOMPtr<nsIPrefLocalizedString> val;
|
||||||
|
nsresult rv = prefBranch->GetComplexValue("intl.accept_languages", NS_GET_IID(nsIPrefLocalizedString),
|
||||||
|
getter_AddRefs(val));
|
||||||
|
if (NS_SUCCEEDED(rv) && val) {
|
||||||
|
nsAutoString temp;
|
||||||
|
val->ToString(getter_Copies(temp));
|
||||||
|
LossyCopyUTF16toASCII(temp, list);
|
||||||
|
}
|
||||||
|
if (!list.IsEmpty()) {
|
||||||
|
const char kComma = ',';
|
||||||
|
const char *p, *p_end;
|
||||||
|
list.BeginReading(p);
|
||||||
|
list.EndReading(p_end);
|
||||||
|
while (p < p_end) {
|
||||||
|
while (nsCRT::IsAsciiSpace(*p)) {
|
||||||
|
if (++p == p_end)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (p == p_end)
|
||||||
|
break;
|
||||||
|
const char *start = p;
|
||||||
|
while (++p != p_end && *p != kComma)
|
||||||
|
/* nothing */ ;
|
||||||
|
nsCAutoString lang(Substring(start, p));
|
||||||
|
lang.CompressWhitespace(PR_FALSE, PR_TRUE);
|
||||||
|
PRInt32 index = GetCJKLangGroupIndex(lang.get());
|
||||||
|
if (index >= 0)
|
||||||
|
GetPrefFonts(sCJKLangGroup[index], aFontEntryList);
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the system locale
|
||||||
|
#ifdef XP_WIN
|
||||||
|
switch (::GetACP()) {
|
||||||
|
case 932: GetPrefFonts(CJK_LANG_JA, aFontEntryList); break;
|
||||||
|
case 936: GetPrefFonts(CJK_LANG_ZH_CN, aFontEntryList); break;
|
||||||
|
case 949: GetPrefFonts(CJK_LANG_KO, aFontEntryList); break;
|
||||||
|
// XXX Don't we need to append CJK_LANG_ZH_HK if the codepage is 950?
|
||||||
|
case 950: GetPrefFonts(CJK_LANG_ZH_TW, aFontEntryList); break;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
const char *ctype = setlocale(LC_CTYPE, NULL);
|
||||||
|
if (ctype) {
|
||||||
|
if (!PL_strncasecmp(ctype, "ja", 2)) {
|
||||||
|
GetPrefFonts(CJK_LANG_JA, aFontEntryList);
|
||||||
|
} else if (!PL_strncasecmp(ctype, "zh_cn", 5)) {
|
||||||
|
GetPrefFonts(CJK_LANG_ZH_CN, aFontEntryList);
|
||||||
|
} else if (!PL_strncasecmp(ctype, "zh_hk", 5)) {
|
||||||
|
GetPrefFonts(CJK_LANG_ZH_HK, aFontEntryList);
|
||||||
|
} else if (!PL_strncasecmp(ctype, "zh_tw", 5)) {
|
||||||
|
GetPrefFonts(CJK_LANG_ZH_TW, aFontEntryList);
|
||||||
|
} else if (!PL_strncasecmp(ctype, "ko", 2)) {
|
||||||
|
GetPrefFonts(CJK_LANG_KO, aFontEntryList);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline gfxFT2Font *
|
// last resort...
|
||||||
gfxFT2FontGroup::FindFontForChar(PRUint32 ch, PRUint32 prevCh, PRUint32 nextCh, gfxFT2Font *aFont)
|
GetPrefFonts(CJK_LANG_JA, aFontEntryList);
|
||||||
{
|
GetPrefFonts(CJK_LANG_KO, aFontEntryList);
|
||||||
gfxFT2Font *selectedFont;
|
GetPrefFonts(CJK_LANG_ZH_CN, aFontEntryList);
|
||||||
|
GetPrefFonts(CJK_LANG_ZH_HK, aFontEntryList);
|
||||||
|
GetPrefFonts(CJK_LANG_ZH_TW, aFontEntryList);
|
||||||
|
|
||||||
// if this character or the next one is a joiner use the
|
platform->SetPrefFontEntries(key, aFontEntryList);
|
||||||
// same font as the previous range if we can
|
|
||||||
if (gfxFontUtils::IsJoiner(ch) || gfxFontUtils::IsJoiner(prevCh) || gfxFontUtils::IsJoiner(nextCh)) {
|
|
||||||
if (aFont && HasCharacter(aFont, ch))
|
|
||||||
return aFont;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (PRUint32 i = 0; i < FontListLength(); i++) {
|
already_AddRefed<gfxFT2Font>
|
||||||
nsRefPtr<gfxFT2Font> font = GetFontAt(i);
|
gfxFT2FontGroup::WhichFontSupportsChar(const nsTArray<nsRefPtr<FontEntry> >& aFontEntryList, PRUint32 aCh)
|
||||||
if (HasCharacter(font, ch))
|
{
|
||||||
return font;
|
for (PRUint32 i = 0; i < aFontEntryList.Length(); i++) {
|
||||||
|
nsRefPtr<FontEntry> fe = aFontEntryList[i];
|
||||||
|
if (fe->HasCharacter(aCh)) {
|
||||||
|
nsRefPtr<gfxFT2Font> font =
|
||||||
|
gfxFT2Font::GetOrMakeFont(fe, &mStyle);
|
||||||
|
return font.forget();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nsnull;
|
return nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
already_AddRefed<gfxFont>
|
||||||
// check the list of fonts
|
gfxFT2FontGroup::WhichPrefFontSupportsChar(PRUint32 aCh)
|
||||||
selectedFont = WhichFontSupportsChar(mGroup->GetFontList(), ch);
|
{
|
||||||
|
if (aCh > 0xFFFF)
|
||||||
|
return nsnull;
|
||||||
|
|
||||||
|
nsRefPtr<gfxFT2Font> selectedFont;
|
||||||
// don't look in other fonts if the character is in a Private Use Area
|
|
||||||
if ((ch >= 0xE000 && ch <= 0xF8FF) ||
|
|
||||||
(ch >= 0xF0000 && ch <= 0x10FFFD))
|
|
||||||
return selectedFont;
|
|
||||||
|
|
||||||
// check out the style's language group
|
// check out the style's language group
|
||||||
if (!selectedFont) {
|
nsAutoTArray<nsRefPtr<FontEntry>, 5> fonts;
|
||||||
nsAutoTArray<nsRefPtr<FontEntry>, 5> fonts;
|
GetPrefFonts(mStyle.langGroup.get(), fonts);
|
||||||
this->GetPrefFonts(mGroup->GetStyle()->langGroup.get(), fonts);
|
selectedFont = WhichFontSupportsChar(fonts, aCh);
|
||||||
selectedFont = WhichFontSupportsChar(fonts, ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
// otherwise search prefs
|
// otherwise search prefs
|
||||||
if (!selectedFont) {
|
if (!selectedFont) {
|
||||||
/* first check with the script properties to see what they think */
|
PRUint32 unicodeRange = FindCharUnicodeRange(aCh);
|
||||||
if (ch <= 0xFFFF) {
|
|
||||||
PRUint32 unicodeRange = FindCharUnicodeRange(ch);
|
|
||||||
|
|
||||||
/* special case CJK */
|
|
||||||
if (unicodeRange == kRangeSetCJK) {
|
|
||||||
if (PR_LOG_TEST(gFontLog, PR_LOG_DEBUG))
|
|
||||||
PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Trying to find fonts for: CJK"));
|
|
||||||
|
|
||||||
nsAutoTArray<nsRefPtr<FontEntry>, 15> fonts;
|
/* special case CJK */
|
||||||
this->GetCJKPrefFonts(fonts);
|
if (unicodeRange == kRangeSetCJK) {
|
||||||
selectedFont = WhichFontSupportsChar(fonts, ch);
|
if (PR_LOG_TEST(gFontLog, PR_LOG_DEBUG))
|
||||||
} else {
|
PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Trying to find fonts for: CJK"));
|
||||||
const char *langGroup = LangGroupFromUnicodeRange(unicodeRange);
|
|
||||||
if (langGroup) {
|
|
||||||
PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Trying to find fonts for: %s", langGroup));
|
|
||||||
|
|
||||||
nsAutoTArray<nsRefPtr<FontEntry>, 5> fonts;
|
nsAutoTArray<nsRefPtr<FontEntry>, 15> fonts;
|
||||||
this->GetPrefFonts(langGroup, fonts);
|
GetCJKPrefFonts(fonts);
|
||||||
selectedFont = WhichFontSupportsChar(fonts, ch);
|
selectedFont = WhichFontSupportsChar(fonts, aCh);
|
||||||
}
|
} else {
|
||||||
|
const char *langGroup = LangGroupFromUnicodeRange(unicodeRange);
|
||||||
|
if (langGroup) {
|
||||||
|
PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Trying to find fonts for: %s", langGroup));
|
||||||
|
|
||||||
|
nsAutoTArray<nsRefPtr<FontEntry>, 5> fonts;
|
||||||
|
GetPrefFonts(langGroup, fonts);
|
||||||
|
selectedFont = WhichFontSupportsChar(fonts, aCh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// before searching for something else check the font used for the previous character
|
if (selectedFont) {
|
||||||
if (!selectedFont && aFont && HasCharacter(aFont, ch))
|
nsRefPtr<gfxFont> f = static_cast<gfxFont*>(selectedFont.get());
|
||||||
selectedFont = aFont;
|
return f.forget();
|
||||||
|
|
||||||
// otherwise look for other stuff
|
|
||||||
if (!selectedFont) {
|
|
||||||
PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Looking for best match"));
|
|
||||||
|
|
||||||
nsRefPtr<gfxWindowsFont> refFont = mGroup->GetFontAt(0);
|
|
||||||
gfxWindowsPlatform *platform = gfxWindowsPlatform::GetPlatform();
|
|
||||||
selectedFont = platform->FindFontForChar(ch, refFont);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return selectedFont;
|
return nsnull;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PRUint32
|
already_AddRefed<gfxFont>
|
||||||
gfxFT2FontGroup::ComputeRanges()
|
gfxFT2FontGroup::WhichSystemFontSupportsChar(PRUint32 aCh)
|
||||||
{
|
{
|
||||||
const PRUnichar *str = mString.get();
|
nsRefPtr<gfxFont> selectedFont;
|
||||||
PRUint32 len = mString.Length();
|
nsRefPtr<gfxFT2Font> refFont = GetFontAt(0);
|
||||||
|
gfxToolkitPlatform *platform = gfxToolkitPlatform::GetPlatform();
|
||||||
mRanges.Clear();
|
selectedFont = platform->FindFontForChar(aCh, refFont);
|
||||||
|
if (selectedFont)
|
||||||
PRUint32 prevCh = 0;
|
return selectedFont.forget();
|
||||||
for (PRUint32 i = 0; i < len; i++) {
|
return nsnull;
|
||||||
const PRUint32 origI = i; // save off incase we increase for surrogate
|
|
||||||
PRUint32 ch = str[i];
|
|
||||||
if ((i+1 < len) && NS_IS_HIGH_SURROGATE(ch) && NS_IS_LOW_SURROGATE(str[i+1])) {
|
|
||||||
i++;
|
|
||||||
ch = SURROGATE_TO_UCS4(ch, str[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
PRUint32 nextCh = 0;
|
|
||||||
if (i+1 < len) {
|
|
||||||
nextCh = str[i+1];
|
|
||||||
if ((i+2 < len) && NS_IS_HIGH_SURROGATE(ch) && NS_IS_LOW_SURROGATE(str[i+2]))
|
|
||||||
nextCh = SURROGATE_TO_UCS4(nextCh, str[i+2]);
|
|
||||||
}
|
|
||||||
gfxFT2Font *fe = FindFontForChar(ch,
|
|
||||||
prevCh,
|
|
||||||
nextCh,
|
|
||||||
(mRanges.Length() == 0) ? nsnull : mRanges[mRanges.Length() - 1].font);
|
|
||||||
|
|
||||||
prevCh = ch;
|
|
||||||
|
|
||||||
if (mRanges.Length() == 0) {
|
|
||||||
TextRange r(0,1);
|
|
||||||
r.font = fe;
|
|
||||||
mRanges.AppendElement(r);
|
|
||||||
} else {
|
|
||||||
TextRange& prevRange = mRanges[mRanges.Length() - 1];
|
|
||||||
if (prevRange.font != fe) {
|
|
||||||
// close out the previous range
|
|
||||||
prevRange.end = origI;
|
|
||||||
|
|
||||||
TextRange r(origI, i+1);
|
|
||||||
r.font = fe;
|
|
||||||
mRanges.AppendElement(r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mRanges[mRanges.Length()-1].end = len;
|
|
||||||
|
|
||||||
PRUint32 nranges = mRanges.Length();
|
|
||||||
return nranges;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfxFT2FontGroup::CreateGlyphRunsFT(gfxTextRun *aTextRun)
|
void gfxFT2FontGroup::CreateGlyphRunsFT(gfxTextRun *aTextRun)
|
||||||
{
|
{
|
||||||
ComputeRanges();
|
ComputeRanges(mRanges, mString.get(), 0, mString.Length());
|
||||||
|
|
||||||
PRUint32 offset = 0;
|
PRUint32 offset = 0;
|
||||||
for (PRUint32 i = 0; i < mRanges.Length(); ++i) {
|
for (PRUint32 i = 0; i < mRanges.Length(); ++i) {
|
||||||
const TextRange& range = mRanges[i];
|
const gfxTextRange& range = mRanges[i];
|
||||||
PRUint32 rangeLength = range.Length();
|
PRUint32 rangeLength = range.Length();
|
||||||
gfxFT2Font *font = range.font ? range.font.get() : GetFontAt(0);
|
gfxFT2Font *font = static_cast<gfxFT2Font *>(range.font ? range.font.get() : GetFontAt(0));
|
||||||
AddRange(aTextRun, font, mString.get(), offset, rangeLength);
|
AddRange(aTextRun, font, mString.get(), offset, rangeLength);
|
||||||
offset += rangeLength;
|
offset += rangeLength;
|
||||||
}
|
}
|
||||||
@ -908,9 +1027,16 @@ gfxFT2Font::GetOrMakeFont(const nsAString& aName, const gfxFontStyle *aStyle)
|
|||||||
return nsnull;
|
return nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRefPtr<gfxFont> font = gfxFontCache::GetCache()->Lookup(fe->Name(), aStyle);
|
nsRefPtr<gfxFT2Font> font = GetOrMakeFont(fe, aStyle);
|
||||||
|
return font.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<gfxFT2Font>
|
||||||
|
gfxFT2Font::GetOrMakeFont(FontEntry *aFontEntry, const gfxFontStyle *aStyle)
|
||||||
|
{
|
||||||
|
nsRefPtr<gfxFont> font = gfxFontCache::GetCache()->Lookup(aFontEntry->Name(), aStyle);
|
||||||
if (!font) {
|
if (!font) {
|
||||||
font = new gfxFT2Font(fe, aStyle);
|
font = new gfxFT2Font(aFontEntry, aStyle);
|
||||||
if (!font)
|
if (!font)
|
||||||
return nsnull;
|
return nsnull;
|
||||||
gfxFontCache::GetCache()->AddNew(font);
|
gfxFontCache::GetCache()->AddNew(font);
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
|
|
||||||
#include "gfxPlatformGtk.h"
|
#include "gfxPlatformGtk.h"
|
||||||
|
|
||||||
|
#include "nsUnicharUtils.h"
|
||||||
#include "gfxFontconfigUtils.h"
|
#include "gfxFontconfigUtils.h"
|
||||||
#ifdef MOZ_PANGO
|
#ifdef MOZ_PANGO
|
||||||
#include "gfxPangoFonts.h"
|
#include "gfxPangoFonts.h"
|
||||||
@ -95,8 +96,11 @@ gfxFontconfigUtils *gfxPlatformGtk::sFontconfigUtils = nsnull;
|
|||||||
|
|
||||||
#ifndef MOZ_PANGO
|
#ifndef MOZ_PANGO
|
||||||
typedef nsDataHashtable<nsStringHashKey, nsRefPtr<FontFamily> > FontTable;
|
typedef nsDataHashtable<nsStringHashKey, nsRefPtr<FontFamily> > FontTable;
|
||||||
|
typedef nsDataHashtable<nsCStringHashKey, nsTArray<nsRefPtr<FontEntry> > > PrefFontTable;
|
||||||
static FontTable *gPlatformFonts = NULL;
|
static FontTable *gPlatformFonts = NULL;
|
||||||
static FontTable *gPlatformFontAliases = NULL;
|
static FontTable *gPlatformFontAliases = NULL;
|
||||||
|
static PrefFontTable *gPrefFonts = NULL;
|
||||||
|
static gfxSparseBitSet *gCodepointsWithNoFonts = NULL;
|
||||||
static FT_Library gPlatformFTLibrary = NULL;
|
static FT_Library gPlatformFTLibrary = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -119,6 +123,9 @@ gfxPlatformGtk::gfxPlatformGtk()
|
|||||||
gPlatformFonts->Init(100);
|
gPlatformFonts->Init(100);
|
||||||
gPlatformFontAliases = new FontTable();
|
gPlatformFontAliases = new FontTable();
|
||||||
gPlatformFontAliases->Init(100);
|
gPlatformFontAliases->Init(100);
|
||||||
|
gPrefFonts = new PrefFontTable();
|
||||||
|
gPrefFonts->Init(100);
|
||||||
|
gCodepointsWithNoFonts = new gfxSparseBitSet();
|
||||||
UpdateFontList();
|
UpdateFontList();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -137,6 +144,10 @@ gfxPlatformGtk::~gfxPlatformGtk()
|
|||||||
gPlatformFonts = NULL;
|
gPlatformFonts = NULL;
|
||||||
delete gPlatformFontAliases;
|
delete gPlatformFontAliases;
|
||||||
gPlatformFontAliases = NULL;
|
gPlatformFontAliases = NULL;
|
||||||
|
delete gPrefFonts;
|
||||||
|
gPrefFonts = NULL;
|
||||||
|
delete gCodepointsWithNoFonts;
|
||||||
|
gCodepointsWithNoFonts = NULL;
|
||||||
|
|
||||||
FT_Done_FreeType(gPlatformFTLibrary);
|
FT_Done_FreeType(gPlatformFTLibrary);
|
||||||
gPlatformFTLibrary = NULL;
|
gPlatformFTLibrary = NULL;
|
||||||
@ -369,15 +380,14 @@ gfxPlatformGtk::UpdateFontList()
|
|||||||
|
|
||||||
nsAutoString name(NS_ConvertUTF8toUTF16(nsDependentCString(str)).get());
|
nsAutoString name(NS_ConvertUTF8toUTF16(nsDependentCString(str)).get());
|
||||||
nsAutoString key(name);
|
nsAutoString key(name);
|
||||||
/* FIXME DFB */
|
ToLowerCase(key);
|
||||||
//ToLowerCase(key);
|
|
||||||
nsRefPtr<FontFamily> ff;
|
nsRefPtr<FontFamily> ff;
|
||||||
if (!gPlatformFonts->Get(key, &ff)) {
|
if (!gPlatformFonts->Get(key, &ff)) {
|
||||||
ff = new FontFamily(name);
|
ff = new FontFamily(name);
|
||||||
gPlatformFonts->Put(key, ff);
|
gPlatformFonts->Put(key, ff);
|
||||||
}
|
}
|
||||||
|
|
||||||
FontEntry *fe = new FontEntry(ff->mName);
|
FontEntry *fe = new FontEntry(ff->Name());
|
||||||
ff->AddFontEntry(fe);
|
ff->AddFontEntry(fe);
|
||||||
|
|
||||||
if (FcPatternGetString(fs->fonts[i], FC_FILE, 0, (FcChar8 **) &str) == FcResultMatch) {
|
if (FcPatternGetString(fs->fonts[i], FC_FILE, 0, (FcChar8 **) &str) == FcResultMatch) {
|
||||||
@ -429,13 +439,12 @@ gfxPlatformGtk::ResolveFontName(const nsAString& aFontName,
|
|||||||
{
|
{
|
||||||
|
|
||||||
nsAutoString name(aFontName);
|
nsAutoString name(aFontName);
|
||||||
/* FIXME: DFB */
|
ToLowerCase(name);
|
||||||
//ToLowerCase(name);
|
|
||||||
|
|
||||||
nsRefPtr<FontFamily> ff;
|
nsRefPtr<FontFamily> ff;
|
||||||
if (gPlatformFonts->Get(name, &ff) ||
|
if (gPlatformFonts->Get(name, &ff) ||
|
||||||
gPlatformFontAliases->Get(name, &ff)) {
|
gPlatformFontAliases->Get(name, &ff)) {
|
||||||
aAborted = !(*aCallback)(ff->mName, aClosure);
|
aAborted = !(*aCallback)(ff->Name(), aClosure);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,8 +460,7 @@ gfxPlatformGtk::ResolveFontName(const nsAString& aFontName,
|
|||||||
if (FcPatternGetString(nfs->fonts[k], FC_FAMILY, 0, (FcChar8 **) &str) != FcResultMatch)
|
if (FcPatternGetString(nfs->fonts[k], FC_FAMILY, 0, (FcChar8 **) &str) != FcResultMatch)
|
||||||
continue;
|
continue;
|
||||||
nsAutoString altName = NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str)));
|
nsAutoString altName = NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str)));
|
||||||
/* FIXME: DFB */
|
ToLowerCase(altName);
|
||||||
//ToLowerCase(altName);
|
|
||||||
if (gPlatformFonts->Get(altName, &ff)) {
|
if (gPlatformFonts->Get(altName, &ff)) {
|
||||||
//printf("Adding alias: %s -> %s\n", utf8Name.get(), str);
|
//printf("Adding alias: %s -> %s\n", utf8Name.get(), str);
|
||||||
gPlatformFontAliases->Put(name, ff);
|
gPlatformFontAliases->Put(name, ff);
|
||||||
@ -486,8 +494,7 @@ gfxPlatformGtk::ResolveFontName(const nsAString& aFontName,
|
|||||||
if (FcPatternGetString(nfs->fonts[k], FC_FAMILY, 0, (FcChar8 **) &str) != FcResultMatch)
|
if (FcPatternGetString(nfs->fonts[k], FC_FAMILY, 0, (FcChar8 **) &str) != FcResultMatch)
|
||||||
continue;
|
continue;
|
||||||
nsAutoString altName = NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str)));
|
nsAutoString altName = NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str)));
|
||||||
/* FIXME: DFB */
|
ToLowerCase(altName);
|
||||||
//ToLowerCase(altName);
|
|
||||||
if (gPlatformFonts->Get(altName, &ff)) {
|
if (gPlatformFonts->Get(altName, &ff)) {
|
||||||
//printf("Adding alias: %s -> %s\n", utf8Name.get(), str);
|
//printf("Adding alias: %s -> %s\n", utf8Name.get(), str);
|
||||||
gPlatformFontAliases->Put(name, ff);
|
gPlatformFontAliases->Put(name, ff);
|
||||||
@ -668,8 +675,7 @@ FontFamily *
|
|||||||
gfxPlatformGtk::FindFontFamily(const nsAString& aName)
|
gfxPlatformGtk::FindFontFamily(const nsAString& aName)
|
||||||
{
|
{
|
||||||
nsAutoString name(aName);
|
nsAutoString name(aName);
|
||||||
/* FIXME: DFB */
|
ToLowerCase(name);
|
||||||
//ToLowerCase(name);
|
|
||||||
|
|
||||||
nsRefPtr<FontFamily> ff;
|
nsRefPtr<FontFamily> ff;
|
||||||
if (!gPlatformFonts->Get(name, &ff)) {
|
if (!gPlatformFonts->Get(name, &ff)) {
|
||||||
@ -687,6 +693,58 @@ gfxPlatformGtk::FindFontEntry(const nsAString& aName, const gfxFontStyle& aFontS
|
|||||||
|
|
||||||
return ff->FindFontEntry(aFontStyle);
|
return ff->FindFontEntry(aFontStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PLDHashOperator
|
||||||
|
FindFontForCharProc(nsStringHashKey::KeyType aKey,
|
||||||
|
nsRefPtr<FontFamily>& aFontFamily,
|
||||||
|
void* aUserArg)
|
||||||
|
{
|
||||||
|
FontSearch *data = (FontSearch*)aUserArg;
|
||||||
|
aFontFamily->FindFontForChar(data);
|
||||||
|
return PL_DHASH_NEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<gfxFont>
|
||||||
|
gfxPlatformGtk::FindFontForChar(PRUint32 aCh, gfxFont *aFont)
|
||||||
|
{
|
||||||
|
if (!gPlatformFonts || !gCodepointsWithNoFonts)
|
||||||
|
return nsnull;
|
||||||
|
|
||||||
|
// is codepoint with no matching font? return null immediately
|
||||||
|
if (gCodepointsWithNoFonts->test(aCh)) {
|
||||||
|
return nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
FontSearch data(aCh, aFont);
|
||||||
|
|
||||||
|
// find fonts that support the character
|
||||||
|
gPlatformFonts->Enumerate(FindFontForCharProc, &data);
|
||||||
|
|
||||||
|
if (data.mBestMatch) {
|
||||||
|
nsRefPtr<gfxFT2Font> font =
|
||||||
|
gfxFT2Font::GetOrMakeFont(static_cast<FontEntry*>(data.mBestMatch.get()),
|
||||||
|
aFont->GetStyle());
|
||||||
|
gfxFont* ret = font.forget().get();
|
||||||
|
return already_AddRefed<gfxFont>(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
// no match? add to set of non-matching codepoints
|
||||||
|
gCodepointsWithNoFonts->set(aCh);
|
||||||
|
|
||||||
|
return nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool
|
||||||
|
gfxPlatformGtk::GetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<FontEntry> > *aFontEntryList)
|
||||||
|
{
|
||||||
|
return gPrefFonts->Get(aKey, aFontEntryList);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gfxPlatformGtk::SetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<FontEntry> >& aFontEntryList)
|
||||||
|
{
|
||||||
|
gPrefFonts->Put(aKey, aFontEntryList);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,8 +74,11 @@ static void do_qt_pixmap_unref (void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
typedef nsDataHashtable<nsStringHashKey, nsRefPtr<FontFamily> > FontTable;
|
typedef nsDataHashtable<nsStringHashKey, nsRefPtr<FontFamily> > FontTable;
|
||||||
|
typedef nsDataHashtable<nsCStringHashKey, nsTArray<nsRefPtr<FontEntry> > > PrefFontTable;
|
||||||
static FontTable *gPlatformFonts = NULL;
|
static FontTable *gPlatformFonts = NULL;
|
||||||
static FontTable *gPlatformFontAliases = NULL;
|
static FontTable *gPlatformFontAliases = NULL;
|
||||||
|
static PrefFontTable *gPrefFonts = NULL;
|
||||||
|
static gfxSparseBitSet *gCodepointsWithNoFonts = NULL;
|
||||||
static FT_Library gPlatformFTLibrary = NULL;
|
static FT_Library gPlatformFTLibrary = NULL;
|
||||||
|
|
||||||
|
|
||||||
@ -91,6 +94,9 @@ gfxQtPlatform::gfxQtPlatform()
|
|||||||
gPlatformFonts->Init(100);
|
gPlatformFonts->Init(100);
|
||||||
gPlatformFontAliases = new FontTable();
|
gPlatformFontAliases = new FontTable();
|
||||||
gPlatformFontAliases->Init(100);
|
gPlatformFontAliases->Init(100);
|
||||||
|
gPrefFonts = new PrefFontTable();
|
||||||
|
gPrefFonts->Init(100);
|
||||||
|
gCodepointsWithNoFonts = new gfxSparseBitSet();
|
||||||
UpdateFontList();
|
UpdateFontList();
|
||||||
|
|
||||||
InitDPI();
|
InitDPI();
|
||||||
@ -105,6 +111,10 @@ gfxQtPlatform::~gfxQtPlatform()
|
|||||||
gPlatformFonts = NULL;
|
gPlatformFonts = NULL;
|
||||||
delete gPlatformFontAliases;
|
delete gPlatformFontAliases;
|
||||||
gPlatformFontAliases = NULL;
|
gPlatformFontAliases = NULL;
|
||||||
|
delete gPrefFonts;
|
||||||
|
gPrefFonts = NULL;
|
||||||
|
delete gCodepointsWithNoFonts;
|
||||||
|
gCodepointsWithNoFonts = NULL;
|
||||||
|
|
||||||
cairo_debug_reset_static_data();
|
cairo_debug_reset_static_data();
|
||||||
|
|
||||||
@ -389,3 +399,55 @@ gfxQtPlatform::FindFontEntry(const nsAString& aName, const gfxFontStyle& aFontSt
|
|||||||
|
|
||||||
return ff->FindFontEntry(aFontStyle);
|
return ff->FindFontEntry(aFontStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PLDHashOperator
|
||||||
|
FindFontForCharProc(nsStringHashKey::KeyType aKey,
|
||||||
|
nsRefPtr<FontFamily>& aFontFamily,
|
||||||
|
void* aUserArg)
|
||||||
|
{
|
||||||
|
FontSearch *data = (FontSearch*)aUserArg;
|
||||||
|
aFontFamily->FindFontForChar(data);
|
||||||
|
return PL_DHASH_NEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<gfxFont>
|
||||||
|
gfxQtPlatform::FindFontForChar(PRUint32 aCh, gfxFont *aFont)
|
||||||
|
{
|
||||||
|
if (!gPlatformFonts || !gCodepointsWithNoFonts)
|
||||||
|
return nsnull;
|
||||||
|
|
||||||
|
// is codepoint with no matching font? return null immediately
|
||||||
|
if (gCodepointsWithNoFonts->test(aCh)) {
|
||||||
|
return nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
FontSearch data(aCh, aFont);
|
||||||
|
|
||||||
|
// find fonts that support the character
|
||||||
|
gPlatformFonts->Enumerate(FindFontForCharProc, &data);
|
||||||
|
|
||||||
|
if (data.mBestMatch) {
|
||||||
|
nsRefPtr<gfxFT2Font> font =
|
||||||
|
gfxFT2Font::GetOrMakeFont(static_cast<FontEntry*>(data.mBestMatch.get()),
|
||||||
|
aFont->GetStyle());
|
||||||
|
gfxFont* ret = font.forget().get();
|
||||||
|
return already_AddRefed<gfxFont>(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
// no match? add to set of non-matching codepoints
|
||||||
|
gCodepointsWithNoFonts->set(aCh);
|
||||||
|
|
||||||
|
return nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool
|
||||||
|
gfxQtPlatform::GetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<FontEntry> > *aFontEntryList)
|
||||||
|
{
|
||||||
|
return gPrefFonts->Get(aKey, aFontEntryList);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gfxQtPlatform::SetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<FontEntry> >& aFontEntryList)
|
||||||
|
{
|
||||||
|
gPrefFonts->Put(aKey, aFontEntryList);
|
||||||
|
}
|
||||||
|
@ -610,6 +610,9 @@ gfxWindowsPlatform::FindFontForCharProc(nsStringHashKey::KeyType aKey,
|
|||||||
{
|
{
|
||||||
FontSearch *data = (FontSearch*)userArg;
|
FontSearch *data = (FontSearch*)userArg;
|
||||||
|
|
||||||
|
#ifdef MOZ_FT2_FONTS
|
||||||
|
aFontFamily->FindFontForChar(data);
|
||||||
|
#else
|
||||||
const PRUint32 ch = data->mCh;
|
const PRUint32 ch = data->mCh;
|
||||||
|
|
||||||
nsRefPtr<FontEntry> fe = aFontFamily->FindFontEntry(*data->mFontToMatch->GetStyle());
|
nsRefPtr<FontEntry> fe = aFontFamily->FindFontEntry(*data->mFontToMatch->GetStyle());
|
||||||
@ -619,7 +622,6 @@ gfxWindowsPlatform::FindFontForCharProc(nsStringHashKey::KeyType aKey,
|
|||||||
|
|
||||||
PRInt32 rank = 0;
|
PRInt32 rank = 0;
|
||||||
|
|
||||||
#ifndef MOZ_FT2_FONTS
|
|
||||||
// skip over non-unicode and bitmap fonts and fonts that don't have
|
// skip over non-unicode and bitmap fonts and fonts that don't have
|
||||||
// the code point we're looking for
|
// the code point we're looking for
|
||||||
if (fe->IsCrappyFont() || !fe->mCharacterMap.test(ch))
|
if (fe->IsCrappyFont() || !fe->mCharacterMap.test(ch))
|
||||||
@ -639,7 +641,7 @@ gfxWindowsPlatform::FindFontForCharProc(nsStringHashKey::KeyType aKey,
|
|||||||
rank += 3;
|
rank += 3;
|
||||||
if (fe->mWindowsPitch == mfe->mWindowsPitch)
|
if (fe->mWindowsPitch == mfe->mWindowsPitch)
|
||||||
rank += 3;
|
rank += 3;
|
||||||
#endif
|
|
||||||
/* italic */
|
/* italic */
|
||||||
const PRBool italic = (data->mFontToMatch->GetStyle()->style != FONT_STYLE_NORMAL);
|
const PRBool italic = (data->mFontToMatch->GetStyle()->style != FONT_STYLE_NORMAL);
|
||||||
if (fe->mItalic != italic)
|
if (fe->mItalic != italic)
|
||||||
@ -658,6 +660,7 @@ gfxWindowsPlatform::FindFontForCharProc(nsStringHashKey::KeyType aKey,
|
|||||||
data->mBestMatch = fe;
|
data->mBestMatch = fe;
|
||||||
data->mMatchRank = rank;
|
data->mMatchRank = rank;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return PL_DHASH_NEXT;
|
return PL_DHASH_NEXT;
|
||||||
}
|
}
|
||||||
@ -678,10 +681,10 @@ gfxWindowsPlatform::FindFontForChar(PRUint32 aCh, gfxFont *aFont)
|
|||||||
if (data.mBestMatch) {
|
if (data.mBestMatch) {
|
||||||
#ifdef MOZ_FT2_FONTS
|
#ifdef MOZ_FT2_FONTS
|
||||||
nsRefPtr<gfxFT2Font> font =
|
nsRefPtr<gfxFT2Font> font =
|
||||||
gfxFT2Font::GetOrMakeFont(data.mBestMatch->mName,
|
gfxFT2Font::GetOrMakeFont(static_cast<FontEntry*>(data.mBestMatch.get()),
|
||||||
aFont->GetStyle());
|
aFont->GetStyle());
|
||||||
gfxFont* ret = font.forget().get();
|
gfxFont* ret = font.forget().get();
|
||||||
return already_AddRefed<gfxFont>(ret);
|
return already_AddRefed<gfxFont>(ret);
|
||||||
#else
|
#else
|
||||||
nsRefPtr<gfxWindowsFont> font =
|
nsRefPtr<gfxWindowsFont> font =
|
||||||
gfxWindowsFont::GetOrMakeFont(static_cast<FontEntry*>(data.mBestMatch.get()),
|
gfxWindowsFont::GetOrMakeFont(static_cast<FontEntry*>(data.mBestMatch.get()),
|
||||||
|
Loading…
Reference in New Issue
Block a user