Hi Lukas,
This time around, I could get it to compile. :-)
Thanks for testing
After testing it against a bunch of my recent everyday LilyPond documents: For most of the files, it seems to work perfectly. (In Okular, I seem to notice very subtle differences in line widths, but those may be rendering artifacts.)
The same is true for glyphs ... I have to investigate if there is a minor ghostscript or cairo or poppler (=previewer) problem
Also, in most cases, the Cairo-generated pdf is much smaller than the original. This seems most promising and not far from production quality!
probably you did not use \pointAndClickOff ;-) At least the code of ly:cairo-draw-round-box in my patch needs optimizations and can be tuned to generate much smaller pdf code.
Noticable defects: - There's no support for colors yet, right?
Coloring was only partially implemented and disabled, it works in the attached patch that can be applied on top of the V2 patch. The attached patch also implements rotation and supports transparent colors. prglprob.ly tests those features.
- \markup \scale ... is ignored. Is this a fundamental limitation, or is this "just not done yet"?
All missing features are "not done yet", I do not expect fundamental problems ... Knut
>From 95935842f96790c7a0423636e3c8a03c2bd83e3a Mon Sep 17 00:00:00 2001 From: Knut Petersen <knup...@gmail.com> Date: Fri, 25 Jun 2021 11:30:53 +0200 Subject: [PATCH] Cairo improvements - implemented rotation - coloring of grobs works - transparency works - improved drawing of ellipses --- lily/cairo.cc | 79 ++++++++++++++++++++++++++++++++++------------- scm/output-ps.scm | 7 ++++- 2 files changed, 63 insertions(+), 23 deletions(-) diff --git a/lily/cairo.cc b/lily/cairo.cc index dd7edc9d25..216b7ea4d4 100644 --- a/lily/cairo.cc +++ b/lily/cairo.cc @@ -436,7 +436,6 @@ LY_DEFINE (ly_cairo_set_paper_height, "ly:cairo-set-paper-height", // This assumes that lily_paper_height is set after lily_paper_width and pdf_file_name surface = cairo_pdf_surface_create(cairo_pdf_filename.c_str(), lily_paper_width, lily_paper_height); cr = cairo_create(surface); - cairo_set_source_rgba(cr,0, 0, 0, 1); return SCM_UNSPECIFIED; } @@ -498,42 +497,37 @@ LY_DEFINE (ly_cairo_set_staff_height, "ly:cairo-set-staff-height", -LY_DEFINE (ly_cairo_setrgbcolor, "ly:cairo-setrgbcolor", - 3, 0, 0, (SCM varr, SCM varg, SCM varb), - "CAIRO equivalent of the postscript primitive setrgbcolor.") +LY_DEFINE (ly_cairo_setrgbacolor, "ly:cairo-setrgbacolor", + 4, 0, 0, (SCM varr, SCM varg, SCM varb, SCM vara), + "CAIRO equivalent of our postscript procedure setrgbacolor" + " defined in music-drawing-routines.ps.") { if (!from_scm<bool> (ly_get_option (ly_symbol2scm ("cairotest")))) return SCM_UNSPECIFIED; LY_ASSERT_TYPE (scm_is_real, varr, 1); LY_ASSERT_TYPE (scm_is_real, varg, 2); LY_ASSERT_TYPE (scm_is_real, varb, 3); + LY_ASSERT_TYPE (scm_is_real, vara, 4); double r = from_scm<Real> (varr); double g = from_scm<Real> (varg); double b = from_scm<Real> (varb); - cairo_set_source_rgba(cr,r, g, b, 1.0); - debug_output (_f ("setrgbcolor r:%f g:%f b:%f", r, g, b)); + double a = from_scm<Real> (vara); + cairo_save(cr); + cairo_set_source_rgba(cr,r, g, b, a); + debug_output (_f ("setrgbacolor r:%f g:%f b:%f a:%f", r, g, b, a)); return SCM_UNSPECIFIED; } -LY_DEFINE (ly_cairo_setrgbacolor, "ly:cairo-setrgbacolor", - 4, 0, 0, (SCM varr, SCM varg, SCM varb, SCM vara), - "CAIRO equivalent of our postscript procedure setrgbacolor" +LY_DEFINE (ly_cairo_resetrgbacolor, "ly:cairo-resetrgbacolor", + 0, 0, 0, (), + "CAIRO equivalent of our postscript procedure resetrgbacolor" " defined in music-drawing-routines.ps.") { if (!from_scm<bool> (ly_get_option (ly_symbol2scm ("cairotest")))) return SCM_UNSPECIFIED; - LY_ASSERT_TYPE (scm_is_real, varr, 1); - LY_ASSERT_TYPE (scm_is_real, varg, 2); - LY_ASSERT_TYPE (scm_is_real, varb, 3); - LY_ASSERT_TYPE (scm_is_real, vara, 4); - double r = from_scm<Real> (varr); - double g = from_scm<Real> (varg); - double b = from_scm<Real> (varb); - double a = from_scm<Real> (vara); - cairo_set_source_rgba(cr,r, g, b, a); - debug_output (_f ("setrgbacolor r:%f g:%f b:%f a:%f", r, g, b, a)); + cairo_restore(cr); return SCM_UNSPECIFIED; } @@ -695,14 +689,13 @@ LY_DEFINE(ly_cairo_draw_ellipse, "ly:cairo-draw-ellipse", double yrad = from_scm<Real> (yradius); double blot = from_scm<Real> (thickness); double cx, cy; - cairo_matrix_t old_matrix; - cairo_get_matrix(cr, &old_matrix); + cairo_save(cr); cairo_get_current_point(cr,&cx, &cy); cairo_translate(cr,cx,cy); cairo_scale(cr,1,yrad/xrad); cairo_new_path(cr); cairo_arc(cr,0,0,xrad*sf,0,2*M_PI); - cairo_set_matrix(cr,&old_matrix); + cairo_restore(cr); cairo_set_line_width(cr,blot*sf); if (fill) { cairo_stroke_preserve(cr); @@ -714,6 +707,47 @@ LY_DEFINE(ly_cairo_draw_ellipse, "ly:cairo-draw-ellipse", +LY_DEFINE(ly_cairo_set_rotation, "ly:cairo-set-rotation", + 3, 0, 0, (SCM angle, SCM varx, SCM vary), + "CAIRO: equivalent of setrotation.") +{ + if (!from_scm<bool> (ly_get_option (ly_symbol2scm ("cairotest")))) + return SCM_UNSPECIFIED; + LY_ASSERT_TYPE (scm_is_real, angle, 1); + LY_ASSERT_TYPE (scm_is_real, varx, 2); + LY_ASSERT_TYPE (scm_is_real, vary, 3); + double ang = from_scm<Real> (angle); + double x = from_scm<Real> (varx); + double y = from_scm<Real> (vary); + debug_output(_f("set_rotation angle:%f, x:%f, y%f", ang, x, y)); + cairo_save(cr); + cairo_translate(cr,x*sf,-y*sf); + cairo_rotate(cr,-ang/180*M_PI); + cairo_translate(cr,-x*sf,y*sf); + return SCM_UNSPECIFIED; +} + + + +LY_DEFINE(ly_cairo_reset_rotation, "ly:cairo-reset-rotation", + 3, 0, 0, (SCM angle, SCM varx, SCM vary), + "CAIRO: equivalent of resetrotation.") +{ + if (!from_scm<bool> (ly_get_option (ly_symbol2scm ("cairotest")))) + return SCM_UNSPECIFIED; + LY_ASSERT_TYPE (scm_is_real, angle, 1); + LY_ASSERT_TYPE (scm_is_real, varx, 2); + LY_ASSERT_TYPE (scm_is_real, vary, 3); + double ang = from_scm<Real> (angle); + double x = from_scm<Real> (varx); + double y = from_scm<Real> (vary); + debug_output(_f("reset_rotation angle:%f, x:%f, y%f", ang, x, y)); + cairo_restore(cr); + return SCM_UNSPECIFIED; +} + + + LY_DEFINE(ly_cairo_at_eof, "ly:cairo-at-eof", 0, 0, 0, (), "CAIRO: Inform cairo to finalize the pdf and to clean up.") @@ -727,6 +761,7 @@ LY_DEFINE(ly_cairo_at_eof, "ly:cairo-at-eof", } + // // // still missing: music-drawing-routines.ps: /draw_partial_ellipse % filled connect x-radius y-radius startangle endangle thickness draw_partial_ellipse diff --git a/scm/output-ps.scm b/scm/output-ps.scm index 788af6141d..09ebf66997 100644 --- a/scm/output-ps.scm +++ b/scm/output-ps.scm @@ -215,19 +215,24 @@ (if a (list r g b a) (list r g b)))) (colors (length colorlist))) + (ly:cairo-setrgbacolor r g b (if (= colors 3) 1.0 a)) (if (= colors 3) (apply ly:format "gsave ~4f ~4f ~4f setrgbcolor\n" colorlist) (apply ly:format "gsave ~4f ~4f ~4f ~4f setrgbacolor\n" colorlist)))) ;; restore color from stack -(define (resetcolor) "grestore\n") +(define (resetcolor) + (ly:cairo-resetrgbacolor) + "grestore\n") ;; rotation around given point (define (setrotation ang x y) + (ly:cairo-set-rotation ang x y) (ly:format "gsave ~4f ~4f translate ~a rotate ~4f ~4f translate\n" x y ang (- x) (- y))) (define (resetrotation ang x y) + (ly:cairo-reset-rotation ang x y) "grestore\n") (define (unknown) -- 2.31.1
\version "2.23.3" \paper { #(set-paper-size "a4") top-margin = 10\mm bottom-margin = 10\mm left-margin = 0\mm line-width = 210\mm } \markup { \center-column { \abs-fontsize #130 \line { "Fouled up" } \vspace #2 \abs-fontsize #70 \line { "beyond all repair!" } \vspace #2 \abs-fontsize #45 \line { \with-color #(x11-color 'red) "Fouled up beyond all repair!" } \vspace #2 \abs-fontsize #22 \line { "Fouled up beyond all repair!" \with-dimensions #'(0 . 0) #'(0 . 0) \with-color #(rgb-color 0.0 1.0 0.0 0.2) \draw-circle #30 #0 ##t "Fouled up beyond all repair!" } \vspace #2 \line { \draw-circle #3 #0.5 ##f \hspace #2 \circle {Foobar} \hspace #2 \draw-circle #3 #0 ##t } \vspace #2 \line { \rotate #-30 \ellipse { Foobar } \hspace #2 \ellipse { "Dr. Fred MBogo" } \hspace #2 \rotate #15 \rotate #15 \oval {Foobar} } \vspace #2 \line {\rotate #-30 "-30" \rotate #0 "000"\rotate #30 "030" \rotate #60 "060" \rotate #90 "090" \rotate #120 "120" \rotate #150 "150" \rotate #180 "180" \rotate #210 "210" \rotate #240 "240" \rotate #270 "270" \rotate #300 "300" \rotate #133 "330" \rotate #360 "360" \rotate #390 "390" } \vspace #2 } }