Я пытаюсь отобразить текст в определенной части изображения в приложении Web Forms. Текст будет введен пользователем, поэтому я хочу изменить размер шрифта, чтобы он соответствовал рамке ограничения.Graphics.MeasureCharacterRanges дает неправильные вычисления размера
У меня есть код, который отлично справляется с моей концепцией концептуальной концепции, но теперь я пытаюсь использовать его у дизайнеров, которые больше, и я получаю некоторые нечетные результаты.
Я бег расчета размера следующим образом:
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());
то я использую следующую строку для отображения текста на изображение Я тянущий из файловой системы:
g.DrawString(text, font, __brush, __textBoundingBox, fmt);
где :
__fonts
являетсяPrivateFontCollection
,PrivateFontCollection.GetFontBySize
это метод расширения, который возвращаетFontFamily
RectangleF __textBoundingBox = new RectangleF(150, 110, 212, 64);
int __minimumSize = 8;
int __startingSize = 48;
Brush __brush = Brushes.White;
int size
начинается в 48 и декрементах в пределах этого циклаGraphics g
имеетSmoothingMode.AntiAlias
иTextRenderingHint.AntiAlias
наборcontext
являетсяSystem.Web.HttpContext
(это выдержка изProcessRequest
метода сIHttpHandler
)
Другие методы:
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);
}
Теперь у меня есть две проблемы.
Во-первых, текст иногда настаивает на упаковке путем вставки разрыва строки в пределах слова, когда он должен просто не подходить, а цикл while - снова уменьшаться. Я не понимаю, почему Graphics.MeasureCharacterRanges
считает, что это помещается в поле, когда оно не должно быть словом в слове. Это поведение проявляется независимо от используемого набора символов (я получаю его в латинских буквах, а также в других частях диапазона Unicode, таких как кириллица, греческий, грузинский и армянский). Есть ли какая-то настройка, которую я должен использовать, чтобы заставить Graphics.MeasureCharacterRanges
быть только переносом слов на символы пробела (или дефисы)? Эта первая проблема такая же, как у post 2499067.
Во-вторых, при масштабировании до нового изображения и размера шрифта Graphics.MeasureCharacterRanges
дает мне высоты, которые дико отключены. RectangleF
Я рисую внутри, соответствует визуально видимой области изображения, поэтому я могу легко увидеть, когда текст декрементируется больше, чем это необходимо. Но когда я передаю ему какой-то текст, звонок GetBounds
дает мне высоту, которая почти вдвое больше, чем она на самом деле берет.
Используя пробную версию и ошибку, чтобы установить __minimumSize
для принудительного выхода из цикла while, я вижу, что текст 24pt помещается в ограничительную рамку, но Graphics.MeasureCharacterRanges
сообщает, что высота этого текста, после визуализации изображения, составляет 122px (когда ограничивающий прямоугольник имеет высоту 64px и он помещается внутри этого поля). Действительно, не заставляя дело, цикл while повторяется до 18pt, после чего Graphics.MeasureCharacterRanges
возвращает значение, которое подходит.
Журнал трассировки отрывок следующим образом:
Уменьшение номера размера шрифта до 24, а размер 193 × 122 и предел составляет 212 × 64
Уменьшения номера размера шрифта до 23, а размер 191 × 117 и предел составляет 212 × 64
Уменьшения номера размера шрифта до 22, а размер 200 × 75 и предел составляет 212 × 64
декремента размера шрифта до 21, а размер 192 × 71 и предел составляет 212 × 64
декремента шрифта размер до 20, размер - 198 × 68, а предел - 212 × 64
Decre альный размер шрифта до 19, а размер 185 × 65 и предел 212 × 64
Записи Веннегора из Гесселинка в DIN-черном на 18 пунктах, размер 178 × 61 и предел 212 × 64
Так почему Graphics.MeasureCharacterRanges
дает мне неправильный результат? Я мог понять, что это, скажем, высота строки шрифта, если цикл остановился около 21pt (что бы визуально соответствовало, если бы я снимал снимки результатов и измерял их в Paint.Net), но он продвигается намного дальше, чем он должен делать потому что, честно говоря, он возвращает неправильные результаты.
+1 для одного из самых документированных вопросов, которые я видел через некоторое время! – SouthShoreAK