On Wed, Mar 21, 2012 at 11:53 AM, <
julian....@googlemail.com> wrote:
> i) Implement a subset of CSS3PagedMedia to set the margin (at least the
> case = 0 to hide all the header/footer) and the page size.
> ii) Implement a new callback on the canvas element that is called during
> the actual printing to print directly to the printing backend.
>
> What's the best way to get the implementation going?
>
> For i), there seems to be a bug already:
>
https://bugzilla.mozilla.org/show_bug.cgi?id=115199
>
> I tried to understand what the patches are doing and couldn't figure it
> out for most parts. For i), is the way to implement this by continue
> working on bug 115199, or should there be a new bug that tries to implement
> only a very dump subset of the CSS3PagedMedia, such that one can set the
> margin to 0 and the page-size and that's it?
>
I think starting with the patch there is the way to go. You'll need to add
code to nsSimplePageSequenceFrame::Reflow to set up margins using the style
data from a (the first) nsPageFrame child.
>From my intuition, the second part ii) might be "easier" to implement then
> the first part, as it is more contained and doesn't require to deal with
> new CSS rules. I'm therefore wondering if you think this is something I
> could try to implement.
>
> So far I have some basic understanding about how the printing stuff works,
> how the CanvasReneringContext is defined in the IDL and cpp file etc. Could
> someone give me some pointers where the actual printing of a canvas element
> to the printing context happens, such that I could try to implement the
> proposed callback?
>
Basically we just render the canvas like normal, but we're rendering it to
a print context.
What I think you need to do is:
-- in nsHTMLCanvasElement::CopyInnerTo in the IsStaticDocument case, set up
a reference from the cloned-for-print canvas to the original canvas
-- in nsSimplePageSequenceFrame::PrintNextPage, before you render the page
via nsLayoutUtils::PaintFrame, traverse the child page frame's frame
subtree (see FrameChildListIterator and its users) looking for
nsHTMLCanvasFrames (via do_QueryFrame). For each one, look up the original
canvas, see if it has an "onprint" (or whatever we call it) event handler
set on it. For those that do:
-- Poke the printed nsHTMLCanvasElement's 2D rendering context
(nsCanvasRenderingContext2D for now) to tell it to change its surface to a
new surface created via
renderingContext->GetThebes()->CurrentSurface()->CreateSimilarSurface()
-- Synchronously dispatch the "print" event to the original canvas.
-- That event should use a custom DOM event class (see for example
nsDOMNotifyPaintEvent) with an extra field that's the 2D rendering context
for the printed nsHTMLCanvasElement
-- To save memory, after calling PaintFrame for the page, go back through
the canvases where you fired the callbacks and clear out their surfaces.
If you're really lucky, that will be enough for printing :-). For print
preview:
-- Add an mIsReadyToPrint flag on nsHTMLCanvasElement, initially false,
-- Add an IsReadyToPrint() method on nsPageFrame that scans the frame
subtree (see FrameChildListIterator) looking for nsHTMLCanvasFrames (via
do_QueryFrame). If any such canvases have their mIsReadyToPrint flag not
set, and the original canvas has an "onprint" callback, the page is not
ready to print.
-- When painting an nsPageFrame in print preview, if !IsReadyToPrint(), for
each not-ready print canvas, clear out its surface and fire an asynchronous
event that dispatches a "print" event to the original canvas, passing the
2D rendering context for the print canvas's context, and when that event
has finished set the mIsReadyToPrint flag on the print canvas.
-- To save memory, periodically check for pages that are offscreen and
clear out the surfaces for the print canvases in them.
At some point, hopefully soon, nsCanvasRenderingContext2D will go away and
you'll need to make these changes to nsCanvasRenderingContext2DAzure
instead.