Low quality result when using TextViewDrawContext.DrawImage

SyntaxEditor for Windows Forms Forum

Posted 9 months ago by Marc Beeson - Precision Mining
Version: 20.1.0400
Avatar

We are migrating from SyntaxEditor version 287 to 400. When using TextViewDrawContext.DrawImage, the glyph has artifact ringing where the transparent background meets the image contents. I have tried using the TextViewDrawContext.PlatformRenderer to access GDI directly, but get a System.InvalidOperationException: 'Object is currently in use elsewhere.' Is there a way to make drawn glyphs render in higher quality?

Screenshot

internal class ErrorLineIndicatorTag : IndicatorClassificationTagBase
{

    private static readonly IClassificationType ErrorIndicatorLineClassificationType = new ClassificationType("Error Line Indicator");
    private static readonly IClassificationType ErrorIndicatorLineNoHighlightClassificationType = new ClassificationType("Error Line Indicator No Highlight");
    private readonly Image m_image;
    private readonly bool m_highlight;

    static ErrorLineIndicatorTag()
    {
        AmbientHighlightingStyleRegistry.Instance.Register(ErrorIndicatorLineClassificationType, new HighlightingStyle { Background = Color.FromArgb(40, Color.Firebrick), BorderColor = Color.FromArgb(40, Color.DarkRed), BorderKind = LineKind.Solid, BackgroundSpansVirtualSpace = true });
        AmbientHighlightingStyleRegistry.Instance.Register(ErrorIndicatorLineNoHighlightClassificationType, new HighlightingStyle());
    }

    public ErrorLineIndicatorTag(bool highlight)
    {
        m_highlight = highlight;
        var imageSize = (int) (16 * ImageLists.DpiScale);
        m_image = ImageLists.GetImage("Error");
    }

    public override IClassificationType ClassificationType { get { return m_highlight ? ErrorIndicatorLineClassificationType : ErrorIndicatorLineNoHighlightClassificationType; } }

    public override void DrawGlyph(TextViewDrawContext context, ITextViewLine viewLine, TagSnapshotRange<IIndicatorTag> tagRange, Rectangle bounds)
    {
        if (bounds.Width > bounds.Height)
            context.DrawImage(new Point((bounds.Width - bounds.Height) / 2 + bounds.X, bounds.Y), m_image);
        else
            context.DrawImage(new Point(bounds.X, (bounds.Height - bounds.Width) / 2 + bounds.Y), m_image);
    }

}

Comments (3)

Posted 9 months ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Marc,

The TextViewDrawContext tries to use core GDI APIs as much as possible since they are very fast compared to GDI+, and they render text spacing correctly.  I believe what's happening is that the TextViewDrawContext is in GDI mode when it enters here.  At least by the official release of build 400, we call the AlphaBlend API to render images.  That should handle semi-transparent images ok. 

Can you e-mail our support address with the image you're trying to draw so we can try the same here and see the issue happening?  Please reference this thread in your e-mail.

Another workaround you could try is to flip to GDI+ temporarily.  Toggle the context.IsNativeRendering to false, draw the image, and then flip it back to true.  I haven't tried that myself but it may help in the meantime.  It would be better to sort out why it's not working in the first place.


Actipro Software Support

Posted 9 months ago by Marc Beeson - Precision Mining
Avatar

Hi,

Thanks for the detailed reply. I have sent an email to the Actipro support email with a project demonstrating the issue.

Your suggestion of toggling IsNativeRendering worked, the icon alpha blending looks good. However the line numbers do not render if this workaround is used. For reference this is the code I used:

public override void DrawGlyph(TextViewDrawContext context, ITextViewLine viewLine, TagSnapshotRange<IIndicatorTag> tagRange, Rectangle bounds)
{
    context.IsNativeRendering = false;
    try
    {
        if (bounds.Width > bounds.Height)
            context.PlatformRenderer.DrawImage(m_image, new Rectangle((bounds.Width - bounds.Height) / 2 + bounds.X, bounds.Y, bounds.Height, bounds.Height));
        else
            context.PlatformRenderer.DrawImage(m_image, new Rectangle(bounds.X, (bounds.Height - bounds.Width) / 2 + bounds.Y, bounds.Width, bounds.Width));
    }
    finally
    {
        context.IsNativeRendering = true;
    }
}
Posted 9 months ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Marc,

Thanks for the sample.  I believe we found a workaround.  We are rebuilding it now and will send a preview build link to you via the related support ticket.


Actipro Software Support

The latest build of this product (v2020.1 build 0402) was released 2 months ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.