Sto provando a visualizzare del testo in una parte specifica di un'immagine in un'app Web Form. Il testo verrà inserito dall'utente, quindi voglio variare la dimensione del carattere per assicurarmi che si adatti al riquadro di delimitazione.Graphics.MeasureCharacterRange che forniscono calcoli di dimensioni errate
Ho codice che stava facendo questo bene sulla mia implementazione proof-of-concept, ma ora sto provando contro le risorse del designer, che sono più grandi, e sto ottenendo alcuni risultati strani.
sto correndo il calcolo formato come segue:
StringFormat fmt = new StringFormat();
fmt.Alignment = StringAlignment.Center;
fmt.LineAlignment = StringAlignment.Near;
fmt.FormatFlags = StringFormatFlags.NoClip;
fmt.Trimming = StringTrimming.None;
int size = __startingSize;
Font font = __fonts.GetFontBySize(size);
while (GetStringBounds(text, font, fmt).IsLargerThan(__textBoundingBox))
{
context.Trace.Write("MyHandler.ProcessRequest",
"Decrementing font size to " + size + ", as size is "
+ GetStringBounds(text, font, fmt).Size()
+ " and limit is " + __textBoundingBox.Size());
size--;
if (size < __minimumSize)
{
break;
}
font = __fonts.GetFontBySize(size);
}
context.Trace.Write("MyHandler.ProcessRequest", "Writing " + text + " in "
+ font.FontFamily.Name + " at " + font.SizeInPoints + "pt, size is "
+ GetStringBounds(text, font, fmt).Size()
+ " and limit is " + __textBoundingBox.Size());
allora io uso la seguente riga per il rendering del testo su un'immagine sto tirando dal filesystem:
g.DrawString(text, font, __brush, __textBoundingBox, fmt);
dove :
__fonts
è unPrivateFontCollection
,PrivateFontCollection.GetFontBySize
è un metodo di estensione che restituisce unFontFamily
RectangleF __textBoundingBox = new RectangleF(150, 110, 212, 64);
int __minimumSize = 8;
int __startingSize = 48;
Brush __brush = Brushes.White;
int size
inizia a 48 e decrementi all'interno di tale cicloGraphics g
haSmoothingMode.AntiAlias
eTextRenderingHint.AntiAlias
impostarecontext
è unaSystem.Web.HttpContext
(questo è un estratto dal metodo di unIHttpHandler
ProcessRequest
)
Gli altri metodi sono:
private static RectangleF GetStringBounds(string text, Font font,
StringFormat fmt)
{
CharacterRange[] range = { new CharacterRange(0, text.Length) };
StringFormat myFormat = fmt.Clone() as StringFormat;
myFormat.SetMeasurableCharacterRanges(range);
using (Graphics g = Graphics.FromImage(new Bitmap(
(int) __textBoundingBox.Width - 1,
(int) __textBoundingBox.Height - 1)))
{
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
Region[] regions = g.MeasureCharacterRanges(text, font,
__textBoundingBox, myFormat);
return regions[0].GetBounds(g);
}
}
public static string Size(this RectangleF rect)
{
return rect.Width + "×" + rect.Height;
}
public static bool IsLargerThan(this RectangleF a, RectangleF b)
{
return (a.Width > b.Width) || (a.Height > b.Height);
}
ora ho due problemi.
In primo luogo, il testo a volte insiste sul wrapping inserendo un'interruzione di riga all'interno di una parola, quando dovrebbe non riuscire ad adattarsi e causare il decremento del ciclo while. Non riesco a capire perché sia lo Graphics.MeasureCharacterRanges
a pensare che ciò rientri nella scatola quando non dovrebbe essere il word-wrapping all'interno di una parola. Questo comportamento viene mostrato indipendentemente dal set di caratteri utilizzato (lo trovo nelle parole dell'alfabeto latino, così come in altre parti della gamma Unicode, come il cirillico, il greco, il georgiano e l'armeno). C'è qualche impostazione che dovrei usare per forzare Graphics.MeasureCharacterRanges
solo per fare il wordwrap nei caratteri di spazi (o trattini)? Questo primo problema è lo stesso di post 2499067.
In secondo luogo, nel ridimensionare la nuova immagine e la dimensione del carattere, Graphics.MeasureCharacterRanges
mi sta dando altezze che sono selvaggiamente fuori. Il disegno RectangleF
all'interno corrisponde ad un'area visivamente apparente dell'immagine, così posso facilmente vedere quando il testo viene decrementato più del necessario. Eppure quando gli passo un po 'di testo, la chiamata GetBounds
mi dà un'altezza che è quasi il doppio di quello che effettivamente sta prendendo.
Utilizzo di tentativi ed errori per impostare __minimumSize
per forzare un'uscita dal ciclo while, posso vedere che il testo 24pt si inserisce all'interno del riquadro di delimitazione, tuttavia Graphics.MeasureCharacterRanges
sta segnalando che l'altezza di quel testo, una volta renderizzata all'immagine, è 122px (quando il riquadro di delimitazione è alto 64 px e rientra in tale riquadro). In effetti, senza forzare la questione, il ciclo while itera fino a 18pt, a quel punto Graphics.MeasureCharacterRanges
restituisce un valore che si adatta.
Il brano registro di traccia è il seguente:
decremento dimensione del carattere a 24, come la dimensione è 193 × 122 e il limite è 212 × 64
decremento dimensione del carattere a 23, come la dimensione è 191 × 117 e il limite è 212 × 64
di decremento dimensione di carattere 22, la dimensione è 200 × 75 e il limite è 212 × 64
Decrementale dimensione di carattere 21, la dimensione è 192 × 71 e il limite è 212 × carattere 64
Decrementale dimensione a 20, poiché la dimensione è 198 × 68 e il limite è 212 × 64
Decre Menting dimensione del carattere a 19, come la dimensione è 185 × 65 ed il limite è 212 × 64
Scrittura Vennegoor of Hesselink DIN-Black a 18pt, la dimensione è 178 × 61 e il limite è 212 × 64
Allora perché è Graphics.MeasureCharacterRanges
mi dà un risultato sbagliato? Potrei capire che è, ad esempio, l'altezza della linea del font se il loop si fermava intorno a 21pt (che sarebbe visivamente in forma, se faccio uno screenshot dei risultati e lo misuro in Paint.Net), ma sta andando molto più lontano di quanto dovrebbe fare perché, francamente, sta restituendo i dannati risultati sbagliati.
+1 per una delle domande più documentate che ho visto da un po '! – SouthShoreAK