Graphics.DrawString (leading, tracking, kerning)

  1. 2 years ago

    Edwin v

    20 Oct 2017 Pre-Release Testers The Netherlands
    Edited 2 years ago

    Hey guys,

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

    Leading is the space between lines of text. Tracking & Kerning control the letter spacing

    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 :(

    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

  2. Sam R

    20 Oct 2017 Pre-Release Testers, Xojo Pro, Third Party Store Hengchun, Pingtung, Taiwan

    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.

    3. 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?

  3. Edwin v

    20 Oct 2017 Pre-Release Testers The Netherlands
    Edited 2 years ago

    @Sam R 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 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.

    @Sam Rowlands it might take me a while to get something that I can share with you (it's in an older project).

    That would be awesome :)

  4. Edwin v

    20 Oct 2017 Pre-Release Testers The Netherlands

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

  5. Sam R

    20 Oct 2017 Pre-Release Testers, Xojo Pro, Third Party Store Hengchun, Pingtung, Taiwan

    @Edwin vden ;Akker 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.

    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.

    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

    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.

  6. Edwin v

    22 Oct 2017 Pre-Release Testers The Netherlands
    Edited 2 years ago

    @Sam R Drop Shadow is quite easy.

    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.

  7. Sam R

    22 Oct 2017 Pre-Release Testers, Xojo Pro, Third Party Store Hengchun, Pingtung, Taiwan

    @Edwin vden ;Akker 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.

  8. Edwin v

    23 Oct 2017 Pre-Release Testers The Netherlands
    Edited 2 years ago

    @Sam R Xojo spoils us with the way it handles objects, it's very developer friendly.

    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.

  9. 6 weeks ago

    Martin T

    Aug 8 Pre-Release Testers Germany

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

  10. Paul L

    Aug 8 Pre-Release Testers Toronto

    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.

  11. Martin T

    Aug 8 Pre-Release Testers Germany
    Edited 6 weeks ago

    Thanks @Paul L 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.

or Sign Up to reply!