bug 144666 Glyph Fill In and Font Fallback

* add support for a font list based on
1st: CSS
2nd: user prefs
3rd: fallbacks based on doc/user language
4th: any font that supports the char
* find the first font in the font list that supports a char
* within each text draw/measure operation bread the text into runs of text
that use the same font

r=louie.zhao@sun.com, sr=jst@netscape.com
This commit is contained in:
bstell%ix.netcom.com 2003-01-17 23:28:44 +00:00
parent 63f72dc958
commit 8b7b8bc0a4
12 changed files with 747 additions and 206 deletions

View File

@ -86,6 +86,7 @@ interface nsIFontCatalogService : nsISupports
in unsigned short spacing);
// Definition for weight
const unsigned short kFCWeightAny = 0;
const unsigned short kFCWeightLight = 300;
const unsigned short kFCWeightBook = 400;
const unsigned short kFCWeightMedium = 400;
@ -96,6 +97,7 @@ interface nsIFontCatalogService : nsISupports
const unsigned short kFCWeighBlack = 900;
// Definition for width
const unsigned short kFCWidthAny = 0;
const unsigned short kFCWidthNarrow = 3;
const unsigned short kFCWidthSemicondensed = 4;
const unsigned short kFCWidthBlock = 5;
@ -106,13 +108,15 @@ interface nsIFontCatalogService : nsISupports
const unsigned short kFCWidthDoubleWide = 9;
// Definition for slant
const unsigned short kFCSlantRoman = 0;
const unsigned short kFCSlantItalic = 1;
const unsigned short kFCSlantOblique = 2;
const unsigned short kFCSlantReverseItalic = 3;
const unsigned short kFCSlantReverseOblique = 4;
const unsigned short kFCSlantAny = 0;
const unsigned short kFCSlantRoman = 1;
const unsigned short kFCSlantItalic = 2;
const unsigned short kFCSlantOblique = 3;
const unsigned short kFCSlantReverseItalic = 4;
const unsigned short kFCSlantReverseOblique = 5;
// Definition for spacing
const unsigned short kFCSpacingAny = 0;
const unsigned short kFCSpacingMonospace = 1;
const unsigned short kFCSpacingProportional = 2;
};

View File

@ -47,6 +47,7 @@
#define NS_FREETYPE2_CID NS_IFREETYPE2_IID
// macros to handle FreeType2 26.6 numbers (26 bit number with 6 bit fraction)
#define FT_16_16_TO_REG(x) ((x)>>16)
#define FT_REG_TO_16_16(x) ((x)<<16)
#define FT_CEIL(x) (((x) + 63) & -64)
#define FT_TRUNC(x) ((x) >> 6)
%}

View File

@ -38,6 +38,7 @@ REQUIRES = xpcom \
widget \
pref \
caps \
locale \
uconv \
view \
necko \

View File

@ -72,7 +72,8 @@ void
WriteCidCharMap(const PRUnichar *aCharIDs, PRUint32 *aCIDs,
int aLen, FILE *aFile)
{
int i, blk_len;
int i, j, blk_len;
int fix_len = 0; // older versions of Ghostscript do not like a len of 2
while (aLen) {
/* determine the # of lines in this block */
@ -81,10 +82,19 @@ WriteCidCharMap(const PRUnichar *aCharIDs, PRUint32 *aCIDs,
else
blk_len = aLen;
if (blk_len == 2) {
fix_len = 1;
fprintf(aFile, "%% add an extra dummy value to the end of this block "
" since older versions of\n");
fprintf(aFile, "%% Ghostscript do not like a block len of 2\n");
}
/* output the block */
fprintf(aFile, "%d begincidchar\n", blk_len);
fprintf(aFile, "%d begincidchar\n", blk_len+fix_len);
for (i=0; i<blk_len; i++)
fprintf(aFile, "<%04X> %d\n", aCharIDs[i], aCIDs[i]);
for (j=0; j<fix_len; j++) // repeat the old value
fprintf(aFile, "<%04X> %d\n", aCharIDs[i-1], aCIDs[i-1]);
fprintf(aFile, "endcidchar\n\n");
/* setup for next block */

View File

@ -56,11 +56,17 @@
#include "nsString.h"
#include "nsFontMetricsPS.h"
#include "nsPostScriptObj.h"
#include "nsFontPSDebug.h"
#include "nspr.h"
#include "nsILanguageAtomService.h"
#ifdef PR_LOGGING
static PRLogModuleInfo *nsDeviceContextPSLM = PR_NewLogModule("nsDeviceContextPS");
#endif /* PR_LOGGING */
PRUint32 gFontPSDebug = 0;
nsIAtom* gUsersLocale = nsnull;
#ifdef WE_DO_NOT_SUPPORT_MULTIPLE_PRINT_DEVICECONTEXTS
static int instance_counter = 0;
#endif /* WE_DO_NOT_SUPPORT_MULTIPLE_PRINT_DEVICECONTEXTS */
@ -121,6 +127,7 @@ nsDeviceContextPS::~nsDeviceContextPS()
delete mPSFontGeneratorList;
mPSFontGeneratorList = nsnull;
}
NS_IF_RELEASE(gUsersLocale);
}
NS_IMETHODIMP
@ -211,6 +218,23 @@ nsDeviceContextPS::InitDeviceContextPS(nsIDeviceContext *aCreatingDeviceContext,
mTTPEnable = PR_FALSE;
}
#ifdef NS_FONTPS_DEBUG
char* debug = PR_GetEnv("NS_FONTPS_DEBUG");
if (debug) {
PR_sscanf(debug, "%lX", &gFontPSDebug);
}
#endif
// the user's locale
nsCOMPtr<nsILanguageAtomService> langService;
langService = do_GetService(NS_LANGUAGEATOMSERVICE_CONTRACTID);
if (langService) {
langService->GetLocaleLanguageGroup(&gUsersLocale);
}
if (!gUsersLocale) {
gUsersLocale = NS_NewAtom("x-western");
}
return NS_OK;
}

View File

