|
|
|
|
@@ -51,6 +51,7 @@
|
|
|
|
|
#include "nsIDialogParamBlock.h"
|
|
|
|
|
#include "nsIWindowWatcher.h"
|
|
|
|
|
#include "nsIStringBundle.h"
|
|
|
|
|
#include "nsDoubleHashtable.h"
|
|
|
|
|
|
|
|
|
|
#include "nsMathMLOperators.h"
|
|
|
|
|
#include "nsMathMLChar.h"
|
|
|
|
|
@@ -59,7 +60,6 @@
|
|
|
|
|
//#define NOISY_SEARCH 1
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------------
|
|
|
|
|
static const PRUnichar kSqrChar = PRUnichar(0x221A);
|
|
|
|
|
static const PRUnichar kSpaceCh = PRUnichar(' ');
|
|
|
|
|
static const nsGlyphCode kNullGlyph = {0, 0};
|
|
|
|
|
|
|
|
|
|
@@ -638,6 +638,21 @@ nsGlyphTable::DrawGlyph(nsIRenderingContext& aRenderingContext,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// class to map a Unicode point to a string (used to store the list of
|
|
|
|
|
// fonts preferred for the base size of certain characters, i.e., when
|
|
|
|
|
// stretching doesn't happen with a char, we use its preferred base fonts)
|
|
|
|
|
class nsBaseFontEntry : public PLDHashInt32Entry
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
nsBaseFontEntry(const void* aKey) : PLDHashInt32Entry(aKey) { }
|
|
|
|
|
~nsBaseFontEntry() { };
|
|
|
|
|
|
|
|
|
|
nsString mFontFamily; // a font-family list a-la CSS
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
DECL_DHASH_WRAPPER(nsBaseFontHashtable, nsBaseFontEntry, PRInt32)
|
|
|
|
|
DHASH_WRAPPER(nsBaseFontHashtable, nsBaseFontEntry, PRInt32)
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------------
|
|
|
|
|
// This is the list of all the applicable glyph tables.
|
|
|
|
|
// We will maintain a single global instance that will only reveal those
|
|
|
|
|
@@ -653,6 +668,9 @@ public:
|
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
|
NS_DECL_NSIOBSERVER
|
|
|
|
|
|
|
|
|
|
// Hashtable to cache the preferred fonts of some chars at their base size
|
|
|
|
|
static nsBaseFontHashtable gBaseFonts;
|
|
|
|
|
|
|
|
|
|
// These are placeholders used to cache the indices (in mTableList) of
|
|
|
|
|
// the preferred extension tables for the particular chars.
|
|
|
|
|
// Each stretchy char can have a preferred ordered list of fonts to
|
|
|
|
|
@@ -752,6 +770,7 @@ NS_IMPL_ISUPPORTS1(nsGlyphTableList, nsIObserver);
|
|
|
|
|
// -----------------------------------------------------------------------------------
|
|
|
|
|
// Here is the global list of applicable glyph tables that we will be using
|
|
|
|
|
static nsGlyphTableList* gGlyphTableList = nsnull;
|
|
|
|
|
nsBaseFontHashtable nsGlyphTableList::gBaseFonts;
|
|
|
|
|
PRInt32* nsGlyphTableList::gParts = nsnull;
|
|
|
|
|
PRInt32* nsGlyphTableList::gVariants = nsnull;
|
|
|
|
|
|
|
|
|
|
@@ -804,8 +823,8 @@ nsGlyphTableList::Finalize()
|
|
|
|
|
delete glyphTable;
|
|
|
|
|
}
|
|
|
|
|
// delete the other variables
|
|
|
|
|
if (gParts) delete gParts;
|
|
|
|
|
if (gVariants) delete gVariants;
|
|
|
|
|
delete gParts;
|
|
|
|
|
delete gVariants;
|
|
|
|
|
gParts = gVariants = nsnull;
|
|
|
|
|
gInitialized = PR_FALSE;
|
|
|
|
|
// our oneself will be destroyed when our |Release| is called by the observer
|
|
|
|
|
@@ -1020,14 +1039,46 @@ PreferredFontEnumCallback(const nsString& aFamily, PRBool aGeneric, void *aData)
|
|
|
|
|
return PR_TRUE; // don't stop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// retrieve a pref value set by the user
|
|
|
|
|
static PRBool
|
|
|
|
|
GetPrefValue(nsIPrefBranch* aPrefBranch, const char* aPrefKey, nsString& aPrefValue)
|
|
|
|
|
{
|
|
|
|
|
aPrefValue.Truncate();
|
|
|
|
|
if (aPrefBranch) {
|
|
|
|
|
nsCOMPtr<nsISupportsString> prefString;
|
|
|
|
|
aPrefBranch->GetComplexValue(aPrefKey,
|
|
|
|
|
NS_GET_IID(nsISupportsString),
|
|
|
|
|
getter_AddRefs(prefString));
|
|
|
|
|
if (prefString) {
|
|
|
|
|
prefString->GetData(aPrefValue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return !aPrefValue.IsEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Store the list of preferred extension fonts for this char
|
|
|
|
|
static void
|
|
|
|
|
SetPreferredTableList(PRUnichar aChar, nsACString& aExtension, nsString& aFamilyList)
|
|
|
|
|
SetPreferredFonts(PRUnichar aChar, const char* aExtension, nsString& aFamilyList)
|
|
|
|
|
{
|
|
|
|
|
#ifdef DEBUG_rbs
|
|
|
|
|
char str[50];
|
|
|
|
|
aFamilyList.ToCString(str, sizeof(str));
|
|
|
|
|
printf("Setting preferred fonts for \\u%04X%s: %s\n", aChar, aExtension, str);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (!strcmp(aExtension, ".base")) {
|
|
|
|
|
// fonts to be used for the base size of the char (i.e., no stretching)
|
|
|
|
|
nsBaseFontEntry* entry = nsGlyphTableList::gBaseFonts.AddEntry(aChar);
|
|
|
|
|
if (entry) {
|
|
|
|
|
entry->mFontFamily = aFamilyList;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PRBool isFontForParts;
|
|
|
|
|
if (aExtension.Equals(NS_LITERAL_CSTRING(".parts")))
|
|
|
|
|
if (!strcmp(aExtension, ".parts"))
|
|
|
|
|
isFontForParts = PR_TRUE;
|
|
|
|
|
else if (aExtension.Equals(NS_LITERAL_CSTRING(".variants")))
|
|
|
|
|
else if (!strcmp(aExtension, ".variants"))
|
|
|
|
|
isFontForParts = PR_FALSE;
|
|
|
|
|
else return; // input is not applicable
|
|
|
|
|
|
|
|
|
|
@@ -1082,36 +1133,32 @@ InitGlobals(nsIPresContext* aPresContext)
|
|
|
|
|
{
|
|
|
|
|
NS_ASSERTION(!gInitialized, "Error -- already initialized");
|
|
|
|
|
gInitialized = PR_TRUE;
|
|
|
|
|
PRInt32 count = nsMathMLOperators::CountStretchyOperator();
|
|
|
|
|
PRUint32 count = nsMathMLOperators::CountStretchyOperator();
|
|
|
|
|
if (!count) {
|
|
|
|
|
// nothing to stretch, so why bother...
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Allocate the placeholders for the preferred parts and variants
|
|
|
|
|
nsGlyphTableList::gParts = new PRInt32[count];
|
|
|
|
|
if (!nsGlyphTableList::gParts)
|
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
nsGlyphTableList::gVariants = new PRInt32[count];
|
|
|
|
|
if (!nsGlyphTableList::gVariants) {
|
|
|
|
|
delete nsGlyphTableList::gParts;
|
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
PRInt32 i;
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
|
nsGlyphTableList::gParts[i] = kNotFound; // i.e., -1
|
|
|
|
|
nsGlyphTableList::gVariants[i] = kNotFound; // i.e., -1
|
|
|
|
|
}
|
|
|
|
|
// Allocate gGlyphTableList
|
|
|
|
|
nsresult rv = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
gGlyphTableList = new nsGlyphTableList();
|
|
|
|
|
if (gGlyphTableList) {
|
|
|
|
|
rv = gGlyphTableList->Initialize();
|
|
|
|
|
nsGlyphTableList::gParts = new PRInt32[count];
|
|
|
|
|
nsGlyphTableList::gVariants = new PRInt32[count];
|
|
|
|
|
if (nsGlyphTableList::gParts && nsGlyphTableList::gVariants) {
|
|
|
|
|
rv = gGlyphTableList->Initialize();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
|
if (NS_FAILED(rv) ||
|
|
|
|
|
!gGlyphTableList ||
|
|
|
|
|
!nsGlyphTableList::gParts ||
|
|
|
|
|
!nsGlyphTableList::gVariants) {
|
|
|
|
|
delete gGlyphTableList;
|
|
|
|
|
delete nsGlyphTableList::gParts;
|
|
|
|
|
delete nsGlyphTableList::gVariants;
|
|
|
|
|
if (gGlyphTableList) delete gGlyphTableList;
|
|
|
|
|
gGlyphTableList = nsnull;
|
|
|
|
|
nsGlyphTableList::gParts = nsnull;
|
|
|
|
|
nsGlyphTableList::gVariants = nsnull;
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
@@ -1120,9 +1167,17 @@ InitGlobals(nsIPresContext* aPresContext)
|
|
|
|
|
It will be deleted at shutdown, even if a failure happens below.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
PRUint32 i;
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
|
nsGlyphTableList::gParts[i] = kNotFound; // i.e., -1
|
|
|
|
|
nsGlyphTableList::gVariants[i] = kNotFound; // i.e., -1
|
|
|
|
|
}
|
|
|
|
|
nsGlyphTableList::gBaseFonts.Init(5);
|
|
|
|
|
|
|
|
|
|
nsCAutoString key;
|
|
|
|
|
nsAutoString value;
|
|
|
|
|
nsCOMPtr<nsIPersistentProperties> mathfontProp;
|
|
|
|
|
nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
|
|
|
|
|
|
|
|
|
// Add the math fonts in the gGlyphTableList in order of preference ...
|
|
|
|
|
// Note: we only load font-names at this stage. The actual glyph tables will
|
|
|
|
|
@@ -1140,27 +1195,11 @@ InitGlobals(nsIPresContext* aPresContext)
|
|
|
|
|
|
|
|
|
|
// Get the default list of mathfonts to be used for stretchy characters
|
|
|
|
|
nsFont font(nsnull, 0, 0, 0, 0, 0);
|
|
|
|
|
nsAutoString familyList;
|
|
|
|
|
nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
|
|
|
|
if (prefBranch) {
|
|
|
|
|
// first, try to see if the user has a value in the pref
|
|
|
|
|
nsCOMPtr<nsISupportsString> prefString;
|
|
|
|
|
prefBranch->GetComplexValue("font.mathfont-family",
|
|
|
|
|
NS_GET_IID(nsISupportsString),
|
|
|
|
|
getter_AddRefs(prefString));
|
|
|
|
|
if (prefString) {
|
|
|
|
|
prefString->GetData(familyList);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (familyList.IsEmpty()) {
|
|
|
|
|
// fallback to the default list
|
|
|
|
|
rv = mathfontProp->GetStringProperty(NS_LITERAL_CSTRING("mathfont-family"),
|
|
|
|
|
value);
|
|
|
|
|
NS_NAMED_LITERAL_CSTRING(defaultKey, "font.mathfont-family");
|
|
|
|
|
if (!GetPrefValue(prefBranch, defaultKey.get(), font.name)) {
|
|
|
|
|
// fallback to the internal default list
|
|
|
|
|
rv = mathfontProp->GetStringProperty(defaultKey, font.name);
|
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
font.name.Assign(value);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
font.name.Assign(familyList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Parse the font list and append an entry for each family to gGlyphTableList
|
|
|
|
|
@@ -1175,25 +1214,57 @@ InitGlobals(nsIPresContext* aPresContext)
|
|
|
|
|
AlertMissingFonts(missingFamilyList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Let the particular characters have their preferred extension tables
|
|
|
|
|
// Let the particular characters have their preferred fonts
|
|
|
|
|
|
|
|
|
|
// First, look the prefs of the user
|
|
|
|
|
char **allKey = nsnull;
|
|
|
|
|
prefBranch->GetChildList("font.mathfont-family.", &count, &allKey);
|
|
|
|
|
for (i = 0; i < count; ++i) {
|
|
|
|
|
#ifdef DEBUG_rbs
|
|
|
|
|
char str[50];
|
|
|
|
|
GetPrefValue(prefBranch, allKey[i], value);
|
|
|
|
|
value.ToCString(str, sizeof(str));
|
|
|
|
|
printf("Found user pref %s: %s\n", allKey[i], str);
|
|
|
|
|
#endif
|
|
|
|
|
if ((30 < strlen(allKey[i])) &&
|
|
|
|
|
GetPrefValue(prefBranch, allKey[i], value)) {
|
|
|
|
|
// expected key:
|
|
|
|
|
// "font.mathfont-family.\uNNNN.base" -- fonts for the base size
|
|
|
|
|
// "font.mathfont-family.\uNNNN.parts" -- fonts for partial glyphs
|
|
|
|
|
// "font.mathfont-family.\uNNNN.variants" -- fonts for larger glyphs
|
|
|
|
|
PRInt32 error = 0;
|
|
|
|
|
// 22 is to skip "font.mathfont-family.\\u";
|
|
|
|
|
PRUnichar uchar = nsCAutoString(allKey[i]+22).ToInteger(&error, 16);
|
|
|
|
|
if (error) continue;
|
|
|
|
|
// 27 is to skip "font.mathfont-family.\\uNNNN"
|
|
|
|
|
SetPreferredFonts(uchar, allKey[i]+27, value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, allKey);
|
|
|
|
|
|
|
|
|
|
// Next, look our internal settings
|
|
|
|
|
nsCOMPtr<nsISimpleEnumerator> iterator;
|
|
|
|
|
if (NS_SUCCEEDED(mathfontProp->Enumerate(getter_AddRefs(iterator)))) {
|
|
|
|
|
PRBool more;
|
|
|
|
|
while ((NS_SUCCEEDED(iterator->HasMoreElements(&more))) && more) {
|
|
|
|
|
nsCOMPtr<nsIPropertyElement> element;
|
|
|
|
|
if (NS_SUCCEEDED(iterator->GetNext(getter_AddRefs(element)))) {
|
|
|
|
|
if (NS_SUCCEEDED(element->GetKey(key)) &&
|
|
|
|
|
NS_SUCCEEDED(element->GetValue(value))) {
|
|
|
|
|
// expected key: "mathfont-family.\uNNNN.parts" or
|
|
|
|
|
// "mathfont-family.\uNNNN.variants"
|
|
|
|
|
if ((22 <= key.Length()) && (0 == key.Find("mathfont-family.\\u"))) {
|
|
|
|
|
if (NS_SUCCEEDED(element->GetKey(key))) {
|
|
|
|
|
// expected key:
|
|
|
|
|
// "font.mathfont-family.\uNNNN.base" -- fonts for the base size
|
|
|
|
|
// "font.mathfont-family.\uNNNN.parts" -- fonts for partial glyphs
|
|
|
|
|
// "font.mathfont-family.\uNNNN.variants" -- fonts for larger glyphs
|
|
|
|
|
if ((30 < key.Length()) &&
|
|
|
|
|
(0 == key.Find("font.mathfont-family.\\u")) &&
|
|
|
|
|
!GetPrefValue(prefBranch, key.get(), value) && // priority to user
|
|
|
|
|
NS_SUCCEEDED(element->GetValue(value))) {
|
|
|
|
|
PRInt32 error = 0;
|
|
|
|
|
key.Cut(0, 18); // 18 is the length of "mathfont-family.\\u";
|
|
|
|
|
key.Cut(0, 23); // 23 is the length of "font.mathfont-family.\\u";
|
|
|
|
|
PRUnichar uchar = key.ToInteger(&error, 16);
|
|
|
|
|
if (error) continue;
|
|
|
|
|
key.Cut(0, 4); // the digits of the unicode point ("NNNN")
|
|
|
|
|
Clean(value);
|
|
|
|
|
SetPreferredTableList(uchar, key, value);
|
|
|
|
|
SetPreferredFonts(uchar, key.get(), value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -1202,6 +1273,18 @@ InitGlobals(nsIPresContext* aPresContext)
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// helper to override CSS and set the default font-family list to be used
|
|
|
|
|
// for the base size of a particular character (i.e., in the situation where
|
|
|
|
|
// stretching doesn't happen).
|
|
|
|
|
static void
|
|
|
|
|
SetBaseFamily(PRUnichar aChar, nsFont& aFont)
|
|
|
|
|
{
|
|
|
|
|
nsBaseFontEntry* entry = nsGlyphTableList::gBaseFonts.GetEntry(aChar);
|
|
|
|
|
if (entry) {
|
|
|
|
|
aFont.name.Assign(entry->mFontFamily);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------------
|
|
|
|
|
// And now the implementation of nsMathMLChar
|
|
|
|
|
|
|
|
|
|
@@ -1470,12 +1553,10 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext,
|
|
|
|
|
const nsStyleFont *font = NS_STATIC_CAST(const nsStyleFont*,
|
|
|
|
|
parentContext->GetStyleData(eStyleStruct_Font));
|
|
|
|
|
nsFont theFont(font->mFont);
|
|
|
|
|
// XXXrbs get rid of this hardcoding - bug 118600
|
|
|
|
|
|
|
|
|
|
// Override with specific fonts if applicable for this character
|
|
|
|
|
PRUnichar uchar = mData[0];
|
|
|
|
|
if (kSqrChar == uchar) { // Special to the sqrt char. Due to
|
|
|
|
|
fontName.Assign(NS_LITERAL_STRING("CMSY10,Math2")); // assumptions in the sqrt code, we need
|
|
|
|
|
SetFirstFamily(theFont, fontName); // to force precedence on this TeX font
|
|
|
|
|
}
|
|
|
|
|
SetBaseFamily(uchar, theFont);
|
|
|
|
|
aRenderingContext.SetFont(theFont, nsnull);
|
|
|
|
|
rv = aRenderingContext.GetBoundingMetrics(mData.get(),
|
|
|
|
|
PRUint32(mData.Length()),
|
|
|
|
|
@@ -1588,7 +1669,7 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext,
|
|
|
|
|
? bm.ascent + bm.descent
|
|
|
|
|
: bm.rightBearing - bm.leftBearing;
|
|
|
|
|
// always break when largeopOnly is set
|
|
|
|
|
if (IsSizeOK(charSize, targetSize, aStretchHint) || largeopOnly) {
|
|
|
|
|
if (largeopOnly || IsSizeOK(charSize, targetSize, aStretchHint)) {
|
|
|
|
|
#ifdef NOISY_SEARCH
|
|
|
|
|
printf(" size:%d OK!\n", size-1);
|
|
|
|
|
#endif
|
|
|
|
|
@@ -1950,10 +2031,8 @@ nsMathMLChar::Paint(nsIPresContext* aPresContext,
|
|
|
|
|
// normal drawing if there is nothing special about this char ...
|
|
|
|
|
// Set the default font and grab some metrics to adjust the placements ...
|
|
|
|
|
PRUint32 len = PRUint32(mData.Length());
|
|
|
|
|
PRUnichar uchar = mData[0];
|
|
|
|
|
if ((1 == len) && (kSqrChar == uchar)) { // Special to the sqrt char. Due to
|
|
|
|
|
fontName.Assign(NS_LITERAL_STRING("CMSY10,Math2")); // assumptions in the sqrt code, we need
|
|
|
|
|
SetFirstFamily(theFont, fontName); // to force precedence on this TeX font
|
|
|
|
|
if (1 == len) {
|
|
|
|
|
SetBaseFamily(mData[0], theFont);
|
|
|
|
|
}
|
|
|
|
|
aRenderingContext.SetFont(theFont, nsnull);
|
|
|
|
|
//printf("Painting %04X like a normal char\n", mData[0]);
|
|
|
|
|
|