10
votes

Le CTFresetSuggestSuggestFresizeWithConstraints () renvoie une taille incorrecte à chaque fois

Selon les documents, CTFRASESETTERSUGGERFRESIMESWITHCONSTRESSIONS () "Détermine la taille du cadre nécessaire à une plage de cordes".

Malheureusement, la taille renvoyée par cette fonction n'est jamais exacte. Voici ce que je fais: xxx

La taille renvoyée a toujours la largeur correcte calculée, mais la hauteur est toujours légèrement plus courte que ce qui est attendu.

Est-ce le moyen correct d'utiliser cette méthode?

y a-t-il d'autre moyen de mettre en place un texte de base?

semble que je ne suis pas le seul à rencontrer des problèmes avec cette méthode. Voir https://devforums.apple.com/message/181450 .

Modifier: J'ai mesuré la même chaîne avec quartz à l'aide de Taillewithfont: , fournissant la même police à la chaîne attribuée et à quartz. Voici les mesures que j'ai reçues:

Texte principal: 133.569336 x 16.592285

Quartz: 135.000000 x 31.000000


2 commentaires

eu même problème. Calcule toujours une ligne de moins que si je le demande pour calculer 3 lignes, cela me donnera le calcul correct pour 2 .. etc.


Voir cette question connexe:


6 Réponses :


5
votes

Pour une seule image de ligne, essayez ceci:

CGFloat wrongHeight = ascent-descent;
CGSize textSize = CGSizeMake(width, wrongHeight);


2 commentaires

Merci beaucoup, MO. Cela m'a aidé à trouver ce qui semble être une solution de contournement fiable pour le suggérant des étiquettes multilignes.


Heureux d'avoir pu aider. Avez-vous vérifié si j'avais raison sur le wrongheight ? Je veux déposer un rapport de bogue. Ps. merci gf.



14
votes

Essayez ceci .. semble fonctionner:

+(CGFloat)heightForAttributedString:(NSAttributedString *)attrString forWidth:(CGFloat)inWidth
{
    CGFloat H = 0;

    // Create the framesetter with the attributed string.
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString( (CFMutableAttributedStringRef) attrString); 

    CGRect box = CGRectMake(0,0, inWidth, CGFLOAT_MAX);

    CFIndex startIndex = 0;

    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, NULL, box);

    // Create a frame for this column and draw it.
    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(startIndex, 0), path, NULL);

    // Start the next frame at the first character not visible in this frame.
    //CFRange frameRange = CTFrameGetVisibleStringRange(frame);
    //startIndex += frameRange.length;

    CFArrayRef lineArray = CTFrameGetLines(frame);
    CFIndex j = 0, lineCount = CFArrayGetCount(lineArray);
    CGFloat h, ascent, descent, leading;

    for (j=0; j < lineCount; j++)
    {
        CTLineRef currentLine = (CTLineRef)CFArrayGetValueAtIndex(lineArray, j);
        CTLineGetTypographicBounds(currentLine, &ascent, &descent, &leading);
        h = ascent + descent + leading;
        NSLog(@"%f", h);
        H+=h;
    }

    CFRelease(frame);
    CFRelease(path);
    CFRelease(framesetter);


    return H;
}



0
votes

Cela peut sembler étrange mais j'ai trouvé que si vous utilisez la fonction CEIL , puis ajoutez +1 à la hauteur, elle fonctionnera toujours. De nombreuses API tiers utilisent cette astuce.


0 commentaires

3
votes

Le problème est que vous devez appliquer un style de paragraphe au texte avant de le mesurer. Si vous ne le faites pas, vous obtenez la valeur par défaut de 0,0. J'ai fourni un échantillon de code pour comment faire cela dans ma réponse à un duplicata de cette question ici ici https://stackoverflow.com/a/ 10019378/1313863 .


0 commentaires

0
votes

Ressuscation.

Lors de la détermination initiale où des lignes doivent être placées dans une trame, le texte de base semble masser la descente + la descente aux fins du calcul de la ligne d'origine. En particulier, il semble que 0,2 * (ascension + descente) soit ajouté à l'ascension, puis la descente et l'ascension résultante sont modifiés par plancher (x + 0,5) , puis les positions de base sont calculé sur la base de ces ascensions et descentes ajustées. Ces deux étapes sont affectées par certaines conditions dont je ne suis pas sûr, et j'ai aussi déjà oublié les styles de paragraphe de points, malgré cela que je ne sais que quelques jours il y a quelques jours.

J'ai déjà démissionné pour simplement envisager une ligne de démarrer à sa base et ne pas essayer de comprendre ce que les lignes réelles atterrissent. Malheureusement, cela ne semble toujours pas être suffisant: les styles de paragraphe ne sont pas reflétés dans CTLINEGETTYPOGROCOGOGOGOGULAIS () , et certaines polices comme Klee qui ont des mentionnements non nuléreuses en train de traverser le chemin rect! Je ne sais pas quoi faire à propos de cela ... probablement pour une autre question.

mise à jour

Il semble ctlinegetboundswithoptions (ligne, 0) obtient les limites de la ligne appropriées, mais pas tout à fait: il y a une lacune entre les lignes et avec certaines polices (Klee à nouveau) l'écart est négatif et le Les lignes se chevauchent ... Je ne sais pas quoi faire à ce sujet. : | Au moins nous sommes légèrement plus proches ??

Et même alors il ne prend toujours pas de styles de paragraphe en considération>: |

CTLINEGETBOUDSWITHOPTIONS () n'est pas répertorié sur le site de la documentation d'Apple, éventuellement due à un bogue dans la version actuelle de leur générateur de documentation. Il s'agit d'une API entièrement documentée, cependant, vous le trouverez dans les fichiers d'en-tête et il a été longuement discuté à la Session 226 de la WWDC 2012.

Aucune des options ne nous est pertinente: elles réduisent les limites record en prenant en compte certains choix de conception de polices (ou augmentent les limites recouvertes de manière aléatoire, dans le cas du nouveau kctlineboundsincluSeextents ). Une option utile en général, cependant, est kctlineboundsuseglyphpathbounds , ce qui est équivalent à ctlinegetimagebounds () mais sans avoir besoin de spécifier un CGContext (et donc sans être soumis à une matrice de texte existante ou à la CTM).


0 commentaires

0
votes

Réponse de Ing.Conti mais à Swift 4: XXX PRE>

J'ai essayé de le garder comme 1: 1 avec le code de l'objectif C mais Swift n'est pas aussi agréable lors de la manipulation des pointeurs de manipulation de certains changements étaient nécessaires pour le casting. p>

J'ai également fait des points de repère comparant ce code (et son homologue Objc) à une autre méthode de hauteur. En tant qu'entrée, j'ai utilisé une chaîne attribuée énorme et très complexe comme entrée et l'a également fait sur la carte SIM afin que les temps eux-mêmes ne soient pas de sens, mais les vitesses relatives sont correctes. P>

Runtime for 1000 iterations (ms) BoundsForRect: 8909.763097763062
Runtime for 1000 iterations (ms) layoutManager: 7727.7010679244995
Runtime for 1000 iterations (ms) CTFramesetterSuggestFrameSizeWithConstraints: 1968.9229726791382
Runtime for 1000 iterations (ms) CTFramesetterCreateFrame ObjC: 1941.6030206680298
Runtime for 1000 iterations (ms) CTFramesetterCreateFrame-Swift: 1912.694974899292


0 commentaires