Deutsches Lilypond Forum (Archiv)
Allgemein => Fragen zu Funktionen => Thema gestartet von: kilgore am Dienstag, 12. Juni 2012, 13:08
-
Hallo Lilys!
Ich such eine Möglichkeit den Platz zwischen den Buchstaben in ein TextMarkup zu vermindern. baseline-skip wird für den Platz zwischen Zeilen benutzt...gibts da was ähnliches für den Platz zwischen den einzelnen Buchstaben, oder ist das eine Sache der Schriftart selber?
Vielen Dank!
kil
-
Also,
eine »Sperren mit negativem Versatzwert zwischen den Buchstaben bzw. »Kerning mit festem Wert unabhängig von der Zeichenpaarung« habe ich nicht im Lilypond-Handbuch gefunden.
Zudem kommt diese Methode den Text zu komprimieren sehr schnell an die Grenzen der Lesbarkeit, die Buchstaben überlappen sich doch recht schnell.
Deshalb wird ein anisotrpisches Skalieren bevorzugt. Also \scale mit einem X-Faktor <= 1.0 und eine Y-Faktor = 1.0.
Bis zu \scale #'(0.6 1.0) sollte die Lesbarkeit nciht beeinträchtigt sein.
Arnold
-
Hallo Arnold,
Danke für deine Hilfe! Das komprimierte Text finde ich ein gute Idee, für diesen Zweck nicht aber geeignet, aber es freut mich trotzdem diese Funktion kennenzulernen. Ich denke ich finde ein Weg zurecht mit dem Text.....
Gruß
kil
-
... gewissermaßen alle Buchstaben als einzel-Markup, und ein \translate dazwischen?
Hab dazu leider keine scheme-Prozedur parat.
Arnold
-
Hallo kilgore,
... gewissermaßen alle Buchstaben als einzel-Markup, und ein \translate dazwischen?
manchmal geht: alle Buchstaben als einzel-Markup und \override #'(word-space . -0.5)
\markup
\override #'(word-space . -0.3) {
\wordwrap {
"a" "b" "c"
}
}
oder vielleicht (Bild im Anhang):
\version "2.14.2"
#(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?)
(let* ((new-args (list-join args " "))
(args+ (reverse (cons " " (reverse new-args))))
(argls (proc args+ '()))
(stils (map (lambda (x)(interpret-markup layout props x)) argls))
(new-stils (reverse (cdr (reverse stils)))))
(stack-chars empty-stencil new-stils nmbr)))
\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) \fontsize #3 \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. }
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) \fontsize #3 \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. }
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) \fontsize #3 \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. }
Das ganze klappt auch mit Zahlen:
\char-space #1 { 234 } -
\char-space #-0.2 { 35 = 199 }.
}
}
Gruß,
Harm
-
Hallo Harm,
Wow klasse! Das funktioniert richtig super, genau das was ich suchte.
Nur ein kleines Problem - Sonderbuchstaben sind nicht unterstützt ( ö é ä etc ). Folgende Fehlermeldung kommt dazu:
(process:3156): Pango-WARNING **: Invalid UTF-8 string passed to pango_layout_set_text()
Programmierfehler: FT_Get_Glyph_Name() Fehler: invalid glyph index
Fortsetzung, die Daumen drücken
Programmierfehler: Glyph hat keinen Namen, aber Zeichensatz unterstützt Glyphnamen.
Glyph U+FFFFFFFF wird übersprungen, Datei /home/kilgore/.fonts/ufonts.com_lucida-sans-typewriter-regular-2.ttf
Fortsetzung, die Daumen drücken
Programmierfehler: invalid UTF-8 string
Fortsetzung, die Daumen drücken
Die Sonderzeichen funktionieren aber normalerweise schon...
Danke euch beide!
Gruß
kil
-
Das Sonderzeichenproblem kommt wohl daher, daß scheme noch den UTF8-String als »Byte-Character-String« bearbeitet. Somit darf man die »Zeichenfolge«, die eigentlich ein einziges Unicode-Zeichen beschreibt, nicht auseinanderbröseln.
etwas genauer:
höchstwertiges Bit = 0 , dann ein einzelnes Byte
die ersten zwei höchstwertigen Bit = 11, dann alle Folgebytes hinzunehmen, bei denen die zwei höststwertigen Bit = 10 sind.
Siehe auch die Beispiele im Wikipedia: http://de.wikipedia.org/wiki/UTF8
Arnold
-
Hallo Arnold,
Danke für die Infos und Link! Ich verstehe die Sache nicht gut genug um es wirklich zu kapieren... Gibts eine Chance die Sonderzeichen auch einzubauen? Also muss ich in scheme irgendwie eingeben, dass es den String anders bearbeiten soll?
Gruß
kil
-
Das Sonderzeichenproblem kommt wohl daher, daß scheme noch den UTF8-String als »Byte-Character-String« bearbeitet. Somit darf man die »Zeichenfolge«, die eigentlich ein einziges Unicode-Zeichen beschreibt, nicht auseinanderbröseln.
Mein string->string-list stammt ursprünglich aus einem file in dem diese Anwendung unproblematisch ist.
Zur Illustration des Problems:
Im guile-interpreter:
guile> (substring "ä" 0 1)
-> "�"
Um dem eigentlichen Problem bei zu kommen habe ich ein weiteres markup-command geschrieben, welches bei Sonderzeichen und Umlauten eingesetzt werden kann. Allerdings müssen die Buchstaben/Zeichen einzeln angegeben werden.
\version "2.14.2"
#(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?)
(let* ((args+ (reverse (cons " " (reverse args))))
(new-args (list-join args+ " "))
(argls (proc new-args '()))
(stils (map (lambda (x)(interpret-markup layout props x)) argls))
(new-stils (reverse (cdr (reverse stils)))))
(stack-chars (car new-stils) (cdr new-stils) nmbr)))
#(define-markup-command (char-spaceII layout props nmbr args)(number? markup-list?)
(let* ((args+ (reverse (cons " " (reverse args))))
(stils (map (lambda (x)(interpret-markup layout props x)) args+))
(new-stils (reverse (cdr (reverse stils))))
)
(stack-chars (car new-stils) (cdr new-stils) nmbr)))
\markup \column {
\char-spaceII #-0.2 {
"é""è""ê""ë""á""à""â""ä""í""ì""î""ï""ó""ò""ô""ö""ú""ù""û""ü""ç""œ""æ"
}
\char-spaceII #2 {
"^°!§$%&/()=?{[]}`´**~#'-.,;:_<>"
"^""°""!""§""$""%""&""/""("")""=""?""{""[""]""}""`""´""*""+"
"~""#""'""-""."","";"":""_""<"">"
}
}
\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) \fontsize #3 \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. }
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) \fontsize #3 \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. }
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) \fontsize #3 \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. }
Das ganze klappt auch mit Zahlen:
\char-space #1 { 234 } -
\char-space #-0.2 { 35 = 199 }.
}
}
Nicolas Sceaux hat es hier: http://lsr.dsi.unimi.it/LSR/Item?id=368 (http://lsr.dsi.unimi.it/LSR/Item?id=368) geschafft das Problem mit Umlauten und Akzenten anzugehen. Eine Übertragung auf das jetzige Problem ist mir allerdings nicht gelungen.
Gruß,
Harm
-
:o
Immer wieder beeindruckt!
Klappt jetzt super! Es ist schon etwas umständlich für längere Anmerkungen, aber zum Glück haben nicht alle Worte der Deutschen Sprache Sonderzeichen ;D
Mein Hoffnung für Lucida Sans Typewriter wächst :)
Gruß
kil
-
Ich schau mal, ob ich übers Wochenende dazu komme, eine UTF8-Variante von string->string-list zu entwickeln.
Arnold
-
Und ich versuche demnächst mit dem Buch "structures and interpretation of computer programs" anzufangen... dann kann ich endlich mal scheme besser verstehen und vielleicht sogar selber schreiben! ;)
-
Hallo kilgore,
sehr empfehlenswert ist auch das »Guile Reference Manual«. Für das aktuelle Lilypond die Version 1.8.
Ich habe eine »Edition 1.1, for use with Guile 1.8.8.5.g9718acd« als PDF gefunden, ich denke es war Teil irgendeiner Linux-Distribution. Unter http://www.gnu.org/software/guile/ fndet man sonst nur die Internet-HTML-Version.
Am meisten 'wühle' ich im Kaptiel »API-Reference« in den Unterkapiteln »Simple Generic Data Types« und »Compound Data Types« herum.
Arnold
-
Hallo Arnold,
Danke für den Tipp! Ja leider finde ich nur die Version 1.8 als PDF zum kaufen... Ich brauche zunächst aber etwas für Anfänger, ich kenne mich sonst nur mit Lilypond Code aus. Da bin ich wirklich ein Neuling zu anderen Codes!
Ich habe schon mit "structures and interpretation of computer programs" angefangen, aber es hackt immer bei den Conditionals... ::)
-
Hallo kilgore,
Zum spacing-problem:
Ich habe mein string->string-list noch mal überarbeitet. Geht wahrscheinlich besser und eleganter, aber es scheint mit Umlauten und Sonderzeichen zu funktionieren. Falls nicht wirst Du Dich schon melden. ;)
\version "2.14.2"
#(define default-strg "éèêëáàâäíìîïóòôöúùûüçæ°§´œ")
#(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")
Works with special characters and german umlaute, too.
"
(if (= (string-length strg) 0)
(begin
(set! ls '(""))
ls)
(begin
(let* ((substrings (if (and (>= (string-length strg) 1)(string-contains default-strg (string-take strg 1)))
(substring strg 0 2)
(substring strg 0 1)))
(string-drop-number (if (and (>= (string-length strg) 1)
(string-contains default-strg (string-take strg 1)))
2
1)))
(set! ls (cons substrings ls))
(if (>= (string-length (string-drop strg string-drop-number)) 1)
(helper-1 (string-drop strg string-drop-number) ls)
(reverse ls))))))
(helper-1 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?)
(let* ((new-args (list-join args " "))
(argls (proc new-args '()))
(stils (map (lambda (x)(interpret-markup layout props x)) argls)))
(stack-chars (car stils) (cdr stils) nmbr)))
\markup \column {
"Test"
\char-space #2.2 {
éèêëáàâäíìîïóòôöúùûüçæœ»
}
\char-space #1 {
"^°!$%&/()=?{[]}`*+~#'-.,;:_<>^§´œ|~¹²³"
}
\char-space #1 {
le garçon
}
\char-space #2 {
ma sœur
}
\vspace #2
}
\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) \fontsize #3 \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. }
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) \fontsize #3 \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. }
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) \fontsize #3 \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. }
Das ganze klappt auch mit Zahlen:
\char-space #1 { 234 } -
\char-space #-0.2 { 35 = 199 }.
}
}
Zu scheme/guile:
Vokabular/Syntax/Grammatik ist recht schnell erlernbar.
Die Hauptprobleme die ich erlebt habe waren:
(1) Mit scheme ist natürlich ein äußerst hoher Grad an Abstraktion erreichbar. Man muß also sehr klar denken, um schreiben zu können was man halt gerade haben will.
Allerdings dürfte die Möglichkeit zur hohen Abstraktionsfähigkeit auf jede Computersprache zutreffen.
(2) In LilyPond ist sehr vieles natürlich bereits vordefiniert, aber, zumindest in diesem Bereich, schlecht oder gar nicht dokumentiert. Man muß also immer wieder in die Installationsdateien schauen und diese studieren, um zu verstehen was wie gemacht wird. Das ist schwierig und zeitaufwendig.
Hilfreich beim lernen war neben dem eigentlichen guile-manual (hat Arnold ja schon verlinkt) auch folgendes manual:
http://www.math.grin.edu/~stone/scheme-web/table-of-contents.html (http://www.math.grin.edu/~stone/scheme-web/table-of-contents.html)
Das geht ein bißchen in Richtung "scheme for dummies", hat mir aber sehr geholfen.
Ich habe schon mit "structures and interpretation of computer programs" angefangen, aber es hackt immer bei den Conditionals...
Wenn Du fragen hast, so werde ich mich bemühen eine Antwort zu finden. ;)
HTH,
Harm
-
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
-
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
-
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!!!
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
-
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.
-
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
-
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
-
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
-
Hallo 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
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
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. :)
-
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
-
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
-
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"
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
-
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.
-
Hallo Arnold,
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.
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 (http://old.nabble.com/Stable-releases-ts33150070.html#a33150070) Thread.
Gruß,
Harm
-
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
-
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:
"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
-
Sehr schön Harm.
~Pierre
-
Hallo Harm,
so funktioniert es tadellos! Vielen herzlichen Dank für die tolle Erweiterung!
Gruß, Robert
-
Hallo Pierre, hallo Robert,
das Ganze war und ist eine Coproduktion von Arnold und mir, wobei Arnold den Löwenanteil beigesteuert hat!
Gruß,
Harm
-
Selbstverständlich auch Dank an Arnold! Eure Co[de]-Produktion sollte wirklich in die nächste Stable integriert werden!