Graphics.DrawString (leading, tracking, kerning)

Hey guys,

Is there a way to adjust the Leading, Tracking and Kerning before drawing a string on a Graphics object?

In the Apple Developer Documentation, I’ve found something on the Core Text page. Somewhere in the Font Object section, it says about Font Metrics. Those are the parameters that control ascent, descent, leading, cap height, x-height, etc.

So, my guess is that the leading parameters could be set using Declares. Am I right?
But I have no experience in dealing with Declares. I have no clue where to get started :frowning:

Right now I do stuff like that in code: drawing every letter individually and positioning it according to how far I want to have the letters and lines being apart. That is not too efficient, right?
I would like to update my text drawing methods using declares, to help speed things up.

FYI: I make my app primarily for MacOS.

Some links:
Cocoa Text Architecture Guide
UIGraphicsGetCurrentContext()
StackOverflow: Setting line spacing in a CTFrame

  1. Drawing each character individually is going to be slow, yes.

  2. There is a graphic.characterSpacing property.

  3. Yes there are Font properties like you see and you can obtain them via declares.

  4. Core Text will give you a lot more control, however it’s a very kettle of fish and in order to render text using Core Text, you must do everything with declares.

I have done some work with CoreText (mainly so that I can draw rotated text), it might take me a while to get something that I can share with you (it’s in an older project).

If you have no experience with Declares, then perhaps the MBS plugin has the functions already coded?

I was kind of hoping that it would be as simple as setting drop shadow or text outline, using a couple of simple declares, that change those settings for a Graphics object.

That would be awesome :slight_smile:

I saw some something in MacOSLib. I still have to see what it does though. There is a module called “CoreText”.

Drop Shadow is quite easy.

#if targetMacOS then Declare Sub CGContextSetShadow lib "Cocoa" (CGContextInstance as integer, X as CGFloat, Y as CGFloat, blur as CGFloat) CGContextSetShadow( g.handle( graphics.handleTypeCGContextRef ), 0, -1, 3 ) #endif G.DrawString "Hello World", 20, 20

Put this is in the paint event of a canvas and voila. Please note that Apple think 0 is at the bottom of the canvas, screen, whereas Xojo think it’s at the top.

In my experience Outline, certainly requires the use of Core Text.

Changing the shadow color, requires a bit more work, but still fairly simple. One thing you MUST bear in mind when working with Apple’s APIs, is their naming convention. If the name contains “Create”, “Copy” or “Init”, you become responsible for manually releasing that object (and then it’s associated memory). In the example below we use “CGColorCreateGenericGRB” to create the CGColor object for the shadow color, so we have to release it.

[code]const shadowColor = &c00408000

#if targetMacOS then
Declare Function CGColorCreateGenericRGB lib “Cocoa” (red as CGFloat, green as CGFloat, blue as CGFloat, alpha as CGFloat) as integer
Declare Sub CGContextSetShadowWithColor lib “Cocoa” (CGContextInstance as integer, X as CGFloat, Y as CGFloat, blur as CGFloat, CGColorRef as integer)
Declare Sub CGColorRelease lib “Cocoa” (colorRef as integer)

Dim CGShadowColor as integer = CGColorCreateGenericRGB( shadowColor.red / 255, shadowColor.Green / 255, shadowColor.Blue / 255, 1.0 - ( shadowColor.alpha / 255 ) )
CGContextSetShadowWithColor( g.handle( graphics.handleTypeCGContextRef ), 0, -1, 3, CGShadowColor )
CGColorRelease CGShadowColor // — Because we used a CoreGraphics “Create” function, we must release it.
#endif
g.foreColor = &cFFFFFF00
G.DrawString “Hello World”, 20, 20[/code]

For simplicity, this code is self contained, but for optimum performance, you shouldn’t create the color in the paint event. You create it when you create your Xojo class instance, and ensure you release it when your class instance is no longer needed. If you change the color, you should release the old value first.

I know, hence the links to those exact methods. I didn’t know about setting the color beforehand (and releasing until instance goes bye bye) though.

Xojo spoils us with the way it handles objects, it’s very developer friendly. There’s a whole bunch of rules regarding memory management once you get outside of Xojo and it’s very easy to forget one.

Yeah, I hear ya. I wonder if that makes us lazy. On the other hand, we can focus more on the actual functionality of our apps. That’s what I like about Xojo.

I should dive more into MacOSLib’s Core Text modules, to see how it can help me with the spacings, as I requested in the OP.

@Sam Rowlands and @Edwin van den Akker : Did you currently found a was to get the leading, tracking and kerning using declares? If yes, how?

There is a character spacing option for the graphics class now.

For line spacing you’d have to draw each line yourself and calculate wrapping.

Thanks @Paul Levine for your message. I know and I’ve already included character spacing and line spacing in my project. What I am looking for is sheared and horizontal scaled text.