Hi everybody!

I played a bit with cairo / cairomm.  Comments are welcome.

Knut

>From 53ecf8bbff40641169edb520419d56394e2d753b Mon Sep 17 00:00:00 2001
From: Knut Petersen <knup...@gmail.com>
Date: Tue, 8 Jun 2021 23:09:02 +0200
Subject: [PATCH] CAIRO: playing and testing

This is just a sketch to show how we could get rid
of ghostscript. The code is minimal, just enough to
demonstrate that this way is possible.

To test: apply the patch, build lilypond and
compile the minimal score given below with
'lilypond -c filename.ly':

  \version "2.23.3"
  \pointAndClickOff
  \header { tagline = ##f }
  \relative c'{
  \repeat unfold 50 {
    c d e f g a b c
    c b a g f e d c
  }  \bar "|."}

In addition to 'filename.pdf' produced by ghostscript
a file 'filename.cairo.pdf' will be produced by cairo.

This patch

  - introduces dependencies on cairo => 1.16 and
    cairomm-1.16.0,

  - adds the necessariy linker and compile flags using
    pkg-config,

  - allows g++ to understand c++17 (required by cairomm),

  - implements some cairo equivalents of
      a) a few postscript primitives and
      b) a few postscript procedures from
         music_drawing_routines.ps.
---
 aclocal.m4                      |  25 ++
 config.make.in                  |   5 +-
 configure.ac                    |   2 +
 lily/cairo.cc                   | 435 ++++++++++++++++++++++++++++++++
 lily/main.cc                    |  10 +
 scm/framework-ps.scm            |  10 +
 scm/lily.scm                    |   2 +
 scm/output-ps.scm               |   4 +
 stepmake/stepmake/c++-vars.make |   2 +-
 9 files changed, 492 insertions(+), 3 deletions(-)
 create mode 100644 lily/cairo.cc

diff --git a/aclocal.m4 b/aclocal.m4
index 0897ead7ab..44a4eac21e 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -857,6 +857,31 @@ AC_DEFUN(STEPMAKE_GOBJECT, [
     fi
 ])
 
