iText - ColumnText texte d'un ajustement de la taille dans le Rectangle
Je veux ajouter du texte dans un rectangle(x,y,w,h). Le texte doit être équipé de la taille du rectangle (dire qu'il a une taille maximale, mais il contient toujours dans le rectangle).
J'ai essayé de mesurer la taille du texte de base sur BaseFont.getWidthPoint()
Le problème, c'est la finale la taille du texte peut pas s'adapter à la rect. Il ressemble à ceci:
Voici mon essai:
PdfContentByte cb = writer.getDirectContent();
cb.saveState();
ColumnText ct = new ColumnText(writer.getDirectContent());
Font font = new Font(BaseFont.createFont());
int rectWidth = 80;
float maxFontSize = getMaxFontSize(BaseFont.createFont(), "text", rectWidth );
font.setSize(maxFontSize);
ct.setText(new Phrase("test", font));
ct.setSimpleColumn(10, 10, rectWidth , 70);
ct.go();
//draw the rect
cb.setColorStroke(BaseColor.BLUE);
cb.rectangle(10, 10, rectWidth , 70);
cb.stroke();
cb.restoreState();
//get max font size base on rect width
private static float getMaxFontSize(BaseFont bf, String text, int width){
float measureWidth = 1;
float fontSize = 0.1f;
float oldSize = 0.1f;
while(measureWidth < width){
measureWidth = bf.getWidthPoint(text, fontSize);
oldSize = fontSize;
fontSize += 0.1f;
}
return oldSize;
}
Pourriez-vous me dire où je me trompe?
Un autre problème, je veux mesurer à la fois la largeur et la hauteur, le texte complètement contient en rectangle et a la taille maximale. Est-il possible de faire cela?
Mise à jour: voici le code source complet qui a fonctionné pour moi:
private static float getMaxFontSize(BaseFont bf, String text, int width, int height){
//avoid infinite loop when text is empty
if(TextUtils.isEmpty(text)){
return 0.0f;
}
float fontSize = 0.1f;
while(bf.getWidthPoint(text, fontSize) < width){
fontSize += 0.1f;
}
float maxHeight = measureHeight(bf, text, fontSize);
while(maxHeight > height){
fontSize -= 0.1f;
maxHeight = measureHeight(bf, text, fontSize);
};
return fontSize;
}
public static float measureHeight(BaseFont baseFont, String text, float fontSize)
{
float ascend = baseFont.getAscentPoint(text, fontSize);
float descend = baseFont.getDescentPoint(text, fontSize);
return ascend - descend;
}
je veux mesurer à la fois la largeur et la hauteur, le texte complètement contient en rectangle et a le maximum de la taille de la police. - voulez-vous dire qu'en une seule ligne (qui est l'endroit où votre code actuel est dirigé) ou voulez-vous aussi pour permettre des sauts de ligne pour mieux remplir le rectangle?
J'ai juste besoin d'une ligne de texte
Dans ce cas, d'appliquer les correctifs je l'ai mentionné dans ma réponse et, en plus, ne pas permettre plus de tailles de police que le rectangle de sommets.
J'ai juste besoin d'une ligne de texte
Dans ce cas, d'appliquer les correctifs je l'ai mentionné dans ma réponse et, en plus, ne pas permettre plus de tailles de police que le rectangle de sommets.
OriginalL'auteur R4j | 2013-12-25
Vous devez vous connecter pour publier un commentaire.
Le principal problème
Le principal problème est que vous utilisez le mauvais arguments en
ct.setSimpleColumn
:Contrairement à la plus tard
cb.rectangle
appelqui a des arguments
float x, float y, float w, float h
(w
eth
étant largeur et hauteur) de la méthodect.setSimpleColumn
a des argumentsfloat llx, float lly, float urx, float ury
(ll être en bas à gauche et ur être en haut à droite). Ainsi, votrect.setSimpleColumn
devrait ressembler à ceci:Une question de côté
En plus à la question principale de votre résultat taille de la police est de 0,1 trop grand; c'est une erreur déjà signalé par @David.
Votre boucle principale dans votre
getMaxFontSize
méthode est: est-ceEssentiellement, cela signifie que les résultats dans
oldSize
(qui s'est finalement retourné) est le premier de taille de police qui ne pas ajustement. Vous pouvez résoudre ce problème en utilisantMême mieux serait une approche uniquement le calcul de la chaîne de largeur une fois, pas à l'aide d'une boucle, par exemple
(Cette méthode utilise l'arithmétique des nombres entiers. Si vous insistez sur un ajustement exact, interrupteur à flotteur ou le double de l'arithmétique.)
OriginalL'auteur mkl
Il y a deux bugs ici, à la fois dans
measureWidth >= width
- en d'autres termes, par le temps de vous échapper de lawhile
boucle,measureWidth
est déjà trop gros pour le rectangle.fontSize++
, ce qui signifie que, après que vous avez utiliséfontSize
pour calculermeasureWidth
, vous êtes à l'augmenter. Lorsque vous faites le contourner, de le retourner, c'est un de plus que la valeur que vous avez testé. Donc, la valeur de retour de la méthode sera un de plus que la dernière valeur que vous avez testés (qui, à cause du point 1., était déjà trop grand).t
caractère toujours tomber dans la nouvelle ligne.La droite. En regardant votre nouveau code que vous avez corrigé le problème (2), mais pas question (1). Vous êtes en rupture de sortir de cette boucle avec une valeur de
oldSize
pour quibf.getWidthPoint(text,oldSize)
est déjà plus grand quewidth
- qui est, il est déjà trop grand.Et vous ne devez pas modifier le code de la question - il faut ajouter tout le nouveau code à la fin. Sinon, il rend la question vide de sens et inutile à tous les futurs utilisateurs du site.
OriginalL'auteur Dawood ibn Kareem
J'ai passé un bon moment pour mettre en œuvre ces fonctionnalités à l'aide de méthode de recherche binaire pour trouver rectangle de montage taille de la police. Et aujourd'hui, je suis tombé sur une méthode intéressante dans la bibliothèque iText...
Il est tout à fait une nouvelle méthode dans la bibliothèque iText
ColumnText
;Dans ma version de la bibliothèque iText il est statique.
Voir les détails: http://developers.itextpdf.com/reference/com.itextpdf.text.pdf.ColumnText
OriginalL'auteur Дмитрий Игоревич