Sub-pixel font smoothing with CGBitmapContext

  • Hi all,

    When I render text into a CGBitmapContext that has been filled with a
    solid color, sub-pixel font smoothing is not applied and text looks
    suboptimal compared to text rendered elsewhere. How can I enable font
    smoothing? Calling CGContextSetShouldSmoothFonts doesn't seem to help.

    Slava
  • On Jan 28, 2009, at 5:15 PM, Slava Pestov wrote:

    > Hi all,
    >
    > When I render text into a CGBitmapContext that has been filled with a
    > solid color, sub-pixel font smoothing is not applied and text looks
    > suboptimal compared to text rendered elsewhere. How can I enable font
    > smoothing? Calling CGContextSetShouldSmoothFonts doesn't seem to help.

      Are you talking about the red/blue edge antialiasing (based on
    pixels having RGB pixels not collocated on the device)?

      I've also tried to get this working (so I can build an CGImageRef
    with embedded text for pixel-accurate blitting to the device via a
    CALayer).  Sadly, I've not been able to figure out a way to tell the
    CGBitmapContext that I intend it to act like it is a particular
    device.  If you find a way, I'd love to try it too =)

    -tim
  • On Jan 28, 2009, at 5:15 PM, Slava Pestov wrote:

    > When I render text into a CGBitmapContext that has been filled with a
    > solid color, sub-pixel font smoothing is not applied and text looks
    > suboptimal compared to text rendered elsewhere. How can I enable font
    > smoothing? Calling CGContextSetShouldSmoothFonts doesn't seem to help.

    Its been a while since I last looked at this, but I think the
    context's format needs to be native endian (add the
    kCGBitmapByteOrder32Host flag).
    --
    David Duncan
    Apple DTS Animation and Printing
  • On Jan 29, 2009, at 10:56 AM, David Duncan wrote:
    > Its been a while since I last looked at this, but I think the
    > context's format needs to be native endian (add the
    > kCGBitmapByteOrder32Host flag).

      Heh; I totally would not have expected that from the name or docs.
    But, adding a case like this in my text rendering testing harness
    shows that it works.  It renders into the CGBitmapContextRef such that
    when I get my CALayer's contents to the resulting CGImageRef, it has
    the proper device-specific antialiasing.  I don't see this mentioned
    anywhere in the docs, but maybe I missed it.

      Here is my test case <http://people.omnigroup.com/bungi/TextDrawing-20090129.zip>

      Thanks!

    -tim
  • On Jan 29, 2009, at 12:34 PM, Timothy Wood wrote:

    >
    > On Jan 29, 2009, at 10:56 AM, David Duncan wrote:
    >> Its been a while since I last looked at this, but I think the
    >> context's format needs to be native endian (add the
    >> kCGBitmapByteOrder32Host flag).
    >
    > Heh; I totally would not have expected that from the name or docs.
    > But, adding a case like this in my text rendering testing harness
    > shows that it works.  It renders into the CGBitmapContextRef such
    > that when I get my CALayer's contents to the resulting CGImageRef,
    > it has the proper device-specific antialiasing.  I don't see this
    > mentioned anywhere in the docs, but maybe I missed it.

    Yea, its not documented, and its probably more of a quirk of the font
    rendering than anything else. It works today, and primarily I offer
    the solution because if it stops working in the future, the worst that
    will happen is you will get text that doesn't use sub-pixel
    antialiasing.

    If you want true control over this, then I would recommend you both
    file a feature enhancement.
    --
    David Duncan
    Apple DTS Animation and Printing
  • On Jan 29, 2009, at 12:41 PM, David Duncan wrote:
    > Yea, its not documented, and its probably more of a quirk of the
    > font rendering than anything else. It works today, and primarily I
    > offer the solution because if it stops working in the future, the
    > worst that will happen is you will get text that doesn't use sub-
    > pixel antialiasing.
    >
    > If you want true control over this, then I would recommend you both
    > file a feature enhancement.

      Hm; if it stops working, then we'd definitely see quirks.  We draw
    text with a raw NSLayoutManager setup in some cases and then overlay a
    NSTextView atop it when editing -- the transition between the two
    antialiasing modes would be pretty obvious.  I'll write up a feature
    request.  Thanks again!

    -tim
  • On Thu, Jan 29, 2009 at 12:56 PM, David Duncan <david.duncan...> wrote:
    > Its been a while since I last looked at this, but I think the context's
    > format needs to be native endian (add the kCGBitmapByteOrder32Host flag).

    Thanks for the tip! I also noticed that I have to use
    kCGImageAlphaPremultipliedFirst instead of
    kCGImageAlphaPremultipliedLast.

    So, just to summarize for the other people following this discussion,
    it seem there are two things that have to be in place for sub-pixel
    font smoothing to work in a CGBitmapContext:

    - You need to create the context with (kCGImageAlphaPremultipliedFirst
    | kCGBitmapByteOrder32Host).
    - Also you must fill the context with a non-transparent background so
    that the sub-pixel blending can take place.

    Also, I discovered the GL_BGRA_ext extension can be used to turn such
    a bitmap into an OpenGL texture.

    Slava
previous month january 2009 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
Go to today