Closed Bug 124543 Opened 23 years ago Closed 23 years ago

MathML "extra" functions not implemented in nsRenderingContextBeos.cpp

Categories

(Core :: MathML, defect)

x86
BeOS
defect
Not set
blocker

Tracking

()

VERIFIED FIXED

People

(Reporter: beos, Assigned: mozilla)

Details

Attachments

(5 files, 9 obsolete files)

nsRenderContextBeOS needs implementations for the following: #ifdef MOZ_MATHML /** * Returns bounding metrics (in app units) of an 8-bit character string * @param aString string to measure * @param aLength number of characters in string * @return aBoundingMetrics struct that contains various metrics (see below) * @return error status */ NS_IMETHOD GetBoundingMetrics(const char* aString, PRUint32 aLength, nsBoundingMetrics& aBoundingMetrics) = 0; /** * Returns bounding metrics (in app units) of an Unicode character string * @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 GetBoundingMetrics() * methods to speed measurements * @return aBoundingMetrics struct that contains various metrics (see below) * @return error status */ NS_IMETHOD GetBoundingMetrics(const PRUnichar* aString, PRUint32 aLength, nsBoundingMetrics& aBoundingMetrics, PRInt32* aFontID = nsnull) = 0; #endif
Attached patch Temporary fix to the build errors (obsolete) (deleted) — Splinter Review
Daniel, I assigned this to you, since you had done work on the gfx package recently. I hope you don't mind. The attachment should at least allow the Tinderbox to build again, until we actually get time to implement these.
Attached patch Temporary fix for build errors (obsolete) (deleted) — Splinter Review
Oops, I should have compiled this before I posted it. Cut and past error fixed.
Attachment #68701 - Attachment is obsolete: true
Second patch looks good Paul, let's just get things building again. r=mozilla@switkin.com
Status: NEW → ASSIGNED
I checked in the temp fix.
Actual implementation
Attachment #68703 - Attachment is obsolete: true
+ mCurrentFont->GetHeight(height); + aBoundingMetrics.ascent = height->ascent; + aBoundingMetrics.descent = height->descent; The bounding metrics' ascent & descent are not the same as the font' ascent & descent + mCurrentFont->GetEdges(aString,aLength,bearings); + aBoundingMetrics.width = mCurrentFont->StringWidth(aString); + aBoundingMetrics.leftBearing = bearings[0].left; + aBoundingMetrics.rightBearing = bearings[aLength -1].right; Unless GetEdges(() which I know not is adding things up, the right bearing is the width of aString[0..length-1] + the right bearking of last character -- a slightly more complicated formula can take care of kerning effets too. See the code in nsFontMetricsWin for example. A good way to test your implementation is to enable #define SHOW_BOUNDING_BOX 1: http://lxr.mozilla.org/seamonkey/source/layout/mathml/base/src/nsIMathMLFrame.h# 21 Then zoom while vieweing to check that, on MathML content, the bounding boxes that will be drawn cover exactly the text. For example, the bbox of <msup> should appear as the smallest rectangle that exactly encloses the base and the superscript.
Oops, my bad. I should have read the description in the header a little closer before just wacking out some code. I'll fix as soon as I find out how to get the proper info.
Attached patch implementation of GetBoundingMetrics for MathML (obsolete) (deleted) — Splinter Review
A "good" implementation of the GetBoundingMetrics methods used by the MathML renderer.
Attachment #71809 - Attachment is obsolete: true
Attached image screen shot of torture test page with bounding boxes (obsolete) (deleted) —
screen shot of torture test page, zoomed to 200%, with bounding boxes shown, using the above patch
+ // The origin in beos is the top left. so we switch these to give what MathML wants, bottom left + aBoundingMetrics.ascent = (nscoord)rect.bottom; + aBoundingMetrics.descent = (nscoord)rect.top; Drawing operations are now made on the baseline. I remember to have patched the BeOS code sometimes ago about that -- but it may have been reversed -- din't check. The screenshot shows that the metrics are still not returned correctly. The baseline is needed to allow you to compute: ascent = bottom - baseline descent = height - ascent (where height = bottom - top --per your comment above) I will attach a reference screenshot for your information.
btw, how does the MathML load the fonts it needs? i.e. where does it do this? I just installed the fonts, and now I'm getting blocks instead of characters.
Attached image screenshot - expected bounding boxes (deleted) —
note how at each level of nesting, elements are embedded in an hierarchy of precise bounding boxes in a way that mirrors the XML parenting relashionship per level.
>btw, how does the MathML load the fonts it needs? i.e. where does it do this? The fonts are loaded in the same way as mainline layout does (i.e., using nsIRenderingContext::SetFont(), etc). But for the fonts to be recognized properly, the ucvmath module needs to be hooked -- see similar bug 107146 - ucvmath not working with Fizzilla.
Well, I know seem to have it drawing the proper bounding boxes for the characters/strings, and the width is correct for the entire equation, but the height is wrong. Any ideas?
Attachment #72738 - Attachment is obsolete: true
Attachment #72742 - Attachment is obsolete: true
Attached image reference rendering of the testcase (deleted) —
The testcase contrast the bounding metrics vs. the usual CSS metrics. The solid blue borders are done with the bounding metrics while the dashed red borders are done with the CSS metrics.
> but the height is wrong. Any ideas? The ascent and descent need to be relative to the baseline as I hinted earlier. The cross-platform origin expected higher-up in consumers of the GetBoundingMetrics() function is at the baseline.
Attached image beos rendering of testcase (obsolete) (deleted) —
as you can see, I am generating the proper bounding boxes for all of the fonts. The only bounding boxes that aren't correct, are the boxes generated based on my bounding boxes, the "global" boxes in the first 2 mathml test cases. If it is able to draw the proper bounding boxes for the strings, then it seems to me to be a problem with mathml calculating the "global" bounding box. Here's the debug output I in my patch for the test case: GetBoundingMetrics for: j (-7.000000,-76.000000,37.000000,22.000000) -> (-7.000000,37.000000,-22.000000,-76.000000) GetBoundingMetrics for: i (7.000000,-76.000000,36.000000,-1.000000) -> (7.000000,36.000000,1.000000,-76.000000) GetBoundingMetrics for: f (9.000000,-77.000000,48.000000,-1.000000) -> (9.000000,48.000000,1.000000,-77.000000) GetBoundingMetrics for: j (-5.000000,-54.000000,25.000000,15.000000) -> (-5.000000,25.000000,-15.000000,-54.000000) GetBoundingMetrics for: i (5.000000,-54.000000,25.000000,-1.000000) -> (5.000000,25.000000,1.000000,-54.000000) GetBoundingMetrics for: f (6.000000,-54.000000,33.000000,-1.000000) -> (6.000000,33.000000,1.000000,-54.000000) GetBoundingMetrics for: jif (-7.000000,-77.000000,96.000000,22.000000) -> (-7.000000,96.000000,-22.000000,-77.000000) GetBoundingMetrics for: jif (-5.000000,-54.000000,67.000000,15.000000) -> (-5.000000,67.000000,-15.000000,-54.000000)
>If it is able to draw the proper bounding boxes for the strings, then it seems >to me to be a problem with mathml calculating the "global" bounding box. The blue bounding boxes are drawn with something like (simplyfing...) : DrawRect(0, 0, ascent + descent, rightBearing - leftBearing) So although, ascent + descent may sum up to the height, it doesn't mean that ascent and descent are correct if taken indivually. As I mentioned earlier, these values need to be set relative to the baseline since this is what the other MathML rendering operations expect.
Just did a lookup in google and it now seems to me that there is possibly another hole in your patch. (http://www.bespecific.com/dialog/bedevtalk/archive/990308/00000103.htm) + // Use the printing metric to get more detail + mCurrentFont->GetBoundingBoxesForStrings(&aString, 1, B_SCREEN_METRIC, &delta, &rect); Are you getting the rect of the *first* character only or what? To test this, you can edit the testcase and change "jif" to "ijf" throughout.
Errata... I was messed up with the names. The function that you are using applies to the full string indeed... GetBoundingBoxesForStrings(): returns an array of BRect objects indicating the bounding rectangles for an array of strings, one BRect per string. These rectangles enclose the entire string they represent.
Attached patch Hopefully the final patch (obsolete) (deleted) — Splinter Review
Seems to be workign properly now. Still switching to top and bottom values, but now negating the descent instead of the ascent, to match how MathML expects things. I then had to offset the values by the total of ascent and descent, to move them to the proper cooridinate space.
Attachment #72902 - Attachment is obsolete: true
Attached image beos rendering of test case (deleted) —
beos rendering of test case showing that it now works.
Attachment #72927 - Attachment is obsolete: true
Comment on attachment 73468 [details] [diff] [review] Hopefully the final patch + // BeOS origin at top left, so the bottom and top values are switched + // for ascent and descent, but we then need to offset those values + // by there totals to obtain the proper bounding box. + float offset = rect.bottom + rect.top; + + // Flip sign of descent for cross-platform compatibility + aBoundingMetrics.ascent = (nscoord)(rect.bottom - offset); + aBoundingMetrics.descent = (nscoord)(0.0 - rect.top + offset); It appears that the documentation (comment?) is buggy. Indeed the formulas are simply reducing to: ascent = rect.bottom - offset = rect.bottom - (rect.bottom + rect.top) = -rect.top descent = - rect.top + offset; = - rect.top + (rect.bottom + rect.top) = rect.bottom [I just checked that you didn't try this combination in your earlier patch...] So the origin is still at the baseline on BeOS, ...but it is the orientation that is _downward_ for _all_ vertical metrics (ascent & descent). The MathML engine expects what X Windows does: the orientation of the ascent is upward (i.e., a postive ascent means the glyph extends above the baseline), while the descent is oriented downward (i.e., a positive descent means the glyph extends below the baseline). So flipping the sign of the ascent on BeOS turns the ascent from downward to upward and this brings things to parity. [On Win32, the orientation is upward for all vertical metrics and that's why I had to flip its ascent to turn it from upward to downward. Hope this quick explantation makes sense...] + aBoundingMetrics.rightBearing = (nscoord)rect.right + 1; Why '+1' ? have you encouuntered fonts with bad metrics that make this necessary? On the screenshot, there seems to be little gaps as a result of this. Since BeOS is using floating arithmetic for its device values, you don't need the casting that may cause even more truncation errors, you could directly use: + aBoundingMetrics.leftBearing = NSToCoordRound(rect.left * mP2T); + aBoundingMetrics.rightBearing = NSToCoordRound(rect.right * mP2T); + aBoundingMetrics.width = NSToCoordRound(width * mP2T); + aBoundingMetrics.ascent = NSToCoordRound(-rect.top * mP2T); + aBoundingMetrics.descent = NSToCoordRound(rect.bottom * mP2T);
Attached patch Updated patch, as per comments from above (obsolete) (deleted) — Splinter Review
I think I was a bit too excited that it was drawing properly, that I did not notice the uglyness of my code. It is now cleaned up, and hopefully the comment explains things better.
Attachment #73468 - Attachment is obsolete: true
+ uint8 *utf8str = new uint8[aLength * 4 + 1]; + uint8 *utf8ptr = utf8str; I was concentratimg on the correctness and didn't pay much attention to other parts... More often than not, there is only a single character passed to the function, and you will be |new|ing all the time. It might be best to use a stack variable and only |new| if the length exceeds the stack. With this, the |new| is rarely going to happen. So: uint8 utf8buf[1024]; uint8* utf8str = &utf8buf; if (aLength * 4 + 1 > 1024) utf8str = new uint8[aLength * 4 + 1]; ...use it... if (utf8str != utf8buf) delete[] utf8str; [There is similar code along these lines in GfxWin, BTW]
Attached patch updated patch, as per comments (deleted) — Splinter Review
updated to try and keep the utf8 conversion on the stack for single char strings
Attachment #73485 - Attachment is obsolete: true
Comment on attachment 73496 [details] [diff] [review] updated patch, as per comments Need some null check in case |new| fails, but just looked up and noted that file is not bothering doing null checks for GetWidth/DrawString/... and to be meaningful, null checks would have to be scattered everywhere throughout that file at some stage. So r=rbs for the patch
Attachment #73496 - Flags: review+
Comment on attachment 73496 [details] [diff] [review] updated patch, as per comments a=roc+moz
Attachment #73496 - Flags: approval+
Patch checked in. Marking fixed.
Status: ASSIGNED → RESOLVED
Closed: 23 years ago
Resolution: --- → FIXED
v
Status: RESOLVED → VERIFIED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: