Closed
Bug 365336
Opened 18 years ago
Closed 17 years ago
text-decoration width should be rounded to the device pixels
Categories
(Core :: Layout: Text and Fonts, defect)
Core
Layout: Text and Fonts
Tracking
()
RESOLVED
FIXED
mozilla1.9alpha8
People
(Reporter: masayuki, Assigned: masayuki)
References
Details
Attachments
(7 files, 8 obsolete files)
We fixed the bug 287624.
The text-decoration has similar problem. We should round the width of the text-decorations at rendering time. (If we implement the 'text-underline-width', 'text-line-through-width' and 'text-overline-width', we can be rounding in style system. But the spec may not be stable.)
I think that this bug doesn't happen on Windows. Because the width of the lines are always returns the rounded value on Windows. I don't know on Linux. I confirmed on Mac.
Assignee | ||
Comment 1•18 years ago
|
||
We currently get this information from font metrics -- and the font metrics may be giving subpixel widths on some platforms and not others.
Assignee | ||
Comment 3•18 years ago
|
||
dbaron:
thanks for the comment.
I think that we should implement the common function that draws the decoration lines in nsCSSRendering, and all frames should use this for drawing docoration lines. If so, we will happy for implementing the text-decoration styles in CSS3.
We get the information from font metrics, but we currently draw the decorations in cross-platform code in nsHTMLContainerFrame, nsTextFrame, etc.
Assignee | ||
Comment 5•18 years ago
|
||
Assignee | ||
Comment 6•18 years ago
|
||
Assignee | ||
Updated•18 years ago
|
Attachment #249925 -
Attachment description: testcase → testcase for nsBlockFrame
Assignee | ||
Comment 7•18 years ago
|
||
This patch supports 2 or more pixels dotted line that is used for spell checker. And it also supports dashed style. That will be used for the composition string of IME on Windows. And it also supports double style. But the double style doesn't works fine, see bug 365414.
The dotted style and dashed styles start the draw with same direction of the text, therefore, if the text is RTL, the right most dot/dash is not painted as shortly.
This patch is including the xul text box frame (nsTextBoxFrame), but I don't know how to test this frame...
Attachment #250022 -
Flags: superreview?(dbaron)
Attachment #250022 -
Flags: review?(dbaron)
Assignee | ||
Comment 8•18 years ago
|
||
roc:
Please check this, this changes few lines in the nsTextFrame.
All the text in e.g. menus is in nsTextBoxFrames.
Looks OK.
Assignee | ||
Comment 10•18 years ago
|
||
looks like the patch works fine on all cases.
Assignee | ||
Comment 11•18 years ago
|
||
This patch is Patch rv1.0 + patch for nsTextFrameThebes. But if I enable nsTextFrameThebes, Fx crashed at starting up. So, I didn't test for it.
Attachment #250022 -
Attachment is obsolete: true
Attachment #252612 -
Flags: superreview?(dbaron)
Attachment #252612 -
Flags: review?(roc)
Attachment #250022 -
Flags: superreview?(dbaron)
Attachment #250022 -
Flags: review?(dbaron)
I don't think we should round the horizontal coordinates (x and width). Fractional values there are not very visible.
+ if (aOffset > 0 || (aOffset == 0 && aAscent == 0)) {
+ // The offset is including the preferred size, we should remove it
+ y += preferredSize;
+ }
Why is this needed?
Assignee | ||
Comment 13•18 years ago
|
||
(In reply to comment #12)
> I don't think we should round the horizontal coordinates (x and width).
> Fractional values there are not very visible.
o.k.
> + if (aOffset > 0 || (aOffset == 0 && aAscent == 0)) {
> + // The offset is including the preferred size, we should remove it
> + y += preferredSize;
> + }
>
> Why is this needed?
I think that if the decoration line is over line, we should align the bottom of the line to the offset position. (for the line should not overlap to the text.) And I think that if the decoration line is line through, we should align the middle of the line to offset position. (for the line should be on middle of the ascent of the text.)
If the actual height is same as preferred size which is specified by the font, the addition will be denied in the next switch statement. (But I should use |aDecoration| for the if statement, probably...)
ok, but I don't understand why we have to have both size and preferredsize.
Assignee | ||
Comment 15•18 years ago
|
||
(In reply to comment #14)
> ok, but I don't understand why we have to have both size and preferredsize.
Because the offsets for the over line and the line through are including the preferredsize. We have another way that is the callers remove the preferred size from the offset value. But the way is not better than current way. The way will create some new bugs if the caller forgets (or don't know) the rule.
Assignee | ||
Comment 16•18 years ago
|
||
updating to latest trunk. and this patch is not rounding the x offset and width.
Attachment #252612 -
Attachment is obsolete: true
Attachment #254427 -
Flags: superreview?(roc)
Attachment #254427 -
Flags: review?(roc)
Attachment #252612 -
Flags: superreview?(dbaron)
Attachment #252612 -
Flags: review?(roc)
Flags: blocking1.9?
Assignee | ||
Updated•18 years ago
|
Attachment #254427 -
Flags: superreview?(roc)
Attachment #254427 -
Flags: review?(roc)
Flags: blocking1.9? → blocking1.9+
Comment 19•18 years ago
|
||
demonstration of 1 pixel separation between letters and underline in one paragraph and 0 pixel separation in other. remove first paragraph to see correct display.
Assignee | ||
Comment 21•17 years ago
|
||
Now, we can use thebes directly in nsCSSRendering.
Therefore, this patch can render better lines than rv1.x.
Roc, I have a question. In nsTextFrameThebes, some gfxFloat (or gfxPoint) params have nscoord (or nsPoint) values. Is it a mistake? Or is there a reason? It is unreadable...
Attachment #254427 -
Attachment is obsolete: true
Attachment #269712 -
Flags: review?(roc)
Assignee | ||
Comment 22•17 years ago
|
||
Oops, sorry.
> +/**
> + * round the app unit to the nearest device pixel.
> + * 'l' is a length by app units. 'aupp' is the app units per the device pixel.
> + */
> +#define ROUND_TO_NEAREST_PIXELS(l,aupp) \
> + (((l) == 0) ? 0 : \
> + ((l) > 0) ? ((l) + ((aupp) / 2)) / (aupp) * (aupp) : \
> + ((l) - ((aupp) / 2)) / (aupp) * (aupp))
> +
Now, this can be removed. Please ignore this.
Assignee | ||
Comment 23•17 years ago
|
||
(In reply to comment #19)
> demonstration of 1 pixel separation between letters and underline in one
> paragraph and 0 pixel separation in other. remove first paragraph to see
> correct display.
Ray:
This patch cannot fix the positioning bug perfectly. We need more work for it...
Assignee | ||
Comment 24•17 years ago
|
||
> + // The y position should be lifted up to half size for the painted line being
> + // aligned to device pixel.
> + y -= size / 2;
fm... it may pull down. (i.g., '+=')
Assignee | ||
Comment 25•17 years ago
|
||
Sorry, this is correct. We should down the line half size.
Attachment #269712 -
Attachment is obsolete: true
Attachment #269720 -
Flags: review?(roc)
Attachment #269712 -
Flags: review?(roc)
Assignee | ||
Comment 26•17 years ago
|
||
And the rv2 patch also fixes the AAed underline for spell checker in new textframe.
What does PaintDecorationLine do that FillClippedRect doesn't do? FillClippedRect is snapping to device pixels when possible.
Assignee | ||
Comment 28•17 years ago
|
||
(In reply to comment #27)
> What does PaintDecorationLine do that FillClippedRect doesn't do?
> FillClippedRect is snapping to device pixels when possible.
If the line is solid, they are same result. Otherwise, FillClippedRect cannot render the other style lines. I hope that we integrate the all text-decoration rendering to one function for bug 59109 and bug 367614.
Assignee | ||
Comment 29•17 years ago
|
||
roc:
would you continue to review?
- gfxFloat pix2app = mTextRun->GetAppUnitsPerDevUnit();
+ gfxFloat p2t = mTextRun->GetAppUnitsPerDevUnit();
Why are you changing the name? The existing name is much better; "twips" is not accurate at all.
+ nsPoint pt(NSToCoordRound(float(aFramePt.x)),
+ NSToCoordRound(float(aFramePt.y)));
Why do you need these float() casts, here and elsewhere?
+ nscoord width = NSToCoordRound(float(GetRect().width));
+ nscoord ascent = NSToCoordRound(float(mAscent));
Why are you doing these conversions? These are already nscoords
+ nsCSSRendering::PaintDecorationLine(aTextPaintStyle.PresContext(),
+ aCtx, overColor,
+ pt, width, size, 0, 0, size,
+ NS_STYLE_TEXT_DECORATION_OVERLINE, NS_STYLE_BORDER_STYLE_SOLID,
Wouldn't it be more correct to pass ascent and -ascent instead of 0 for the ascent and offset?
+ * @param aSize the height of the decoration line
How about calling it aHeight? Similar for aPreferredSize/aPreferredHeight.
I think the parameters to nsCSSRendering::PaintDecorationLine should be gfxFloats instead of nscoord. That would avoid lossy rounding and simplify code.
I don't think you need to Save() and Restore() here. nsTextFrameThebes doesn't. We don't require stroke state to be preserved.
+ gfxFloat y = NS_round((aPt.y + aAscent - aOffset) * t2p);
I think you need to round aOffset to device pixels before using it. Otherwise, if aOffset is not an integer number of pixels, the offset between the baseline and the decoration line may be drawn with a different number of pixels depending on the value of aPt.y + aAscent.
+ gfxFloat dashWidth = 0.0;
+ gfxFloat dash[2];
Make these local to the code blocks that use them.
+ case NS_STYLE_TEXT_DECORATION_OVERLINE:
+ // The offset is including the preferred size, we should remove it
+ y += preferredSize;
+ // the bottom of the decoration line should be aligned to the top of the
+ // text.
+ y -= totalHeight;
+ break;
+ case NS_STYLE_TEXT_DECORATION_LINE_THROUGH: {
+ // The offset is including the preferred size, we should remove it
+ y += preferredSize;
+ // the middle of the decoration line should be aligned to the middle of
+ // the original strike out offset.
+ gfxFloat halfsize;
+ if (preferredSize > totalHeight / 2.0)
+ halfsize = preferredSize;
+ else {
+ halfsize = NS_round(totalHeight / 2.0);
+ }
+ y -= halfsize;
+ break;
I think you should make these adjustments to aOffset instead of y, and do them before we round aOffset to pixels.
Assignee | ||
Comment 31•17 years ago
|
||
(In reply to comment #30)
> + nsPoint pt(NSToCoordRound(float(aFramePt.x)),
> + NSToCoordRound(float(aFramePt.y)));
>
> Why do you need these float() casts, here and elsewhere?
non-casted converting from double (gfxFloat) to float makes warning on VC.
Assignee | ||
Comment 32•17 years ago
|
||
(In reply to comment #30)
> I don't think you need to Save() and Restore() here. nsTextFrameThebes doesn't.
> We don't require stroke state to be preserved.
The dotted/dashed style breaks current working, we need them...
Assignee | ||
Comment 33•17 years ago
|
||
Roc, by your suggestion, the offset problem is fixed! It's great.
Attachment #269720 -
Attachment is obsolete: true
Attachment #274517 -
Flags: superreview?(roc)
Attachment #274517 -
Flags: review?(roc)
Attachment #269720 -
Flags: review?(roc)
(In reply to comment #31)
> (In reply to comment #30)
> > + nsPoint pt(NSToCoordRound(float(aFramePt.x)),
> > + NSToCoordRound(float(aFramePt.y)));
> >
> > Why do you need these float() casts, here and elsewhere?
>
> non-casted converting from double (gfxFloat) to float makes warning on VC.
Then I think you should add an overloaded version of NSToCoordRound that takes a double parameter.
> The dotted/dashed style breaks current working, we need them...
What do you mean? There are places where we assume that the current line style is solid? Where? Even if so, you can easily move Save() into the DOTTED/DASHED cases of the first switch, and move Restore() into the DOTTED/DASHED cases of the last switch.
Could you use names like offsetPixel instead of offset_pixel to be more consistent with the surrounding code?
+ if (aPreferredHeight > totalHeight / 2.0)
+ halfHeight = aPreferredHeight;
+ else {
+ halfHeight = totalHeight / 2.0;
+ }
use PR_MAX.
+ // The offset is including the preferred size, we should remove it
// The offset includes the preferred height, we should remove it
+ // The y position should be downed to half size for the painted line being
+ // aligned to device pixel.
// The y position should be set to the middle of the line.
Assignee | ||
Comment 35•17 years ago
|
||
(In reply to comment #34)
> (In reply to comment #31)
> > (In reply to comment #30)
> > > + nsPoint pt(NSToCoordRound(float(aFramePt.x)),
> > > + NSToCoordRound(float(aFramePt.y)));
> > >
> > > Why do you need these float() casts, here and elsewhere?
> >
> > non-casted converting from double (gfxFloat) to float makes warning on VC.
>
> Then I think you should add an overloaded version of NSToCoordRound that takes
> a double parameter.
yeah, but the code has been removed, should I add the new function in this patch?
Attachment #274517 -
Attachment is obsolete: true
Attachment #274909 -
Flags: superreview?(roc)
Attachment #274909 -
Flags: review?(roc)
Attachment #274517 -
Flags: superreview?(roc)
Attachment #274517 -
Flags: review?(roc)
Assignee | ||
Comment 36•17 years ago
|
||
Oops, sorry. I forgot some changes.
Attachment #274909 -
Attachment is obsolete: true
Attachment #275008 -
Flags: superreview?(roc)
Attachment #275008 -
Flags: review?(roc)
Attachment #274909 -
Flags: superreview?(roc)
Attachment #274909 -
Flags: review?(roc)
Assignee | ||
Comment 37•17 years ago
|
||
Sorry, this is better..
Attachment #275008 -
Attachment is obsolete: true
Attachment #275010 -
Flags: superreview?(roc)
Attachment #275010 -
Flags: review?(roc)
Attachment #275008 -
Flags: superreview?(roc)
Attachment #275008 -
Flags: review?(roc)
Comment on attachment 275010 [details] [diff] [review]
Patch rv3.2.1
ok great!
Attachment #275010 -
Flags: superreview?(roc)
Attachment #275010 -
Flags: superreview+
Attachment #275010 -
Flags: review?(roc)
Attachment #275010 -
Flags: review+
Assignee | ||
Comment 39•17 years ago
|
||
checked-in.
Status: ASSIGNED → RESOLVED
Closed: 17 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla1.9 M8
Updated•17 years ago
|
Flags: in-testsuite?
Comment 40•17 years ago
|
||
> + gfxPoint pt((start + aPt.x) * a2p, (aLine->mBounds.y + aPt.y) * a2p);
Is there a reason this is not using AppUnitsToDevPixels? If the problem is that this rounds, perhaps we just need an API that doesn't do that instead of rolling our own? Or perhaps this code should use NSAppUnitsToFloatPixels directly with the value it got off the prescontext?
Thing is, as the code is written (doing |foo * (1.0 / bar)|) you actually get rounding errors compared to doing |foo / bar| directly. We don't really want that.
Assignee | ||
Comment 41•17 years ago
|
||
yeah, I need non-rounded pixels out of nsCSSRendering. And now, gfxFloat is double, not float.
Comment 42•17 years ago
|
||
Sounds like we should have a followup bug on the API impedance mismatch, then. This code should really be able to use NSAppUnitsToFloatPixels or equivalent instead of having to hand-roll it.
we should also have a followup patch to use division here instead of multiplication (or preferably the new API).
You need to log in
before you can comment on or make changes to this bug.
Description
•