dk / Prima

prima.eu.org
Other
106 stars 27 forks source link

Prima Cairo backend #22

Closed Teslos closed 9 years ago

Teslos commented 9 years ago

Dear Dimtry,

I am trying to implement Cairo backend for PDL::Graphics::Prima library. Current implementation of Prima::Cairo::Drawable is on my repo: https://github.com/Teslos/Prima/blob/master/Prima/Cairo/Drawable.pm I started with the Prima::PS::Drawable and used Cairo library to implement some of functionality of PS::Drawable. I have several questions concerning the implementation: 1.) I am not really sure how to implement the font capabilities of Prima in Cairo. Currently, most of the fonts functionality is copied from PS::Drawable so I think it would be better to eliminate the code duplication by subclassing the PS::Drawable in some way... 2.) How to test the code to get same results as PS::Drawable? I think that standard Test::More etc.. can't guaranty pixel for pixel testing of the Canvas surface. 3.) I think it is also easy to add Cairo backend for rendering the widgets in PDL::Graphics::Prima. The small example of analog clock implemented with Gtk and Cairo is here: https://github.com/Teslos/Cairo-Perl/blob/master/analog_clock.pl But I don't know how to implement that in Prima, maybe you have some suggestions.

Thank you very much for your help!

Best regards, ∃t.

dk commented 9 years ago

Hi Teslos,

I agree with your approach, copying Drawable's implementation from PS. But please take a look here: https://github.com/dk/Prima-Cairo/blob/master/lib/Prima/Cairo/Drawable.pm . It's more than adding Cairo support to PS, it's Cairo support to Prima, including PS. I basically started doing the same, but haven't got time to finish, so it's halfway done.

Now with your questions:

1) I didn't try Cairo text rendering yet, so I can't help yet with the Cairo side. But as for the Prima side, I think the best approach will be to mimic the PS implementation, that exposes Prima-specific font API to the caller (fonts, font_encodings, font_match, set_font, get_font, get_text_width, get_font_abc, get_font_ranges).

2) I'm using Cairo::ImageSurface for testing in Prima::Cairo, with pixel testing. However I don't think you can test the postscript output that Cairo produces (well of course you can grep the output for specific commands, but that's very unreliable). Alternatively, one can make a developer's test (the one that will skip all tests by default) that renders the PS output using ghostscript onto a PNG image, and analyze pixels there.

3) I hope it is! I'm very little familiar with PDL::G::P, but it is indeed easy to blend Prima and Cairo together. You're welcome to take a look at examples: https://github.com/dk/Prima-Cairo/tree/master/examples (the FPS shooter is there too :)

Other than this, I'd be very glad to help you, I hope we could join forces on this project.

Sincerely, Dmitry

Teslos commented 9 years ago

Hi Dimtry,

I will fork your repo and try to help you with the project. Can you suggest what I can work on.. Concerning PDL::G::P I have tried some examples from the official version and it creates reasonable output from Cairo backend. It is only that I still didn't get all bugs fixed (axis offset, positions of the labels etc..). The biggest problem is text rendering. As you probably know PDL::G::P internally uses all sophisticated text abilities from Prima, like text_wrap etc... to position titles and labels. Once, the Prima-specific API is implemented in Cairo backend, I hope PDL::G::P will work without problems because it is fully complaint to the Prima::Drawable interface.

Sincerely, ∃t.

dk commented 9 years ago

Hi Teslos!

Thank you for the proposition :) There are five big areas that are in need of development in Prima::Cairo:

1) fonts - this one just didn't started yet. All the API functions listed above are needed. 2) images - drawing/stretching images, bitmaps, and, especially icons on Prima::Cairo::Drawable can be tricky. 3) clipping - clip rects and regions 4) line and fill patterns - I started playing with it, transparent patterns are tricky. 5) primitives - ellipse, chord, polyline, pixel etc

You're welcome to try whatever area you find most interesting, and I'll be glad to help you along the way.

Cheers! Dmitry

Teslos commented 9 years ago

Hi Dmitry,

