Подтвердить что ты не робот

System.Drawing.Graphics.DrawString - исключение "Параметр недействительно"

Иногда сообщения об исключениях для Microsoft бесполезны. Я создал хороший небольшой MVC-метод для рендеринга текста. Тело метода находится ниже. Когда он достигает метода "DrawString", я получаю исключение: "Параметр недопустим".

Обратите внимание, что шрифт, насколько я могу судить, правильно построен (я просто использую Arial в 10pt), размер прямоугольника положительный и действительный, кисть - это белый SolidBrush, а флаги формата не влияют на вывод, т.е. если я исключаю флаги формата из вызова, я все равно получаю сообщение об ошибке.

Вызов DrawString находится справа внизу.

public ActionResult RenderText(
    string fontFamily,
    float pointSize,
    string foreColor,
    string backColor,
    bool isBold,
    bool isItalic,
    bool isVertical,
    string align,
    string[] allText,
    int textIndex)
{
    // method renders a horizontal or vertical text image, taking all the text strings that will be rendered in each image
    // and sizing the final bitmap according to which text would take the most space, thereby making it possible to render
    // a selection of text images all at the same size.

    Response.ContentType = "image/png";

    var fmt = StringFormat.GenericTypographic;
    if(isVertical)
        fmt.FormatFlags = StringFormatFlags.DirectionVertical;

    Func<string,StringAlignment> getAlign = (s => {
        switch(s.ToLower())
        {
            case "right": return StringAlignment.Far;
            case "center": return StringAlignment.Center;
            default: return StringAlignment.Near;
        }
    });
    fmt.LineAlignment = isVertical ? StringAlignment.Center : getAlign(align);
    fmt.Alignment = isVertical ? getAlign(align) : StringAlignment.Center;

    var strings = (allText ?? new string[0]).Where(t => t.Length > 0).ToList();
    if(strings.Count == 0)
        strings.Add("[Missing Text]");

    FontStyle style = FontStyle.Regular;
    if(isBold)
        if(isItalic)
            style = FontStyle.Bold | FontStyle.Italic;
        else
            style = FontStyle.Bold;
    else if(isItalic)
        style = FontStyle.Italic;

    Font font = new Font(fontFamily, pointSize, style, GraphicsUnit.Point);
    Color fc = foreColor.IsHexColorString() ? foreColor.ToColorFromHex() : foreColor.ToColor();
    Color bc = backColor.IsHexColorString() ? backColor.ToColorFromHex() : backColor.ToColor();

    var maxSize = new Size(0,0);
    using(var tmp = new Bitmap(100, 200))
        using(var gfx = Graphics.FromImage(tmp))
            foreach(var txt in strings)
            {
                var size = gfx.MeasureString(txt, font, 1000, fmt);
                maxSize = new Size(
                    Math.Max(Convert.ToInt32(isVertical ? size.Height : size.Width), maxSize.Width),
                    Math.Max(Convert.ToInt32(isVertical ? size.Width : size.Height), maxSize.Width)
                );
            }

    using(var bmp = new Bitmap(maxSize.Width, maxSize.Height))
    {
        using(var gfx = Graphics.FromImage(bmp))
        {
            gfx.CompositingMode = CompositingMode.SourceCopy;
            gfx.CompositingQuality = CompositingQuality.HighQuality;
            gfx.SmoothingMode = SmoothingMode.HighQuality;
            gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;

            var rect = new RectangleF(new PointF(0,0), maxSize);
            gfx.FillRectangle(new SolidBrush(bc), rect);
            gfx.DrawString(strings[textIndex], font, new SolidBrush(fc), rect, fmt);
        }
        bmp.Save(Response.OutputStream, ImageFormat.Png);
    }
    return new EmptyResult();
}
4b9b3361

Ответ 1

Ну, я выяснил причину проблемы. Что-то очень неясное. Код работает, когда я удаляю эту строку:

gfx.CompositingMode = CompositingMode.SourceCopy;

Ответ 2

Что может помочь при отладке, уменьшает методы. Например, вы можете заменить

FontStyle style = FontStyle.Regular;
if(isBold)
    if(isItalic)
        style = FontStyle.Bold | FontStyle.Italic;
    else
        style = FontStyle.Bold;
else if(isItalic)
    style = FontStyle.Italic;

по

FontStyle style = GetFontStyle(isBold, isItalic);

и

public FontStyle GetFontStyle(bool isBold, bool isItalic)
{
    if(isBold)
        if(isItalic)
            return FontStyle.Bold | FontStyle.Italic;
        else
            return FontStyle.Bold;
    else if(isItalic)
        return FontStyle.Italic;
    else
        return FontStyle.Regular;
}

Это делает ваш код более читабельным, и это облегчает вам помощь других.

На самом деле никакого преступления не было!

С уважением, Ans Vlug