Re: [webkit-dev] How does Zooming Work?

2009-10-07 Thread Alex Milowski
On Tue, Oct 6, 2009 at 9:09 PM, Dan Bernstein m...@apple.com wrote:

 On Oct 6, 2009, at 8:49 PM, Alex Milowski wrote:

 What exactly happens during a zoom (command +/-) ?

 Depends on the flavor of zoom (“full-page” zoom vs. text-only zoom), but in
 both cases, a full style recalculation for the document is forced.

 I have code that works well but layout doesn't seem to happen after
 a zoom in/out operation.  If I then resize the window, that forces a
 layout for the zoomed size and things adjust themselves
 appropriately (because layout() eventually gets called).

 So, what sequence of events happens after a zoom?

 Frame::setZoomFactor() calls Document::recalcStyle(Force). If after that the
 document has a renderer (which would be a RenderView) and that renderer is
 marked for layout, then FrameView::layout() is called, which will call
 RenderView::layout() and recursively lay out every render tree object marked
 as needing layout.

 One explanation for what you’re seeing would be that as your objects’ style
 changes, they fail to call setNeedsLayout() (or
 setNeedsLayoutAndPerfWidthsRecalc()), and therefore layout doesn’t occur at
 that time. An alternative, less likely, explanation is that your objects
 have anonymous children, but they don’t propagate the style changes
 correctly to those children.

The style changes seem to be propagating properly.  I've dug into this
quite a bit more.  Here's the layout method for mrow that attempts to
notify the math operators to stretch to a certain height:

void RenderMathRow::layout() {
RenderBlock::layout();

// calculate the maximum height
int maxHeight = 0;
int currentHeight = offsetHeight();

RenderObject* current = firstChild();
while (current) {
if (current-isBoxModelObject()) {

RenderBoxModelObject* box = toRenderBoxModelObject(current);

// Check to see if this box has a larger height
if (box-offsetHeight()maxHeight)
maxHeight = box-offsetHeight();
}
current = current-nextSibling();
}

if (maxHeight!=currentHeight) {
   style()-setHeight(Length(maxHeight,Fixed));
   setNeedsLayoutAndPrefWidthsRecalc();

   // notify contained operators they may need to relayout their
stretched operators
current = firstChild();
while (current) {
if (current-isRenderMathOperator()) {
RenderMathOperator* mathop = toRenderMathOperator(current);
mathop-stretchOperator(maxHeight);
}
current = current-nextSibling();
}
}
}


I modify the style of the mrow (a copy of the style) and change the height
of the container (the mrow).  This code correctly works the first time and
will adjust properly after a zoom in/out if you resize the window.

The stretchOperator() method marks the child as needing layout.  As the
children of mrow are stacked as a set of inlines (mostly likely all
inline-block),
there must be something that is not propagating.

Also, I notice on a zoom in that the render tree for the MathML is
being partially
recreated.  New instances of the children of mrow are created.  Their initial
layout() call then does not have the new maxHeight value.  Afterwards, they
are marked for layout just as in the initial layout.

I've narrowed the problem down to this sequence of events:

   1. RenderMathRow::layout() is called (from the outside)
   2. RenderMathRow::layout() calls RenderBlock::layout()
   3. Subsequent calls to RenderMathOperator::layout() are causes by (2).  The
   stretch height has not been set at that moment.
   4. If the height has changed:

   a. The height of RenderMathRow is set and it is told it needs layout
   b. Each RenderMathOperator child is notified of the stretch height and
   told it needs layout.
   5. RenderMathRow::layout() is called (from the outside)
   6. RenderMathRow::layout() calls RenderBlock::layout()
   7. Subsequent calls to RenderMathOperator::layout() are causes by (2).  The
   stetch height is now set properly and the height of the
inline-block is now correct.

What is interesting is that after a zoom, 1-4 happen.  5-7 only happen
after a resize
event.  My suspicion is that even though the RenderMathRow instance has marked
itself and its RenderMathOperator children as needing layout, that is
somehow not
noticed until the window resize.

I can solve this right now by adding another call to
RenderBlock::layout() in the
RenderMathRow::layout() method.  I shouldn't have to do that and I've
noticed that
such direct double calls can cause other problems.

