Notenkopf mit PostScript erzeugen

Begonnen von erich, Samstag, 9. Mai 2020, 22:50

« vorheriges - nächstes »

erich

Hallo allen

Mir kommt die Vermeidung von PostScript so vor, wie, wenn ich LaTeX vermeiden würde und statt dessen mathematische Formeln in HTML setzen sollte; jedoch: für einfache Fälle braucht man kein schweres Geschütz!

Es besteht der Wunsch darzustellen, wie man über Inkscape zu PostScript kommt. Vielleicht ist dann Harm so nett und stellt das Gleiche ohne Verwendung von PostScript dar.

In meinem Testordner befinden sich die beiden Scripte
head.ly

\version "2.20.0"
head = \markup \postscript #"
.1 .1 scale
8 15 translate
gsave
newpath
0 setgray
1 0 0 -1 0 13 6 array astore concat gsave
3.773 12.859 moveto
0.332 12.301 -0.902 9.32 1.016 6.199 curveto
2.938 3.074 7.285 0.992 10.734 1.543 curveto
14.184 2.09 15.43 5.066 13.5 8.203 curveto
11.57 11.344 7.219 13.418 3.773 12.859 curveto
closepath
3.773 12.859 moveto
fill
1 0 0 1 2.5 3.5 6 array astore concat gsave
newpath
1 setgray
2.449 7.609 moveto
0.168 7.207 -0.668 5.199 0.578 3.121 curveto
1.82 1.039 4.68 -0.328 6.965 0.066 curveto
9.246 0.461 10.094 2.469 8.84 4.559 curveto
7.59 6.648 4.73 8.008 2.449 7.609 curveto
closepath
2.449 7.609 moveto fill
grestore "


und testhead.ly

\version "2.20.0"
\include "/home/erich/Test/head.ly"
\paper {
  indent = 0
  paper-height = 20
  paper-width = 40}
