Closed Bug 1393907 Opened 8 years ago Closed 8 years ago

Add handling for border bevels

Categories

(Core :: Graphics: WebRender, enhancement, P1)

Other Branch
enhancement

Tracking

()

RESOLVED FIXED
mozilla60
Tracking Status
firefox56 --- unaffected
firefox57 --- unaffected
firefox60 --- fixed

People

(Reporter: kats, Assigned: mtseng)

References

Details

(Whiteboard: [wr-reserve] [gfx-noted])

Attachments

(1 file, 1 obsolete file)

I looked into this a little bit and since understanding the code is nontrivial here's an explanation that hopefully makes it easier. Normally borders are rectangles that have four sides. However in the case of tables, borders get collapsed with other borders and need to be drawn one "side" at a time. Additionally, because of vertical/horizontal writing mode genericness, a lot of the table code deals with "block" and "inline" directions, which are logical abstractions over the physical "horizontal" and "vertical" directions. So when BCBlockDirSeg::CreateWebRenderCommands is called, it's supposed to draw one border segment in the "block" direction, and when BCInlineDirSeg::CreateWebRenderCommands is called, it's supposed to draw one border segment in the "inline" direction. I used the layout/reftests/writing-mode/tables/vertical-border-collapse-1.html and vertical-border-collapse-1-ref.html files as examples here. In these pages, the outermost table border (the thick light/dark gray one) has two horizontal segments (top and bottom sides) which are considered the "block" direction and two vertical segments (left and right sides) which are considered the "inline" direction. The way we are currently drawing these segments is just creating a "full" border (4 sides) but setting three of the sides to border-style:none so that they don't get drawn. We set the color and thickness on the remaining side (we use the left side for "block" and top side for "inline") and create a display item from that. The intent is that WR will draw just the one side of the border, which will correspond to the segment that we want to be drawing. This works, except for border-beveling. That's when two colors meet at a corner, and the corner is supposed to be drawn with a 45-degree angle split between the two colors. (See the above test pages in Gecko for the visuals). WR does beveling internally, if you give it a border to draw with different colors on adjacent edges. However with what we're doing here (just asking it to draw one edge) it doesn't do beveling, so we end up with un-beveled borders, which is wrong. That's what the TODO is for. The beveling information is provided in the param->*Bevel* fields. For example in the test case above, the top border needs beveling on the "bottom" side of the border segment (the bottom-left and bottom-right corners need to be shifted inward horizontally) and so that is represented by param->mStartBevelSide = eSideBottom, param->mStartBevelOffset = 480 (8 CSS px), param->mEndBevelSide = eSideBottom, param->mEndBevelOffset = 480. This indicates the bottom "start" (left in this case) side needs to be shifted in by 8 CSS pixels, and the bottom "end" side likewise. The existing Gecko code to do this is at [1]. The way it works is turns that border segment rectangle into a Point[4] and then fiddles with the corner coordinates to do the bevelling. In order to do this in WR we have three options: (1) Don't send a border display item to WR, but instead send a quad that already had the bevel adjustment applied (2) Send the border display item with the bevel information to WR, and have WR apply the bevel adjustment before drawing (3) Do some crazy hacking where instead of setting the other three border sides to border-style:none, set them to be transparent with appropriate widths, which presumably will make WR do the correct beveling. I'm not sure if this will even work, and it might not be able to handle all the different beveling scenarios that Gecko wants to handle. [1] http://searchfox.org/mozilla-central/rev/cd82cacec2cf734768827ff85ba2dba90a534c5e/layout/painting/nsCSSRendering.cpp#3398-3432
Priority: P3 → P2
Whiteboard: [gfx-noted] → [wr-mvp] [gfx-noted]
Priority: P2 → P3
Whiteboard: [wr-mvp] [gfx-noted] → [wr-reserve] [gfx-noted]
This is still not working correctly, right?
Flags: needinfo?(bugmail)
To be knowledge, yeah, still not working correctly.
Flags: needinfo?(bugmail)
Assignee: nobody → howareyou322
Looking.
Assignee: howareyou322 → mtseng
This should block wr-nightly.
Blocks: stage-wr-nightly
No longer blocks: stage-wr-trains
Attached patch Handle bevel borders. (obsolete) — Splinter Review
Since bevel only appear outmost border of table. I collect all bevel border and combined them as a single border with four sides. MozReview-Commit-ID: Bvu8Zf56YDF
Attachment #8943171 - Flags: review?(bugmail)
Comment on attachment 8943171 [details] [diff] [review] Handle bevel borders. Review of attachment 8943171 [details] [diff] [review]: ----------------------------------------------------------------- ::: layout/tables/nsTableFrame.cpp @@ +6652,5 @@ > > + ~BCPaintBorderAction() > + { > + if (mMode == Mode::CREATE_WEBRENDER_COMMANDS) { > + mCreateWebRenderCommandsData.~BCCreateWebRenderCommandsData(); This is a little scary, it at least needs a comment to explain that mCreateWebRenderCommandsData is inside a union and so doesn't get destroyed normally, but the BCBorderParameters need to get destroyed. @@ +7477,5 @@ > return; > } > > + if (param->mStartBevelOffset != 0 || param->mEndBevelOffset != 0) { > + mozilla::Side bevelSide = param->mStartBevelOffset != 0 ? param->mStartBevelSide : param->mEndBevelSide; Isn't it possible for both the start and end to be nonzero? How does this deal with that scenario? Or are you assuming that if both are nonzero, then the two bevel side parameters will be the same? I think that might be a valid assumption, but it should have a comment and/or an assert. @@ +7480,5 @@ > + if (param->mStartBevelOffset != 0 || param->mEndBevelOffset != 0) { > + mozilla::Side bevelSide = param->mStartBevelOffset != 0 ? param->mStartBevelSide : param->mEndBevelSide; > + > + // Left border has right side bevel and vice versa. > + // Top border has bottom side bevel and vice versa. This comment needs a bit more explanation. I'd say: // The left border is going to be beveled on its right edge because that's the edge that intersects other borders (in this case the top and bottom borders). Correspondingly, if the bevel side is "right" that means we are operating on the left border, and so store the parameters for that entry in aBevelBorders. Same goes for the other directions. @@ +7764,5 @@ > + if (param->mStartBevelOffset != 0 || param->mEndBevelOffset != 0) { > + mozilla::Side bevelSide = param->mStartBevelOffset != 0 ? param->mStartBevelSide : param->mEndBevelSide; > + > + // Left border has right side bevel and vice versa. > + // Top border has bottom side bevel and vice versa. // See detailed comment on equivalent code in BCBlockDirSeg::CreateWebRenderCommands @@ +8053,5 @@ > + borderRect = LayoutDeviceRect::FromUnknownRect(NSRectToRect(param->mBorderRect + aOffsetToReferenceFrame, > + param->mAppUnitsPerDevPixel)); > + borderColor = param->mBorderColor; > + borderStyle = param->mBorderStyle; > + backfaceIsVisible = param->mBackfaceIsVisible; This should probably be |= to combine the different backfaceIsVisible properties properly and not just pick up the last one. (And the variable would need to be initialized to false)
Attachment #8943171 - Flags: review?(bugmail)
Since bevel only appear outmost border of table. I collect all bevel border and combined them as a single border with four sides. MozReview-Commit-ID: Bvu8Zf56YDF
Attachment #8945009 - Flags: review?(bugmail)
Attachment #8943171 - Attachment is obsolete: true
Comment on attachment 8945009 [details] [diff] [review] Handle bevel borders. Review of attachment 8945009 [details] [diff] [review]: ----------------------------------------------------------------- Looks good, and thank you for finishing this off! I can fix the typo and land it for you. ::: layout/tables/nsTableFrame.cpp @@ +6653,5 @@ > + ~BCPaintBorderAction() > + { > + // mCreateWebRenderCommandsData is in a union which means the destructor > + // wouldn't be called when BCPaintBorderAction get destroyed. So call the > + // destroctor here explicitly. typo: destructor
Attachment #8945009 - Flags: review?(bugmail) → review+
(In reply to Kartikaya Gupta (email:kats@mozilla.com) from comment #10) > Comment on attachment 8945009 [details] [diff] [review] > Handle bevel borders. > > Review of attachment 8945009 [details] [diff] [review]: > ----------------------------------------------------------------- > > Looks good, and thank you for finishing this off! I can fix the typo and > land it for you. Thank you very much!
Status: NEW → RESOLVED
Closed: 8 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla60
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: