зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
51fe74d152
Коммит
64296389a6
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
%}
|
||||
|
|
|
@ -38,6 +38,7 @@ REQUIRES = xpcom \
|
|||
widget \
|
||||
pref \
|
||||
caps \
|
||||
locale \
|
||||
uconv \
|
||||
view \
|
||||
necko \
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,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; 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 +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; 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 +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<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 +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<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 +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<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 +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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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 = 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; 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;
|
||||
}
|
||||
|
||||
/** ---------------------------------------------------
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 = '_';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче