-1

Is there way to adjusting the width of certain characters in WPF textBlock or GlyphRun element?

I do not want to increase the space between the characters, but to increase the width of the characters themselves as in the picture:

enter image description here

The following code prints on the screen the letters 'ABC abc', what should I do to make some of the letters 200% or 300% wide?

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       Title="MainWindow" Height="200" Width="300">
    <Grid>
        <Image Stretch="None" SnapsToDevicePixels="True">
            <Image.Source>
                <DrawingImage x:Name="drawingImage" />
            </Image.Source>
        </Image>
    </Grid>
</Window>
public partial class MainWindow : Window
{

    GlyphTypeface glyphTypeface;
    double renderingEmSize, advanceWidth, advanceHeight;
    Point baselineOrigin;

    public MainWindow()
    {
        InitializeComponent();

        new Typeface("segoe ui").TryGetGlyphTypeface(out glyphTypeface);

        renderingEmSize = 12;

        advanceWidth = glyphTypeface.AdvanceWidths[0] * renderingEmSize;
        advanceHeight = glyphTypeface.Height * renderingEmSize;
        baselineOrigin = new Point(0, glyphTypeface.Baseline * renderingEmSize);

        drawingImage.Drawing = Render();

    }

    private Drawing Render()
    {
        var line = "ABC abc";

        var drawing = new DrawingGroup();
        using (var drawingContext = drawing.Open())
        {
            var glyphRun = ConvertTextToGlyphRun(
                glyphTypeface, renderingEmSize,
                advanceWidth, advanceHeight,
                baselineOrigin, line);

            var guidelines = new GuidelineSet();
            guidelines.GuidelinesX.Add(baselineOrigin.X);
            guidelines.GuidelinesY.Add(baselineOrigin.Y);
            drawingContext.PushGuidelineSet(guidelines);
            drawingContext.DrawGlyphRun(Brushes.Black, glyphRun);
            drawingContext.Pop();
        }

        return drawing;
    }

    static GlyphRun ConvertTextToGlyphRun(
        GlyphTypeface glyphTypeface, 
        double renderingEmSize, 
        double advanceWidth, 
        double advanceHeight,
        Point baselineOrigin,
        string line)
    {
        var glyphIndices = new List<ushort>();
        var advanceWidths = new List<double>();
        var glyphOffsets = new List<Point>();

        var y = baselineOrigin.Y;
        var x = baselineOrigin.X;

        for (int j = 0; j < line.Length; ++j)
        {
            var glyphIndex = glyphTypeface.CharacterToGlyphMap[line[j]];
            glyphIndices.Add(glyphIndex);
            advanceWidths.Add(0);
            glyphOffsets.Add(new Point(x, y));
            x += glyphTypeface.AdvanceWidths[glyphIndex] * renderingEmSize;
        }

        return new GlyphRun(
            glyphTypeface,
            0,
            false,
            renderingEmSize,
            glyphIndices,
            baselineOrigin,
            advanceWidths,
            glyphOffsets,
            null, null, null, null, null);
    }
}
codeDom
  • 1,623
  • 18
  • 54
  • Possible duplicate of [How can I specify letter spacing or kerning, in a WPF TextBox?](https://stackoverflow.com/questions/5843562/how-can-i-specify-letter-spacing-or-kerning-in-a-wpf-textbox) – David Sep 18 '17 at 20:29
  • Not duplicate I do not want to increase the space between the characters, but to increase the width of the characters themselves – codeDom Sep 18 '17 at 20:43
  • @DavidDay That is the exact opposite. While it asks how to "modify the spacing between characters", the question asker here says they "do **not** want to increase the space between the characters" – Clemens Sep 18 '17 at 20:45
  • there are lots of ways, making your question very broad. That said, if you're happy with the CSS "solution", which scales the entire text block, characters and spacing alike, you can do the same exact thing in WPF, by setting a transform on the text element (e.g. `TextBlock`). How about you post some code, i.e. a good [mcve], show what you've tried, and explain what _specifically_ you still can't figure out? – Peter Duniho Sep 18 '17 at 21:43
  • See also [FontStretch](https://msdn.microsoft.com/en-us/library/system.windows.controls.control.fontstretch.aspx) property, depending on the level of precision you want to be able to control the width. – Peter Duniho Sep 18 '17 at 21:54
  • @Peter Duniho I edited the question. – codeDom Sep 19 '17 at 05:34

2 Answers2

0

I think, it should helps

<StackPanel>
    <TextBox x:Name="originalABC">ABC</TextBox>
    <TextBlock x:Name="transformedABC">
        <TextBlock.RenderTransform>
            <ScaleTransform CenterX="0" CenterY="0" ScaleX="3" ScaleY="1" />
        </TextBlock.RenderTransform>
        ABC
    </TextBlock>
</StackPanel>

screenshot

  • Thank you, is there a way that only certain characters will be wider than the others and not all the text? – codeDom Sep 19 '17 at 06:02
0

Add two lines to your code for transform:

drawingContext.PushGuidelineSet(guidelines);
drawingContext.PushTransform(new ScaleTransform(2, 1)); // <= new line
drawingContext.DrawGlyphRun(Brushes.Black, glyphRun);
drawingContext.Pop();                                   // <= new line
drawingContext.Pop();

from here.

codeDom
  • 1,623
  • 18
  • 54