viele, kurze strings in einem View zeichnen ist sehr langsam

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

  • viele, kurze strings in einem View zeichnen ist sehr langsam

    Hi,

    ich muss auf einem view sehr viel information anzeigen. Das sind alles einzelne strings die an bestimmte positionen auf dem view gezeichnet werden sollen.

    im moment mach ich das in etwa so:

    Quellcode

    1. [infoTextStorage replaceCharactersInRange:NSMakeRange(0,[infoTextStorage length]) withString:infoString];
    2. glyphRange = [infoLayoutManager glyphRangeForTextContainer:infoTextContainer];
    3. [infoLayoutManager drawGlyphsForGlyphRange:glyphRange atPoint:thePoint];
    Das ganze ist aber sehr langsam. wenn man das einige male wiederholt kommt da massig zeit zusammen.
    Zeile 1 braucht 10% der zeit,
    Zeile 2 braucht 27% der zeit,
    Zeile 3 braucht 62% der zeit,
    den verbleibenden 1% wird für das erstellen von TextStorage, TextContainer, LayoutManager etc benötigt.

    Hat jemand ne idee wie ich das beschleunigen könnte?

    Vielen Dank
  • RE: viele, kurze strings in einem View zeichnen ist sehr langsam

    Wenn das ein mehr oder weniger fester Text ist, kannst du ihn in Bezier-Pfade umwandeln und diese speichern. Beim Neuzeichnen schmeißt du dann nur die PFade heraus. Das beschleunigt die Sache ungemein.

    Wenn er sich natürlich ständig ändert, bringt das nichts.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Du musst ihm sogar die Glyphen sagen.

    Das wundert mich auch!

    Hmmm, vielleicht kann dir MCDan noch etwas sagen, der naturgemäß das gleiche Problem hatte. Er hat auch mal den Ober-Text-System-Cheffe-Freak auf der WWDC angesprochen. Wenn ich mich recht entsinne, kam so etwas wie In Leopard wird's schneller" als Antwort. Frag ihn halt mal.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • als ich sagte dass ich dem bp die glyphen sagen könnte meinte ich dass ich die glyphen nichtmal mehr rausfinden müsste weil ich sie bereits zu den entsrechenden zeichen habe, aber dann doch leiber layoutmanager und die characters verwende weil das schneller ging als BezierPath.

    gibt es bei den bezierpaths irgendwelche tricks oder so, denn mir kommt auch das zeichnen von linien und rechtecken nicht besonders schnell vor...

    Vielleicht meldet sich MCDan ja hier im thread wenn er ihn mal sieht ;)
  • Also der Text System Guru bei Apple (Douglas Davidson) hat mir gesagt, dass ich unter Leopard CoreText verwenden soll, da dies viel schneller als das Cocoa Text System sei, welches in Leopard quasi auf CoreText aufsetzt. Leider bringt mir dies aktuell nicht viel, da ich Tables (noch) nicht Leopard only haben möchte. :(

    Aktuell verwende ich ein Text System aus Text Storage, Text Container und Layout Manager bei dem ich jeweils den Text Storage bzw. den Attributed String austausche und dann über den Layout Manager ausgebe. Wenn ich das Text System richtig verstanden habe, dann bringt dies nicht viel, da die Glyphs im LayoutManager gecacht werden und bei jeder Änderung im TextStorage dieser Cache entsprechend gelöscht bzw. auf ungültig gesetzt wird. Der Geschwindigkeitsvorteil durch das Caching im Layout Manager ist bei diese Methode also gleich Null.

    Die Möglichkeit den Text in einem BezierPath zu speichern und dann über diesen auszugeben habe ich noch nicht weiter untersucht. Hat dies schon mal jemand gemacht und bring dies die erhoffte Geschwindigkeit?
  • RE: viele, kurze strings in einem View zeichnen ist sehr langsam

    Original von gritsch
    ich muss auf einem view sehr viel information anzeigen. Das sind alles einzelne strings die an bestimmte positionen auf dem view gezeichnet werden sollen.
    Wird da jedemal der komplette View neu gezeichnet? Oder prüft die drawRect:-Methode -getRectsBeingDrawn:count: was überhaupt sichtbar ist?

    -- hns
  • Habe mal so was zusammen gebastelt. Da es aber an einer nicht Performance releanten Stelle verwende habe hat es mich nie so richtig interessiert. Wenn es jemand hilft so was zu machen dann schaut es euch doch mal an.


    Quellcode

    1. @implementation NSFont (NSFont_BezierPathGenerationAdditions)
    2. - (NSBezierPath*) bezierPathForString:(NSString*)string {
    3. NSTextContainer* textContainer = [[[NSTextContainer alloc] init] autorelease];
    4. [textContainer setLineFragmentPadding:0.0];
    5. NSLayoutManager* layoutManager = [[[NSLayoutManager alloc] init] autorelease];
    6. [layoutManager addTextContainer:textContainer];
    7. NSTextStorage* textStorage = [[[NSTextStorage alloc] initWithString:string] autorelease];
    8. [textStorage setFont:self];
    9. [textStorage addLayoutManager:layoutManager];
    10. NSRange stringRange=NSMakeRange(0,[string length]);
    11. NSMutableData* glyphData=[NSMutableData dataWithLength:sizeof(NSGlyph)*stringRange.length+1];
    12. NSGlyph* glyphs=(NSGlyph*)[glyphData mutableBytes];
    13. int glyphCount = [layoutManager getGlyphs:glyphs range:stringRange];
    14. NSBezierPath* bezierPath=[[[NSBezierPath alloc] init] autorelease];
    15. [bezierPath moveToPoint: NSMakePoint (10.0, 10.0)];
    16. // [bezierPath moveToPoint:NSMakePoint(0.0, 0.0)];
    17. [bezierPath appendBezierPathWithGlyphs:glyphs count:glyphCount inFont:self];
    18. return bezierPath;
    19. }
    20. @end
    Alles anzeigen
  • Also ich habe es jetzt mal ausprobiert und über BezierPaths ist es wirklich ein wenig schneller als über das Text System.

    Allerdings habe ich zwei Probleme:

    1) Da mein View flipped ist steht der BezierPath bzw. der Text darin auf dem Kopf

    2) Wie kann ich den erstellten BezierPath an einer variablen Stelle ausgeben?

    Ich schätze, dass die Lösung für beide Probleme in einer Änderung der affine transformation liegt, richtig?

    Da meine Texte nicht nur einfach in einer Zeile stehen, erstelle ich den BezierPath wie folgt:

    Quellcode

    1. NSBezierPath *newTextBezierPath = [[NSBezierPath alloc] init];
    2. NSRange glyphRange = [layoutManager glyphRangeForTextContainer:textContainer];
    3. if (glyphRange.length > 0)
    4. {
    5. int i;
    6. for (i = 0; i < glyphRange.length; i++)
    7. {
    8. [newTextBezierPath moveToPoint:[layoutManager locationForGlyphAtIndex:i]];
    9. [newTextBezierPath appendBezierPathWithGlyph:[layoutManager glyphAtIndex:i] inFont:[style font]];
    10. }
    11. }
    12. [self setTextBezierPath:newTextBezierPath];
    13. [newTextBezierPath release];
    Alles anzeigen
    Der BezierPath wird natürlich nur ein mal erstellt wenn sich der Text ändert und dann bei Bedarf immer wieder mit fill ausgegeben.
  • Original von gritsch
    wie hast du das angestellt dass BP schneller ist als das textsystem?

    Der BezierPath wird ja nur ein mal erstellt, wenn sich der Text ändert. Wenn der Anwender also nur scrollt, oder etwas markiert, dann wird immer der selbe Text ausgegeben und somit der bereits erstellte BezierPath verwendet.

    Verändern sich Deine Texte permanent oder nur hin und wieder mal?