+AC_DEFUN(STEPMAKE_CAIRO, [
+    PKG_CHECK_MODULES(CAIRO, $1 >= $3, have_cairo=yes, true)
+    if test "$have_cairo" = yes; then
+        AC_DEFINE(HAVE_CAIRO)
+        AC_SUBST(CAIRO_CFLAGS)
+        AC_SUBST(CAIRO_LIBS)
+    else
+        r="cairo-devel"
+        ver="`$PKG_CONFIG --modversion $1`"
+        STEPMAKE_ADD_ENTRY($2, ["$r >= $3 (installed: $ver)"])
+    fi
+])
+
+AC_DEFUN(STEPMAKE_CAIROMM, [
+    PKG_CHECK_MODULES(CAIROMM, $1 >= $3, have_cairomm=yes, true)
+    if test "$have_cairomm" = yes; then
+        AC_DEFINE(HAVE_CAIROMM)
+        AC_SUBST(CAIROMM_CFLAGS)
+        AC_SUBST(CAIROMM_LIBS)
+    else
+        r="cairomm-devel"
+        ver="`$PKG_CONFIG --modversion $1`"
+        STEPMAKE_ADD_ENTRY($2, ["$r >= $3 (installed: $ver)"])
+    fi
+])
 
 AC_DEFUN(STEPMAKE_FREETYPE2, [
     PKG_CHECK_MODULES(FREETYPE2, $1 >= $3, have_freetype2=yes, true)
diff --git a/config.make.in b/config.make.in
index a2f40565ce..d7a5e47d56 100644
--- a/config.make.in
+++ b/config.make.in
@@ -13,10 +13,10 @@ AR = @AR@
 BISON = @BISON@
 CC = @CC@
 CONFIG_CPPFLAGS = $(FLEXLEXER_CPPFLAGS) @CPPFLAGS@
-CONFIG_CXXFLAGS = @CXXFLAGS@ $(GUILE_CFLAGS) $(FREETYPE2_CFLAGS) $(PANGO_FT2_CFLAGS)
+CONFIG_CXXFLAGS = @CXXFLAGS@ $(GUILE_CFLAGS) $(FREETYPE2_CFLAGS) $(PANGO_FT2_CFLAGS) @CAIROMM_CFLAGS@
 CONFIG_DEFINES = @DEFINES@
 CONFIG_LDFLAGS = @LDFLAGS@
-CONFIG_LIBS = @LIBS@ @EXTRA_LIBS@ @GLIB_LIBS@ @GUILE_LIBS@ @PANGO_FT2_LIBS@ @FONTCONFIG_LIBS@ @FREETYPE2_LIBS@
+CONFIG_LIBS = @LIBS@ @EXTRA_LIBS@ @GLIB_LIBS@ @GUILE_LIBS@ @PANGO_FT2_LIBS@ @FONTCONFIG_LIBS@ @FREETYPE2_LIBS@ @CAIROMM_LIBS@
 CROSS = @cross_compiling@
 CXX = @CXX@
 CXXABI_LIBS = @CXXABI_LIBS@
@@ -31,6 +31,7 @@ FLEX = @FLEX@
 FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
 FONTFORGE = @FONTFORGE@
 FREETYPE2_LIBS = @FREETYPE2_LIBS@
+CAIROMM_LIBS = @CAIROMM_LIBS@
 GLIB_LIBS = @GLIB_LIBS@ @GOBJECT_LIBS@
 GS_API = @GS_API@
 GS920 = @GS920@
diff --git a/configure.ac b/configure.ac
index 5806508371..bbd1323440 100644
--- a/configure.ac
+++ b/configure.ac
@@ -320,6 +320,8 @@ if test "$have_pangoft2_with_otf_feature" != yes ; then
 fi
 STEPMAKE_FONTCONFIG(fontconfig, REQUIRED, 2.4.0)
 STEPMAKE_FREETYPE2(freetype2, REQUIRED, 2.3.9)
+STEPMAKE_CAIRO(cairo, REQUIRED, 1.16.0)
+STEPMAKE_CAIROMM(cairomm-1.16, REQUIRED, 1.16.0)
 STEPMAKE_GLIB(glib-2.0, REQUIRED, 2.38)
 STEPMAKE_GOBJECT(gobject-2.0, REQUIRED, 2.38)
 
diff --git a/lily/cairo.cc b/lily/cairo.cc
new file mode 100644
index 0000000000..1eb0bed0a8
--- /dev/null
+++ b/lily/cairo.cc
@@ -0,0 +1,435 @@
+/*
+  This file is part of LilyPond, the GNU music typesetter.
+
+  Copyright (C) 2021 Knut Petersen <knup...@gmail.com>
+
+  LilyPond is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LilyPond is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#include "international.hh"
+#include "lily-guile.hh"
+#include "program-option.hh"
+#include "warn.hh"
+
+#include <string>
+#include <cairommconfig.h>
+#include <cairomm/context.h>
+#include <cairomm/surface.h>
+#include <cmath>
+//#include <glib.h>
+
+using std::string;
+using std::vector;
+
+double lily_output_units;
+double lily_output_scale;
+double lily_page_height;
+double lily_page_width;
+double lily_paper_height;
+double lily_paper_width;
+double lily_staff_line_thickness;
+double lily_line_width;
+double lily_staff_height;
+string lily_basename;
+
+
+double deg = M_PI / 180.0;
+double sf;
+
+
+string cairo_pdf_filename;
+Cairo::RefPtr<Cairo::PdfSurface> surface;
+Cairo::RefPtr<Cairo::Context> cr;
+Cairo::RefPtr<Cairo::ToyFontFace> musicfont;
+double musicfontscale;
+
+LY_DEFINE(ly_cairo_def_music_font, "ly:cairo-def-music-font",
+          3, 0, 0, (SCM scaledname, SCM fontname, SCM scaling),
+          "CAIRO: define a scaled music font.")
+{
+  if (!from_scm<bool> (ly_get_option (ly_symbol2scm ("cairotest")))) { return SCM_UNSPECIFIED; }
+  LY_ASSERT_TYPE (scm_is_string, scaledname, 1);
+  LY_ASSERT_TYPE (scm_is_string, fontname, 2);
+  LY_ASSERT_TYPE (scm_is_real, scaling, 3);
+  string sn =  ly_scm2string (scaledname);
+  string fn = ly_scm2string (fontname);
+  double scalefac = from_scm<Real> (scaling);
+  message (_f ("def-music-font: scaledname: %s, fontname: %s, scaling: %f", sn.c_str(), fn.c_str(), scalefac));
+  musicfont =  Cairo::ToyFontFace::create(fn,
+                               Cairo::ToyFontFace::Slant::NORMAL,
+                               Cairo::ToyFontFace::Weight::NORMAL);
+  musicfontscale = scalefac;
+  return SCM_UNSPECIFIED;
+}
+
+LY_DEFINE(ly_cairo_show_named_glyph, "ly:cairo-show-named-glyph",
+          2, 0, 0, (SCM scaledname, SCM glyphname),
+          "CAIRO: show a named glyph of a scaled font.")
+{
+  if (!from_scm<bool> (ly_get_option (ly_symbol2scm ("cairotest")))) { return SCM_UNSPECIFIED; }
+  LY_ASSERT_TYPE (scm_is_string, scaledname, 1);
+  LY_ASSERT_TYPE (scm_is_string, glyphname, 2);
+  string font = ly_scm2string (scaledname);
+  string glyph = ly_scm2string (glyphname);
+  message (_f ("show_named_glyph: scaledfont: %s glyph: %s",font.c_str(), glyph.c_str()));
+  long unsigned int gc = 0;
+  double cx, cy;
+
+  if      (glyph == "noteheads.s2") {gc = 0xaa;}
+  else if (glyph == "clefs.G")      {gc = 0x83;}
+  else if (glyph == "timesig.C44")  {gc = 0x8f;}
+
+  if (gc != 0) {
+    // FIXME
+    cr->set_font_face(musicfont);
+    cr->set_font_size(musicfontscale * lily_output_units);
+    cr->get_current_point(cx, cy);
+    cr->show_glyphs(vector <cairo_glyph_t> {{gc, cx, cy }});
+  }
+
+  return SCM_UNSPECIFIED;
+}
+
+
+
+LY_DEFINE (ly_cairo_showpage, "ly:cairo-showpage",
+           0, 0, 0, (),
+           "CAIRO:  equivalent of the postscript primitive showpage.")
+{
+  if (!from_scm<bool> (ly_get_option (ly_symbol2scm ("cairotest")))) { return SCM_UNSPECIFIED; }
+  debug_output (_f ("showpage"));
+  cr->show_page();
+  return SCM_UNSPECIFIED;
+}
+
+LY_DEFINE (ly_cairo_restore, "ly:cairo-restore",
+           0, 0, 0, (),
+           "CAIRO:  equivalent of the postscript primitive restore.")
+{
+  if (!from_scm<bool> (ly_get_option (ly_symbol2scm ("cairotest")))) { return SCM_UNSPECIFIED; }
+  debug_output (_f ("restore"));
+  cr->restore();
+  return SCM_UNSPECIFIED;
+}
+
+LY_DEFINE (ly_cairo_save, "ly:cairo-save",
+           0, 0, 0, (),
+           "CAIRO:  equivalent of the postscript primitive save.")
+{
+  if (!from_scm<bool> (ly_get_option (ly_symbol2scm ("cairotest")))) { return SCM_UNSPECIFIED; }
+  debug_output (_f ("save"));
+  cr->save();
+  return SCM_UNSPECIFIED;
+}
+
+
+LY_DEFINE (ly_cairo_moveto, "ly:cairo-moveto",
+           2, 0, 0, (SCM varx, SCM vary),
+           "CAIRO: equivalent of the postscript primitive moveto.")
+{
+  if (!from_scm<bool> (ly_get_option (ly_symbol2scm ("cairotest")))) { return SCM_UNSPECIFIED; }
+  LY_ASSERT_TYPE (scm_is_real, varx, 1);
+  LY_ASSERT_TYPE (scm_is_real, vary, 2);
+  double x=from_scm<Real> (varx);
+  double y=from_scm<Real> (vary);
+  message (_f ("moveto x: %f y: %f", x, y));
+  cr->move_to(x*sf,-y*sf);
+  return SCM_UNSPECIFIED;
+}
+
+
+
+LY_DEFINE (ly_cairo_set_basename, "ly:cairo-set-basename",
+           1, 0, 0, (SCM str),
+           "CAIRO: set lily-basename.")
+{
+  if (!from_scm<bool> (ly_get_option (ly_symbol2scm ("cairotest")))) { return SCM_UNSPECIFIED; }
+  LY_ASSERT_TYPE (scm_is_string, str, 1);
+  lily_basename = ly_scm2string (str);
+  cairo_pdf_filename = lily_basename + ".cairo.pdf";
+  debug_output (_f ("set-basename:             %s",lily_basename));
+  debug_output (_f ("cairo_pdf_filename is     %s",cairo_pdf_filename));
+  return SCM_UNSPECIFIED;
+}
+
+
+LY_DEFINE (ly_cairo_set_lily_output_units, "ly:cairo-set-lily-output-units",
+           1, 0, 0, (SCM val),
+           "CAIRO: set lily-output-units.")
+{
+  if (!from_scm<bool> (ly_get_option (ly_symbol2scm ("cairotest")))) { return SCM_UNSPECIFIED; }
+  LY_ASSERT_TYPE (scm_is_real, val, 1);
+  lily_output_units = from_scm<Real> (val);
+  sf = lily_output_units * lily_output_scale;
+  debug_output (_f ("set-lily-output-units:    %f, sf: %f",lily_output_units, sf));
+  return SCM_UNSPECIFIED;
+}
+
+LY_DEFINE (ly_cairo_set_output_scale, "ly:cairo-set-output-scale",
+           1, 0, 0, (SCM val),
+           "CAIRO: set output-scale.")
+{
+  if (!from_scm<bool> (ly_get_option (ly_symbol2scm ("cairotest")))) { return SCM_UNSPECIFIED; }
+  LY_ASSERT_TYPE (scm_is_real, val, 1);
+  lily_output_scale = from_scm<Real> (val);
+  sf = lily_output_units * lily_output_scale;
+  debug_output (_f ("set-output-scale:         %f sf: %f",lily_output_scale, sf));
+  return SCM_UNSPECIFIED;
+}
+
+LY_DEFINE (ly_cairo_set_page_height, "ly:cairo-set-page-height",
+           1, 0, 0, (SCM val),
+           "CAIRO: set page-height.")
+{
+  if (!from_scm<bool> (ly_get_option (ly_symbol2scm ("cairotest")))) { return SCM_UNSPECIFIED; }
+  LY_ASSERT_TYPE (scm_is_real, val, 1);
+  lily_page_height = from_scm<Real> (val);
+  debug_output (_f ("set-page-height:          %f",lily_page_height));
+  return SCM_UNSPECIFIED;
+}
+
+LY_DEFINE (ly_cairo_set_page_width, "ly:cairo-set-page-width",
+           1, 0, 0, (SCM val),
+           "CAIRO: set page-width.")
+{
+  if (!from_scm<bool> (ly_get_option (ly_symbol2scm ("cairotest")))) { return SCM_UNSPECIFIED; }
+  LY_ASSERT_TYPE (scm_is_real, val, 1);
+  lily_page_width = from_scm<Real> (val);
+  debug_output (_f ("set-page-width:           %f",lily_page_width));
+  return SCM_UNSPECIFIED;
+}
+
+LY_DEFINE (ly_cairo_set_paper_height, "ly:cairo-set-paper-height",
+           1, 0, 0, (SCM val),
+           "CAIRO: set paper-height.")
+{
+  if (!from_scm<bool> (ly_get_option (ly_symbol2scm ("cairotest")))) { return SCM_UNSPECIFIED; }
+  LY_ASSERT_TYPE (scm_is_real, val, 1);
+  lily_paper_height = from_scm<Real> (val);
+  debug_output (_f ("set-paper-height:         %f",lily_paper_height));
+  // This assumes that lily_paper_height is set after lily_paper_width and pdf_file_name
+  surface = Cairo::PdfSurface::create(cairo_pdf_filename, lily_paper_width, lily_paper_height);
+  cr = Cairo::Context::create(surface);
+  cr->set_source_rgba(0, 0, 0, 1);
+  return SCM_UNSPECIFIED;
+}
+LY_DEFINE (ly_cairo_set_paper_width, "ly:cairo-set-paper-width",
+           1, 0, 0, (SCM val),
+           "CAIRO: set paper-width.")
+{
+  if (!from_scm<bool> (ly_get_option (ly_symbol2scm ("cairotest")))) { return SCM_UNSPECIFIED; }
+  LY_ASSERT_TYPE (scm_is_real, val, 1);
+  lily_paper_width = from_scm<Real> (val);
+  debug_output (_f ("set-paper-width:          %f",lily_paper_width));
+  return SCM_UNSPECIFIED;
+}
+
+LY_DEFINE (ly_cairo_set_staff_line_thickness, "ly:cairo-set-staff-line-thickness",
+           1, 0, 0, (SCM val),
+           "CAIRO: set staff-line-thickness.")
+{
+  if (!from_scm<bool> (ly_get_option (ly_symbol2scm ("cairotest")))) { return SCM_UNSPECIFIED; }
+  LY_ASSERT_TYPE (scm_is_real, val, 1);
+  lily_staff_line_thickness = from_scm<Real> (val);
+  debug_output (_f ("set-staff-line-thickness: %f",lily_staff_line_thickness));
+  return SCM_UNSPECIFIED;
+}
+
+LY_DEFINE (ly_cairo_set_line_width, "ly:cairo-set-line-width",
+           1, 0, 0, (SCM val),
+           "CAIRO: set line-width.")
+{
+  if (!from_scm<bool> (ly_get_option (ly_symbol2scm ("cairotest")))) { return SCM_UNSPECIFIED; }
+  LY_ASSERT_TYPE (scm_is_real, val, 1);
+  lily_line_width= from_scm<Real> (val);
+  debug_output (_f ("set-line-width:           %f",lily_line_width));
+  return SCM_UNSPECIFIED;
+}
+
+LY_DEFINE (ly_cairo_set_staff_height, "ly:cairo-set-staff-height",
+           1, 0, 0, (SCM val),
+           "CAIRO: set staff-height.")
+{
+  if (!from_scm<bool> (ly_get_option (ly_symbol2scm ("cairotest")))) { return SCM_UNSPECIFIED; }
+  LY_ASSERT_TYPE (scm_is_real, val, 1);
+  lily_staff_height = from_scm<Real> (val);
+  debug_output (_f ("set-staff-height:         %f",lily_staff_height));
+  return SCM_UNSPECIFIED;
+}
+
+
+
+//  music-drawing-routines.ps: /setrgbacolor % r g b
+LY_DEFINE (ly_cairo_setrgbcolor, "ly:cairo-setrgbcolor",
+           3, 0, 0, (SCM varr, SCM varg, SCM varb),
+           "CAIRO equivalent of the postscript primitive setrgbcolor.")
+{
+  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);
+  double r = from_scm<Real> (varr);
+  double g = from_scm<Real> (varg);
+  double b = from_scm<Real> (varb);
+  cr->set_source_rgba(r, g, b, 1.0);
+  debug_output (_f ("setrgbcolor r:%f g:%f b:%f", r, g, b));
+  return SCM_UNSPECIFIED;
+}
+
+//  music-drawing-routines.ps: /setrgbacolor % r g b a
+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);
+  double a = from_scm<Real> (vara);
+  cr->set_source_rgba(r, g, b, a);
+  debug_output (_f ("setrgbacolor r:%f g:%f b:%f a:%f", r, g, b, a));
+  return SCM_UNSPECIFIED;
+}
+
+
+
+// /draw_line % dx dy x y thickness draw_line
+LY_DEFINE (ly_cairo_draw_line, "ly:cairo-draw-line",
+           5, 0, 0, (SCM vardx, SCM vardy, SCM varx, SCM vary, SCM blotdiam),
+           "CAIRO equivalent of our postscript procedure draw_line"
+           " 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, vardx, 1);
+  LY_ASSERT_TYPE (scm_is_real, vardy, 2);
+  LY_ASSERT_TYPE (scm_is_real, varx, 3);
+  LY_ASSERT_TYPE (scm_is_real, vary, 4);
+  LY_ASSERT_TYPE (scm_is_real, blotdiam, 5);
+  double dx=from_scm<Real> (vardx);
+  double dy=from_scm<Real> (vardy);
+  double x=from_scm<Real> (varx);
+  double y=from_scm<Real> (vary);
+  double d=from_scm<Real> (blotdiam);
+  cr->set_line_width(d*sf);
+  cr->set_line_cap(Cairo::Context::LineCap::ROUND);
+  cr->rel_move_to(x*sf,-y*sf);
+  cr->rel_line_to(dx*sf,-dy*sf);
+  cr->stroke();
+  debug_output (_f ("draw_line dx:%f dy:%f x:%f y:%f blotdiam:%f",
+               from_scm<Real> (vardx), from_scm<Real> (vardy), from_scm<Real> (varx), from_scm<Real> (vary), from_scm<Real> (blotdiam)));
+  return SCM_UNSPECIFIED;
+}
+
+// /draw_dashed_line % dx dy thickness dashpattern offset draw_dashed_line
+//
+// still missing
+//
+
+// music-drawing-routines.ps: /draw_round_box % width height x y blot
+LY_DEFINE (ly_cairo_draw_round_box, "ly:cairo-draw-round-box",
+           5, 0, 0, (SCM width, SCM height, SCM varx, SCM vary, SCM blotdiam),
+           "CAIRO equivalent of our postscript procedure draw_round_box"
+           " 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, width, 1);
+  LY_ASSERT_TYPE (scm_is_real, height, 2);
+  LY_ASSERT_TYPE (scm_is_real, varx, 3);
+  LY_ASSERT_TYPE (scm_is_real, vary, 4);
+  LY_ASSERT_TYPE (scm_is_real, blotdiam, 5);
+  double w=from_scm<Real> (width);
+  double h=from_scm<Real> (height);
+  double x=from_scm<Real> (varx);
+  double y=from_scm<Real> (vary);
+  double d=from_scm<Real> (blotdiam);
+  double r = d / 2;
+  debug_output (_f ("draw_round_box width:%f height:%f x:%f y:%f blotdiam:%f", w, h, x, y, d));
+  if (r == 0) {
+    cr->rel_move_to(x*sf,-y*sf);
+    cr->rel_line_to(0,-h*sf);
+    cr->rel_line_to(w*sf,0);
+    cr->rel_line_to(0,h*sf);
+    cr->rel_line_to(-w*sf,0);
+    cr->close_path();
+    cr->fill();
+  } else {
+    double cx, cy;
+    cr->rel_move_to(x*sf, -y*sf);
+    cr->get_current_point(cx, cy);
+    cr->begin_new_sub_path();
+    cr->arc(cx+w*sf,cy-h*sf,r*sf,-90*deg,0*deg);
+    cr->arc(cx+w*sf,cy,r*sf,0*deg,90*deg);
+    cr->arc(cx,cy,r*sf,90*deg,180*deg);
+    cr->arc(cx,cy-h*sf,r*sf,180*deg,270*deg);
+    cr->close_path();
+    cr->fill();
+  }
+  return SCM_UNSPECIFIED;
+}
+
+
+
+// music-drawing-routines.ps: /draw_polygon % fill? x(n) y(n) x(n-1) y(n-1) ... x(0) y(0) n blot
+//
+// still missing
+//
+
+// music-drawing-routines.ps: /draw_circle % filled? radius thickness draw_circle
+//
+// still missing
+//
+
+// music-drawing-routines.ps: /draw_ellipse % filled? x-radius y-radius thickness draw_ellipse
+//
+// still missing
+//
+
+// music-drawing-routines.ps: /draw_partial_ellipse % filled connect x-radius y-radius startangle endangle thickness draw_partial_ellipse
+// % Note that filled is not boolean to permit for different graylevels (ie for trill keys)
+//
+// still missing
+//
+
+// /print_glyphs % w dx dy glyph print_glyphs
+//
+// still missing
+//
+
+// music-drawing-routines.ps: /mark_URI% llx lly urx ury URI
+//
+// still missing
+//
+
+// music-drawing-routines.ps: /mark_page_link % llx lly urx ury page
+//
+// still missing
+//
+
+
+
+// music-drawing-routines.ps: /stroke_and_fill?
+
+// Inclusion of encapsulated postscript files will probably not be supported
+//
+// music-drawing-routines.ps: /BeginEPSF
+// music-drawing-routines.ps: /EndEPSF
+
+
+
diff --git a/lily/main.cc b/lily/main.cc
index 5564222b35..ddbeefe59f 100644
--- a/lily/main.cc
+++ b/lily/main.cc
@@ -145,6 +145,10 @@ static Long_option_init options_static[]
     0, "eps", 'E',
     _i ("generate Encapsulated PostScript files")
   },
+  {
+    0, "cairotest", 'c',
+    _i ("generate a *.cairo.pdf test file")
+  },
   {
     _i ("KEY"), "pspdfopt", 'O',
     _i ("set ps/pdf optimization to KEY, which is either\n"
@@ -679,6 +683,12 @@ parse_argv (int argc, char **argv)
           }
           break;
 
+        case 'c':
+          {
+            init_scheme_variables_global += "(cairotest . #t)\n";
+          }
+          break;
+
         case 'd':
           {
             string arg (option_parser->optional_argument_str0_);
diff --git a/scm/framework-ps.scm b/scm/framework-ps.scm
index 18dc6a7166..aaef98cc4f 100644
--- a/scm/framework-ps.scm
+++ b/scm/framework-ps.scm
@@ -51,6 +51,7 @@
   "")
 
 (define (ps-define-font font font-name scaling)
+  (ly:cairo-def-music-font (ps-font-command font) font-name scaling)
   (if (ly:get-option 'music-font-encodings)
       (string-append
        "/" (ps-font-command font) "-N"
@@ -87,6 +88,11 @@
      "/" ps-key " "
      (value->string (ly:output-def-lookup layout ly-key)) " def\n"))
 
+  (ly:cairo-set-lily-output-units (/ (ly:bp 1)))
+  (ly:cairo-set-output-scale (ly:output-def-lookup layout 'output-scale))
+  (ly:cairo-set-page-height (ly:output-def-lookup layout 'paper-height))
+  (ly:cairo-set-page-width (ly:output-def-lookup layout 'paper-width))
+  (ly:cairo-set-staff-height (ly:output-def-lookup layout 'staff-height))
   (string-append
    "/lily-output-units "
    (number->string (/ (ly:bp 1))) " def %% millimeter\n"
@@ -123,6 +129,7 @@
     "gsave 0 paper-height translate set-ps-scale-to-lily-scale\n"))
   (ly:outputter-dump-stencil outputter page-stencil)
   (ly:outputter-dump-string outputter ".endtransparencygroup\n.poppdf14devicefilter\n")
+  (ly:cairo-showpage)
   (ly:outputter-dump-string outputter "stroke grestore\nshowpage\n"))
 
 (define (supplies-or-needs paper load-fonts?)
@@ -163,6 +170,8 @@
                 (ly:output-def-lookup paper 'output-scale))
                (ly:bp 1)))
          (landscape? (eq? (ly:output-def-lookup paper 'landscape) #t)))
+    (ly:cairo-set-paper-width (if landscape? h w))
+    (ly:cairo-set-paper-height (if landscape? w h))
     (format #f "%%DocumentMedia: ~a ~,2f ~,2f ~a ~a ~a\n"
                (ly:output-def-lookup paper 'papersizename)
                (if landscape? h w)
@@ -765,6 +774,7 @@ mark {ly~a_stream} /CLOSE pdfmark
          (landscape? (eq? (ly:output-def-lookup paper 'landscape) #t))
          (page-number (1- (ly:output-def-lookup paper 'first-page-number)))
          (page-count (length page-stencils)))
+    (ly:cairo-set-basename basename)
     (cond-expand
      (guile-2 (set-port-encoding! port "Latin1"))
      (else))
diff --git a/scm/lily.scm b/scm/lily.scm
index 06760089f0..5b3f99f4ea 100644
--- a/scm/lily.scm
+++ b/scm/lily.scm
@@ -258,6 +258,8 @@ EPS backend.")
     (backend ps
              "Select backend.  Possible values: 'eps, 'null,
 'ps, 'scm, 'svg.")
+    (cairotest #f
+                          "Also generate a .cairo.pdf file.")
     (check-internal-types #f
                           "Check every property assignment for types.")
     (clip-systems #f
diff --git a/scm/output-ps.scm b/scm/output-ps.scm
index 3373108f8d..c730a4067f 100644
--- a/scm/output-ps.scm
+++ b/scm/output-ps.scm
@@ -60,6 +60,7 @@
              phase))
 
 (define (draw-line thick x1 y1 x2 y2)
+  (ly:cairo-draw-line (- x2 x1) (- y2 y1) x1 y1 thick)
   (ly:format "~4f ~4f ~4f ~4f ~4f draw_line\n"
              (- x2 x1) (- y2 y1)
              x1 y1 thick))
@@ -159,6 +160,7 @@
       ""))
 
 (define (named-glyph font glyph)
+  (ly:cairo-show-named-glyph (ps-font-command font) glyph)
   (if (and (ly:get-option 'music-font-encodings) (string-startswith (ly:font-file-name font) "emmentaler"))
       (if (string-endswith (ly:font-file-name font)"-brace")
           (if (or (string-startswith glyph "brace1") (string-startswith glyph "brace2"))
@@ -177,6 +179,7 @@
   "")
 
 (define (settranslation x y)
+  (ly:cairo-moveto x y)
   (ly:format " ~4f ~4f moveto\n" x y))
 
 (define (polygon points blot-diameter filled?)
@@ -192,6 +195,7 @@
          (width (- right (+ halfblot x)))
          (y (- halfblot bottom))
          (height (- top (+ halfblot y))))
+    (ly:cairo-draw-round-box width height x y blotdiam)
     (ly:format "~4f ~4f ~4f ~4f ~4f draw_round_box\n"
                width height x y blotdiam)))
 
diff --git a/stepmake/stepmake/c++-vars.make b/stepmake/stepmake/c++-vars.make
index f0368aec58..090bca9fcf 100644
--- a/stepmake/stepmake/c++-vars.make
+++ b/stepmake/stepmake/c++-vars.make
@@ -1,6 +1,6 @@
 ALL_LDFLAGS = $(LDFLAGS) $(CONFIG_LDFLAGS) $(MODULE_LDFLAGS) $(CONFIG_LDFLAGS)
 
-EXTRA_CXXFLAGS = -std=c++11 -fno-exceptions -W -Wall -Wconversion -Woverloaded-virtual
+EXTRA_CXXFLAGS = -std=c++17 -fno-exceptions -W -Wall -Wconversion -Woverloaded-virtual
 
 o-dep-out = $(outdir)/$(subst .o,.dep,$(notdir $@))#
 EXTRA_CXXFLAGS += -MMD -MP -MF $(o-dep-out) -MT $(outdir)/$(notdir $@)
-- 
2.31.1

  • Cairo Knut Petersen
    • Re: Cairo Jonas Hahnfeld via Discussions on LilyPond development

Reply via email to