I have tried to add new primitives and fillPattern and linePattern, you can take a look at my repo. There is a small test cairo_drawable.pl in the examples/. At first I was a little bit confused with implementation of the Prima::Cairo. I expected that only Prima::Drawable functions are exposed publicly and internally they use Cairo library. But now I think that exposing Cairo draw functions directly to Prima is excellent idea. One of the benefits is that user which knows Cairo already, can directly draw on the Prima widgets. You can check my analog_clock example. Here only the widget code was changed (from Gtk to Prima) and everything worked without problems:) Second you can do some nice hacks as drawing patterns in Prima and then create cairo surface from it that can be used to do 2d plotting (fillPattern uses this).

I had some problems with compiling Prima with tiff jpeg and gif support (I can't run FPS shooter :). I am running Mac OS X 10.9.3 with MacPorts and all these libraries are installed. I suppose Makefile.PL can't find it on my system as MacPorts uses non-standard unix paths for libs.

Best regards, ∃t.

dk commented 9 years ago

On Sun, Jul 13, 2014 at 09:18:42AM -0700, ∃teslos wrote:

Hi Dmitry,

I have tried to add new primitives and fillPattern and linePattern, you can take a look at my repo. There is a small test cairo_drawable.pl in the examples/.

Hi Teslos,

This is great! I like how it works! Does it also work with colors other than black and white, and with other ROPs (in particularly, with rop::NoOper that makes the pattern transparent)?

At first I was a little bit confused with implementation of the Prima::Cairo. I expected that only Prima::Drawable functions are exposed publicly and internally they use Cairo library. But now I think that exposing Cairo draw functions directly to Prima is excellent idea. One of the benefits is that user which knows Cairo already, can directly draw on the Prima widgets. You can check my analog_clock example.

This is a nice example, I'd like to include it in the distro. I've made a diff (see attached) so it blinks less, and there's some trouble when the window gets resized.

I had some problems with compiling Prima with tiff jpeg and gif support (I can't run FPS shooter :). I am running Mac OS X 10.9.3 with MacPorts and all these libraries are installed. I suppose Makefile.PL can't find it on my system as MacPorts uses non-standard unix paths for libs.

You're not the first person to complain about it. However I don't have a mac, and the one I have in the virtualbox with Xcode 3 and other old stuff seems to be working barely ok, but together with libjpeg. If you could come with a patch to Makefile.PL for Mac, so it knows where to looks for these libraries, that would be really great!

Other than this, I like your progress very much ! I've added you as a collaborator to the Prima-Cairo project on github, you're welcome to commit the good stuff there :)

/dk

Best regards, ∃t.


Reply to this email directly or view it on GitHub: https://github.com/dk/Prima/issues/22#issuecomment-48844823

Sincerely, Dmitry Karasik diff --git a/examples/analog_clock.pl b/examples/analog_clock.pl index 9a9ef17..b40da48 100644 --- a/examples/analog_clock.pl +++ b/examples/analog_clock.pl @@ -85,23 +85,24 @@ my($width, $height); my $w = Prima::MainWindow->new( text => 'Analog clock', size => [300,300],

dk commented 9 years ago

diff --git a/examples/analog_clock.pl b/examples/analog_clock.pl index 9a9ef17..b40da48 100644 --- a/examples/analog_clock.pl +++ b/examples/analog_clock.pl @@ -85,23 +85,24 @@ my($width, $height); my $w = Prima::MainWindow->new( text => 'Analog clock', size => [300,300],

dk commented 9 years ago

oh this just doesn't work well with diff ...

Teslos commented 9 years ago

Hi Dimtry,

Thanks for your help and comments! Concerning the fillPattern, it works with other colours. I tested it with the using the rgb24 format for cairo surface. I think it also works with rop operations, do you have a small example in Prima which shows how the transparency works with rop::NoOper (when I tried rop::NoOper in the fillPattern and it shows only white background).
In the Cairo.xs there is code: case 25: bc_rgbi_rgb(dest_buf, src_buf, w); { int j; Byte * alpha = dest_buf + 3; for (j = 0; j < w; j++, alpha += 4) mask_buf_byte[j] = (*alpha < 127) ? 0 : 1; } bc_byte_mono_cr( mask_buf_byte, mask_buf, w, colorref_byte); break; that copies alpha channel, so I tried creating $im->type(im::RGB) Prima image and creating cairo surface from it : my $surface = Prima::Cairo::to_cairo_surface($im, 'argb32'); but this creates empty image.

Maybe it is necessary also to define alpha channel in Prima Image. Thanks one more time for your help, I will try to fix Makefile.PL for mac os x so I can compile FPS shooter:)

Best regards, ∃t.

Teslos commented 9 years ago

Sorry I forgot, maybe we can use Gist for diffs. I never used it before but it looks ok :)

∃t.

dk commented 9 years ago

On Mon, Jul 14, 2014 at 03:22:32PM -0700, ∃teslos wrote:

Hi Dimtry,

Thanks for your help and comments! Concerning the fillPattern, it works with other colours. I tested it with the using the rgb24 format for cairo surface. I think it also works with rop operations, do you have a small example in Prima which shows how the transparency works with rop::NoOper (when I tried rop::NoOper in the fillPattern and it shows only white background).

Hi Teslos,

Yes indeed you were right. I assumed that rop2=NoOper is identical with how the background is treated in lines and patterns, but it is not actually in Prima, which I believe a very old bug, or possibly a common denominator between win32 ,x11, and postscript. I plan to investigate this further, and hope that I can make ropNoOper to behave good with patterns, but so far yes, it doesn't seem to make any sense to implement that in Cairo, until the issue in resolved in Prima.

However, rop2=noOper works with line patterns. Try to paint fat lines with rop2 set to ropNoOper and ropCopyPut, with, f.ex., backColor(cl::Yellow) to see the difference.

In the Cairo.xs there is code: case 25: bc_rgbi_rgb(dest_buf, src_buf, w); { int j; Byte * alpha = dest_buf + 3; for (j = 0; j < w; j++, alpha += 4) mask_buf_byte[j] = (*alpha < 127) ? 0 : 1; } bc_byte_mono_cr( mask_buf_byte, mask_buf, w, colorref_byte); break; that copies alpha channel, so I tried creating $im->type(im::RGB) Prima image and creating cairo surface from it : my $surface = Prima::Cairo::to_cairo_surface($im, 'argb32'); but this creates empty image.

Maybe it is necessary also to define alpha channel in Prima Image.

Yes, that was a bug! Please test the latest github version if that works for you

Thanks one more time for your help, I will try to fix Makefile.PL for mac os x so I can compile FPS shooter:)

