Reputation: 11
I am currently trying to implement the Bravada OTF Font from http://www.smufl.org/fonts/ in a Delphi music application. While I can easily render the private extended unicode characters to a TPaintBox using either TextOut or DrawTextW, it appears OpenType ligatures may not be handled within Delphi.
Specifically, certain unicode characters serve as modifiers ... per the README for Bravada:
"In Bravura Text, ligatures are used to adjust the vertical position of individual symbols. First, you enter the code point corresponding to the amount by which you want to change the vertical position, and then you enter the code point for the symbol itself. Provided the application you are using supports OpenType ligatures, you should see the symbol appear at the desired vertical position."
"So to position, say, a black notehead at the G4 staff position, you would first enter U+EB89 (lower by two staff positions) followed immediately by U+E0A4 (the black notehead)."
My rudimentary attempts like this:
Canvas.TextOut(10,10, #$EB89+#$E0A4);
Only reveal two characters, not moving E084 by the vertical offset desired. Knowing that clients are responsible for understanding the ligature rules and responding accordingly, are there any workable options available in Delphi for OTF features? I'd love to raw draw to the canvas but even if there is a more advanced canvas VCL out there... I'll take it.
Upvotes: 1
Views: 351
Reputation: 598434
VCL's TCanvas
class is a thin wrapper around Microsoft's GDI API. GDI by itself does not support what you are asking for. However, you can use Microsoft's DirectWrite API (part of DirectX), which does support OpenType and its advanced features.
DirectWrite takes advantage of the advances in OpenType Font technology to enable high quality typography within a Windows application...
...
The OpenType support provided by DirectWrite enables developers to add to their applications advanced typographic features and support for international text.
It is possible to have DirectWrite render to a GDI surface. It would first render to an in-memory bitmap HDC
, which you could then draw onto the TPaintBox
afterwards, by either:
wrapping the rendered HDC
in a temp TCanvas
object and then copying it to the TPaintBox.Canvas
using the TCanvas.CopyRect()
or TCanvas.Draw()
method.
copying it directly to the HDC
provided by TPaintBox.Canvas.Handle
using GDI's BitBlt()
or StretchBlt()
function.
Upvotes: 1