1

In GDI to get the ABC widths (left bearing, right bearing etc) for a character I would call GetCharABCWidths.

How do I achieve the same measurements using SharpDX or DirectWrite, and should I expect the values to match between this and GDI for the same characters?

What have I done so far? Become lost in the lack of documentation for Direct* and SharpDX.

Vanquished Wombat
  • 9,075
  • 5
  • 28
  • 67
  • 1
    [`GetDesignGlyphMetrics`](https://msdn.microsoft.com/en-us/library/windows/desktop/dd370986.aspx), perhaps? I'm not terribly familiar with DirectWrite, but even in GDI, it is rare that I've ever needed `GetCharABCWidths`. Normally, what you really need to know is the dimensions of a particular string (even if that string consists of only a single character), so you would just call `DrawString` with `DT_CALCRECT` or whatever. I'm sure DirectWrite has a similar "MeasureText" function. – Cody Gray - on strike Jun 16 '17 at 16:46
  • Yeah @CodyGray, you'd think it would be a cake-walk after GDI. GetDesignGlyphMetrics returns a structure which `Obtains ideal (resolution-independent) glyph metrics in font design units` Not quite the same as good ole GDI.In fact I need the A & B widths for some accurate alignment needs. – Vanquished Wombat Jun 16 '17 at 17:03
  • 1
    No, I really wouldn't. GDI is a cake walk as far as I'm concerned. It's also the sharpest text rendering that I can get on my machine, *and* the fastest. Everything since then has been a regression, as far as I'm concerned, at least for text output and other non-graphics-intensive drawing tasks. – Cody Gray - on strike Jun 16 '17 at 17:12
  • Am beginning to realise the same. My app will run as a service which leads me to DirectWrite and WARP. I just have to push on. Out of interest should I expect ABC widths to match across GDI & DirectWrite ? – Vanquished Wombat Jun 17 '17 at 17:35

1 Answers1

4
/// <summary>
///  Takes a string, text format, and associated constraints, and produces an object that represents the fully analyzed and formatted result.
/// </summary>
/// <param name="factory">an instance of <see cref="T:SharpDX.DirectWrite.Factory" /></param>
/// <param name="text">An array of characters that contains the string to create a new <see cref="T:SharpDX.DirectWrite.TextLayout" /> object from. This array must be of length stringLength and can contain embedded NULL characters.</param>
/// <param name="textFormat">A pointer to an object that indicates the format to apply to the string.</param>
/// <param name="maxWidth">The width of the layout box.</param>
/// <param name="maxHeight">The height of the layout box.</param>
/// <unmanaged>HRESULT CreateTextLayout([In, Buffer] const wchar* string,[None] UINT32 stringLength,[None] IDWriteTextFormat* textFormat,[None] FLOAT maxWidth,[None] FLOAT maxHeight,[Out] IDWriteTextLayout** textLayout)</unmanaged>
public TextLayout(Factory factory, string text, TextFormat textFormat, float maxWidth, float maxHeight)

Sample code:

using (var dwFactory = new SharpDX.DirectWrite.Factory())
{
  var textLayout = new TextLayout(dwFactory, "ABC", textFormat, float.PositiveInfinity, float.PositiveInfinity);
  var width = textLayout.Metrics.Width
  ...
}
Dan Byström
  • 9,067
  • 5
  • 38
  • 68
  • Thanks Dan - I really appreciate your input, but its not obvious how to get char ABC widths from this, can you explain a little please? – Vanquished Wombat Jun 19 '17 at 08:42
  • Sure. Updated. You have to set "textFormat" to an appropriate value. – Dan Byström Jun 19 '17 at 08:59
  • Ok thanks - so far my understanding is that this gives the width of the string of characters in the second parameter, when laid out in the specified font characteristics etc. My use of terminology 'ABC' was intended to explain that I am looking for the same functionality as the old GDI GetCharABCWidths() - link in my OP - function which I think differs from the TextLayout() function in that the GDI fn gives left middle and right bearing (AKA as 'ABC' widths in GDI). I could be entirely wrong but I think TextLayout() gives the size of the full string, but not in metrics per character? – Vanquished Wombat Jun 19 '17 at 09:09
  • Ah. Correct. I'm not sure how much metrics you need. If it's just character widths, maybe you can try something like: var widths = "ABC".Select(_ => new TextLayout(dwFactory, _.ToString(), textFormat, float.PositiveInfinity, float.PositiveInfinity)).ToList(); – Dan Byström Jun 19 '17 at 09:19
  • I thought the same however I have found currently that the overhang metrics in TextLayout() seem to be zero in all cases in our current development. I have someone investigating this but wanted to check if the SO community knew of a more appropriate approach. Also, I have a lot of chars to measure and am fearful that the repeated use of TextLayout() will be an overhead. Generally I am expecting DirectWrite to provide equivalent or better capability than GDI, I am just having fun(!) trying to find my way through the [Labyrinth](http://philipcoppens.com/crete_labyrinth.html) without a map. – Vanquished Wombat Jun 19 '17 at 09:27