Any ideas what is wrong?  Do I need to notify the parent of
RenderMathRow somehow?

-- 
--Alex Milowski
The excellence of grammar as a guide is proportional to the paucity of the
inflexions, i.e. to the degree of analysis effected by the language
considered.

Bertrand Russell in a footnote of Principles of Mathematics

Re: [webkit-dev] How does Zooming Work?

2009-10-07 Thread Alex Milowski
After chatting with David Hyatt, the answer seems to be, in my
own words, smack your fingers with a ruler.  My current layout()
method leaves with the RenderMathRow instance and some of
its descendants needing layout.  That's a violation of the API
contract for layout().

I should make sure I don't need layout at the end by adding:

   setNeedsLayout(false);

That would have caused my current implementation to fail to do what
I wanted.

The simple fix for me is to call RenderBlock::layout() again within
the context of my method.  If that causes other problems, I'll have to
deal with those problems individually.

For now, that fixes my problems with zoom.


-- 
--Alex Milowski
The excellence of grammar as a guide is proportional to the paucity of the
inflexions, i.e. to the degree of analysis effected by the language
considered.

Bertrand Russell in a footnote of Principles of Mathematics
___
webkit-dev mailing list
webkit-dev@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev


[webkit-dev] How does Zooming Work?

2009-10-06 Thread Alex Milowski
What exactly happens during a zoom (command +/-) ?

I have code that works well but layout doesn't seem to happen after
a zoom in/out operation.  If I then resize the window, that forces a
layout for the zoomed size and things adjust themselves
appropriately (because layout() eventually gets called).

So, what sequence of events happens after a zoom?

Also, if I need layout() to be called for things to be handled properly, is
something out of place?

This all relates to the stretchy operator code in the MathML rendering.  The
operator's box stretches correctly after layout but after a zoom, it doesn't
stretch until layout happens again.

-- 
--Alex Milowski
The excellence of grammar as a guide is proportional to the paucity of the
inflexions, i.e. to the degree of analysis effected by the language
considered.

Bertrand Russell in a footnote of Principles of Mathematics
___
webkit-dev mailing list
webkit-dev@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev


Re: [webkit-dev] How does Zooming Work?

2009-10-06 Thread Dan Bernstein


On Oct 6, 2009, at 8:49 PM, Alex Milowski wrote:


What exactly happens during a zoom (command +/-) ?


Depends on the flavor of zoom (“full-page” zoom vs. text-only zoom),  
but in both cases, a full style recalculation for the document is  
forced.



I have code that works well but layout doesn't seem to happen after
a zoom in/out operation.  If I then resize the window, that forces a
layout for the zoomed size and things adjust themselves
appropriately (because layout() eventually gets called).

So, what sequence of events happens after a zoom?


Frame::setZoomFactor() calls Document::recalcStyle(Force). If after  
that the document has a renderer (which would be a RenderView) and  
that renderer is marked for layout, then FrameView::layout() is  
called, which will call RenderView::layout() and recursively lay out  
every render tree object marked as needing layout.


One explanation for what you’re seeing would be that as your objects’  
style changes, they fail to call setNeedsLayout() (or  
setNeedsLayoutAndPerfWidthsRecalc()), and therefore layout doesn’t  
occur at that time. An alternative, less likely, explanation is that  
your objects have anonymous children, but they don’t propagate the  
style changes correctly to those children.


Also, if I need layout() to be called for things to be handled  
properly, is

something out of place?


No, layout() is the correct way to update the layout after a style  
change. To ensure that it happens, objects should mark themselves for  
layout in response to the style change when necessary.  
RenderObject::styleDidChange() is an example, and most render objects  
that override styleDidChange() invoke their base class’s  
implementation, so they get marked for layout as needed.


This all relates to the stretchy operator code in the MathML  
rendering.  The
operator's box stretches correctly after layout but after a zoom, it  
doesn't

stretch until layout happens again.


I hope the above helps you debug the problem. You may want to  
experiment with more localized style changes (such that should affect  
only your object of interest) and see whether they work and if not,  
why not.

___
webkit-dev mailing list
webkit-dev@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev