From 64296389a6448c4d49929f66297433d066c1cbb1 Mon Sep 17 00:00:00 2001 From: "bstell%ix.netcom.com" Date: Fri, 17 Jan 2003 06:51:17 +0000 Subject: [PATCH] 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 --- gfx/idl/nsIFontCatalogService.idl | 14 +- gfx/idl/nsIFreeType2.idl | 1 + gfx/src/ps/Makefile.in | 1 + gfx/src/ps/nsCidMap.cpp | 14 +- gfx/src/ps/nsDeviceContextPS.cpp | 24 + gfx/src/ps/nsFontMetricsPS.cpp | 584 +++++++++++++++++++------ gfx/src/ps/nsFontMetricsPS.h | 48 +- gfx/src/ps/nsFontPSDebug.h | 77 ++++ gfx/src/ps/nsRenderingContextPS.cpp | 128 ++++-- gfx/src/ps/nsRenderingContextPS.h | 8 + gfx/src/ps/nsType8.cpp | 10 +- gfx/src/x11shared/nsFT2FontCatalog.cpp | 42 +- 12 files changed, 745 insertions(+), 206 deletions(-) create mode 100644 gfx/src/ps/nsFontPSDebug.h diff --git a/gfx/idl/nsIFontCatalogService.idl b/gfx/idl/nsIFontCatalogService.idl index 4457085b618..f4e111fbf6b 100644 --- a/gfx/idl/nsIFontCatalogService.idl +++ b/gfx/idl/nsIFontCatalogService.idl @@ -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; }; diff --git a/gfx/idl/nsIFreeType2.idl b/gfx/idl/nsIFreeType2.idl index 45cef4ef3c9..504bc82fe09 100644 --- a/gfx/idl/nsIFreeType2.idl +++ b/gfx/idl/nsIFreeType2.idl @@ -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) %} diff --git a/gfx/src/ps/Makefile.in b/gfx/src/ps/Makefile.in index e7fe711ff84..772bcf79c27 100644 --- a/gfx/src/ps/Makefile.in +++ b/gfx/src/ps/Makefile.in @@ -38,6 +38,7 @@ REQUIRES = xpcom \ widget \ pref \ caps \ + locale \ uconv \ view \ necko \ diff --git a/gfx/src/ps/nsCidMap.cpp b/gfx/src/ps/nsCidMap.cpp index f3fde395728..836af51fa1a 100644 --- a/gfx/src/ps/nsCidMap.cpp +++ b/gfx/src/ps/nsCidMap.cpp @@ -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 %d\n", aCharIDs[i], aCIDs[i]); + for (j=0; j %d\n", aCharIDs[i-1], aCIDs[i-1]); fprintf(aFile, "endcidchar\n\n"); /* setup for next block */ diff --git a/gfx/src/ps/nsDeviceContextPS.cpp b/gfx/src/ps/nsDeviceContextPS.cpp index 9ea78ab14c6..78b1d63c28d 100644 --- a/gfx/src/ps/nsDeviceContextPS.cpp +++ b/gfx/src/ps/nsDeviceContextPS.cpp @@ -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 langService; + langService = do_GetService(NS_LANGUAGEATOMSERVICE_CONTRACTID); + if (langService) { + langService->GetLocaleLanguageGroup(&gUsersLocale); + } + if (!gUsersLocale) { + gUsersLocale = NS_NewAtom("x-western"); + } + return NS_OK; } diff --git a/gfx/src/ps/nsFontMetricsPS.cpp b/gfx/src/ps/nsFontMetricsPS.cpp index 2627e43c3b1..2b7684a5e6a 100644 --- a/gfx/src/ps/nsFontMetricsPS.cpp +++ b/gfx/src/ps/nsFontMetricsPS.cpp @@ -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; iCount(); 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,13 @@ nsFontMetricsPS::RealizeFont() if (mFont && mDeviceContext) { float dev2app; mDeviceContext->GetDevUnitsToAppUnits(dev2app); - mFontPS->RealizeFont(this, dev2app); + fontps *font = (fontps*)mFontsPS->ElementAt(0); + NS_ASSERTION(font && font->entry, "no font available"); + if (font && !font->fontps && font->entry) + font->fontps = CreateFontPS(font->entry, *mFont, this); + NS_ASSERTION(font && font->fontps, "no font available"); + if (font && font->fontps) + font->fontps->RealizeFont(this, dev2app); } } @@ -351,10 +383,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; iGetWidth(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 +416,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; iGetWidth(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 +460,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 +550,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 +560,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 +684,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 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 pref(do_GetService(NS_PREF_CONTRACTID, &rv)); + NS_ENSURE_SUCCESS(rv, PR_FALSE); - nsCOMPtr 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 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 +793,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 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 lang; nsCAutoString emptyStr; - for (i = 0; iGetCharPref(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 (; iCount(); 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 fcs(do_GetService(kFCSCID, &rv)); NS_ENSURE_SUCCESS(rv, rv); @@ -759,23 +1037,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 item; - rv = entryList->GetElementAt(0, getter_AddRefs(item)); + rv = entryList->GetElementAt(i, getter_AddRefs(item)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr 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 +1129,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 +1148,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 +1168,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 +1181,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 +1210,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 +1224,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 diff --git a/gfx/src/ps/nsFontMetricsPS.h b/gfx/src/ps/nsFontMetricsPS.h index 12b64bc018d..798898ef902 100644 --- a/gfx/src/ps/nsFontMetricsPS.h +++ b/gfx/src/ps/nsFontMetricsPS.h @@ -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) @@ -243,16 +254,35 @@ public: #include "nsIFreeType2.h" +typedef struct { + nsITrueTypeFontCatalogEntry *entry; + nsFontPS *fontps; + unsigned short *ccmap; +} fontps; + +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); diff --git a/gfx/src/ps/nsFontPSDebug.h b/gfx/src/ps/nsFontPSDebug.h new file mode 100644 index 00000000000..83198e7ec06 --- /dev/null +++ b/gfx/src/ps/nsFontPSDebug.h @@ -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 . + * + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Brian Stell . + * + * 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 + diff --git a/gfx/src/ps/nsRenderingContextPS.cpp b/gfx/src/ps/nsRenderingContextPS.cpp index 5b6f287bf2c..5f77aaca68a 100644 --- a/gfx/src/ps/nsRenderingContextPS.cpp +++ b/gfx/src/ps/nsRenderingContextPS.cpp @@ -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 langGroup = nsnull; + mFontMetrics->GetLangGroup(getter_AddRefs(langGroup)); + mPSObj->setlanggroup(langGroup.get()); + + 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; iGetFont(), 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 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; iGetFont(), 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; } /** --------------------------------------------------- diff --git a/gfx/src/ps/nsRenderingContextPS.h b/gfx/src/ps/nsRenderingContextPS.h index f5a5a6aa5e6..23de9d4d892 100644 --- a/gfx/src/ps/nsRenderingContextPS.h +++ b/gfx/src/ps/nsRenderingContextPS.h @@ -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); diff --git a/gfx/src/ps/nsType8.cpp b/gfx/src/ps/nsType8.cpp index 3e2678429d6..4f96af9d474 100644 --- a/gfx/src/ps/nsType8.cpp +++ b/gfx/src/ps/nsType8.cpp @@ -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 = '_'; } } diff --git a/gfx/src/x11shared/nsFT2FontCatalog.cpp b/gfx/src/x11shared/nsFT2FontCatalog.cpp index 4923ca115f1..8a3ce3550b2 100644 --- a/gfx/src/x11shared/nsFT2FontCatalog.cpp +++ b/gfx/src/x11shared/nsFT2FontCatalog.cpp @@ -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; inumFonts; 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; }