off-screen rendering

1,576 views
Skip to first unread message

roxa...@gmail.com

unread,
Nov 23, 2012, 5:11:07 AM11/23/12
to cefp...@googlegroups.com
Does anyone have any example how its done? So little info exist on this killer feature..

Czarek Tomczak

unread,
Nov 23, 2012, 10:06:25 AM11/23/12
to cefp...@googlegroups.com
What is your use case, what do you need it for?

In CEF there is CefRenderHandler with following methods: GetViewRect(), GetScreenRect(), GetScreenPoint(), OnPopupShow(), OnPopupSize(), OnPaint(), OnCursorChange().

There is also CefWindowInfo class with methods: SetAsOffScreen(), SetTransparentPainting(), SetAsChild(), SetAsPopup().

There is an example of offscreen-rendering in CEF, run the test browser "cefclient.exe" that comes with cefpython starting with version 0.42, in the menu select Tests > Off-Screen Rendering Example, the implementation is in these files:

Czarek.

roxa...@gmail.com

unread,
Dec 2, 2012, 12:24:56 PM12/2/12
to cefp...@googlegroups.com
Goal is to have GUI system in panda3d ( https://www.panda3d.org/ ) application driven by CEF. I am aware cef1 can do that, but was not sure if cef python bindings expose required elements, for some reason calls like SetAsOffScreen i could not find anywhere in cef python files

roxa...@gmail.com

unread,
Dec 2, 2012, 1:05:00 PM12/2/12
to cefp...@googlegroups.com
Actually What i am missing in cef python is CefWindowInfo.. Is it not there or i just cant find it?

Czarek Tomczak

unread,
Dec 2, 2012, 3:14:09 PM12/2/12
to cefp...@googlegroups.com
I've created an issue in the CEF Python issue tracker to add off-screen rendering support:

Czarek.

roxa...@gmail.com

unread,
Dec 3, 2012, 11:10:20 AM12/3/12
to cefp...@googlegroups.com
thank you! cant wait for it to be added :)

ric...@gmail.com

unread,
Dec 28, 2012, 2:23:00 PM12/28/12
to cefp...@googlegroups.com
I see some progress has been done with off screen rendering. Very cool.
Does that mean we can screen capture a webpage, including the stuff you need to scroll to? I know IE can do this.

Czarek Tomczak

unread,
Dec 28, 2012, 3:10:31 PM12/28/12
to cefp...@googlegroups.com
Yes, you can screen capture webpage for both off-screen rendering
& window rendering. Browser object has a method GetImage(), there
is an example in cefadvanced.py (Python.SaveImage) on how to 
deal with PaintBuffer and save it to a PNG file. To capture a screen
containing all scrollable content you have to call Browser.SetSize(
width, height), but first you would need to detect in javascript what
is the total height of the content on a webpage.

Cheers,
Czarek.

ric...@gmail.com

unread,
Dec 29, 2012, 11:11:53 AM12/29/12
to cefp...@googlegroups.com
So far it's working great, but there seems to be some something missing.
It works, my image has the hidden content, and no scroll bar. Problem is that it only looks good the 2nd time I click my link. The 1st time I click, the hidden content is missing.

(from cefPython v0.51_32bit, modification of cefadvanced)
I modified SaveImage() to take an optional width and height.
I get the content size from Jquery, and pass it along to the function.
I run Browser.SetSize() before Browser.GetImage()

- Seems fine, but not able to paint the off-screen content the 1st time around.
I tried adding Browser.Reload() and even Time.sleep() just in case the content hasn't loaded since I ran Browser.SetSize(). I think there is some sort of buffer refresh that's needed, but not what.

Notes:
- This method only works if you only have a vertical scroll bar. If you have both scroll bars, it doesn't render the off-screen content corectly.
- if you run Browser.SetSize() at a size that does not include your scroll bar, you must run it again to re-include your scroll bar, or else it will be disabled until you resize your window.

ric...@gmail.com

unread,
Dec 29, 2012, 11:34:54 AM12/29/12
to cefp...@googlegroups.com
Find my working test code here: (the HTML and PY are in the same file)
http://mediabakers.com/files/test_code_off-screen_content.txt

Czarek Tomczak

unread,
Dec 29, 2012, 11:57:03 AM12/29/12
to cefp...@googlegroups.com
I think that you should create a separate off-screen browser just to capture the image, resizing visible window to a height bigger than the screen is probably not a good idea. An off-screen browser can be created by calling WindowInfo.SetAsOffscreen(), see Panda3D example. You should call GetImage() from OnLoadEnd() event.

I am thinking of adding such example do cefadvanced.py, if you manage to do it before me try to put the code in a separate function, not SaveImage() and share with us.

Czarek.

Czarek Tomczak

unread,
Dec 29, 2012, 12:01:26 PM12/29/12
to cefp...@googlegroups.com
I think the problem is that you capture the image immediately after the call to SetSize(), but CEF has not yet handled the Paint event, maybe you should try sleeping for 1 second after the call to SetSize()?

Czarek.

ric...@gmail.com

unread,
Dec 29, 2012, 12:03:01 PM12/29/12
to cefp...@googlegroups.com
Tried the following after SetSize(), no luck:

import time
time.sleep(5)

Czarek Tomczak

unread,
Dec 29, 2012, 12:06:39 PM12/29/12
to cefp...@googlegroups.com
Your jQuery code gives me height=672px every time in the cefadvanced.py example.

Czarek.

ric...@gmail.com

unread,
Dec 29, 2012, 12:19:27 PM12/29/12
to cefp...@googlegroups.com
You are correct, I should have used $(document) instead. I updated my file.

Czarek Tomczak

unread,
Dec 29, 2012, 12:36:08 PM12/29/12
to cefp...@googlegroups.com
From the documentation of SetSize() method:
http://code.google.com/p/cefpython/wiki/Browser

Set the size of the specified element. This method is only
used when window rendering is disabled. This function is 
asynchronous, after a call to SetSize() the 
RenderHandler.OnPaint() event might still have the old size, 
you would have to ignore it and wait for the next one
RenderHandler.OnPaint() event.

Its only purpose is for off-screen rendering, you shouldn't rely
on it working in this case, as you got probably lucky and it 
might break in the future.

time.sleep() is not enough, because CEF doesn't know that it
needs to refresh the view, as this function is only for off-screen
rendering, if you used off-screen time.sleep() should be enough.
If you really need to do it this way then after the call to SetSize()
you would have to something on the webpage to force a paint
event, modify something on the page and then sleep for a moment
and only then capture the image.

I've created this topic on CEF forum:
"CefBrowser.SetSize() when window rendering is enabled?"

Czarek.

ric...@gmail.com

unread,
Dec 29, 2012, 1:49:15 PM12/29/12
to cefp...@googlegroups.com
"... you would have to something on the webpage to force a paint event ..."

The 2 step idea seems to work. Needs some work to be more straight forward and cleaner, but this does work.

http://mediabakers.com/files/test_code_off-screen_content-fixed.txt

Czarek Tomczak

unread,
Dec 29, 2012, 1:56:32 PM12/29/12
to cefp...@googlegroups.com
Next time please create your own topic and post questions there.

Czarek.
Reply all
Reply to author
Forward
0 new messages