11
votes

Longueur de la chaîne qui conviendra à une largeur spécifique

Je suis sûr que je manque quelque chose d'évident, j'ai une zone dans laquelle j'avais l'intention de dessiner du texte. Je connais sa hauteur et sa largeur de la région. Je souhaite savoir combien de caractères / mots ira dans la largeur, les caractères de préférence. Deuxième question, si la ligne est trop longue, je voudrais dessiner une deuxième ligne, alors je suppose que je dois aussi avoir la hauteur du texte, y compris ce qui compte tout ce qu'il considère le rembourrage vertical droit?

Je préférerais aussi connaître l'inverse, c'est-à-dire combien de caractères je peux correspondre à une largeur spécifique.

Je suppose que le fait que WPF ne soit pas contraint aux pixels aura une certaine inauguration sur la réponse?

En fin de compte, je planifie le texte d'emballage autour des images en forme irrégulière intégrées dans le texte.

Tous les pointeurs dans la bonne direction seraient super.

merci


0 commentaires

3 Réponses :


-1
votes

Ceci est impossible car les caractères ont une longueur différente, par exemple W est beaucoup plus large que moi (sauf si vous utilisez une police comme de messagerie neuve).


3 commentaires

Ce n'est pas impossible. L'ensemble de la typographie dépend de pouvoir faire cela. Historiquement, nous avons eu des choses comme MeestEtext et mestructions, et l'événement de mesure sur les articles. Pensez-y, regardez la page Web que vous lisez, remarquez comment le texte s'inscrit dans l'espace disponible.


Ah,'but Typographie ne va pas comme toi. C'est comme la construction d'une maison du toit. Vous ne savez pas combien de caractères entrent dans une largeur, vous savez à quel point un texte spécifique est large. Sans concerner le texte, calculer la largeur n'est pas possible. Typogpahy ne commence pas avec un "texte aléatoire inconnu" à mesurer.


Désolé, je ne voulais pas donner cette impression. Je connais le texte et je sais la largeur de la ligne que cela doit entrer. Je connais la police, la taille de la police et ainsi de suite. J'ai donc tous les bits dont j'ai besoin pour pouvoir le calculer, je ne savais pas comment :)




3
votes

La réponse de Brokenglass est excellente, mais en fonction des caractéristiques de votre application, vous pouvez trouver une meilleure performance avec une recherche binaire. Si la majorité de vos chaînes correspondent à la largeur disponible ou que vous devez généralement être coupé par un caractère ou deux, puis une recherche linéaire est la meilleure. Cependant, si vous avez beaucoup de longues chaînes qui seront sévèrement tronquées, la recherche binaire suivante fonctionnera bien.

Notez que les deux à la fois disponibles et fontine sont spécifiées dans des unités indépendantes de l'appareil (1 / 96ths d'un pouce). En outre, utilisez le TextFormattingMode qui correspond à la façon dont vous dessinez votre texte. P>

public static string TruncateTextToFitAvailableWidth(
    string text, 
    double availableWidth, 
    string fontName, 
    double fontSize)
{
    if(availableWidth <= 0)
        return string.Empty;

    Typeface typeface = new Typeface(fontName);

    int foundCharIndex = BinarySearch(
        text.Length,
        availableWidth,
        predicate: (idxValue1, value2) =>
        {
            FormattedText ft = new FormattedText(
                text.Substring(0, idxValue1 + 1), 
                CultureInfo.CurrentCulture, 
                FlowDirection.LeftToRight, 
                typeface, 
                fontSize, 
                Brushes.Black,
                numberSubstitution: null,
                textFormattingMode: TextFormattingMode.Ideal);

            return ft.WidthIncludingTrailingWhitespace.CompareTo(value2);
        });

    int numChars = (foundCharIndex < 0) ? ~foundCharIndex : foundCharIndex + 1;

    return text.Substring(0, numChars);
}

/**
<summary>
See <see cref="T:System.Array.BinarySearch"/>. This implementation is exactly the same,
except that it is not bound to any specific type of collection. The behavior of the
supplied predicate should match that of the T.Compare method (for example, 
<see cref="T:System.String.Compare"/>).
</summary>
*/      
public static int BinarySearch<T>(
    int               length,
    T                 value,
    Func<int, T, int> predicate) // idxValue1, value2, compareResult
{
    return BinarySearch(0, length, value, predicate);
}

public static int BinarySearch<T>(
    int               index,
    int               length,
    T                 value,
    Func<int, T, int> predicate)
{
    int lo = index;
    int hi = (index + length) - 1;

    while(lo <= hi)
    {
        int mid = lo + ((hi - lo) / 2);

        int compareResult = predicate(mid, value);

        if(compareResult == 0)
            return mid;
        else if(compareResult < 0)
            lo = mid + 1;
        else
            hi = mid - 1;
    }

    return ~lo;
}


2 commentaires

Votre réponse est trop compliquée, il y a une solution beaucoup plus simple. Tout ce que vous avez à faire est de calculer le pourcentage de la taille de la chaîne trop petite ou trop grande pour l'espace donné et de l'échelle de la taille de la police avec ce facteur.


Changer la taille de la police n'est pas acceptable pour l'OP ou notre application.