On 25.06.21 15:04, David Kastrup wrote:

Well, the PostScript code sucks for a reason.  It goes to tremendous
effort to make stems in bitmaps end up more consistent in thickness than
rendering left and right edge independently would.

Yes. But I havn't had a look at the 'strokeadjust with cairo' topic.

For those who are interested: The aattached patch adds uri hyperlinks and 
internal page hyperlinks (forward references to page numbers have a problem). 
Also included: partial ellipses, needed by the woodwind diagram code.

Knut

>From b38e3023e3d2cf15362a03605808b10d2f866488 Mon Sep 17 00:00:00 2001
From: Knut Petersen <knup...@gmail.com>
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<bool> (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<bool> (filled);
   double xrad = from_scm<Real> (xradius);
   double yrad = from_scm<Real> (yradius);
   double blot = from_scm<Real> (thickness);
+  bool fill = from_scm<bool> (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<bool> (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<Real> (xradius);
+  double yrad = from_scm<Real> (yradius);
+  double sang = from_scm<Real> (startangle);
+  double eang = from_scm<Real> (endangle);
+  double blot = from_scm<Real> (thickness);
+  bool conn = from_scm<bool> (connected);
+  bool fill = from_scm<bool> (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<bool> (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<Real>(scm_car (varx));
+  double y = from_scm<Real>(scm_car (vary));
+  double w = from_scm<Real>(scm_cdr (varx)) - x;
+  double h = y - from_scm<Real>(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<bool> (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<int>(target);
+  double x = from_scm<Real>(scm_car (varx));
+  double y = from_scm<Real>(scm_car (vary));
+  double w = from_scm<Real>(scm_cdr (varx)) - x;
+  double h = y - from_scm<Real>(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

Reply via email to