From 443291acc18c4ce63eb9595f1416f553f94127f3 Mon Sep 17 00:00:00 2001 From: "rbs%maths.uq.edu.au" Date: Thu, 27 Sep 2001 18:29:17 +0000 Subject: [PATCH] bug 99010 - font changes. r=shanjian@netscape.com, sr=waterson@netscape.com --- gfx/public/nsFont.h | 34 ++++++- gfx/public/nsIRenderingContext.h | 151 +++++++++++++++++++++---------- gfx/src/nsFont.cpp | 36 ++++++-- 3 files changed, 162 insertions(+), 59 deletions(-) diff --git a/gfx/public/nsFont.h b/gfx/public/nsFont.h index fa1e64c3216..ecbc54c3511 100644 --- a/gfx/public/nsFont.h +++ b/gfx/public/nsFont.h @@ -49,6 +49,20 @@ // Enumerator callback function. Return PR_FALSE to stop typedef PRBool (*nsFontFamilyEnumFunc)(const nsString& aFamily, PRBool aGeneric, void *aData); +// IDs for generic fonts +// NOTE: 0, 1 are reserved for the special IDs of the default variable +// and fixed fonts in the presentation context, see nsIPresContext.h +const PRUint8 kGenericFont_NONE = 0x00; +// Special +const PRUint8 kGenericFont_moz_variable = 0x00; // for the default variable width font +const PRUint8 kGenericFont_moz_fixed = 0x01; // our special "use the user's fixed font" +// CSS +const PRUint8 kGenericFont_serif = 0x02; +const PRUint8 kGenericFont_sans_serif = 0x04; +const PRUint8 kGenericFont_monospace = 0x08; +const PRUint8 kGenericFont_cursive = 0x10; +const PRUint8 kGenericFont_fantasy = 0x20; + // Font structure. struct NS_GFX nsFont { // The family name of the font @@ -67,20 +81,29 @@ struct NS_GFX nsFont { // line-through). The decorations can be binary or'd together. PRUint8 decorations; - // The size of the font, in nscoord units + // The logical size of the font, in nscoord units nscoord size; + // The aspect-value (ie., the ratio actualsize:actualxheight) that any + // actual physical font created from this font structure must have when + // rendering or measuring a string. A value of 0 means no adjustment + // needs to be done. + float sizeAdjust; + // Initialize the font struct with an iso-latin1 name nsFont(const char* aName, PRUint8 aStyle, PRUint8 aVariant, - PRUint16 aWeight, PRUint8 aDecoration, nscoord aSize); + PRUint16 aWeight, PRUint8 aDecoration, nscoord aSize, + float aSizeAdjust=0.0f); // Initialize the font struct with a (potentially) unicode name nsFont(const nsString& aName, PRUint8 aStyle, PRUint8 aVariant, - PRUint16 aWeight, PRUint8 aDecoration, nscoord aSize); + PRUint16 aWeight, PRUint8 aDecoration, nscoord aSize, + float aSizeAdjust=0.0f); // Make a copy of the given font nsFont(const nsFont& aFont); + nsFont(); ~nsFont(); PRBool operator==(const nsFont& aOther) const { @@ -93,10 +116,13 @@ struct NS_GFX nsFont { // Utility method to interpret name string // enumerates all families specified by this font only - // returns PR_TRUE if completed, PF_FALSE if stopped + // returns PR_TRUE if completed, PR_FALSE if stopped // enclosing quotes will be removed, and whitespace compressed (as needed) PRBool EnumerateFamilies(nsFontFamilyEnumFunc aFunc, void* aData) const; void GetFirstFamily(nsString& aFamily) const; + + // Utility method to return the ID of a generic font + static void GetGenericID(const nsString& aGeneric, PRUint8* aID); }; #define NS_FONT_STYLE_NORMAL 0 diff --git a/gfx/public/nsIRenderingContext.h b/gfx/public/nsIRenderingContext.h index 16f3272d490..b646b9c16df 100644 --- a/gfx/public/nsIRenderingContext.h +++ b/gfx/public/nsIRenderingContext.h @@ -57,6 +57,7 @@ struct nsFont; struct nsPoint; struct nsPathPoint; struct nsRect; +struct nsTextDimensions; #ifdef MOZ_MATHML struct nsBoundingMetrics; #endif @@ -579,65 +580,76 @@ public: NS_IMETHOD GetWidth(const PRUnichar *aString, PRUint32 aLength, nscoord &aWidth, PRInt32 *aFontID = nsnull) = 0; + /** + * Returns the dimensions of a string, i.e., the overall extent of a string + * whose rendering may involve switching between different fonts that have + * different metrics. + * @param aString string to measure + * @param aLength number of characters in string + * @param aFontID an optional out parameter used to store a + * font identifier that can be passed into the DrawString() + * methods to speed measurements + * @return aDimensions struct that contains the extent of the string (see below) + */ + NS_IMETHOD GetTextDimensions(const char* aString, PRUint32 aLength, + nsTextDimensions& aDimensions) = 0; + NS_IMETHOD GetTextDimensions(const PRUnichar* aString, PRUint32 aLength, + nsTextDimensions& aDimensions, PRInt32* aFontID = nsnull) = 0; + #ifdef _WIN32 /** * Given an available width and an array of break points, - * returns the width (in app units) of the text that fit and + * returns the dimensions (in app units) of the text that fit and * the number of characters that fit. The number of characters * corresponds to an entry in the break array. - * If no font has been Set, the results are undefined. - * @param aString 8-bit character string to measure - * @param aLength number of characters in string - * @param aAvailWidth the available space in which the text must fit - * @param aBreaks array of places to break. Specified as offsets from the + * If no font has been set, the results are undefined. + * @param aString, string to measure + * @param aLength, number of characters in string + * @param aAvailWidth, the available space in which the text must fit + * @param aBreaks, array of places to break. Specified as offsets from the * start of the string - * @param aNumBreaks the number of entries in the break array. The last + * @param aNumBreaks, the number of entries in the break array. The last * entry in the break array must equal the length of the string - * @param aWidth out parameter for width - * @param aNumCharsFit the number of characters that fit in the available space - * @param aFontID an optional out parameter used to store a + * @param aDimensions, out parameter for the dimensions, the ascent and descent + * of the last word are left out to allow possible line-breaking before + * the last word. However, the width of the last word is included. + * @param aNumCharsFit, the number of characters that fit in the available space + * @param aLastWordDimensions, dimensions of the last word, the width field, + * dimensions.width, should be -1 for an unknown width. But the + * ascent and descent are expected to be known. + * @param aFontID, an optional out parameter used to store a * font identifier that can be passed into the DrawString() * methods to speed rendering * @return error status */ - NS_IMETHOD GetWidth(const char *aString, - PRInt32 aLength, - PRInt32 aAvailWidth, - PRInt32* aBreaks, - PRInt32 aNumBreaks, - nscoord& aWidth, - PRInt32& aNumCharsFit, - PRInt32* aFontID = nsnull) = 0; + NS_IMETHOD GetTextDimensions(const char* aString, + PRInt32 aLength, + PRInt32 aAvailWidth, + PRInt32* aBreaks, + PRInt32 aNumBreaks, + nsTextDimensions& aDimensions, + PRInt32& aNumCharsFit, + nsTextDimensions& aLastWordDimensions, + PRInt32* aFontID = nsnull) = 0; - /** - * Given an available width and an array of break points, - * returns the width (in app units) of the text that fit and - * the number of characters that fit. The number of characters - * corresponds to an entry in the break array. - * If no font has been Set, the results are undefined. - * @param aString Unicode string to measure - * @param aLength number of characters in string - * @param aAvailWidth the available space in which the text must fit - * @param aBreaks array of places to break. Specified as offsets from the - * start of the string - * @param aNumBreaks the number of entries in the break array. The last - * entry in the break array must equal the length of the string - * @param aWidth out parameter for width - * @param aNumCharsFit the number of characters that fit in the available space - * @param aFontID an optional out parameter used to store a - * font identifier that can be passed into the DrawString() - * methods to speed rendering - * @return error status - */ - NS_IMETHOD GetWidth(const PRUnichar *aString, - PRInt32 aLength, - PRInt32 aAvailWidth, - PRInt32* aBreaks, - PRInt32 aNumBreaks, - nscoord& aWidth, - PRInt32& aNumCharsFit, - PRInt32* aFontID = nsnull) = 0; + NS_IMETHOD GetTextDimensions(const PRUnichar* aString, + PRInt32 aLength, + PRInt32 aAvailWidth, + PRInt32* aBreaks, + PRInt32 aNumBreaks, + nsTextDimensions& aDimensions, + PRInt32& aNumCharsFit, + nsTextDimensions& aLastWordDimensions, + PRInt32* aFontID = nsnull) = 0; #endif + /* + * XXX Buggy APIs: the DrawString() APIs are not implemented according + * to their signature. Indeed aX and aY are not interpreted as the + * coordinates of the baseline. + * XXX TODO: replace the buggy DrawString() APIs with the newer DrawString2() + * APIs and fix callers. The newer APIs are the ones to use in conjunction + * with GetTextDimensions(). + */ /** * Draw a string in the RenderingContext @@ -651,6 +663,15 @@ public: nscoord aX, nscoord aY, const nscoord* aSpacing = nsnull) = 0; + /** + * Same as above, with the difference that the implementation is + * correctly intepreting aX and aY as the horizontal and vertical + * starting point of the baseline + */ + NS_IMETHOD DrawString2(const char *aString, PRUint32 aLength, + nscoord aX, nscoord aY, + const nscoord* aSpacing = nsnull) = 0; + /** * Draw a string in the RenderingContext * @param aString A PRUnichar of the string @@ -666,6 +687,10 @@ public: nscoord aX, nscoord aY, PRInt32 aFontID = -1, const nscoord* aSpacing = nsnull) = 0; + NS_IMETHOD DrawString2(const PRUnichar *aString, PRUint32 aLength, + nscoord aX, nscoord aY, + PRInt32 aFontID = -1, + const nscoord* aSpacing = nsnull) = 0; /** * Draw a string in the RenderingContext @@ -860,6 +885,40 @@ public: //stop using it. #define NS_COPYBITS_TO_BACK_BUFFER 0x0008 +/* Struct used to represent the overall extent of a string + whose rendering may involve switching between different + fonts that have different metrics. +*/ +struct nsTextDimensions { + // max ascent amongst all the fonts needed to represent the string + nscoord ascent; + + // max descent amongst all the fonts needed to represent the string + nscoord descent; + + // width of the string + nscoord width; + + + nsTextDimensions() + { + Clear(); + } + + /* Set all member data to zero */ + void + Clear() { + ascent = descent = width = 0; + } + + /* Sum with another dimension */ + void + Combine(const nsTextDimensions& aOther) { + if (ascent < aOther.ascent) ascent = aOther.ascent; + if (descent < aOther.descent) descent = aOther.descent; + width += aOther.width; + } +}; #ifdef MOZ_MATHML /* Struct used for accurate measurements of a string in order diff --git a/gfx/src/nsFont.cpp b/gfx/src/nsFont.cpp index b2b8a43905d..2d0ddfa825b 100644 --- a/gfx/src/nsFont.cpp +++ b/gfx/src/nsFont.cpp @@ -40,7 +40,8 @@ #include "nsString.h" nsFont::nsFont(const char* aName, PRUint8 aStyle, PRUint8 aVariant, - PRUint16 aWeight, PRUint8 aDecoration, nscoord aSize) + PRUint16 aWeight, PRUint8 aDecoration, nscoord aSize, + float aSizeAdjust) { name.AssignWithConversion(aName); style = aStyle; @@ -48,10 +49,12 @@ nsFont::nsFont(const char* aName, PRUint8 aStyle, PRUint8 aVariant, weight = aWeight; decorations = aDecoration; size = aSize; + sizeAdjust = aSizeAdjust; } nsFont::nsFont(const nsString& aName, PRUint8 aStyle, PRUint8 aVariant, - PRUint16 aWeight, PRUint8 aDecoration, nscoord aSize) + PRUint16 aWeight, PRUint8 aDecoration, nscoord aSize, + float aSizeAdjust) : name(aName) { style = aStyle; @@ -59,6 +62,7 @@ nsFont::nsFont(const nsString& aName, PRUint8 aStyle, PRUint8 aVariant, weight = aWeight; decorations = aDecoration; size = aSize; + sizeAdjust = aSizeAdjust; } nsFont::nsFont(const nsFont& aOther) @@ -69,6 +73,11 @@ nsFont::nsFont(const nsFont& aOther) weight = aOther.weight; decorations = aOther.decorations; size = aOther.size; + sizeAdjust = aOther.sizeAdjust; +} + +nsFont::nsFont() +{ } nsFont::~nsFont() @@ -82,6 +91,7 @@ PRBool nsFont::Equals(const nsFont& aOther) const (weight == aOther.weight) && (decorations == aOther.decorations) && (size == aOther.size) && + (sizeAdjust == aOther.sizeAdjust) && name.EqualsIgnoreCase(aOther.name)) { return PR_TRUE; } @@ -96,18 +106,15 @@ nsFont& nsFont::operator=(const nsFont& aOther) weight = aOther.weight; decorations = aOther.decorations; size = aOther.size; + sizeAdjust = aOther.sizeAdjust; return *this; } - static PRBool IsGenericFontFamily(const nsString& aFamily) { - return PRBool(aFamily.EqualsIgnoreCase("serif") || - aFamily.EqualsIgnoreCase("sans-serif") || - aFamily.EqualsIgnoreCase("cursive") || - aFamily.EqualsIgnoreCase("fantasy") || - aFamily.EqualsIgnoreCase("monospace") || - aFamily.EqualsIgnoreCase("-moz-fixed")); // our special "use the user's fixed font" + PRUint8 generic; + nsFont::GetGenericID(aFamily, &generic); + return generic != kGenericFont_NONE; } const PRUnichar kNullCh = PRUnichar('\0'); @@ -190,3 +197,14 @@ void nsFont::GetFirstFamily(nsString& aFamily) const EnumerateFamilies(FontEnumCallback, &aFamily); } +/*static*/ +void nsFont::GetGenericID(const nsString& aGeneric, PRUint8* aID) +{ + *aID = kGenericFont_NONE; + if (aGeneric.EqualsIgnoreCase("-moz-fixed")) *aID = kGenericFont_moz_fixed; + else if (aGeneric.EqualsIgnoreCase("serif")) *aID = kGenericFont_serif; + else if (aGeneric.EqualsIgnoreCase("sans-serif")) *aID = kGenericFont_sans_serif; + else if (aGeneric.EqualsIgnoreCase("cursive")) *aID = kGenericFont_cursive; + else if (aGeneric.EqualsIgnoreCase("fantasy")) *aID = kGenericFont_fantasy; + else if (aGeneric.EqualsIgnoreCase("monospace")) *aID = kGenericFont_monospace; +}