Reputation: 689
I need to convert some text-to-bitmap rendering routines in existing C++ code that is using GDI and GDI+ to use DirectWrite (CFF support and OTF-feature support required).
I'm new to DirectWrite. Spending some time on research on what's required for the migration of existing functionality and doing some prototyping, I encountered an issue: My problem is that DirectWrite (out of the box) doesn't support character spacing adjustment (which is a requirement for the existing app), at least not on Windows 7. I know it comes with Windows 8, but another requirement for this existing app is to run on Windows 7, unfortunately.
What I found in my research so far is that the way to go seems to implement a custom DirectWrite Text Layout, but I haven't found any good guideline on how to do this, especially in regards for character spacing (the documentation/examples on MSDN in regards of how to create a custom Text Layout are a little vague for my taste).
As I figure this must have been done before, before spending days and/or weeks of research and developement on re-inventing the wheel, does anybody here know a sample implementation of a DirectWrite text layout with custom character spacing I could use as a starting point or tutorial?
UPDATE1: Not an answer but - I found out that the IDWriteTextLayout1 interface (which supports setting the Character spaces) not only comes with Windows 8, but also with "Windows 7 Platform Update for SP1" (KB 2670838) on Windows 7. as I can require that for out app to run properly, this solves my issue, although it doesn't answer my question.
Upvotes: 4
Views: 856
Reputation: 2409
A custom layout is pretty complex due to bidi and line wrapping and the need to call the lower level API's, but a sample is here [https://msdn.microsoft.com/en-us/library/windows/desktop/dd941711(v=vs.85).aspx]. As for character spacing, once you have the array of glyph advances back from the shaping process (IDWriteTextAnalyzer::GetGlyphs), just add a delta onto all the advances. In the linked SDK sample, you would add a for
loop inside FlowLayout::ShapeGlyphRuns
so that it happens before line wrapping and drawing.
STDMETHODIMP FlowLayout::ShapeGlyphRuns(IDWriteTextAnalyzer* textAnalyzer)
{
...
hr = ShapeGlyphRun(textAnalyzer, runIndex, glyphStart);
...
// Add additional character spacing to each trailing edge of each glyph.
for (auto& advance : glyphAdvances_)
{
advance += 5.0f;
}
...
}
Note an API ApplyCharacterSpacing
was also added to Windows 8 which is more robust than adding it manually yourself because it considers more complex scripts with multiple glyphs per cluster (but of course if you have that API, then you also already have IDWriteTextLayout::SetCharacterSpacing
).
Upvotes: 2