我可以使用自定义文本渲染器在SharpDX中创建文本大纲吗?

时间:2016-05-19 00:09:14

标签: c# text sharpdx glyph

背景

之前我正在渲染文字,并通过向每一边绘制轮廓1px然后将文字放在顶部来给它一个发光的轮廓:

// Draw outline 1px to each side
context2D.DrawTextLayout(new Vector2(-1, 0), _textLayout, _highlightBrush, DrawTextOptions.NoSnap);
context2D.DrawTextLayout(new Vector2(0, -1), _textLayout, _highlightBrush, DrawTextOptions.NoSnap);
context2D.DrawTextLayout(new Vector2(1, 0), _textLayout, _highlightBrush, DrawTextOptions.NoSnap);
context2D.DrawTextLayout(new Vector2(0, 1), _textLayout, _highlightBrush, DrawTextOptions.NoSnap);
// Draw text on top of outline
context2D.DrawTextLayout(new Vector2(0, 0), _textLayout, _foregroundBrush, DrawTextOptions.NoSnap);

example 1

这很有效。但我意识到我需要让我的字符串的不同部分具有不同的前景色和高光。

Example 2

我可以将两个单独的TextLayout并排,但我已经不得不缩放我的字体以适应容器大小,并排执行两个部分似乎真的很复杂,这是我当前的缩放代码试图找到适合容器的最佳字体大小:

private void CreateTextFormatAndLayout( string text )
{
    float maxFontSize = _settings.BoardLayout.ActualGradeMaxFontSize;
    float minFontSize = _settings.BoardLayout.ActualGradeMinFontSize;
    var factory = DeviceManager.DirectWriteFactory;

    SharpDX.DirectWrite.TextFormat textFormat = null;
    SharpDX.DirectWrite.TextLayout textLayout = null;

    // step backward through font sizes till we find one that fits
    for ( float fontSize = maxFontSize; fontSize > minFontSize; fontSize -= .5f ) {

        // if have leftover values from previous loop, dispose
        if ( textFormat != null )
            textFormat.Dispose();
        if ( textLayout != null )
            textLayout.Dispose();

        // generate sharpdx format and layout based on current font size
        textFormat = new SharpDX.DirectWrite.TextFormat(factory, "Arial", SharpDX.DirectWrite.FontWeight.Normal, SharpDX.DirectWrite.FontStyle.Normal, fontSize);
        textFormat.WordWrapping = SharpDX.DirectWrite.WordWrapping.NoWrap;
        textFormat.TextAlignment = SharpDX.DirectWrite.TextAlignment.Center;
        textLayout = new SharpDX.DirectWrite.TextLayout(factory, text, textFormat, _regionWidthPx, _regionWidthPx);

        // if text will fit in the container break
        if ( textLayout.Metrics.Width < _regionWidthPx )
            break;
    }

    // Set format and layout
    _textFormat = ToDispose(textFormat);
    _textLayout = ToDispose(textLayout);
}

当我发现你可以为TextLayout的不同部分创建自定义处理程序时。 (字形)我不太了解字形,但这个例子似乎表明它并不太难:

Example of using custom renderer

我正在尝试做什么

我想做类似的事情,除了我想传递两个颜色我的自定义文本渲染器,并让它渲染轮廓。我不是在寻找代码审查,我大多想知道我是否在正确的轨道上。我的MultiBrush想法是完全错误还是我可以这样做?我相信其他人必须进行高级文本格式化。这是我的基本想法,如果需要我可以更多地充实它,但我想任何熟悉SharpDX的人都能看到我想要做的事情:

public class MultiBrush : ComObject
{
    public MultiBrush( Brush foreground, Brush highlight )
    {
        ForegroundBrush = foreground;
        HighlightBrush = highlight;
    }

    public Brush ForegroundBrush;
    public Brush HighlightBrush;
}

public class CustomColorRenderer : SharpDX.DirectWrite.TextRendererBase
{
    private RenderTarget renderTarget;
    private MultiBrush defaultBrush;

    public void AssignResources( RenderTarget renderTarget, MultiBrush defaultBrush )
    {
        this.renderTarget = renderTarget;
        this.defaultBrush = defaultBrush;
    }

    public override Result DrawGlyphRun( object clientDrawingContext, float baselineOriginX, float baselineOriginY, MeasuringMode measuringMode, GlyphRun glyphRun, GlyphRunDescription glyphRunDescription, ComObject clientDrawingEffect )
    {
        MultiBrush sb = defaultBrush;
        if ( clientDrawingEffect != null && clientDrawingEffect is MultiBrush ) {
            sb = (MultiBrush)clientDrawingEffect;
        }

        try {
            // render shadow 1 px away
            this.renderTarget.DrawGlyphRun(new Vector2(baselineOriginX + 1, baselineOriginY + 1), glyphRun, sb.HighlightBrush, measuringMode);
            // render main text
            this.renderTarget.DrawGlyphRun(new Vector2(baselineOriginX, baselineOriginY), glyphRun, sb.ForegroundBrush, measuringMode);
            return Result.Ok;
        }
        catch {
            return Result.Fail;
        }
    }
}
...

CustomColorRenderer customRenderer = new CustomColorRenderer();
textLayout = new TextLayout(dwFactory, introText, textFormat, 300.0f, 200.0f);

SolidColorBrush brush1 = new SolidColorBrush(DeviceManager.Direct2DContext, _foregroundColor);
SolidColorBrush brush2 = new SolidColorBrush(DeviceManager.Direct2DContext, _highlightColor);
multiBrush = new MultiBrush(brush1, brush2);

// Apply custom modification to text
textLayout.SetDrawingEffect(multiBrush, new TextRange(10, 20));
// Render custom text
textLayout.Draw(customRenderer, 0, 0);

0 个答案:

没有答案