>From b38e3023e3d2cf15362a03605808b10d2f866488 Mon Sep 17 00:00:00 2001 From: Knut Petersen Date: Fri, 25 Jun 2021 21:45:00 +0200 Subject: [PATCH] CAIRO: Add 1) uri and internal hyperlinks 2) partial ellipses Internal page hyperlinks to pages that have not been generated seem to be broken ... a cairo bug or a problem of the documentation? Partial ellipses are needed by the woodwind diagram code. Still some features are missing ... --- lily/cairo.cc | 115 ++++++++++++++++++++++++++++++++++++++++------ scm/output-ps.scm | 3 ++ 2 files changed, 103 insertions(+), 15 deletions(-) diff --git a/lily/cairo.cc b/lily/cairo.cc index 216b7ea4d4..c5efa6af74 100644 --- a/lily/cairo.cc +++ b/lily/cairo.cc @@ -676,7 +676,7 @@ LY_DEFINE(ly_cairo_draw_circle, "ly:cairo-draw-circle", LY_DEFINE(ly_cairo_draw_ellipse, "ly:cairo-draw-ellipse", 4, 0, 0, (SCM xradius, SCM yradius, SCM thickness, SCM filled), - "CAIRO: equivalent of our postscript procedure draw_circle.") + "CAIRO: equivalent of our postscript procedure draw_ellipse.") { if (!from_scm (ly_get_option (ly_symbol2scm ("cairotest")))) return SCM_UNSPECIFIED; @@ -684,10 +684,10 @@ LY_DEFINE(ly_cairo_draw_ellipse, "ly:cairo-draw-ellipse", LY_ASSERT_TYPE (scm_is_real, yradius, 2); LY_ASSERT_TYPE (scm_is_real, thickness, 3); LY_ASSERT_TYPE (scm_is_bool, filled, 4); - bool fill = from_scm (filled); double xrad = from_scm (xradius); double yrad = from_scm (yradius); double blot = from_scm (thickness); + bool fill = from_scm (filled); double cx, cy; cairo_save(cr); cairo_get_current_point(cr,&cx, &cy); @@ -707,6 +707,47 @@ LY_DEFINE(ly_cairo_draw_ellipse, "ly:cairo-draw-ellipse", +LY_DEFINE(ly_cairo_draw_partial_ellipse, "ly:cairo-draw-partial-ellipse", + 7, 0, 0, (SCM xradius, SCM yradius, SCM startangle, SCM endangle, SCM thickness, SCM connected, SCM filled), + "CAIRO: equivalent of our postscript procedure draw_partial_ellipse.") +{ + if (!from_scm (ly_get_option (ly_symbol2scm ("cairotest")))) + return SCM_UNSPECIFIED; + LY_ASSERT_TYPE (scm_is_real, xradius, 1); + LY_ASSERT_TYPE (scm_is_real, yradius, 2); + LY_ASSERT_TYPE (scm_is_real, startangle, 3); + LY_ASSERT_TYPE (scm_is_real, endangle, 4); + LY_ASSERT_TYPE (scm_is_real, thickness, 5); + LY_ASSERT_TYPE (scm_is_bool, connected, 6); + LY_ASSERT_TYPE (scm_is_bool, filled, 7); + double xrad = from_scm (xradius); + double yrad = from_scm (yradius); + double sang = from_scm (startangle); + double eang = from_scm (endangle); + double blot = from_scm (thickness); + bool conn = from_scm (connected); + bool fill = from_scm (filled); + double cx, cy; + 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,-eang/180*M_PI,-sang/180*M_PI); + if (conn) + cairo_close_path(cr); + cairo_restore(cr); + cairo_set_line_width(cr,blot*sf); + if (fill) { + cairo_stroke_preserve(cr); + cairo_fill(cr); + } else + cairo_stroke(cr); + return SCM_UNSPECIFIED; +} + + + LY_DEFINE(ly_cairo_set_rotation, "ly:cairo-set-rotation", 3, 0, 0, (SCM angle, SCM varx, SCM vary), "CAIRO: equivalent of setrotation.") @@ -748,6 +789,63 @@ LY_DEFINE(ly_cairo_reset_rotation, "ly:cairo-reset-rotation", +LY_DEFINE(ly_cairo_url_link, "ly:cairo-url-link", + 3, 0, 0, (SCM target, SCM varx, SCM vary), + "CAIRO: Add an URL link.") +{ + if (!from_scm (ly_get_option (ly_symbol2scm ("cairotest")))) + return SCM_UNSPECIFIED; + LY_ASSERT_TYPE (scm_is_string, target, 1); + LY_ASSERT_TYPE (scm_is_pair, varx, 2); + LY_ASSERT_TYPE (scm_is_pair, vary, 3); + string url = ly_scm2string (target); + double x = from_scm(scm_car (varx)); + double y = from_scm(scm_car (vary)); + double w = from_scm(scm_cdr (varx)) - x; + double h = y - from_scm(scm_cdr (vary)); + double cx, cy; + cairo_get_current_point(cr,&cx, &cy); + string attr = "rect=[ " + std::to_string (cx + x*sf) + " " + std::to_string (cy - y*sf) + " " + + std::to_string (w*sf) + " " + std::to_string (h*sf) + " ] uri='" + url + "'"; + cairo_tag_begin (cr, CAIRO_TAG_LINK, attr.c_str()); + cairo_tag_end (cr, CAIRO_TAG_LINK); + debug_output(_f("url-link %s",attr.c_str())); + return SCM_UNSPECIFIED; +} + + + +// FIXME Links to pages that already have been generated work fine, +// links with forward references do _not_ work in cairo 1.16. +// This is either a documentation flaw or a cairo bug. Maybe a named +// destination can be used? I'll have to investigate that. +// +LY_DEFINE(ly_cairo_page_link, "ly:cairo-page-link", + 3, 0, 0, (SCM target, SCM varx, SCM vary), + "CAIRO: Add a page link.") +{ + if (!from_scm (ly_get_option (ly_symbol2scm ("cairotest")))) + return SCM_UNSPECIFIED; + LY_ASSERT_TYPE (scm_is_integer, target, 1); + LY_ASSERT_TYPE (scm_is_pair, varx, 2); + LY_ASSERT_TYPE (scm_is_pair, vary, 3); + int page = from_scm(target); + double x = from_scm(scm_car (varx)); + double y = from_scm(scm_car (vary)); + double w = from_scm(scm_cdr (varx)) - x; + double h = y - from_scm(scm_cdr (vary)); + double cx, cy; + cairo_get_current_point(cr,&cx, &cy); + string attr = "rect=[ " + std::to_string (cx + x*sf) + " " + std::to_string (cy - y*sf) + " " + + std::to_string (w*sf) + " " + std::to_string (h*sf) + " ] page=" + std::to_string (page) + " pos=[0.0 0.0]"; + cairo_tag_begin (cr, CAIRO_TAG_LINK, attr.c_str()); + cairo_tag_end (cr, CAIRO_TAG_LINK); + message(_f("page-link %s",attr.c_str())); + 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.") @@ -759,16 +857,3 @@ LY_DEFINE(ly_cairo_at_eof, "ly:cairo-at-eof", debug_output(_f("CAIRO: Finished Pdf, cairo surface and context destroyed.")); return SCM_UNSPECIFIED; } - - - -// -// -// still missing: music-drawing-routines.ps: /draw_partial_ellipse % filled connect x-radius y-radius startangle endangle thickness draw_partial_ellipse -// music-drawing-routines.ps: /mark_URI% llx lly urx ury URI -// music-drawing-routines.ps: /mark_page_link % llx lly urx ury page -// music-drawing-routines.ps: /draw_dashed_line % dx dy thickness dashpattern offset draw_dashed_line -// -// lots of other things ... rotation, transformations, ... transparency, ... etc, etc -// -// diff --git a/scm/output-ps.scm b/scm/output-ps.scm index 09ebf66997..c8730326c6 100644 --- a/scm/output-ps.scm +++ b/scm/output-ps.scm @@ -67,6 +67,7 @@ x1 y1 thick)) (define (partial-ellipse x-radius y-radius start-angle end-angle thick connect fill) + (ly:cairo-draw-partial-ellipse x-radius y-radius start-angle end-angle thick connect fill) (ly:format "~a ~a ~4f ~4f ~4f ~4f ~4f draw_partial_ellipse\n" (if fill "true" "false") (if connect "true" "false") @@ -239,6 +240,7 @@ "unknown\n") (define (url-link url x y) + (ly:cairo-url-link url x y) (ly:format "~a ~a currentpoint vector_add ~a ~a currentpoint vector_add (~a) mark_URI\n" (car x) (car y) @@ -247,6 +249,7 @@ url)) (define (page-link page-no x y) + (ly:cairo-page-link page-no x y) (if (number? page-no) (ly:format "~a ~a currentpoint vector_add ~a ~a currentpoint vector_add ~a mark_page_link\n" (car x) -- 2.31.1