\header {tagline = ##f}
\score {
  \new Staff \with {\remove "Time_signature_engraver"
                    clefGlyph = ##f}
  \new Voice {\override Staff.Clef #'stencil = #ly:text-interface::print
              \override Staff.Clef #'text = \head
              s}
}


Damit kann das Bild

siehe unten -  [oder kann man das auch hier einfügen? und wenn JA, wie macht man das?]

erzeugt werden. Zu beachten ist, dass die Notenlinie nicht im Innern der schwarzen Elipse erscheint.

In Inkscape erzeugt man zwei konzentrische Elipsen ohne Rand und dreht diese um 28°, dann transformiert man sie in Pfade und reduziert das Dokument auf die Größe der Figur.

Das Dokument wird als headClef.svg ausgegeben.

Mit der Anweisung

inkscape -E headClef.ps headClef.svg
[\code]

wird eine PostScript-Datei erzeugt.

[code]
%!PS-Adobe-3.0 EPSF-3.0
%%Creator: cairo 1.15.10 (http://cairographics.org)
%%CreationDate: Sat May  9 16:17:26 2020
%%Pages: 1
%%DocumentData: Clean7Bit
%%LanguageLevel: 2
%%BoundingBox: 0 0 15 12
%%EndComments
%%BeginProlog
50 dict begin
/q { gsave } bind def
/Q { grestore } bind def
/cm { 6 array astore concat } bind def
/w { setlinewidth } bind def
/J { setlinecap } bind def
/j { setlinejoin } bind def
/M { setmiterlimit } bind def
/d { setdash } bind def
/m { moveto } bind def
/l { lineto } bind def
/c { curveto } bind def
/h { closepath } bind def
/re { exch dup neg 3 1 roll 5 3 roll moveto 0 rlineto
      0 exch rlineto 0 rlineto closepath } bind def
/S { stroke } bind def
/f { fill } bind def
/f* { eofill } bind def
/n { newpath } bind def
/W { clip } bind def
/W* { eoclip } bind def
/BT { } bind def
/ET { } bind def
/BDC { mark 3 1 roll /BDC pdfmark } bind def
/EMC { mark /EMC pdfmark } bind def
/cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def
/Tj { show currentpoint cairo_store_point } bind def
/TJ {
  {
    dup
    type /stringtype eq
    { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse
  } forall
  currentpoint cairo_store_point
} bind def
/cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore
    cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def
/Tf { pop /cairo_font exch def /cairo_font_matrix where
      { pop cairo_selectfont } if } bind def
/Td { matrix translate cairo_font_matrix matrix concatmatrix dup
      /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point
      /cairo_font where { pop cairo_selectfont } if } bind def
/Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def
      cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def
/g { setgray } bind def
/rg { setrgbcolor } bind def
/d1 { setcachedevice } bind def
/cairo_data_source {
  CairoDataIndex CairoData length lt
    { CairoData CairoDataIndex get /CairoDataIndex CairoDataIndex 1 add def }
    { () } ifelse
} def
/cairo_flush_ascii85_file { cairo_ascii85_file status { cairo_ascii85_file flushfile } if } def
/cairo_image { image cairo_flush_ascii85_file } def
/cairo_imagemask { imagemask cairo_flush_ascii85_file } def
%%EndProlog
%%BeginSetup
%%EndSetup
%%Page: 1 1
%%BeginPageSetup
%%PageBoundingBox: 0 0 15 12
%%EndPageSetup
q 0 0 15 12 rectclip
1 0 0 -1 0 12 cm q
0 g
3.664 11.406 m 0.219 10.848 -1.016 7.867 0.906 4.746 c 2.824 1.621 7.172
-0.461 10.621 0.086 c 14.07 0.637 15.32 3.613 13.195 6.562 c 11.07 9.512
6.855 11.832 3.664 11.406 c h
3.664 11.406 m f
1 g
4.891 9.516 m 2.609 9.117 1.77 7.109 3.016 5.027 c 4.262 2.949 7.121 1.582
9.402 1.977 c 11.688 2.371 12.531 4.375 11.281 6.469 c 10.027 8.559 7.168
9.918 4.891 9.516 c h
4.891 9.516 m f
Q Q
showpage
%%Trailer
end
%%EOF

Der obere Teil der Datei besteht aus Abkürzungen, die teilweise im unteren Teil angewendet sind.

Der untere Teil

q 0 0 15 12 rectclip
1 0 0 -1 0 12 cm q
0 g
3.664 11.406 m 0.219 10.848 -1.016 7.867 0.906 4.746 c 2.824 1.621 7.172
-0.461 10.621 0.086 c 14.07 0.637 15.32 3.613 13.195 6.562 c 11.07 9.512
6.855 11.832 3.664 11.406 c h
3.664 11.406 m f
1 g
4.891 9.516 m 2.609 9.117 1.77 7.109 3.016 5.027 c 4.262 2.949 7.121 1.582
9.402 1.977 c 11.688 2.371 12.531 4.375 11.281 6.469 c 10.027 8.559 7.168
9.918 4.891 9.516 c h
4.891 9.516 m f
Q Q

stehen die Pfade der beiden Elipsen; in diesem streicht man die 1. Zeile, da man keinen Rand haben will; in der unteren Zeile streicht man ein 'Q'. Man ersetzt die Abkürzungen gemäß ihrer Definition im oberen Teil und erhält:


gsave
newpath
0 setgray
1 0 0 -1 0 13 6 array astore concat gsave
3.773 12.859 moveto
0.332 12.301 -0.902 9.32 1.016 6.199 curveto
2.938 3.074 7.285 0.992 10.734 1.543 curveto
14.184 2.09 15.43 5.066 13.5 8.203 curveto
11.57 11.344 7.219 13.418 3.773 12.859 curveto
closepath
3.773 12.859 moveto
fill
1 0 0 1 2.5 3.5 6 array astore concat gsave
newpath
1 setgray
2.449 7.609 moveto
0.168 7.207 -0.668 5.199 0.578 3.121 curveto
1.82 1.039 4.68 -0.328 6.965 0.066 curveto
9.246 0.461 10.094 2.469 8.84 4.559 curveto
7.59 6.648 4.73 8.008 2.449 7.609 curveto
closepath
2.449 7.609 moveto fill

grestore "


Das Script ergänzt man um die Zeilen

\version "2.20.0"

headClef = \markup \postscript #"
.1 .1 scale
8 15 translate


Die Parameter für 'scale' und 'translate' gewinnt man durch ausprobieren in LilyPond.

Gruß
Erich


Manuela

Danke Erich für die ausführliche Darstellung
Danke für eure Hilfe
viele Grüße
-- Manuela

harm6

Hallo Erich,

hat ein bißchen gedauert bis ich die Zeit für eine Antwort fand...

ZitatVielleicht ist dann Harm so nett und stellt das Gleiche ohne Verwendung von PostScript dar.

Nicht das wir uns falsch verstehen, ich hab nichts gegen postscript. Aber man muß einige Punkte berücksichtigen, wenn man \markup \postscript ... verwendet.
Der wichtigste ist, daß Ausdehnungen der Grafik nicht direkt gesetzt werden.

Aber es gibt wohl noch andere, wenn ich zum Beispiel Dein \head verwende mit folgendem Code:

#(set-global-staff-size 80)

\version "2.20.0"
%\include "/home/erich/Test/head.ly"
\paper {
  indent = 0
  paper-height = 70
  %paper-width = 40
}

\header { tagline = ##f }

\version "2.20.0"
head = \markup \postscript #"
.1 .1 scale
8 15 translate
gsave
newpath
0 setgray
1 0 0 -1 0 13 6 array astore concat gsave
3.773 12.859 moveto
0.332 12.301 -0.902 9.32 1.016 6.199 curveto
2.938 3.074 7.285 0.992 10.734 1.543 curveto
14.184 2.09 15.43 5.066 13.5 8.203 curveto
11.57 11.344 7.219 13.418 3.773 12.859 curveto
closepath
3.773 12.859 moveto
fill
1 0 0 1 2.5 3.5 6 array astore concat gsave
newpath
1 setgray
2.449 7.609 moveto
0.168 7.207 -0.668 5.199 0.578 3.121 curveto
1.82 1.039 4.68 -0.328 6.965 0.066 curveto
9.246 0.461 10.094 2.469 8.84 4.559 curveto
7.59 6.648 4.73 8.008 2.449 7.609 curveto
closepath
2.449 7.609 moveto fill
grestore "

\score {
  \new Staff \with { \remove "Time_signature_engraver" clefGlyph = ##f }
  \new Voice {
  \override Staff.Clef.stencil = #ly:text-interface::print
  \override Staff.Clef.text = \head
 
  \key cis \major
  c'1
  \clef alto
  d'
  }
}


So kommt folgendes Bild dabei raus (ich habs riesig gemacht, damit man auch die Kleinigkeiten sehen kann):

Sicherlich nicht was man haben will, ich habe auch keine Ahnung warum das so ist.

Anstelle von \head habe ich folgendes versucht. Ich bin von Deinen Werten ausgegangen und habe sie so verändert, daß sie sich alle auf (0 0 moveto) beziehen und auf ein 1/10 reduziert. Y-Coordinaten auf -1/10.
Das kann man sicher noch besser machen. Am heutigen Feiertag fühle ich mich bemerkenswert faul...
Ansonsten nutze ich alltägliche markup-commands:

mrkpII =
\markup
\override #'(filled . #t)
{
  \combine
  \path
    #0.05
    #'((moveto 0.0 0.0)
      (curveto
        -0.3441
        0.0558
        -0.4675
        0.3539
        -0.2757
        0.666)
      (curveto
        -0.0835
        0.9785
        0.3512
        1.1867
        0.6961
        1.1316)
      (curveto
        1.0411
        1.0769
        1.1657
        0.7793
        0.9727
        0.4656)
      (curveto
        0.7797
        0.1515
        0.3446
        -0.0558999999999999
        0.0
        -0.0)
      (closepath))
  \translate #'(0.12 . 0.17)
  \with-color #white
  \path
    #0.05
    #'((moveto 0.0 0.0)
       (curveto
         -0.2281
         0.0402
         -0.3117
         0.241
         -0.1871
         0.4488)
       (curveto
         -0.0629
         0.657
         0.2231
         0.7937
         0.4516
         0.7543)
       (curveto 0.6797 0.7148 0.7645 0.514 0.6391 0.305)
       (curveto
         0.5141
         0.0961
         0.2281
         -0.0399
         0.0
         0.0)
       (closepath))

}

#(set-global-staff-size 80)

\version "2.20.0"
%\include "/home/erich/Test/head.ly"
\paper {
  indent = 0
  paper-height = 70
  %paper-width = 40
}

\header { tagline = ##f }

\version "2.20.0"


\score {
  \new Staff \with { \remove "Time_signature_engraver" clefGlyph = ##f }
  \new Voice {
  \override Staff.Clef.stencil = #ly:text-interface::print
  \override Staff.Clef.text = \mrkpII
 
  \key cis \major
  c'1
  \clef alto
  d'
  }
}


Dann kommt dieses Bild dabei raus:


Ich hab mich jetzt nicht darum gekümmert die Clefs noch vertikal zu verschieben...
Aber man sieht das alles da ist.


Also nichts gegen postscript an sich, aber mit Umsicht!
\path ist im Vergleich mit \postscript fast immer die bessere Wahl.


Gruß,
  Harm

erich

#3
Hallo Harm

vielen Dank für Deine Mühe!

Mir scheint, Du hast die Daten für die beiden Ellipsen (Pfade) aus meinen Daten errechnet (transformiert).
So gesehen besteht zunächst mal die Aufgabe darin: wie komme ich zu den Daten für die Pfade.
Das Transformieren sollte doch auch unmittelbar in Inkscape funktionieren; man könne so zunächst graphisch arbeiten.

Gruß
Erich

P.S. Ich lese gerade:
ZitatDie neue Funktion make-path-stencil erlaubt die Verwendung aller absolut und relativ positionierten path-Befehle, mithin:

lineto, rlineto, curveto, rcurveto, moveto, rmoveto, closepath. Ebenfalls unterstützt sind die aus SVG-Pfaden bekannten entsprechenden Einbuchstabenversionen:

L, l, C, c, M, m, Z und z. Die neue Funktion ist mit der ursprünglichen make-connected-path-stencil-Funktion kompatibel. Vgl. auch 'scm/stencil.scm'.

das sollte die Umarbeitung einer aus Inkscape gewonnenen Datei erheblich vereinfachen

Arnold

Hallo Harm und Erich,

persönlich erstelle ich das Postsricpt immer noch direkt im Texteditor (und such anschließend in Gostscript die Fehlermeldungen zu meinen Tippfehlern).

Mit dieser Erfahrung den head in Harms Code angesehen, zeigt mir gleich, daß auf drei gsave nur ein grestore folgt. Wird dieses head-Markup oft genug aufgerufen, dann könnte GS der Arbeitsspeicher ausgehen, denn je Aufruf bleiben zwei Grafik-Status-Sicherungen (incl. aktuellem Pfad) stehen.

Nun, in den Markup-Kommandos stehen mittlerweile alle für Postscript typischen Pfad-Konstruktoren zur Verfügung (und damit auch für andere Backends wie SVG).
Meine letzten Anwendungen von Postscript waren z. Bsp.

  • Blattschneidemarken (wo ich meine Grafik relativ zum Papierformat-Ursprung zeichnen mußte)
  • ein Logo, welches als Postscript-Type3-font definiert ist, und auch noch in absoluter Schriftgröße und in einem festen Abstand zum Blattrand positioniert werden soll
  • und, noch in Vorbereitung, spezielle Notenköpfe, welche ich auch als Postscript-Type3-Font definiere, um durch Ausnutzung der Font-Machinery die PDF-Größe gering zu halten. Da frage ich auch den aktuellen font-size nach und skaliere das Postscript um den entsprechenden magstep-Wert.

Arnold



harm6

Hallo Erich,

Zitat von: Erich
Mir scheint, Du hast die Daten für die beiden Ellipsen (Pfade) aus meinen Daten errechnet (transformiert).
In der Tat. Ich hatte ja auch geschrieben was ich wie gemacht habe (auch wenn ich die verwendete procedure nicht gepostet habe.)

Zitat von: Erich
So gesehen besteht zunächst mal die Aufgabe darin: wie komme ich zu den Daten für die Pfade.
Jep.

Zitat von: Erich
Das Transformieren sollte doch auch unmittelbar in Inkscape funktionieren; man könne so zunächst graphisch arbeiten.
Ob und wie das in Inkscape geht, weiß ich nicht.
Allerdings war ja zu sehen, daß man vor Überraschungen nicht gefeit ist...

Zu make-path-stencil, make-connected-path-stencil und dem markup-command \path:
Sowohl \path als auch make-path-stencil generieren ihren output via:
    (ly:make-stencil `(path ...))
make-connected-path-stencil nutzt make-path-stencil.
Alle obigen setzen korrekte Ausdehnungen.

Also kein natives postscript wie beim markup-command \postscript.

Insoweit denke ich, daß wir nicht mehr weit auseinander liegen.

Mein einziger Punkt war eigentlich zu betonen, daß natives postscript (oder dessen Übertragung) Probleme mit sich bringen kann.
Auf der anderen Seite haben \path und die anderen Befehle nur eine limitierte Auswahl an postscript-Befehlen...



Gruß,
  Harm