@ -49,9 +49,14 @@
#ifdef MOZ_ENABLE_FREETYPE2
#include "nsType8.h"
#endif
#include "nsFontPSDebug.h"
extern nsIAtom *gUsersLocale;
#define NS_IS_BOLD(weight) ((weight) > 400 ? 1 : 0)
static nsFontPS* CreateFontPS(nsITrueTypeFontCatalogEntry*, const nsFont&,
nsFontMetricsPS*);
static NS_DEFINE_CID(kFCSCID, NS_FONTCATALOGSERVICE_CID);
/** ---------------------------------------------------
* See documentation in nsFontMetricsPS.h
@ -72,9 +77,24 @@ nsFontMetricsPS :: ~nsFontMetricsPS()
mFont = nsnull;
}
if (mFontPS) {
delete mFontPS;
mFontPS = nsnull;
if (mFontsPS) {
int i;
for (i=0; i<mFontsPS->Count(); i++) {
fontps *fontPS = (fontps *)mFontsPS->ElementAt(i);
if (!fontPS)
continue;
NS_IF_RELEASE(fontPS->entry);
if (fontPS->fontps)
delete fontPS->fontps;
if (fontPS->ccmap)
FreeCCMap(fontPS->ccmap);
delete fontPS;
}
delete mFontsPS;
}
if (mFontsAlreadyLoaded) {
delete mFontsAlreadyLoaded;
}
if (mDeviceContext) {
@ -100,8 +120,14 @@ nsFontMetricsPS :: Init(const nsFont& aFont, nsIAtom* aLangGroup,
//don't addref this to avoid circular refs
mDeviceContext = (nsDeviceContextPS *)aContext;
mFontPS = nsFontPS::FindFont(aFont, this);
NS_ENSURE_TRUE(mFontPS, NS_ERROR_FAILURE);
mFontsPS = new nsVoidArray();
NS_ENSURE_TRUE(mFontsPS, NS_ERROR_OUT_OF_MEMORY);
mFontsAlreadyLoaded = new nsHashtable();
NS_ENSURE_TRUE(mFontsAlreadyLoaded, NS_ERROR_OUT_OF_MEMORY);
// make sure we have at least one font
nsFontPS *fontPS = nsFontPS::FindFont('a', aFont, this);
NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE);
RealizeFont();
return NS_OK;
@ -125,7 +151,15 @@ nsFontMetricsPS::RealizeFont()
if (mFont && mDeviceContext) {
float dev2app;
mDeviceContext->GetDevUnitsToAppUnits(dev2app);
mFontPS->RealizeFont(this, dev2app);
fontps *font = (fontps*)mFontsPS->ElementAt(0);
#ifdef MOZ_ENABLE_FREETYPE2
NS_ASSERTION(font && font->entry, "no font available");
if (font && !font->fontps && font->entry)
font->fontps = CreateFontPS(font->entry, *mFont, this);
#endif
NS_ASSERTION(font && font->fontps, "no font available");
if (font && font->fontps)
font->fontps->RealizeFont(this, dev2app);
}
}
@ -351,10 +385,29 @@ nsFontMetricsPS::GetFontHandle(nsFontHandle &aHandle)
NS_IMETHODIMP
nsFontMetricsPS :: GetStringWidth(const char *aString,nscoord& aWidth,nscoord aLength)
{
NS_ENSURE_TRUE(mFontPS, NS_ERROR_NULL_POINTER);
aWidth = mFontPS->GetWidth(aString, aLength);
return NS_OK;
aWidth = 0;
if (aLength == 0)
return NS_OK;
nsFontPS* fontPS = nsFontPS::FindFont(aString[0], *mFont, this);
NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE);
nscoord i, start = 0;
for (i=0; i<aLength; i++) {
nsFontPS* fontThisChar = nsFontPS::FindFont(aString[i], *mFont, this);
NS_ASSERTION(fontThisChar,"failed to find a font");
NS_ENSURE_TRUE(fontThisChar, NS_ERROR_FAILURE);
if (fontThisChar != fontPS) {
// measure text up to this point
aWidth += fontPS->GetWidth(aString+start, i-start);
start = i;
fontPS = fontThisChar;
}
}
// measure the last part
if (aLength-start)
aWidth += fontPS->GetWidth(aString+start, aLength-start);
return NS_OK;
}
@ -365,14 +418,43 @@ nsFontMetricsPS :: GetStringWidth(const char *aString,nscoord& aWidth,nscoord aL
NS_IMETHODIMP
nsFontMetricsPS :: GetStringWidth(const PRUnichar *aString,nscoord& aWidth,nscoord aLength)
{
NS_ENSURE_TRUE(mFontPS, NS_ERROR_NULL_POINTER);
aWidth = mFontPS->GetWidth(aString, aLength);
aWidth = 0;
if (aLength == 0)
return NS_OK;
nsFontPS* fontPS = nsFontPS::FindFont(aString[0], *mFont, this);
NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE);
nscoord i, start = 0;
for (i=0; i<aLength; i++) {
nsFontPS* fontThisChar = nsFontPS::FindFont(aString[i], *mFont, this);
NS_ASSERTION(fontThisChar,"failed to find a font");
NS_ENSURE_TRUE(fontThisChar, NS_ERROR_FAILURE);
if (fontThisChar != fontPS) {
// measure text up to this point
aWidth += fontPS->GetWidth(aString+start, i-start);
start = i;
fontPS = fontThisChar;
}
}
// measure the last part
if (aLength-start)
aWidth += fontPS->GetWidth(aString+start, aLength-start);
return NS_OK;
}
nsFontPS*
nsFontPS::FindFont(char aChar, const nsFont& aFont,
nsFontMetricsPS* aFontMetrics)
{
PRUnichar uc = (unsigned char)aChar;
return FindFont(uc, aFont, aFontMetrics);
}
// nsFontPS
nsFontPS*
nsFontPS::FindFont(const nsFont& aFont, nsFontMetricsPS* aFontMetrics)
nsFontPS::FindFont(PRUnichar aChar, const nsFont& aFont,
nsFontMetricsPS* aFontMetrics)
{
nsFontPS* fontPS;
@ -380,14 +462,27 @@ nsFontPS::FindFont(const nsFont& aFont, nsFontMetricsPS* aFontMetrics)
nsDeviceContextPS* dc = aFontMetrics->GetDeviceContext();
NS_ENSURE_TRUE(dc, nsnull);
if (dc->mTTPEnable) {
fontPS = nsFontPSFreeType::FindFont(aFont, aFontMetrics);
fontPS = nsFontPSFreeType::FindFont(aChar, aFont, aFontMetrics);
if (fontPS)
return fontPS;
}
#endif
/* Find in afm font */
fontPS = nsFontPSAFM::FindFont(aFont, aFontMetrics);
if (aFontMetrics->GetFontsPS()->Count() > 0) {
fontps *fps = (fontps*)aFontMetrics->GetFontsPS()->ElementAt(0);
NS_ENSURE_TRUE(fps, nsnull);
fontPS = fps->fontps;
}
else {
fontPS = nsFontPSAFM::FindFont(aFont, aFontMetrics);
fontps *fps = new fontps;
NS_ENSURE_TRUE(fps, nsnull);
fps->entry = nsnull;
fps->fontps = fontPS;
fps->ccmap = nsnull;
aFontMetrics->GetFontsPS()->AppendElement(fps);
}
return fontPS;
}
@ -457,7 +552,7 @@ nsFontPSAFM::~nsFontPSAFM()
nscoord
nsFontPSAFM::GetWidth(const char* aString, PRUint32 aLength)
{
nscoord width;
nscoord width = 0;
if (mAFMInfo) {
mAFMInfo->GetStringWidth(aString, width, aLength);
}
@ -467,7 +562,7 @@ nsFontPSAFM::GetWidth(const char* aString, PRUint32 aLength)
nscoord
nsFontPSAFM::GetWidth(const PRUnichar* aString, PRUint32 aLength)
{
nscoord width;
nscoord width = 0;
if (mAFMInfo) {
mAFMInfo->GetStringWidth(aString, width, aLength);
}
@ -591,26 +686,99 @@ nsFontPSAFM::GetBoundingMetrics(const PRUnichar* aString,
#ifdef MOZ_ENABLE_FREETYPE2
#define WIDEN_8_TO_16_BUF_SIZE 1024
nsFontPS*
nsFontPSFreeType::FindFont(const nsFont& aFont, nsFontMetricsPS* aFontMetrics)
PRBool
nsFontPSFreeType::CSSFontEnumCallback(const nsString& aFamily, PRBool aGeneric,
void* aFpi)
{
fontPSInfo* fpi = (fontPSInfo*)aFpi;
nsCAutoString familyname;
if (aGeneric) {
// need lang to lookup generic pref
if (strlen(fpi->lang.get()) == 0) {
return PR_TRUE; // keep trying
}
nsXPIDLCString value;
nsresult rv;
nsCOMPtr<nsIPref> pref(do_GetService(NS_PREF_CONTRACTID, &rv));
NS_ENSURE_SUCCESS(rv, PR_TRUE); // keep trying
nsCAutoString name("font.name.");
name.AppendWithConversion(aFamily.get());
name.Append(char('.'));
name.Append(fpi->lang);
pref->CopyCharPref(name.get(), getter_Copies(value));
if (!value.get())
return PR_TRUE; // keep trying
// strip down to just the family name
PRUint32 startFamily = value.FindChar('-') + 1;
PRUint32 endFamily = value.FindChar('-', startFamily);
familyname.Append(Substring(value, startFamily, endFamily - startFamily));
FIND_FONTPS_PRINTF(("generic font \"%s\" -> \"%s\"", name.get(),
familyname.get()));
}
else
familyname.AppendWithConversion(aFamily);
AddFontEntries(familyname, fpi->lang, fpi->weight,
nsIFontCatalogService::kFCWidthAny, fpi->slant,
nsIFontCatalogService::kFCSpacingAny, fpi);
return PR_TRUE;
}
PRBool
nsFontPSFreeType::AddUserPref(nsIAtom *aLang, const nsFont& aFont,
fontPSInfo *aFpi)
{
nsCAutoString emptyStr;
fontPSInfo *fpi = (fontPSInfo*)aFpi;
nsresult rv = NS_OK;
nsCAutoString fontName;
nsCOMPtr<nsIPref> pref(do_GetService(NS_PREF_CONTRACTID, &rv));
NS_ENSURE_SUCCESS(rv, PR_FALSE);
nsCOMPtr<nsIAtom> lang;
aFontMetrics->GetLangGroup(getter_AddRefs(lang));
NS_ENSURE_TRUE(lang, nsnull);
nsXPIDLCString value;
pref->CopyCharPref("font.default", getter_Copies(value));
if (!value.get())
return PR_FALSE;
nsCOMPtr<nsITrueTypeFontCatalogEntry> entry;
rv = FindFontEntry(aFont, lang, getter_AddRefs(entry));
NS_ENSURE_SUCCESS(rv, nsnull);
NS_ENSURE_TRUE(entry, nsnull);
nsCAutoString name("font.name.");
name.Append(value);
name.Append(char('.'));
name.Append(fpi->lang);
pref->CopyCharPref(name.get(), getter_Copies(value));
if (!value.get())
return PR_FALSE;
// strip down to just the family name
PRUint32 startFamily = value.FindChar('-') + 1;
PRUint32 endFamily = value.FindChar('-', startFamily);
fontName.Append(Substring(value, startFamily, endFamily - startFamily));
AddFontEntries(fontName, fpi->lang, fpi->weight,
nsIFontCatalogService::kFCWidthAny, fpi->slant,
nsIFontCatalogService::kFCSpacingAny, fpi);
// wildcard the language
AddFontEntries(fontName, emptyStr, fpi->weight,
nsIFontCatalogService::kFCWidthAny, fpi->slant,
nsIFontCatalogService::kFCSpacingAny, fpi);
return PR_TRUE;
}
static nsFontPS*
CreateFontPS(nsITrueTypeFontCatalogEntry *aEntry, const nsFont& aFont,
nsFontMetricsPS* aFontMetrics)
{
nsresult rv;
nsDeviceContextPS* dc = aFontMetrics->GetDeviceContext();
NS_ENSURE_TRUE(dc, nsnull);
nsCAutoString familyName, styleName;
entry->GetFamilyName(familyName);
entry->GetStyleName(styleName);
aEntry->GetFamilyName(familyName);
aEntry->GetStyleName(styleName);
ToLowerCase(familyName);
ToLowerCase(styleName);
@ -627,128 +795,240 @@ nsFontPSFreeType::FindFont(const nsFont& aFont, nsFontMetricsPS* aFontMetrics)
if (!psFontGen) {
psFontGen = new nsFT2Type8Generator;
NS_ENSURE_TRUE(psFontGen, nsnull);
rv = ((nsFT2Type8Generator*)psFontGen)->Init(entry);
rv = ((nsFT2Type8Generator*)psFontGen)->Init(aEntry);
if (NS_FAILED(rv)) {
delete psFontGen;
return nsnull;
}
psFGList->Put(&key, (void *) psFontGen);
}
nsFontPSFreeType* fontPS = new nsFontPSFreeType(aFont, aFontMetrics);
NS_ENSURE_TRUE(fontPS, nsnull);
rv = fontPS->Init(entry, psFontGen);
nsFontPSFreeType* font = new nsFontPSFreeType(aFont, aFontMetrics);
NS_ENSURE_TRUE(font, nsnull);
rv = font->Init(aEntry, psFontGen);
if (NS_FAILED(rv)) {
delete fontPS;
delete font;
return nsnull;
}
return (nsFontPS*)fontPS;
return font;
}
typedef struct {
nsVoidArray *fontNames;
nsVoidArray *isGeneric;
} font_enum_info;
static PRBool PR_CALLBACK
GenericFontEnumCallback(const nsString& aFamily, PRBool aGeneric, void* aData)
nsFontPS*
nsFontPSFreeType::FindFont(PRUnichar aChar, const nsFont& aFont,
nsFontMetricsPS* aFontMetrics)
{
font_enum_info* fei = NS_STATIC_CAST(font_enum_info*, aData);
char* name = ToNewCString(aFamily);
if (name) {
fei->fontNames->AppendElement(name);
fei->isGeneric->AppendElement((void*)aGeneric);
return PR_TRUE;
}
return PR_FALSE;
}
nsresult
nsFontPSFreeType::FindFontEntry(const nsFont& aFont, nsIAtom* aLanguage,
nsITrueTypeFontCatalogEntry** aEntry)
{
font_enum_info fei;
nsresult rv = NS_OK;
nsCOMPtr<nsIPref> pref(do_GetService(NS_PREF_CONTRACTID, &rv));
NS_ENSURE_SUCCESS(rv, rv);
PRUint16 weight = NS_IS_BOLD(aFont.weight)
? (PRUint16)nsIFontCatalogService::kFCWeightBold
: (PRUint16)nsIFontCatalogService::kFCWeightMedium;
PRUint16 slant = aFont.style;
nsVoidArray fontNames;
nsVoidArray isGeneric;
fei.fontNames = &fontNames;
fei.isGeneric = &isGeneric;
// ignore return value
aFont.EnumerateFamilies(GenericFontEnumCallback, &fei);
const PRUnichar* langStr = nsnull;
aLanguage->GetUnicode(&langStr);
nsCAutoString language;
language.AppendWithConversion(langStr);
*aEntry = nsnull;
PRInt32 i;
PRBool inited = PR_FALSE;
int anyWeight = nsIFontCatalogService::kFCWeightAny;
int anyWidth = nsIFontCatalogService::kFCWidthAny;
int anySlant = nsIFontCatalogService::kFCSlantAny;
int anySpacing = nsIFontCatalogService::kFCSpacingAny;
nsCOMPtr<nsIAtom> lang;
nsCAutoString emptyStr;
for (i = 0; i<fontNames.Count(); i++) {
nsCAutoString fontName;
void *tmp = isGeneric[i];
PRBool isGeneric = (PRBool)tmp;
if (isGeneric) {
//lookup the font pref
nsXPIDLCString value;
nsCAutoString fontNameKey("font.name.");
fontNameKey.Append((char *)fontNames[i]);
fontNameKey.Append(char('.'));
fontNameKey.Append(language);
pref->GetCharPref(fontNameKey.get(), getter_Copies(value));
free(fontNames[i]);
if (!value.get())
nsCAutoString locale;
fontPSInfo fpi, fpi2;
fpi.fontps = aFontMetrics->GetFontsPS();
int i = 0;
nsCAutoString familyName, stylename;
while (1) {
//
// see if it is already in the list of fonts
//
for (; i<fpi.fontps->Count(); i++) {
fontps *fi = (fontps *)fpi.fontps->ElementAt(i);
if (!fi->entry || !fi->ccmap) {
NS_ASSERTION(fi->entry, "invalid entry");
NS_ASSERTION(fi->ccmap, "invalid ccmap");
continue;
// strip down to just the family name
PRUint32 startFamily = value.FindChar('-') + 1;
PRUint32 endFamily = value.FindChar('-', startFamily + 1);
fontName.Append(Substring(value, startFamily, endFamily - startFamily));
}
if (CCMAP_HAS_CHAR(fi->ccmap, aChar)) {
if (!fi->fontps) {
if (gFontPSDebug & NS_FONTPS_DEBUG_FIND_FONT) {
fi->entry->GetFamilyName(familyName);
fi->entry->GetStyleName(stylename);
FIND_FONTPS_PRINTF(("CreateFontPS %s/%s", familyName.get(),
stylename.get()));
}
fi->fontps = CreateFontPS(fi->entry, aFont, aFontMetrics);
}
if (fi->fontps)
return fi->fontps;
}
}
else {
fontName.Append((char *)fontNames[i]);
//
// it is not already in the list of fonts
// so add more fonts to the list
//
if (!inited) {
fpi.nsfont = &aFont;
fpi.alreadyLoaded = aFontMetrics->GetFontsAlreadyLoadedList();
aFontMetrics->GetLangGroup(getter_AddRefs(lang));
if (!lang)
lang = NS_NewAtom("x-western");
const PRUnichar *langStr;
lang->GetUnicode(&langStr);
if (langStr)
fpi.lang.AppendWithConversion(langStr);
gUsersLocale->GetUnicode(&langStr);
if (langStr)
locale.AppendWithConversion(langStr);
if (NS_IS_BOLD(fpi.nsfont->weight))
fpi.weight = nsIFontCatalogService::kFCWeightBold;
else
fpi.weight = nsIFontCatalogService::kFCWeightMedium;
if (fpi.nsfont->style == NS_FONT_STYLE_NORMAL)
fpi.slant = nsIFontCatalogService::kFCSlantRoman;
else
fpi.slant = nsIFontCatalogService::kFCSlantItalic;
inited = PR_TRUE;
}
ToLowerCase(fontName);
rv = GetFontEntry(fontName, language, weight, 0, slant, 0, aEntry);
NS_ENSURE_SUCCESS(rv, rv);
if (*aEntry) return rv;
rv = GetFontEntry(fontName, emptyStr, weight, 0, slant, 0, aEntry);
NS_ENSURE_SUCCESS(rv, rv);
if (*aEntry) return rv;
//
// Add fonts to the list following the CSS spec, user pref
// After that slowly loosen the spec to enlarge the list
//
int state = aFontMetrics->GetFontPSState();
aFontMetrics->IncrementFontPSState();
rv = GetFontEntry(fontName, emptyStr, 0, 0, 0, 0, aEntry);
NS_ENSURE_SUCCESS(rv, rv);
if (*aEntry) return rv;
switch (state) {
case 0:
FIND_FONTPS_PRINTF(("get the CSS specified entries for the element's "
"language"));
aFont.EnumerateFamilies(nsFontPSFreeType::CSSFontEnumCallback, &fpi);
break;
case 1:
FIND_FONTPS_PRINTF(("get the CSS specified entries for the user's "
"locale"));
fpi2 = fpi;
fpi2.lang = locale;
aFont.EnumerateFamilies(nsFontPSFreeType::CSSFontEnumCallback, &fpi2);
break;
case 2:
FIND_FONTPS_PRINTF(("get the CSS specified entries for any language"));
fpi2 = fpi;
fpi2.lang = emptyStr;
aFont.EnumerateFamilies(nsFontPSFreeType::CSSFontEnumCallback, &fpi2);
break;
case 3:
FIND_FONTPS_PRINTF(("get the user pref for the element's language"));
AddUserPref(lang, aFont, &fpi);
break;
case 4:
FIND_FONTPS_PRINTF(("get the user pref for the user's locale"));
fpi2 = fpi;
fpi2.lang = locale;
aFont.EnumerateFamilies(nsFontPSFreeType::CSSFontEnumCallback, &fpi2);
break;
case 5:
FIND_FONTPS_PRINTF(("get all the entries for this language/style"));
AddFontEntries(emptyStr, fpi.lang, fpi.weight, anyWidth, fpi.slant,
anySpacing, &fpi);
break;
case 6:
FIND_FONTPS_PRINTF(("get all the entries for the locale/style"));
AddFontEntries(emptyStr, locale, fpi.weight, anyWidth, fpi.slant,
anySpacing, &fpi);
break;
case 7:
FIND_FONTPS_PRINTF(("wildcard the slant/weight variations of CSS"
"specified entries for the element's language"));
fpi2 = fpi;
fpi2.weight = anyWeight;
fpi2.slant = 0;
aFont.EnumerateFamilies(nsFontPSFreeType::CSSFontEnumCallback, &fpi2);
break;
case 8:
FIND_FONTPS_PRINTF(("wildcard the slant/weight variations of CSS "
"specified entries for the user's locale"));
fpi2 = fpi;
fpi2.lang = locale;
fpi2.weight = anyWeight;
fpi2.slant = 0;
aFont.EnumerateFamilies(nsFontPSFreeType::CSSFontEnumCallback, &fpi2);
break;
case 9:
FIND_FONTPS_PRINTF(("wildcard the slant/weight variations of CSS "
"specified entries for any language"));
fpi2 = fpi;
fpi2.lang = emptyStr;
fpi2.weight = anyWeight;
fpi2.slant = 0;
aFont.EnumerateFamilies(nsFontPSFreeType::CSSFontEnumCallback, &fpi2);
break;
case 10:
FIND_FONTPS_PRINTF(("wildcard the slant/weight variations of the user "
"pref"));
fpi2 = fpi;
fpi2.lang = emptyStr;
fpi2.weight = anyWeight;
fpi2.slant = 0;
AddUserPref(lang, aFont, &fpi2);
break;
case 11:
FIND_FONTPS_PRINTF(("wildcard the slant/weight variations for this "
"language"));
AddFontEntries(emptyStr, fpi.lang, anyWeight, anyWidth, anySlant,
anySpacing, &fpi);
break;
case 12:
FIND_FONTPS_PRINTF(("wildcard the slant/weight variations of the "
"locale"));
AddFontEntries(emptyStr, locale, anyWeight, anyWidth, anySlant,
anySpacing, &fpi);
break;
case 13:
FIND_FONTPS_PRINTF(("get ALL font entries"));
AddFontEntries(emptyStr, emptyStr, anyWeight, anyWidth, anySlant,
anySpacing, &fpi);
break;
default:
// try to always return a font even if no font supports this char
if (fpi.fontps->Count()) {
FIND_FONTPS_PRINTF(("failed to find a font supporting 0x%04x so "
"returning 1st font in list", aChar));
fontps *fi = (fontps *)fpi.fontps->ElementAt(0);
if (!fi->fontps)
fi->fontps = CreateFontPS(fi->entry, aFont, aFontMetrics);
return fi->fontps;
}
FIND_FONTPS_PRINTF(("failed to find a font supporting 0x%04x", aChar));
return (nsnull);
}
}
rv = GetFontEntry(emptyStr, language, weight, 0, slant, 0, aEntry);
NS_ENSURE_SUCCESS(rv, rv);
if (*aEntry) return rv;
rv = GetFontEntry(emptyStr, language, 0, 0, 0, 0, aEntry);
NS_ENSURE_SUCCESS(rv, rv);
if (*aEntry) return rv;
return rv;
return nsnull;
}
nsresult
nsFontPSFreeType::GetFontEntry(nsACString& aFamilyName, nsACString& aLanguage,
PRUint16 aWeight, PRUint16 aWidth,
PRUint16 aSlant, PRUint16 aSpacing,
nsITrueTypeFontCatalogEntry** aEntry)
nsFontPSFreeType::AddFontEntries(nsACString& aFamilyName, nsACString& aLanguage,
PRUint16 aWeight, PRUint16 aWidth,
PRUint16 aSlant, PRUint16 aSpacing,
fontPSInfo* aFpi)
{
nsresult rv = NS_OK;
nsCAutoString name(aFamilyName);
nsCAutoString lang(aLanguage);
ADD_ENTRY_FONTPS_PRINTF((" family = '%s'", name.get()));
ADD_ENTRY_FONTPS_PRINTF((" lang = '%s'", lang.get()));
ADD_ENTRY_FONTPS_PRINTF((" aWeight = %d", aWeight));
ADD_ENTRY_FONTPS_PRINTF((" aWidth = %d", aWidth));
ADD_ENTRY_FONTPS_PRINTF((" aSlant = %d", aSlant));
ADD_ENTRY_FONTPS_PRINTF((" aSpacing = %d", aSpacing));
nsCOMPtr<nsIFontCatalogService> fcs(do_GetService(kFCSCID, &rv));
NS_ENSURE_SUCCESS(rv, rv);
@ -759,23 +1039,49 @@ nsFontPSFreeType::GetFontEntry(nsACString& aFamilyName, nsACString& aLanguage,
getter_AddRefs(entryList));
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 count = 0;
PRUint32 i, count = 0;
NS_ENSURE_TRUE(entryList, NS_ERROR_FAILURE);
rv = entryList->Count(&count);
NS_ENSURE_SUCCESS(rv, rv);
ADD_ENTRY_FONTPS_PRINTF((" count = %d", count));
*aEntry = nsnull;
if (count > 0) {
for (i=0; i<count; i++) {
nsCOMPtr<nsISupports> item;
rv = entryList->GetElementAt(0, getter_AddRefs(item));
rv = entryList->GetElementAt(i, getter_AddRefs(item));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsITrueTypeFontCatalogEntry> entry(do_QueryInterface(item, &rv));
NS_ENSURE_SUCCESS(rv, rv);
*aEntry = entry;
NS_IF_ADDREF(*aEntry);
nsCAutoString fontname, stylename;
if (gFontPSDebug & NS_FONTPS_DEBUG_ADD_ENTRY) {
entry->GetFamilyName(fontname);
entry->GetStyleName(stylename);
}
// check if already in list
nsVoidKey key((void*)entry);
if (aFpi->alreadyLoaded->Get(&key)) {
ADD_ENTRY_FONTPS_PRINTF((" -- '%s/%s' already loaded",
fontname.get(), stylename.get()));
continue;
}
ADD_ENTRY_FONTPS_PRINTF((" load '%s/%s'", fontname.get(),
stylename.get()));
PRUint16 *ccmap;
PRUint32 size;
entry->GetCCMap(&size, &ccmap);
nsITrueTypeFontCatalogEntry *e = entry;
NS_IF_ADDREF(e);
fontps *fps = new fontps;
NS_ENSURE_TRUE(fps, NS_ERROR_OUT_OF_MEMORY);
fps->entry = entry;
fps->fontps = nsnull;
fps->ccmap = ccmap;
aFpi->fontps->AppendElement(fps);
aFpi->alreadyLoaded->Put(&key, (void*)1);
}
return rv;
@ -825,17 +1131,17 @@ nscoord
nsFontPSFreeType::GetWidth(const char* aString, PRUint32 aLength)
{
PRUnichar unichars[WIDEN_8_TO_16_BUF_SIZE];
PRUint32 len, length = 0;
PRUint32 len, width = 0;
while ( aLength > 0 ) {
len = PR_MIN(aLength, WIDEN_8_TO_16_BUF_SIZE);
for (PRUint32 i=0; i < len; i++) {
unichars[i] = (PRUnichar)((unsigned char)aString[i]);
}
length += GetWidth(unichars, len);
width += GetWidth(unichars, len);
aString += len;
aLength -= len;
}
return length;
return width;
}
@ -844,7 +1150,7 @@ nsFontPSFreeType::GetWidth(const PRUnichar* aString, PRUint32 aLength)
{
FT_UInt glyph_index;
FT_Glyph glyph;
FT_Pos origin_x = 0;
double origin_x = 0;
// get the face/size from the FreeType cache
FT_Face face = getFTFace();
@ -864,10 +1170,10 @@ nsFontPSFreeType::GetWidth(const PRUnichar* aString, PRUint32 aLength)
nsresult rv = mFt2->ImageCacheLookup(iCache, &mImageDesc,
glyph_index, &glyph);
if (NS_FAILED(rv)) {
origin_x += face->size->metrics.x_ppem/2 + 2;
origin_x += FT_REG_TO_16_16(face->size->metrics.x_ppem/2 + 2);
continue;
}
origin_x += FT_16_16_TO_REG(glyph->advance.x);
origin_x += glyph->advance.x;
}
NS_ENSURE_TRUE(mFontMetrics, 0);
@ -877,8 +1183,10 @@ nsFontPSFreeType::GetWidth(const PRUnichar* aString, PRUint32 aLength)
float dev2app;
dc->GetDevUnitsToAppUnits(dev2app);
origin_x *= dev2app;
origin_x /= FT_REG_TO_16_16(1);
return NSToCoordRound(origin_x * dev2app);
return NSToCoordRound((nscoord)origin_x);
}
FT_Face
@ -904,6 +1212,7 @@ nsFontPSFreeType::DrawString(nsRenderingContextPS* aContext,
NS_ENSURE_TRUE(aContext, 0);
nsPostScriptObj* psObj = aContext->GetPostScriptObj();
NS_ENSURE_TRUE(psObj, 0);
nscoord width = 0;
psObj->moveto(aX, aY);
@ -917,10 +1226,11 @@ nsFontPSFreeType::DrawString(nsRenderingContextPS* aContext,
}
psObj->show(unichars, len, "", 1);
mPSFontGenerator->AddToSubset(unichars, len);
width += GetWidth(unichars, len);
aString += len;
aLength -= len;
}
return GetWidth(aString, aLength);
return width;
}
nscoord

View File

@ -51,6 +51,8 @@
#include "nsCompressedCharMap.h"
#include "nsPostScriptObj.h"
#include "nsIFontCatalogService.h"
#include "nsVoidArray.h"
#include "nsHashtable.h"
class nsPSFontGenerator;
class nsDeviceContextPS;
@ -114,8 +116,12 @@ public:
inline void SetAveCharWidth(nscoord aAveCharWidth) { mAveCharWidth = aAveCharWidth; };
inline void SetSpaceWidth(nscoord aSpaceWidth) { mSpaceWidth = aSpaceWidth; };
inline nsFontPS* GetFontPS() { return mFontPS; }
inline nsDeviceContextPS* GetDeviceContext() { return mDeviceContext; }
inline nsFont* GetFont() { return mFont; };
inline nsVoidArray* GetFontsPS() { return mFontsPS; };
inline nsHashtable *GetFontsAlreadyLoadedList() {return mFontsAlreadyLoaded;};
inline int GetFontPSState() { return mFontPSState; };
inline void IncrementFontPSState() { mFontPSState++; };
#if defined(XP_WIN)
// this routine is defined here so the PostScript module can be debugged
@ -157,7 +163,9 @@ protected:
nscoord mSpaceWidth;
nscoord mAveCharWidth;
nsFontPS* mFontPS;
nsVoidArray *mFontsPS;
nsHashtable *mFontsAlreadyLoaded;
int mFontPSState;
};
class nsFontPS
@ -168,7 +176,10 @@ public:
virtual ~nsFontPS();
NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
static nsFontPS* FindFont(const nsFont& aFont, nsFontMetricsPS* aFontMetrics);
static nsFontPS* FindFont(char aChar, const nsFont& aFont,
nsFontMetricsPS* aFontMetrics);
static nsFontPS* FindFont(PRUnichar aChar, const nsFont& aFont,
nsFontMetricsPS* aFontMetrics);
static nsPSFontGenerator* GetPSFontGenerator(nsFontMetricsPS* aFontMetrics,
nsCStringKey& aKey);
inline PRInt32 SupportsChar(PRUnichar aChar)
@ -239,20 +250,39 @@ public:
nsString mFamilyName;
};
typedef struct {
nsITrueTypeFontCatalogEntry *entry;
nsFontPS *fontps;
unsigned short *ccmap;
} fontps;
#ifdef MOZ_ENABLE_FREETYPE2
#include "nsIFreeType2.h"
typedef struct {
nsVoidArray *fontps;
const nsFont* nsfont;
nsCAutoString lang;
nsHashtable *alreadyLoaded;
PRUint16 slant;
PRUint16 weight;
} fontPSInfo;
class nsFontPSFreeType : public nsFontPS
{
public:
static nsFontPS* FindFont(const nsFont& aFont, nsFontMetricsPS* aFontMetrics);
static nsFontPS* FindFont(PRUnichar aChar, const nsFont& aFont,
nsFontMetricsPS* aFontMetrics);
static nsresult FindFontEntry(const nsFont& aFont, nsIAtom* aLanguage,
nsITrueTypeFontCatalogEntry** aEntry);
static nsresult GetFontEntry(nsACString& aFamilyName, nsACString& aLanguage,
PRUint16 aWeight, PRUint16 aWidth,
PRUint16 aSlant, PRUint16 aSpacing,
nsITrueTypeFontCatalogEntry** aEntry);
static nsresult AddFontEntries(nsACString& aFamilyName,
nsACString& aLanguage,
PRUint16 aWeight, PRUint16 aWidth,
PRUint16 aSlant, PRUint16 aSpacing,
fontPSInfo* aFpi);
static PRBool CSSFontEnumCallback(const nsString& aFamily, PRBool aGeneric,
void* aFpi);
nsresult Init(nsITrueTypeFontCatalogEntry* aEntry,
nsPSFontGenerator* aPSFontGen);
@ -292,6 +322,8 @@ protected:
FTC_Image_Desc mImageDesc;
static PRBool AddUserPref(nsIAtom *aLang, const nsFont& aFont,
fontPSInfo *aFpi);
int ascent();
int descent();
PRBool getXHeight(unsigned long &aVal);

View File

@ -0,0 +1,77 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* ex: set tabstop=8 softtabstop=2 shiftwidth=2 expandtab:
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Golden Hills Computer Services code.
*
* The Initial Developer of the Original Code is
* Brian Stell <bstell@ix.netcom.com>.
*
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Stell <bstell@ix.netcom.com>.
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsFontPSDebug_h__
#define nsFontPSDebug_h__
#define NS_FONTPS_DEBUG_FIND_FONT 0x01
#define NS_FONTPS_DEBUG_ADD_ENTRY 0x02
#undef NS_FONTPS_DEBUG
#define NS_FONTPS_DEBUG 1
#ifdef NS_FONTPS_DEBUG
# define DEBUG_PRINTF(x) \
DEBUG_PRINTF_MACRO(x, 0xFFFF)
# define DEBUG_PRINTF_MACRO(x, type) \
PR_BEGIN_MACRO \
if (gFontPSDebug & (type)) { \
printf x ; \
printf(", %s %d\n", __FILE__, __LINE__); \
} \
PR_END_MACRO
#else
# define DEBUG_PRINTF_MACRO(x, type) \
PR_BEGIN_MACRO \
PR_END_MACRO
#endif
#define FIND_FONTPS_PRINTF(x) \
DEBUG_PRINTF_MACRO(x, NS_FONTPS_DEBUG_FIND_FONT)
#define ADD_ENTRY_FONTPS_PRINTF(x) \
DEBUG_PRINTF_MACRO(x, NS_FONTPS_DEBUG_ADD_ENTRY)
extern PRUint32 gFontPSDebug;
#endif

View File

@ -1100,33 +1100,37 @@ nsRenderingContextPS :: DrawString(const char *aString, PRUint32 aLength,
nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE);
nsFontPS* fontPS = metrics->GetFontPS();
nsCOMPtr<nsIAtom> langGroup;
mFontMetrics->GetLangGroup(getter_AddRefs(langGroup));
mPSObj->setlanggroup(langGroup);
if (aLength == 0)
return NS_OK;
nsFontPS* fontPS = nsFontPS::FindFont(aString[0], *metrics->GetFont(), metrics);
NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE);
PRInt32 x = aX;
PRInt32 y = aY;
mPSObj->setlanggroup(nsnull);
fontPS->SetupFont(this);
PRInt32 dxMem[500];
PRInt32* dx0 = 0;
if (aSpacing) {
dx0 = dxMem;
if (aLength > 500) {
dx0 = new PRInt32[aLength];
NS_ENSURE_TRUE(dx0, NS_ERROR_OUT_OF_MEMORY);
PRUint32 i, start = 0;
for (i=0; i<aLength; i++) {
nsFontPS* fontThisChar;
fontThisChar = nsFontPS::FindFont(aString[i], *metrics->GetFont(), metrics);
NS_ENSURE_TRUE(fontThisChar, NS_ERROR_FAILURE);
if (fontThisChar != fontPS) {
// draw text up to this point
aX += DrawString(aString+start, i-start, aX, aY, fontPS,
aSpacing?aSpacing+start:nsnull);
start = i;
// setup for following text
fontPS = fontThisChar;
fontPS->SetupFont(this);
}
mTranMatrix->ScaleXCoords(aSpacing, aLength, dx0);
}
mTranMatrix->TransformCoord(&x, &y);
fontPS->DrawString(this, NS_PIXELS_TO_POINTS(x), NS_PIXELS_TO_POINTS(y), aString, aLength);
if ((aSpacing) && (dx0 != dxMem)) {
delete [] dx0;
}
// draw the last part
if (aLength-start)
DrawString(aString+start, aLength-start, aX, aY, fontPS,
aSpacing?aSpacing+start:nsnull);
return NS_OK;
}
@ -1145,12 +1149,6 @@ nsRenderingContextPS :: DrawString(const PRUnichar *aString, PRUint32 aLength,
nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE);
nsFontPS* fontPS = metrics->GetFontPS();
NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE);
PRInt32 x = aX;
PRInt32 y = aY;
nsCOMPtr<nsIAtom> langGroup = nsnull;
mFontMetrics->GetLangGroup(getter_AddRefs(langGroup));
mPSObj->setlanggroup(langGroup.get());
@ -1158,8 +1156,77 @@ nsRenderingContextPS :: DrawString(const PRUnichar *aString, PRUint32 aLength,
/* build up conversion table */
mPSObj->preshow(aString, aLength);
if (aLength == 0)
return NS_OK;
nsFontPS* fontPS = nsFontPS::FindFont(aString[0], *metrics->GetFont(), metrics);
NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE);
fontPS->SetupFont(this);
PRUint32 i, start = 0;
for (i=0; i<aLength; i++) {
nsFontPS* fontThisChar;
fontThisChar = nsFontPS::FindFont(aString[i], *metrics->GetFont(), metrics);
NS_ENSURE_TRUE(fontThisChar, NS_ERROR_FAILURE);
if (fontThisChar != fontPS) {
// draw text up to this point
aX += DrawString(aString+start, i-start, aX, aY, fontPS,
aSpacing?aSpacing+start:nsnull);
start = i;
// setup for following text
fontPS = fontThisChar;
fontPS->SetupFont(this);
}
}
// draw the last part
if (aLength-start)
DrawString(aString+start, aLength-start, aX, aY, fontPS,
aSpacing?aSpacing+start:nsnull);
return NS_OK;
}
PRInt32
nsRenderingContextPS::DrawString(const char *aString, PRUint32 aLength,
nscoord &aX, nscoord &aY, nsFontPS* aFontPS,
const nscoord* aSpacing)
{
nscoord width = 0;
PRInt32 x = aX;
PRInt32 y = aY;
PRInt32 dxMem[500];
PRInt32* dx0 = 0;
if (aSpacing) {
dx0 = dxMem;
if (aLength > 500) {
dx0 = new PRInt32[aLength];
NS_ENSURE_TRUE(dx0, NS_ERROR_OUT_OF_MEMORY);
}
mTranMatrix->ScaleXCoords(aSpacing, aLength, dx0);
}
mTranMatrix->TransformCoord(&x, &y);
width = aFontPS->DrawString(this, NS_PIXELS_TO_POINTS(x), NS_PIXELS_TO_POINTS(y), aString, aLength);
if ((aSpacing) && (dx0 != dxMem)) {
delete [] dx0;
}
return width;
}
PRInt32
nsRenderingContextPS::DrawString(const PRUnichar *aString, PRUint32 aLength,
nscoord aX, nscoord aY, nsFontPS* aFontPS,
const nscoord* aSpacing)
{
nscoord width = 0;
PRInt32 x = aX;
PRInt32 y = aY;
if (aSpacing) {
// Slow, but accurate rendering
const PRUnichar* end = aString + aLength;
@ -1167,16 +1234,17 @@ nsRenderingContextPS :: DrawString(const PRUnichar *aString, PRUint32 aLength,
x = aX;
y = aY;
mTranMatrix->TransformCoord(&x, &y);
fontPS->DrawString(this, NS_PIXELS_TO_POINTS(x), NS_PIXELS_TO_POINTS(y), aString, 1);
aFontPS->DrawString(this, NS_PIXELS_TO_POINTS(x), NS_PIXELS_TO_POINTS(y), aString, 1);
aX += *aSpacing++;
aString++;
}
width = aX;
} else {
mTranMatrix->TransformCoord(&x, &y);
fontPS->DrawString(this, NS_PIXELS_TO_POINTS(x), NS_PIXELS_TO_POINTS(y), aString, aLength);
width = aFontPS->DrawString(this, NS_PIXELS_TO_POINTS(x), NS_PIXELS_TO_POINTS(y), aString, aLength);
}
return NS_OK;
return width;
}
/** ---------------------------------------------------

View File

@ -165,6 +165,14 @@ public:
NS_IMETHOD DrawString(const nsString& aString, nscoord aX, nscoord aY,
PRInt32 aFontID,
const nscoord* aSpacing);
protected:
PRInt32 DrawString(const PRUnichar *aString, PRUint32 aLength,
nscoord aX, nscoord aY, nsFontPS* aFontPS,
const nscoord* aSpacing);
PRInt32 DrawString(const char *aString, PRUint32 aLength,
nscoord &aX, nscoord &aY, nsFontPS* aFontPS,
const nscoord* aSpacing);
public:
NS_IMETHOD GetTextDimensions(const char* aString, PRUint32 aLength,
nsTextDimensions& aDimensions);

View File

@ -66,7 +66,7 @@
static void hex_out(unsigned char *buf, PRUint32 n, FILE *f, PRUint32 *pos);
static void spaces_to_underlines(char *aToName);
static void flatten_name(char *aToName);
static int FT2SubsetToCidKeyedType1(nsIFreeType2 *aFt2, FT_Face aFace,
const PRUnichar *aCharIDs, int aLen,
const char *aFontName,
@ -193,7 +193,7 @@ FT2ToType1FontName(FT_Face aFace, int aWmode)
}
sprintf(fontname, "%s.%s.%ld.%d", aFace->family_name, aFace->style_name,
aFace->face_index, aWmode?1:0);
spaces_to_underlines(fontname);
flatten_name(fontname);
return fontname;
}
@ -587,11 +587,15 @@ FT2SubsetToCidKeyedType1(nsIFreeType2 *aFt2, FT_Face aFace,
}
static void
spaces_to_underlines(char *aString)
flatten_name(char *aString)
{
for (; *aString; aString++) {
if (*aString == ' ')
*aString = '_';
else if (*aString == '(')
*aString = '_';
else if (*aString == ')')
*aString = '_';
}
}

View File

@ -720,6 +720,8 @@ nsFT2FontCatalog::GetFontNames(const nsACString & aFamilyName,
nsFontCatalog* aFC)
{
int i;
PRUint16 min_weight = PR_MAX(0, aWeight-125);
PRUint16 max_weight = PR_MIN(999, aWeight+125);
nsCAutoString familyName, language;
FONT_CATALOG_PRINTF(("looking for FreeType font matching"));
@ -761,28 +763,18 @@ nsFT2FontCatalog::GetFontNames(const nsACString & aFamilyName,
}
/* column headers for the debug output*/
FONT_CATALOG_PRINTF(("%s\t%-20s\t%-8s\t%-8s\t%-8s%-8s%-8s\t%-8s\t%-8s",
FONT_CATALOG_PRINTF(("%s\t%-20s\t%-8s\t%-8s\t%-8s%-8s%-8s\t%-8s\t",
"mFlags",
"mFamilyName",
"CodePageRange1",
"mCodePageRange1",
"mCodePageRange2",
"mWeight",
"mWidth",
"mStyleFlags",
"fce->mFaceFlags",
"Ismatched"));
"fce->mFaceFlags"));
for (i=0; i<mFontCatalog->numFonts; i++) {
nsFontCatalogEntry *fce = mFontCatalog->fonts[i];
FONT_CATALOG_PRINTF(("%0x\t%-20s\t%08lx\t%08lx\t%i\t%i\t%08lx\t%08lx\t",
fce->mFlags,
fce->mFamilyName,
fce->mCodePageRange1,
fce->mCodePageRange2,
fce->mWeight,
fce->mWidth,
fce->mStyleFlags,
fce->mFaceFlags));
// not all "fce" are valid
if (!fce->mFlags&FCE_FLAGS_ISVALID)
continue;
@ -793,23 +785,33 @@ nsFT2FontCatalog::GetFontNames(const nsACString & aFamilyName,
if (!language.IsEmpty() &&
!((fce->mCodePageRange1 & bit1) || (fce->mCodePageRange2 & bit2)))
continue;
// weight
if (aWeight && (aWeight != fce->mWeight))
// weight (the meaning is not well defined so allow some variance)
if ((aWeight != kFCWeightAny)
&& ((fce->mWeight < min_weight) || (fce->mWeight > max_weight)))
continue;
// width
if (aWidth && (aWidth != fce->mWidth))
if ((aWidth != kFCWidthAny) && (aWidth != fce->mWidth))
continue;
// slant
if (aSlant && !((fce->mStyleFlags & FT_STYLE_FLAG_ITALIC) == italicBit))
if ((aSlant != kFCSlantAny)
&& !((fce->mStyleFlags & FT_STYLE_FLAG_ITALIC) == italicBit))
continue;
// spacing
if (aSpacing && !((fce->mFaceFlags & FT_FACE_FLAG_FIXED_WIDTH) == monoBit))
if ((aSpacing != kFCSpacingAny)
&& !((fce->mFaceFlags & FT_FACE_FLAG_FIXED_WIDTH) == monoBit))
continue;
// match all patterns
FONT_CATALOG_PRINTF(("%s", "matching"));
FONT_CATALOG_PRINTF(("%0x\t%-20s\t%08lx\t%08lx\t%i\t%i\t%08lx\t%08lx",
fce->mFlags,
fce->mFamilyName,
fce->mCodePageRange1,
fce->mCodePageRange2,
fce->mWeight,
fce->mWidth,
fce->mStyleFlags,
fce->mFaceFlags));
AddFont(aFC, fce);
}
FONT_CATALOG_PRINTF(("\n"));
return;
}