You're welcome, thanks for your work!

Best regards, ∃t.


Reply to this email directly or view it on GitHub: https://github.com/dk/Prima/issues/22#issuecomment-48968010

Sincerely, Dmitry Karasik

dk commented 9 years ago

Hmm yes that works:

https://gist.github.com/dk/502a4ffc99997f122f57

/dk

On Mon, Jul 14, 2014 at 03:42:14PM -0700, ∃teslos wrote:

Sorry I forgot, maybe we can use Gist for diffs. I never used it before but it looks ok :)

∃t.


Reply to this email directly or view it on GitHub: https://github.com/dk/Prima/issues/22#issuecomment-48969708

Sincerely, Dmitry Karasik

dk commented 9 years ago

Dear Teslos,

I've just investigated issue with rop2 under win32, x11, and postscript and this is all a bit frustrating. The win32 does not support transparent patterns (not Prima, but Windows itself). Therefore it was turned off in X11 and Postscript.

But I thought that line patterns will be rendered correctly - however unfortunately it is not right. All three implementations have bugs - win32 ignores ropCopyPut even though theoretically winapi should support it. X11 supports ropCopyPut but ignores background color. Postscript correctly draws lines with ropCopyPut but ignores ropNoOper (but this I've just fixed)!

For the cairo backend, it means that if you can implement rop2 for ropNoOper and ropNoCopyPut, then please do, it will be a nice thing to have, if in the future we will have cairo as a full-fledged (or even default) backend. So for the reference implementation, here's the script that tests it:

https://gist.github.com/dk/4232953cbf1c21f5dc4e

but it needs the latest Prima snapshot from github. I hope this helps!