Autor Thema: Spacing zwischen Buchstaben in TextMarkup  (Gelesen 12282 mal)

kilgore

  • Member
Re: Spacing zwischen Buchstaben in TextMarkup
« Antwort #15 am: Sonntag, 17. Juni 2012, 13:44 »
Spacing:

Ja ja ja! wirklich prima :)

Scheme:

Danke für das Link. "Scheme für Dummies" ist genau was ich brauche. Ich habe schon ein bisschen damit angefangen und es ist sehr verständlich. Damit werde ich wohl viel weiter kommen!

Danke Danke!

Gruß
kil

Arnold

  • Member
Re: Spacing zwischen Buchstaben in TextMarkup
« Antwort #16 am: Montag, 18. Juni 2012, 09:22 »
Und hier meine Überarbeitung der Routine (nur bis zum string->string-list):
\version "2.14.2"

#(define (utf-8-string->wide-char-list str)
  "Convert a UTF-8 byte string into an list with interger representing the UNICODE character codes"
  (let
   ((erg '())
    (len (string-length str))
    (mult 1)
    (sum 0))
   (do ((ct (- len 1) (1- ct))) ((< ct 0)) ; process backward
    (let ((numeric (char->integer (string-ref str ct))))
     (if (< numeric #x80)
      (begin ; 7-Bit-ASCII stand alone character
       (if (not (equal? mult 1)) (begin
         (ly:warning "utf-8-string->wide-char-list: UTF-8-string out of sequence!")
         (set! mult 1) (set! sum 0)))
       (set! erg (cons numeric erg)))
      (if (< numeric #xc0)
       (begin ; 10. ..... = UTF-8 expansion byte
        (set! sum (+ sum (* mult (- numeric #x80))))
        (set! mult (* 64 mult)))
       (if (< numeric #xe0)
        (begin ; 110. .... = UTF-8 start of two byte sequence
         (if (not (equal? mult 64))
          (ly:warning "utf-8-string->wide-char-list: UTF-8-string out of sequence!")
          (begin
           (set! sum (+ sum (* mult (- numeric #xc0))))
           (set! erg (cons sum erg))))
         (set! mult 1) (set! sum 0))
        (if (< numeric #xf0)
         (begin ; 1110 .... = UTF-8 start of three byte sequence
          (if (not (equal? mult 4096))
           (ly:warning "utf-8-string->wide-char-list: UTF-8-string out of sequence!")
           (begin
            (set! sum (+ sum (* mult (- numeric #xe0))))
            (set! erg (cons sum erg))))
          (set! mult 1) (set! sum 0))
         (if (< numeric #xf8)
          (begin ; 1111 0... = UTF-8 start of four byte sequence
           (if (not (equal? mult 262144))
            (ly:warning "utf-8-string->wide-char-list: UTF-8-string out of sequence!")
            (begin
             (set! sum (+ sum (* mult (- numeric #xf0))))
             (set! erg (cons sum erg))))
           (set! mult 1) (set! sum 0))
          (begin ; This would be the header of a UTF-8 encoding of an UNICODE character
                 ; with more than 21 bits - this does not exist!
           (ly:warning "utf-8-string->wide-char-list: UTF-8-string out of sequence!")
           (set! mult 1) (set! sum 0)))))))))
   erg))

#(define unicode-diacritics ; these are the UNICODE ranges of the diacritical symbols, which
                            ; should not be insulated form their predestinating glyph.
  '(                        ; this list (ascending order) tends to be incomplete
   ( #x0300 . #x036f )
   ( #x0483 . #x0489 )
   ( #x20d0 . #x20ff )
 ))

#(define (int-in-regions num reglist)
  (if (not (pair? reglist)) #f
   (if (not (pair? (car reglist))) #f
    (if (< num (caar reglist)) #f
     (if (<= num (cdar reglist)) #t
      (int-in-regions num (cdr reglist)))))))

#(define (wide-char-diacritic? codepoint)
 ; does this UNICODE codepoint refer to a diacrity modifyer?
  (int-in-regions codepoint unicode-diacritics))


#(define (wide-char-list->utf-8-glyphlist wcl)
 ; convert a list of UNICODE codepoint integers
 ; into a list of one character UTF-8 strings,
 ; but do not separate the conbining diacritical modifyers
 ; (append them to the character strings)
  (let ((erg '()) (add-to-current #f))
   (for-each (lambda (u)
     (let ((us (if (eq? u 0) "\0" (ly:wide-char->utf-8 u))))
      (if add-to-current
       (set-car! erg (string-append us (car erg)))
       (set! erg (cons us erg)))
      (set! add-to-current (wide-char-diacritic? u))))
    (reverse wcl))
   erg))

#(define (wide-char-list->utf-8 wcl)
 ; Helper function to define utf-8 strings with a few special characters in it
  (let ((erg ""))
   (for-each (lambda (x)
     (if (string? x)
      (set! erg (string-append erg x))
      (if (integer? x)
       (if (eq? x 0)
        (set! erg (string-append erg "\0"))
        (set! erg (string-append erg (ly:wide-char->utf-8 x))))
       (if (list? x)
        (set! erg (string-append erg (wide-char-list->utf-8 x)))))))
    wcl)
   erg))



#(define (string->string-list strg)
  (wide-char-list->utf-8-glyphlist (utf-8-string->wide-char-list strg)))
Ich bin also auf die Basis von UNICODE und UTF-8 zurückgekehrt und habe 'Fundamentalfunktionen' dazu erzeugt. Die sollten ja dann auch mit Chinesischen Schriftzeichen zusammenarbeiten, nicht nur mit Umlauten, hoch- und tiefgestellten Ziffern und Smilies.
Die Demo-Texte habe ich auch leicht abgeändert:
\markup \wordwrap {
        Dies ist ein langer Text bei dem
        \with-color #'(1 0.5 0) \bold \char-space #1 { einige }
        Worte
        \with-color #'(1 0.5 0) \scale #'( 1.5 . 1.0) \char-space #1 { sehr breit }
        geschrieben sind,
        \with-color #'(0 0.5 0) \char-space #-0.2 { andere } werden jedoch
        \with-color #'(0 0.5 0) \char-space #-0.2 { enger geschrieben, }
        und einige sogar
        \with-color #'(0.7 0 0.1) \char-space #-0.375 { übermäßig " " eng. }
        Das ganze klappt auch mit Zahlen:
        \char-space #1 { 234 } -
        \char-space #-0.2 { 35 = 199 }.
}

\markup \wordwrap {
     \override #'(font-name . "Purisa") {
        Dies ist ein langer Text bei dem
        \with-color #'(1 0.5 0) \bold \char-space #1 { einige }
        Worte
        \with-color #'(1 0.5 0) \scale #'( 1.5 . 1.0) \char-space #1 { sehr breit }
        geschrieben sind,
        \with-color #'(0 0.5 0) \char-space #-0.35 { andere } werden jedoch
        \with-color #'(0 0.5 0) \char-space #-0.35 { enger geschrieben, }
        und einige sogar
        \with-color #'(0.7 0 0.1) \char-space #-0.375 { übermäßig " " eng. }
        Das ganze klappt auch mit Zahlen:
        \char-space #1 { 234 } -
        \char-space #-0.2 { 35 = 199 }.
        }
}

\markup \wordwrap {
     \override #'(font-name . "Comic Sans MS") {
        Dies ist ein langer Text bei dem
        \with-color #'(1 0.5 0) \bold \char-space #1 { einige }
        Worte
        \with-color #'(1 0.5 0) \scale #'( 1.5 . 1.0) \char-space #1 { sehr breit }
        geschrieben sind,
        \with-color #'(0 0.5 0) \char-space #-0.2 { andere } werden jedoch
        \with-color #'(0 0.5 0) \char-space #-0.2 { enger geschrieben, }
        und einige sogar
        \with-color #'(0.7 0 0.1) \char-space #-0.375 { übermäßig " " eng. }
        Das ganze klappt auch mit Zahlen:
        \char-space #1 { 234 } -
        \char-space #-0.2 { 35 = 199 }.
     }
}

Und die eigentliche Beschreibung zu letzt:

#(utf-8-string->wide-char-list str) liest einen UTF-8-String und gibt eine Liste mit Ganzzahlen zurück. Diese Ganzahlen stellen die Unicode-Zeichennummern dar.

#(wide-char-list->utf-8-glyphlist list) konvertiert diese Liste dann in eine Liste kürzest möglicher Strings, das heißt, die sogenannten Modifizierer im Unicode ‒ deren Aufgabe ist es, das Aussehen des vorangehenden Zeichens zu verändern, z. Bsp. einen Akzent hinzuzufügen, das Zeichen durchzustreichen, zu unterstrichen, zu umkreisen, einen kleinen Buchstaben darüber zu stellen; leider beherrschen nur wenige Ausgaberoutinen diese hohe Kunst ‒ werden nicht vom eigentlichen Zeichen abgetrennt.

#(wide-char-list->utf-8 list) ist eine Hilfsroutine um Zeichenketten mit einzelen UNICODE-Zeichen bequem definieren zu können, wenn man diese nicht durch ein spezielles Tastaturlayout bequem eingeben kann. Die Elemente dieser Liste sind entweder einzelne Teilstrings oder die Nummer des UNICODE-Zeichens (Ganzzahl). Das Ergebnis ist eine einzelne Zeichenkette.


Noch zu implementieren wäre, wie die Leerzeichen vor und nach den \\char-space -Blöcken gehandhabt werden sollen, ob das \translate (Verschieben, Sperren, Kerning) vor und/oder nach dem Block anzuwenden ist. Die in der Anwendung einfachste Lösung wären vielleicht vier unterschiedliche \char-space-Varianten.

Ach ja, mit Guile 2.0 wird es womöglich ganz anders aussehen!

Arnold

harm6

  • Member
Re: Spacing zwischen Buchstaben in TextMarkup
« Antwort #17 am: Montag, 18. Juni 2012, 12:08 »
Hallo Arnold,

ich kann nur sagen: wow!!
Da ich mich in dieser Materie nicht auskenne, hätte ich es nie so hinbekommen.
Vielen, vielen Dank!!!

Zitat von: Arnold
Noch zu implementieren wäre, wie die Leerzeichen vor und nach den \\char-space -Blöcken gehandhabt werden sollen, ob das \translate (Verschieben, Sperren, Kerning) vor und/oder nach dem Block anzuwenden ist. Die in der Anwendung einfachste Lösung wären vielleicht vier unterschiedliche \char-space-Varianten.

Vier unterschiedliche \char-space-Varianten ist aufwendig.
Was hälst Du von folgendem:

#(define-markup-command (char-space layout props nmbr args)(number? markup-list?)
#:properties ((word-space 0.6))
  (let* ((new-args (list-join args " "))
         (argls (proc new-args '()))
         (stils (map (lambda (x)(interpret-markup layout props x)) argls)))

 (ly:stencil-combine-at-edge 
   (ly:stencil-combine-at-edge
      (ly:make-stencil "" (cons 0 (abs (* nmbr word-space))) (cons 0 0))
         X RIGHT
         (stack-chars (car stils) (cdr stils) nmbr)
         0)
           X RIGHT
            (ly:make-stencil "" (cons 0 (abs (* nmbr word-space))) (cons 0 0))
            0)))

Und falls es nicht gefällt kann man \override #'(word-space . xy) einfügen:

\markup {
        Das ist ein
        \with-color #'(1 0.5 0)
          \fontsize #3
            \override #'(word-space . 3)
              \char-space #1 { sehr breiter }
        Textbestandteil.
}


Gruß,
  Harm

Arnold

  • Member
Re: Spacing zwischen Buchstaben in TextMarkup
« Antwort #18 am: Montag, 18. Juni 2012, 12:48 »
Hallo Harm,

ich hab's zwar noch nicht ausprobiert, aber ich glaube nicht das dies mein Problem löst.
Du hast doch sicher gesehen, daß der Links- und Rechtsseitige Leerraum um den \char-space-Text herum unterschiedlich groß ist. Dieses Verhalten sollte man auf einfach Weise steuern können.
Bei gespreiztem Text (innerhalb einens normalen Textes) möchte man meisten die beiden Wortzwischenräume vor und nach dem Textblock vergößert haben.
Bei gestauchtem Text innerhalb eines normalen Textes möchte man meinsten die Wortzwischenräume unskaliert belassen.
Oder 'wissenschaftlicher' ausgedrückt: Der Lesbarkeit kommt es zugute, wenn der Wortzwischenraum sich an dem Maximum der Wortspreizungen (Stauchung wird interpretiert als eine Spreizung mit negativem Wert) links und rechts des Wortzwischenraums orientiert.

Gruß, Arnold

Übrigens, diese Routine könnte auch eine Möglichkeit sein, die Ligaturbildung von Pango zu beeinflussen - ich hab's aber auch noch nicht ausprobiert. Seit 2.14.2 findet Lilypond auf meinem Rechner einen Font Monospace.ttf, den ich aus einem Postscriptfont über einen Webservice konvertiert habe. Wenn ich nun eine Eingabe mit dem Stil »\typewriter« anzeigen möchte, und darin die Zeichenfolge »st« vorkommt, dann kommt das »st« als Ligatur ins PDF, mit der Breite eines einzelen Schreibmaschinen-Zeichens.
Ja, ich weiß, daß Problem wäre einen anderen Thread wert. Für die 2.15.x habe ich mir schon ein \markup \replace definiert, welches an alle ASCII-Buchstaben ein U+200c-Zeichen hintenanhängt, damit keine Ligarutbildung mehr erfolgen kann. Leider halt auch wenn auf den Buchstaben ein Modifizierer folgt.

harm6

  • Member
Re: Spacing zwischen Buchstaben in TextMarkup
« Antwort #19 am: Montag, 18. Juni 2012, 15:12 »
Hallo Arnold,

in meinem letzten Versuch zu \char-space hatte ich links und rechts vom gestauchten/gespreizten Text einen unsichtbaren stencil hinzugefügt, um überhaupt Zugriff auf den Wortzwischenraum zu bekommen. Zumindest an diesen Stellen wird der Leerraum durch \char-space ja sonst gar nicht angesprochen.
Das Ergebnis ist auch besser als zuvor.

Nachdem Du auf die unterschiedlichen Wortzwischenräume um den \char-space-Text hingewiesen hast, hab' ich nochmal genau hingeschaut und dabei festgestellt, daß man dieses Phänomen auch bei einem markup ohne \char-space beobachten kann!

Wenn Du folgenden Code compilierst so siehst Du (bei hinreichender Vergrößerung), daß der Wortzwischenraum links und rechts des farbigen Abschnitts nicht gleich ist:

\markup {
        Das ist ein
        \with-color #'(1 0.5 0)
        { sehr breiter }
        Textbestandteil.
}

Da ich keine Ahnung habe warum dem so ist, habe ich auch keinen Verbesserungsvorschlag. :(

Weißt Du weiter?


Gruß,
  Harm

Arnold

  • Member
Re: Spacing zwischen Buchstaben in TextMarkup
« Antwort #20 am: Dienstag, 19. Juni 2012, 08:21 »
Entschuldige, Harm!
Wie konnte ich an Deinen Künsten zweifeln?
Ließ ich mich zu sehr leiten vom empfohlenen Wahlspruch der Programmierer, der da lautet »man muß alles bezweifeln, aber nie verzweifeln«?


Ich hab's mir am Abend angesehen, den Defaultwert etwas gefälliger gestaltet, und am morgen hatte ich noch die Idee mit weiteren Optionswerten, wenn man den linken vom rechten spacing-Wert unterscheiden muß:
#(define-markup-command (char-space layout props nmbr args)(number? markup-list?)
#:properties ((word-space 0.6) (word-space-left #f) (word-space-right #f))
  (let* ((new-args (list-join args " "))
         (argls (proc new-args '()))
         (pos-nmbr (if (> nmbr 0.0) nmbr 0.0)) ; 'nmbr' limited to be not below 0.0
         (stils (map (lambda (x)(interpret-markup layout props x)) argls)))

 (ly:stencil-combine-at-edge 
   (ly:stencil-combine-at-edge
      (ly:make-stencil "" (cons 0 (abs (* pos-nmbr 3 (if (number? word-space-left) word-space-left word-space)))) (cons 0 0))
         X RIGHT
         (stack-chars (car stils) (cdr stils) nmbr)
         0)
           X RIGHT
            (ly:make-stencil "" (cons 0 (abs (* pos-nmbr 3 (if (number? word-space-right) word-space-right word-space)))) (cons 0 0))
            0)))


Als Demonstrationsbeispiel habe ich noch folgendes benutzt:
\markup \wordwrap {
    Der Zwischenraum
    \override #'(word-space-left . 2.5) \char-space #0.5 { links }
    und
    \override #'(word-space-right . 2.5) \char-space #0.5 { rechts }
    des gesperrten Textes kann individuell skaliert werden,
    aber natürlich auch
    \override #'(word-space . 2.5) \char-space #0.5 { beide }
    Seiten gemeinsam.
    Dies kann vor allem dann nötig werden, wenn
    \override #'(word-space-right . 0.0) \char-space #0.35 { unterschiedlich }
    \char-space #0.85 { gesperrte }
    Texte direkt aufeinander folgen.
}

Mittlerweile denke ich, die Routine ist fast LSR-reif. Ich müßte nochmal auf der UNICODE-Seite nachsehen und die »combining diacritical marks« neu auflisten.

Arnold

kilgore

  • Member
Re: Spacing zwischen Buchstaben in TextMarkup
« Antwort #21 am: Dienstag, 19. Juni 2012, 12:38 »
Ihr seid beide unglaublich! Auch wenn ich nur die hälfte verstehe, lese ich trotzdem gern durch euren Code :)

freut mich sehr, dieses thema angesprochen zu haben!

dankbare grüße,
kil

harm6

  • Member
Re: Spacing zwischen Buchstaben in TextMarkup
« Antwort #22 am: Dienstag, 19. Juni 2012, 14:32 »
Hallo Arnold,

Zitat von: Arnold
Entschuldige, Harm!
Wie konnte ich an Deinen Künsten zweifeln?
Ließ ich mich zu sehr leiten vom empfohlenen Wahlspruch der Programmierer, der da lautet »man muß alles bezweifeln, aber nie verzweifeln«?
lol
Aber mal im Ernst. Ich bin was scheme/guile angeht ein absoluter Autodidakt. Nach allem was ich von Dir in Wort und Code gelesen habe bist Du da deutlich fundierter gebildet. Insoweit schätze ich mich glücklich, wenn jemand mit Deinen Qualitäten meinen Code begutachtet!!

ad \char-space
Deine Erweiterungen finde ich klasse.
Als alter Paranoiker habe ich noch ein paar Sonderfälle zugänglich gemacht, sodaß Argumente wie {}, { "" }, {"A"} etc nicht zu einem Crash führen.

#(define-markup-command (char-space layout props nmbr args)(number? markup-list?)
#:properties ((word-space 0.6) (word-space-left #f) (word-space-right #f))
  (let* ((args-rev (remove (lambda (x) (string=? "" x)) args))
         (new-args (list-join args-rev " "))
         (argls (proc new-args '()))
         (pos-nmbr (max nmbr 0.0)) ; 'nmbr' limited to be not below 0.0
         (stils (map (lambda (x)(interpret-markup layout props x)) argls))
         (first-stil (if (eq? argls '()) point-stencil (car stils))))

 (ly:stencil-combine-at-edge 
   (ly:stencil-combine-at-edge
      (ly:make-stencil "" (cons 0 (abs (* pos-nmbr 3 (if (number? word-space-left) word-space-left word-space)))) (cons 0 0))
         X RIGHT
         (if (<= (length argls) 1)
           first-stil
           (stack-chars first-stil (cdr stils) nmbr))
         0)
           X RIGHT
            (ly:make-stencil "" (cons 0 (abs (* pos-nmbr 3 (if (number? word-space-right) word-space-right word-space)))) (cons 0 0))
            0)))

\markup \column {
        "Tests for paranoiacs"
        \char-space #0.5 {  }
        xy
        \char-space #0.5 { "" }
        xy
        \override #'(word-space-left . 0)
        \char-space #0.5 { a "" a }
        xy
        \char-space #0.5 { "" "" }
        \override #'(word-space-left . 0)
        \char-space #0.5 { "" a "" }
        xy
        \override #'(word-space-left . 0)
        \char-space #0.5 { a }
        xy
        \override #'(word-space-left . 0)
        \char-space #0.8 { "់" }
        xy
        \override #'(word-space-left . 0)
        \char-space #0.8 { "asdäöüព្រះជាម្ចាស់" }
        \vspace #3
}

Wer mehr wissen möchte wie die string-Manipulationen funktionieren kann folgenden Code benutzen, der fast alles im Terminal anzeigt.

% testing functions
 
#(define strg "asdäöüព្រះជាម្ចាស់")
     
#(let* ((l1 (utf-8-string->wide-char-list strg))
        (l2 (wide-char-list->utf-8-glyphlist l1))
        (new-strg (wide-char-list->utf-8 l1))
        (strg? (string? new-strg)))
  (newline)
  (newline)(display "\"The string\"__")(display strg)
  (newline)(display "\"List of integers, \n  representing the UNICODE character codes\"__")(display l1)
  (newline)(display "\"List of one character UTF-8 strings\"__")(display l2)
  (newline)(display "\"Back to string\"__")(display new-strg)
  (newline)(display "\"string?\"__")(display strg?))
 
#(let* ((strg-lst (string->string-list strg))
        (new-strg (string-list->string strg-lst))
        (strg? (string? new-strg)))
     (newline)
     (newline)(display "\"The string\"__")(display strg)
     (newline)(display "\"The string-list\"__")(display strg-lst)
     (newline)(display "\"Back to string\"__")(display new-strg)
     (newline)(display "\"string?\"__")(display strg?)
     (newline))

ad LSR

Zitat von: Arnold
Mittlerweile denke ich, die Routine ist fast LSR-reif. Ich müßte nochmal auf der UNICODE-Seite nachsehen und die »combining diacritical marks« neu auflisten.

Den Code zur utf-8-string-Manipulation halte ich für viel zu wertvoll um ihn "nur" ins LSR zu packen.
Falls Du wirklich davon überzeugt bist, daß er generell funktioniert, sollte er direkt in LilyPond integriert werden. Ich habe von UNICODE/utf-8-Codierungen allerdings keine Ahnung, insofern vertraue ich Deiner Expertise.
Falls ich Dein ok kriege, könnte ich, als ersten Schritt zu Voll-Implementierung, den Code auf der devel-list posten.
Was meinst Du?
Und hilft es bei Deinem st-Ligatur-Problem?

BTW, ich habe noch eine Definition von `string-list->string' hinzugefügt. Wird hier nicht gebraucht und ist eigentlich ja auch nur eine Umbenennung von `wide-char-list->utf-8' aber der Name ist vielleicht etwas eingängiger.

@kilgore
Zitat
Ihr seid beide unglaublich! Auch wenn ich nur die hälfte verstehe, lese ich trotzdem gern durch euren Code :)

freut mich sehr, dieses thema angesprochen zu haben!

Ich habe ein eigenes Interesse an der Materie und wenn ich Arnold richtig verstanden habe, so geht es ihm genauso.
Wenn alles klappt wie erhofft, gewinnen wir alle. Was kann es besseres geben?!


Gruß,
  Harm

P.S. Im Anhang nochmal das komplette file. Ich habe zur Demonstration auch ein paar kambodschanische Zeichen verwendet:ព្រះជាម្ចាស់. Ich hoff sie werden auf jedem Rechner auch akkurat angezeigt. Lily hat keine Probleme damit. :)

Arnold

  • Member
Re: Spacing zwischen Buchstaben in TextMarkup
« Antwort #23 am: Dienstag, 19. Juni 2012, 16:48 »
Hallo Harm.

Kein (Rechte-)Problem. Poste nur meinen Translator an die Development Site (wenn die combining diacritical marks aktualisiert sind). Um UNICODE habe ich schon lange etwas gekümmert, und auch die Übersetzungen zwischen UTF-8 und UTF-16 hin und zurück habe ich schon vor langer Zeit in einer C-Anwendung programmiert. Es war also nur ein Zurückrufen und Übertragen von bereits vorhandenen Impelentierungen. Nur die Tabelle der »combining diacritical marks« möchte ich noch überarbeiten, bevor Du die Routinen weitergibst.

Mit dem Fontproblem ist's wohl noch nicht so weit - und mit meinem Workaround komme ich derzeit ganz gut zurecht.

Wenn Du was für mich tun wilst, dann schau mal, wie man das »neue Segno« (\bar "S" und Co.) zur Kooperation mit \repeat volta bringt. Die Lösung könnte ein 'apply context' für »Segno bitte hier« sein, welches dann im gleichen Engraver ausgewertet wird, welcher letztlich die Wiederholungszeichen für \repeat & \alternative setzt. Der hat erst kürzlich zwei weitere Variablen bekommen, (jetzt drei gesamt) mit denen der Anwender seine Wiederholungszeichenwünsche angeben kann - mit dieser angedachten Erweiterung wären's halt dann sieben (für die mit-Segno-Zeichen-Varianten und das Segno-Zeichen ohne Wiederholungszeichen zusätzlich).

Auch ich bin bei Scheme ein Autodidakt. Aber ich habe schon recht viel programmiert, zum größten Teil in C (nicht C++), aber auch in enigen applikationsspezifischen Programmiersprachen oder mit anwendungsspezifischen APIs in C.

Die nächsten Wochen wird's wohl etwas weniger werden mit meiner Teilahme an diesem Forum. Ich muß mich mal etwas mehr um »Stradella« und »Steirische« kümmern - auch da bin ich schon auf sehr hilfreiche Funktionsvorlagen von Dir gestoßen. Und dann muß ich auch noch ein paar Hornstimmen abschreiben (und transponieren).

Vielleicht schreibe ich noch für die Lilypond-News mal einen Beitrag über ein »undocumented Feature«. Ich benutze seit Version 2.10.33 Ziffern in meinen Lilypond-Variablennamen (aber nur, weil ich nicht die ASCII-Ziffern verwende - U+207x und U#208x lassen grüßen)


Also, auf weiterhin gute, sich wunderbar ergänzende Zusammenarbeit,
und der Paranoiker paßt ja gut zum oben genannten Wahlspruch der Programmierer.

Arnold
« Letzte Änderung: Dienstag, 19. Juni 2012, 16:49 von Arnold »

Arnold

  • Member
Re: Spacing zwischen Buchstaben in TextMarkup
« Antwort #24 am: Mittwoch, 20. Juni 2012, 09:34 »
Und hier nun die erweiterte Liste »unicode-diacritics«, wie ich sie aus den Dokumenten von www.unicode.org herausgelesen habe.
Sie ist ganz schön lang geworden:
#(define unicode-diacritics ; These are the UNICODE ranges of the diacritical symbols, which
                            ; should not be insulated form their predestinating glyph.
                            ; Look at the code charts at www.unicode.org for more information.
                            ; As long as this table is entered manually there is a high risk of errors.
 '(                         ; This list (ascending order) tends to be incomplete
   ; Combining Diacritical Marks
   ( #x0300 . #x036f )
   ; Cyrillic
   ( #x0483 . #x0489 )
   ; Hebrew
   ( #x0591 . #x05bd )
   ( #x05bf . #x05bf )
   ( #x05c1 . #x05c2 )
   ( #x05c4 . #x05c5 )
   ( #x05c7 . #x05c7 )
   ; Arabic
   ( #x0610 . #x061a )
   ( #x064b . #x065f )
   ( #x0670 . #x0670 )
   ( #x06d6 . #x06dc )
   ( #x06df . #x06e4 )
   ( #x06ea . #x06ed )
   ; Syriac
   ( #x0711 . #x0711 )
   ( #x0730 . #x074a )
   ; Thaana
   ( #x07a6 . #x07b0 )
   ; NKo
   ( #x07eb . #x07f3 )
   ; Samaritan
   ( #x0816 . #x0823 )
   ( #x0825 . #x0827 )
   ( #x0829 . #x082d )
   ; Mandaic
   ( #x0859 . #x085b )
   ; Arabic Extended-A
   ( #x08e4 . #x08fe )
   ; Devanagari
   ( #x0900 . #x0903 )
   ( #x093a . #x093c )
   ( #x0934 . #x094f )
   ( #x0951 . #x0957 )
   ( #x0962 . #x0963 )
   ; Bengali
   ( #x0981 . #x0983 )
   ( #x09bc . #x09bc )
   ( #x09be . #x09cd )
   ( #x09d7 . #x09d7 )
   ( #x09e2 . #x09e3 )
   ; Gurmukhi
   ( #x0a01 . #x0a03 )
   ( #x0a3c . #x0a3c )
   ( #x0a3e . #x0a42 )
   ( #x0a47 . #x0a48 )
   ( #x0a4b . #x0a4d )
   ( #x0a51 . #x0a51 )
   ( #x0a70 . #x0a71 )
   ( #x0a75 . #x0a75 )
   ; Gujarati
   ( #x0a81 . #x0a83 )
   ( #x0abc . #x0abc )
   ( #x0abe . #x0acd )
   ( #x0ae2 . #x0ae4 )
   ; Oriya
   ( #x0b01 . #x0b03 )
   ( #x0b3c . #x0b3c )
   ( #x0b3e . #x0b56 )
   ( #x0b62 . #x0b64 )
   ; Tamil
   ( #x0b82 . #x0b82 )
   ( #x0bb4 . #x0bcd )
   ( #x0bd7 . #x0bd7 )
   ; Telugu
   ( #x0c01 . #x0c03 )
   ( #x0c3e . #x0c56 )
   ( #x0c62 . #x0c63 )
   ; Kannada
   ( #x0c82 . #x0c83 )
   ( #x0cbc . #x0cd6 )
   ( #x0ce2 . #x0ce3 )
   ; Malayalam
   ( #x0d02 . #x0d03 )
   ( #x0d3e . #x0d4d )
   ( #x0d57 . #x0d57 )
   ( #x0d62 . #x0d63 )
   ; Sinhala
   ( #x0d82 . #x0d83 )
   ( #x0dca . #x0df3 )
   ; Thai
   ( #x0e31 . #x0e31 )
   ( #x0e34 . #x0e3a )
   ( #x0e47 . #x0e4e )
   ; Lao
   ( #x0eb1 . #x0eb1 )
   ( #x0eb4 . #x0ebc )
   ( #x0ec8 . #x0ecd )
   ; Tibetan
   ( #x0f18 . #x0f19 )
   ( #x0f35 . #x0f35 )
   ( #x0f37 . #x0f37 )
   ( #x0f39 . #x0f39 )
   ( #x0f3e . #x0fef )
   ( #x0f71 . #x0f84 )
   ( #x0f86 . #x0f87 )
   ( #x0f8d . #x0fbc )
   ; Myanmar
   ( #x102b . #x1039 )
   ( #x103a . #x103e )
   ( #x1056 . #x1059 )
   ( #x105e . #x1060 )
   ( #x1062 . #x1064 )
   ( #x1067 . #x106d )
   ( #x1071 . #x1074 )
   ( #x1082 . #x108d )
   ( #x108f . #x108f )
   ( #x109a . #x109d )
   ; Tagalog
   ( #x1712 . #x1714 )
   ; Hanunoo
   ( #x1732 . #x1734 )
   ; Buhid
   ( #x1752 . #x1753 )
   ; Tagbanwa
   ( #x1772 . #x1773 )
   ; Khmer
   ( #x17b6 . #x17d1 )
   ( #x17d3 . #x17d3 )
   ( #x17dd . #x17dd )
   ; Limbu
   ( #x1920 . #x193b )
   ; New Tai Lue
   ( #x19b0 . #x19c0 )
   ( #x19c8 . #x19c9 )
   ; Buginese
   ( #x1a17 . #x1a1b )
   ; Tai Tahm
   ( #x1a55 . #x1a7f )
   ; Balinese
   ( #x1b00 . #x1b04 )
   ( #x1b34 . #x1b44 )
   ( #x1b6b . #x1b73 )
   ; Sundanese
   ( #x1b80 . #x1b82 )
   ( #x1ba1 . #x1baa )
   ( #x1bac . #x1bad )
   ; Batak
   ( #x1be6 . #x1bf3 )
   ; Lepcha
   ( #x1c24 . #x1c37 )
   ; Vedic Extensions
   ( #x1cd0 . #x1ce8 )
   ( #x1ced . #x1ced )
   ( #x1cf2 . #x1cf4 )
   ; Combining Diacritical Marks Supplement
   ( #x1dc0 . #x1dff )
   ; Combining Diacritical Marks for Symbols
   ( #x20d0 . #x20ff )
   ; Coptic
   ( #x2cef . #x2cf1 )
   ; Cyrillic Extended-A
   ( #x2d40 . #x2dff )
   ; Hiragana
   ( #x3099 . #x309a )
   ; Cyrillic Extended-B
   ( #xa66f . #xa67d )
   ( #xa69f . #xa69f )
   ; Syloti Nagri
   ( #xa802 . #xa802 )
   ( #xa806 . #xa806 )
   ( #xa80b . #xa80b )
   ( #xa823 . #xa827 )
   ; Saurashtra
   ( #xa880 . #xa881 )
   ( #xa8b4 . #xa8c4 )
   ; Devanagari Extended
   ( #xa8e0 . #xa8f1 )
   ; Kayah Li
   ( #xa926 . #xa92d )
   ; Rejang
   ( #xa947 . #xa953 )
   ; Javanese
   ( #xa980 . #xa983 )
   ( #xa9b3 . #xa9c0 )
   ; Cham
   ( #xaa29 . #xaa36 )
   ( #xaa43 . #xaa43 )
   ( #xaa4c . #xaa4d )
   ; Myanmar Extended-A
   ( #xaa7b . #xaa7b )
   ; Tai Viet
   ( #xaab0 . #xaab0 )
   ( #xaab2 . #xaab4 )
   ( #xaabe . #xaabf )
   ( #xaac1 . #xaac1 )
   ; Meetei Mayek Extensions
   ( #xaaeb . #xaaef )
   ( #xaaf5 . #xaaf5 )
   ; Meetei Mayek
   ( #xabe3 . #xabed )
   ; Alphabetic Presentation Forms
   ( #xfb1e . #xfb1e )
   ; Combining Half Marks
   ( #xfe20 . #xfe26 )
   ; Kharoshthi
   ( #x10a01 . #x10a0f )
   ( #x10a38 . #x10a3a )
   ; Brahmi
   ( #x11000 . #x11002 )
   ( #x11038 . #x11046 )
   ; Kaithi
   ( #x11080 . #x11082 )
   ( #x110b0 . #x110ba )
   ; Chakma
   ( #x11100 . #x11102 )
   ( #x11127 . #x11132 )
   ( #x11134 . #x11134 )
   ; Sharada
   ( #x11180 . #x11182 )
   ( #x111b3 . #x111c0 )
   ; Takri
   ( #x116ab . #x116b7 )
   ; Miao
   ( #x16f51 . #x16f7e )
   ; Musical Symbols
   ( #x1d165 . #x1d168 )
   ( #x1d16d . #x1d172 )
   ( #x1d17b . #x1d182 )
   ( #x1d185 . #x1d18b )
   ( #x1d1aa . #x1d1ad )
   ; Ancient Greek Musical Notation
   ( #x1d242 . #x1d244 )
   ;;; I hope, I did not make any mistake while typing this table
 ))

Also, bis demnächst (bei einem anderen Thema)
Arnold
« Letzte Änderung: Mittwoch, 20. Juni 2012, 09:46 von Arnold »

harm6

  • Member
Re: Spacing zwischen Buchstaben in TextMarkup
« Antwort #25 am: Sonntag, 24. Juni 2012, 10:16 »
Hallo Arnold,

nochmals Vielen Dank für Deine Arbeit!!

Im Hinblick auf eine mögliche Implementierung in den source-code hatte ich noch zwei Gedanken.
Leider habe ich beide nicht umsetzen können:

(1)
Seitens der Entwickler wird häufig die Nase gerümpft, wenn man `do' benutzt. Stattdessen wird Rekursion als mehr "scheme-isch" empfohlen.
Also habe ich es versucht, allerdings funktioniert meine Änderung nicht mit Umlauten/Sonderzeichen. Da bekomme ich die Warnung.
Es kann aber auch nicht völlig falsch sein, denn mit einfachen Buchstaben klappt es.

Was mache ich falsch?

#(define (utf-8-string->wide-char-list str)

   (define (helper counter erg str)
      "Convert a UTF-8 byte string into an list with integer representing the UNICODE character codes"
      (let
       ((mult 1)
        (sum 0))
     
        (let ((numeric (char->integer (string-ref str counter))))
         (if (< numeric #x80)   ;; #x80 -> 128
          (begin ; 7-Bit-ASCII stand alone character
           (if (not (equal? mult 1))
            (begin
             (ly:warning "utf-8-string->wide-char-list: UTF-8-string out of sequence!")
             (set! mult 1) (set! sum 0)))
           (set! erg (cons numeric erg)))
          (if (< numeric #xc0)   ;; #xc0 -> 192
           (begin ; 10. ..... = UTF-8 expansion byte
            (set! sum (+ sum (* mult (- numeric #x80))))
            (set! mult (* 64 mult)))
           (if (< numeric #xe0)
            (begin ; 110. .... = UTF-8 start of two byte sequence
             (if (not (equal? mult 64))
              (ly:warning "utf-8-string->wide-char-list: UTF-8-string out of sequence!")
              (begin
               (set! sum (+ sum (* mult (- numeric #xc0))))
               (set! erg (cons sum erg))))
             (set! mult 1) (set! sum 0))
            (if (< numeric #xf0)
             (begin ; 1110 .... = UTF-8 start of three byte sequence
              (if (not (equal? mult 4096))
               (ly:warning "utf-8-string->wide-char-list: UTF-8-string out of sequence!")
               (begin
                (set! sum (+ sum (* mult (- numeric #xe0))))
                (set! erg (cons sum erg))))
              (set! mult 1) (set! sum 0))
             (if (< numeric #xf8)
              (begin ; 1111 0... = UTF-8 start of four byte sequence
               (if (not (equal? mult 262144))
                (ly:warning "utf-8-string->wide-char-list: UTF-8-string out of sequence!")
                (begin
                 (set! sum (+ sum (* mult (- numeric #xf0))))
                 (set! erg (cons sum erg))))
               (set! mult 1) (set! sum 0))
              (begin ; This would be the header of a UTF-8 encoding of an UNICODE character
                     ; with more than 21 bits - this does not exist!
               (ly:warning "utf-8-string->wide-char-list: UTF-8-string out of sequence!")
               (set! mult 1) (set! sum 0))))))))
     (if (= counter 0)
       erg
       (helper (- counter 1) erg str))))

   (helper (- (string-length str) 1) '() str))

Komplettes file im Anhang.

(2)
Es sollte möglich sein `smallCaps' aus /scm/define-markup-commands.scm neu zu definieren, so daß es mit allen Buchstaben/Sonderzeichen funktioniert.
Im Moment gibt es noch die Einschränkung: "Note: @code{\\smallCaps} does not support accented characters."

Um hier erfolgreich zu sein müßte eine Abfrage entwickelt werden, ob der erste Buchstabe groß geschrieben ist oder nicht.
Wie könnte man das machen?

BTW, es gibt ja den Befehl `string-capitalize'.
Das ist natürlich ein Befehl und keine Frage, aber er klappt auch nicht immer:
(string-capitalize "asdfg") -> "Asdfg" 
wie gewünscht. Aber:
(string-capitalize "äsdfg") -> "äSdfg"


Zitat von: Arnold
Vielleicht schreibe ich noch für die Lilypond-News mal einen Beitrag über ein »undocumented Feature«. Ich benutze seit Version 2.10.33 Ziffern in meinen Lilypond-Variablennamen (aber nur, weil ich nicht die ASCII-Ziffern verwende - U+207x und U#208x lassen grüßen)
Mach das!
Ich habe selber schon mal in diese Richtung gepostet:
http://lists.gnu.org/archive/html/bug-lilypond/2011-12/msg00832.html
Allerdings ohne Reaktion.


Gruß,
  Harm

Arnold

  • Member
Re: Spacing zwischen Buchstaben in TextMarkup
« Antwort #26 am: Montag, 25. Juni 2012, 10:49 »
Hallo Harm,

beim utf-8-string->wide-char-list bist Du vielleicht etwas übers Ziel hinausgeschossen.
Die Byte-String-Liste wird von hinten bearbeitet, weil
1. einfach verkettete Listen am bequemsten von hinten nach vorne erstellt werden
2. und UTF-8 auch in Rückwärtsrichtung eindeutig ist
So würde ich die do-Schleife
   (do ((ct (- len 1) (1- ct))) ((< ct 0)) ; process backward
    (let ((numeric (char->integer (string-ref str ct))))
durch eine for-each-Schleife
(for-each (lambda (single-byte-char)
  (let ((numeric (char->integer single-byte-char)))
  ...
  ))
  (reverse (string->list str)))
ersetzen.

Wirklich Scheme-like ist der selbst-rekursive Aufruf am Ende - es wartet der erste Aufruf nicht, bis sein Unteraufruf abgeschlossen wird, nur um dessen Ergebniswert zurückzugeben, stattdessen wird die Ablaufsteuerung direkt an seinen rekursiven Aufruf übergeben. Wird aber das Ergebnis eines rekursiven Aufrufs noch weiterverarbeitet, dann wird eine neue Instanz der Routine gestartet.

Das andere Problem liegt darin, daß das aktuell verwendete Guile 1.8 die Zeichenketten als Byte-Zeichenketten bearbeitet und UTF-8 so allenfalls ohne Änderung druchschleust.
Ist Dir etwas bekannt, wann Lilypond auf Guile 2.0 ungestellt werden soll?
Solange Guile 1.8 verwendet wird, muß sich der Programmierer selbst um die Bearbeitung des UNICODE kümmern - aber ob mit Guile 2.0 alle UNICODE-Zeichenklassifizierungen vorhanden sein werden, ist auch nicht so sicher.  Da sich UNICODE auch immer weiterentwickelt, sollte man sowieso sich eine Erweiterungsmöglichkeit vorbereiten.
Im Endeffekt wären also für die UNICOE-Klassifizierungs-Routinen eingene Äquivalente zu schreiben, und diese dann auch in den Bearbeitungsfunktionen zu verwenden (also auch hier Äquivalente auch zu den Scheme-Funktionen).
Ich werde mir also demnächst die Groß-Kleinbuchstaben-Klassifzierung und -Querzuordnung für den LGC-Bereich (Latin - Greek - Cyrillic) im UNICODE ansehen. Ich denke, daß ich da was hinbekommen, und es könnten auch wertvolle Daten-Quellen auf der UNICODE-Internet-Seite zur verfügung stehen.

harm6

  • Member
Re: Spacing zwischen Buchstaben in TextMarkup
« Antwort #27 am: Montag, 25. Juni 2012, 16:24 »
Hallo Arnold,

Zitat
beim utf-8-string->wide-char-list bist Du vielleicht etwas übers Ziel hinausgeschossen.
(...)
So würde ich die do-Schleife
(...)
durch eine for-each-Schleife
(...)
ersetzen.

vielen Dank für den Hinweis, jetzt klappts tadellos.


Zitat
Ist Dir etwas bekannt, wann Lilypond auf Guile 2.0 ungestellt werden soll?

Leider nicht. Was diesem Thema am nächsten kommt sind einige Beiträge in diesem Thread.

Gruß,
  Harm

RobUr

  • Member
Re: Spacing zwischen Buchstaben in TextMarkup
« Antwort #28 am: Freitag, 9. Oktober 2015, 15:58 »
Hallo zusammen,

bin immer wieder begeistert, wie ihr mit Scheme hantiert und Lily derartig erweitert!

Ein kleines Problem habe ich mit dem Snippet von Harm aus Antwort #22: es verarbeitet keine Sonderzeichen, in meinem Fall die AE-Ligatur. Mein Code:
\version "2.18.2"

%%%%%%%%%%%%%%%%%%
%% SPATIONIEREN %%

#(define (string->string-list strg)
   (define (helper-1 strg ls)
    "
    Converts a string into a list of strings,
    every string of the list has string-length 1
    e.g "1234" -> '("1" "2" "3" "4")
    "
      (if (= (string-length strg) 0)
        (begin
          (set! ls '(""))
          ls)
        (begin
          (set! ls (cons (substring strg 0 1) ls))
          (if (>= (string-length (string-drop strg 1)) 1)
            (helper-1 (string-drop strg 1) ls)
            (reverse ls)))))

  (if (string? strg)
    (helper-1 strg '())
    strg))
 
#(define (proc l1 l2)
    "
    l1 is supposed to be a list of strings.
    proc will return a new list l2, build of the
    elements of l1.
    Every string of l2 has string-length 1
    e.g '("12" "34") -> '("1" "2" "3" "4")
    "
  (if (null? l1)
     l2
     (begin
       (set! l2 (append l2 (string->string-list (car l1))))
       (proc (cdr l1) l2))))
 
#(define (stack-chars stencil stils kern)
   (set! stencil (ly:stencil-combine-at-edge stencil X RIGHT (car stils) kern))
   (if (null? (cdr stils))
     stencil
     (stack-chars stencil (cdr stils) kern)))

#(define-markup-command (char-space layout props nmbr args)(number? markup-list?)
#:properties ((word-space 0.6) (word-space-left #f) (word-space-right #f))
  (let* ((args-rev (remove (lambda (x) (string=? "" x)) args))
         (new-args (list-join args-rev " "))
         (argls (proc new-args '()))
         (pos-nmbr (max nmbr 0.0)) ; 'nmbr' limited to be not below 0.0
         (stils (map (lambda (x)(interpret-markup layout props x)) argls))
         (first-stil (if (eq? argls '()) point-stencil (car stils))))

 (ly:stencil-combine-at-edge 
   (ly:stencil-combine-at-edge
      (ly:make-stencil "" (cons 0 (abs (* pos-nmbr 3 (if (number? word-space-left) word-space-left word-space)))) (cons 0 0))
         X RIGHT
         (if (<= (length argls) 1)
           first-stil
           (stack-chars first-stil (cdr stils) nmbr))
         0)
           X RIGHT
            (ly:make-stencil "" (cons 0 (abs (* pos-nmbr 3 (if (number? word-space-right) word-space-right word-space)))) (cons 0 0))
            0)))

%%%%%%%%%%%%%%%%%%

\header {
poet = \markup \concat {
\char-space #0.288 { "CANTIONES SACR" } "Æ"
}

composer = \markup {
\char-space #0.288 { "CANTIONES SACRÆ" }
}
}

\markup { "Sonderzeichen, z.B. Æ, funktionieren nicht innerhalb \char-space :-(" }

Im Terminal werden folgende Fehlermeldungen/Warnungen ausgegeben:
(process:7043): Pango-WARNING **: Invalid UTF-8 string passed to pango_layout_set_text()

Warnung: Kein Glyph f"ur Zeichen U+EFFFFFFF in Schriftart >>/Users/<myUserName>/Library/Fonts/CenturySchL-Roma.otf<<

(process:7043): Pango-WARNING **: Invalid UTF-8 string passed to pango_layout_set_text()
Warnung: Kein Glyph f"ur Zeichen U+EFFFFFFF in Schriftart >>/Users/<myUserName>/Library/Fonts/CenturySchL-Roma.otf<<

Umgebung: LP 2.18.2 unter Mac OS X 10.4.11

Wie muss das Snippet angepasst werden, damit es funktioniert?

Herzlichen Dank und beste Grüße –
Robert

harm6

  • Member
Re: Spacing zwischen Buchstaben in TextMarkup
« Antwort #29 am: Freitag, 9. Oktober 2015, 19:22 »
Hallo Robert,

der ganze Sinn dieses Threads ist es ja, das auch die Sonderzeichen bei verändertem kerning wie gewünscht funktionieren.
Allerdings habe ich gesehen, daß ich den letzten Stand damals nicht explicit gepostet hatte (das wäre char-space-04.ly gewesen).

Im Anhang jetzt charspace-05.ly. Eigentlich ist aber nur die Version auf 2.18.2 geändert und ich habe im Beispiel mit Deinem Code rumgespielt. Ergebnis als png auch im Anhang.

Falls Du nicht das gleiche bekommst, ist es wahrscheinlich dem unterschiedlichen Betriebssystem geschuldet (Linux hier). Du könntest dann die Test-Funktionen einkommentieren und schauen, wo es Differenzen zu meinem output gibt:

Zitat
"The string"__asdäöüøéàÆ
"List of integers,
  representing the UNICODE character codes"__(97 115 100 228 246 252 248 233 224 198)
"List of one character UTF-8 strings"__(a s d ä ö ü ø é à Æ)
"Back to string"__asdäöüøéàÆ
"string?"__#t

"The string"__asdäöüøéàÆ
"The string-list"__(a s d ä ö ü ø é à Æ)
"Back to string"__asdäöüøéàÆ
"string?"__#t



Gruß,
  Harm