wie kann man "writing direction" bei einer beliebigen Textzeile abfragen?

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • wie kann man "writing direction" bei einer beliebigen Textzeile abfragen?

    Ich habe es ehrlich versucht, aber noch nichts herausgefunden...

    Z.B. habe ich so was ausprobiert:

    NSLayoutManager* layoutManager = [[NSLayoutManager alloc] init];
    NSTextStorage* textStorage = [[NSTextStorage alloc] initWithString:@"abc"];
    [textStorage addLayoutManager:layoutManager];
    NSRange stringRange=NSMakeRange(0,[@"abc" length]);
    NSMutableData* glyphData=[NSMutableData dataWithLength:sizeof(CGGlyph)*stringRange.length+1];
    CGGlyph* glyphs=(CGGlyph*)[glyphData mutableBytes];
    unsigned char *bidiLevelBuffer = calloc([@"abc" length], sizeof(unsigned char));

    int glyphCount = (int)[layoutManager getGlyphsInRange:stringRange glyphs:glyphs properties:NULL characterIndexes:NULL bidiLevels:bidiLevelBuffer];

    NSLog(@"--- %i, \"%s\"", glyphCount, bidiLevelBuffer);

    mit dem Ergebnis:

    2021-12-29 10:39:54.694104+0300 aTypeTrainer4Mac[61412:3479843] --- 3, ""

    also blieb bidiLevelBuffer leer...

    ...

    any ideas?
    Gruss aus Russland :)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Valentin V. ()

  • bitte code-tags verwenden, dann wird es lesbarer :)

    Hier wurde mal etwas ähnliches diskutiert: NSTextView + NSAttributedString + writingDirection

    Sonst gilt: baseWritingDirection ist zunächst eine Eigenschaft des NSParagraphStyle. Vgl. developer.apple.com/documentat…ngdirection?language=objc

    Abfragen kann man das direkt am textStorage (das ist ein NSMutableAttributedString der auch einen NSParagraphStyle kennt).
    D.h. wenn kein NSParagraphStyle gesetzt ist, dann wird vermutlich NSWritingDirectionNatural verwendet.

    Das alles ist aber der Input für den NSLayoutManager der das in Glyphen verwurstelt.

    Schließlich zum bidiBuffer: der liefert Byte-Werte zwischen 0 und 61 - keinen druckbaren %s...
    Siehe: developer.apple.com/documentat…yphsinrange?language=objc

    Wenn da alle Bytes 0 sind (oder schon das erste) kommt ein leerer String raus.

    PS: statt [@"abc" length] würde ich besser [textStorage length] nehmen... Dann braucht es das @"abc" nur einmal.
  • Danke!

    Leider weiss ich das alles bereits, es bringt mich aber irgendwie nicht weiter...

    "Schließlich zum bidiBuffer: der liefert Byte-Werte zwischen 0 und 61 - keinen druckbaren %s..."

    ich merke schon, dass da mit dem Format etwas nicht stimmt -
    es wird nur der Anfang von dem Buffer angezapft...

    wie wäre es angemessen in dem Fall?

    wobei wenn ich nur @"a" nehme, kommt am Ende gleicht nichts raus, sollte aber...

    ...

    noch einmal: es gibt eine beliebige Textzeile!

    wie ermittelt man die Schreibrichtung, wenn man im voraus nichts von der verwendeten Sprache weiss?????...
    Gruss aus Russland :)

    Dieser Beitrag wurde bereits 13 mal editiert, zuletzt von Valentin V. ()

  • Der bidi-Buffer ist ein byte-Array und kein String.
    Daher taugt %s zur Ausgabe nichts.
    Lösung: alle Bytes in einer Schleife per %02x (oder %d) einzeln ausgeben...
    Vermutlich sind dann alle 0x00 was m.E. pauschale Schreibrichtung links -> rechts bedeuten würde.

    Frage: warum sollte bei @"a" etwas herauskommen wenn kein NSParagraphStyle gesetzt ist? Was erwartest Du als Ausgabe?
  • Danke!

    das Problem liegt aber darin, dass ich die angewendete Sprache NICHT angeben kann,
    weil es in meinem Fall eine x-beliebige Sprache sein könnte -
    wie kann man an einem Buchstaben die Sprache erkennen?
    und ich brauche es auch nicht - nur die Sreibrichtung interessiert mich...

    aber - irgendwie - erkennt z.B. NSTextField die Sreibrichtung bereits an einem einzigen Buchstaben -
    es ist ja offensichtlich, aber WIE kann man es nachmachen?
    Gruss aus Russland :)
  • Ah, Du willst aus einem einzigen Buchstaben die Schreibrichtung erkennen?
    Wie geht das in dem Beispiel mit NSTextField? Hab ich noch nie ausprobiert. Schreibt man da ein arabisches Zeichen rein und es schaltet von rechts auf links weiter selbst wenn man dann lateinisch weitertippt?
    Das ist soweit ich weiss nicht ganz eindeutig...
    en.wikipedia.org/wiki/Bidirectional_text#Marks
    Irgendeine Spracheinstellung oder Default braucht es schon irgendwie.
    Ich nehme an NSTextField hat da eine Heuristik?
    Andererseits kann ich im Interface-Builder die "Text Direction" als Natural, Left-to-Right oder Right-to-Left vorgeben.
    Hinter diesem Mechanismus steckt die baseWritingDirection von NSControl (von dem ein NSTextField abgeleitet ist).
    Evtl. steckt hinter "Natural" eine Automatik. Da steht in der Doku nämlich dass das nur ein "Hint" ist.
    Aber wie oben im Wikipedia-Link kann die Writing-Direction auch im Unicode-Text selbst drinstehen (U+200E LEFT-TO-RIGHT MARK LRM).
    D.h. es müsste sich direkt aus einem beliebigen NSString ableiten lassen indem man die Algorithmen implementiert: unicode.org/reports/tr9/
    Vielleicht hilft ja die C-Referenzimplementierung unicode.org/Public/PROGRAMS/BidiReferenceC/14.0.0/ um zu verstehen was AppKit macht.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von hns ()

  • hns schrieb:

    Wie geht das in dem Beispiel mit NSTextField? Hab ich noch nie ausprobiert. Schreibt man da ein arabisches Zeichen rein und es schaltet von rechts auf links weiter selbst wenn man dann lateinisch weitertippt?
    Du kannst es in TextEdit sehen - ja, es wird die Richtung gleich gewechselt, wenn eine andere Sprache kommt -
    dies wird gerade in bidiLevels notiert (bidirectional), wobei eine Richtung wird immer mit geraden Zahlen notiert und andere -
    mit ungeraden - und die Levels dürfen eingeschachtelt werden... von 0 bis 61 werden sie nummeriert...

    also im Grunde muss man die Levels-Kodierung ordentlich entziffern - und dann klärt sich alles von selber...
    Gruss aus Russland :)
  • dankend für die Empfehlungen, möchte ich die Aufgabe prezisieren:

    ursprünglich gehe ich von einer Tastaturbelegung aus -
    die wird von dem Benutzer aktiviert -
    dann muss ich - unter Anderem - die entsprechende Scheibrichtung ermitteln -
    dafür habe ich schon ein Provisorium, womit ich aber nicht ganz zufrieden bin
    und so will ich endlich das Problem ordentlich lösen

    um die Sprache an sich geht es gar nicht - es geht um Buchstaben,
    die mehreren Sprachen dienen können

    so denke immer fester an bidiLevels - die muss ich nun ordentlich kennen lernen
    Gruss aus Russland :)
  • Ich hab es mal auspobiert über Emoji&Symbole (Zeichentabelle). Wenn man da nach "arab" sucht kann man arabische Buchstaben in TextEdit tippen und das zweite wird links vom ersten eingefügt. Sobald man auf der Tastatur weitertippt, gehen die lateinischen wieder nach Rechts.

    Die bidiLevels scheinen also für den Anwendungsfall schon richtig zu sein, wenn es davon abhängen soll was jemand tippt - wie auch immer also z.B. über auch über die Zeichentabelle oder Unicode auf der Tastatur. Und nicht davon abhängen, welche Spracheinstellungen vorgenommen wurden oder welche Tastaturbelegung gewählt wurde Es sollte nur vom Unicode in der textStorage abhängen.

    Wenn Du die bidiLevels noch sinnvoll aus der textStorage auslesen kannst, dann hast Du gewonnen :) Ich denke die Links auf die Unicode-Algorithmen können zum Verständnis der Codierung beitragen. Da habe ich auch etwas neues gelernt, nämlich dass es sie gibt und wo ich sie finde...

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von hns ()

  • Valentin V. schrieb:


    ich wäre froh, wenn mir jemand an einem Beispiel zeigen würde, wie der Method

    getGlyphsInRange:glyphs:properties:characterIndexes:bidiLevels:

    funktioniert in Bezug auf die bidiLevels-Ermittlung
    Erstmal ein Disclaimer: Ich bin nicht sicher, ob mein Test wirklich Deinen Anwendungsfall widerspiegelt: In einer meiner Apps habe ich ein NSTextField, dessen Eingabe zum Zeichnen von Bezier-Kurven genutzt wird ... das bot sich zum Testen an. Ich habe also den genannten Befehls des NSLayoutManagers um einen Buffer für die bidiLevel ergänzt:

    Quellcode

    1. unsigned char bidiLevels[glyphRange.length];
    2. CGGlyph glyphArray[glyphRange.length];
    3. NSUInteger glyphCount = [manager getGlyphsInRange:glyphRange glyphs:glyphArray properties:NULL characterIndexes:NULL bidiLevels:&bidiLevels[0]];
    4. for (int i = 0; i < glyphCount; i++)
    5. {
    6. NSLog(@"--- %i, \"%hhx\"", i, bidiLevels[i]);
    7. }

    Wenn ich nun z. B. durch Wechsel der Eingabequelle hebräische Zeichen eingebe, erhalte ich in der Ausgabe einen bidiLevel von "1", während z. B. deutsche Eingaben "0" ergeben.

    Ansonsten wäre sicher für andere interessant, Deine Lösung zu erfahren...

    Guten Rutsch Euch allen, Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • Valentin V. schrieb:

    Ich habe es DOCH geschafft und zwar auf einer GANZ anderen Weise!

    sollte es jemanden interessieren, werde ich mich anstrengen, um es zu schildern...

    wenn gaaanz kurz: mittels PDFDocument's
    Glückwunsch - aber bei dem Workaround stellen sich einem die Fußnägel hoch :)
    Da hätte man genauso gut eine umfangreiche Datenbank für alle Unicode-Zeichen erstellen können wo LTR oder RTL drinsteht und die abfragen.

    Ganz dumme Frage zu Deiner "nicht geschafft"-Version: wie hast Du im eingangs genannten Beispiel die arabischen oder andere Zeichen in den Beispielstring @"abc" gepackt? Vielleicht war das schon der Fehler...
    Außerdem würde es mich nicht wundern, wenn es nur geht wenn ein (ggf. leerer) NSParagraphStyle definiert ist.

    Einen schönen Silvesterabend und einen guten Start ins neue Jahr!
  • MyMattes schrieb:

    Wenn ich nun z. B. durch Wechsel der Eingabequelle hebräische Zeichen eingebe, erhalte ich in der Ausgabe einen bidiLevel von "1", während z. B. deutsche Eingaben "0" ergeben.
    Danke für den Test! Es scheint, dass Du es hingekriegt hast so, wie es sein muss.

    Leider konnte ich bis jetzt Deinen Erfolg nicht nachmachen -
    ich versuchte Deinen Code in meinen einzugliedern und bekam nur 0 in beiden Fällen...

    Somit bitte ich Dich sehr, Dein Beispiel um einpaar Zeilen zu ergänzen, dass es eine vollständige Einheit wird,
    die man dann als das Ganze ausprobieren könnte, und danke Dir im voraus für die Mühe.
    Gruss aus Russland :)