NSBezierPath append CGGlyph

  • I'm doing some work with Quartz and have a buffer of CGGlyphs. I am
    trying to append them to an NSBezierPath but I cannot find an
    appropriate method.

    I tried simply casting them to (NSGlyph *) which obviously didn't
    work. Any suggestions?

    - Keith
  • On Sep 1, 2007, at 8:59 AM, Keith Duncan wrote:

    > I'm doing some work with Quartz and have a buffer of CGGlyphs. I am
    > trying to append them to an NSBezierPath but I cannot find an
    > appropriate method.
    >
    > I tried simply casting them to (NSGlyph *) which obviously didn't
    > work. Any suggestions?

    NSGlyph is not an object, it's an int.  Try casting them to a NSGlyph
    (no asterisk)
  • > NSGlyph is not an object, it's an int.  Try casting them to a
    > NSGlyph (no asterisk)

    Actually NSGlyph is an unsigned integer, whereas CGGlyph is an
    unsigned short. However I have a buffer (C style array) of CGGlyphs.

    The method I was using was -[NSBezierPath's
    appendBezierPathWithGlyphs:count:inFont:] which expects a buffer of
    NSGlyphs. So you see my cast was correct it just seems that there is
    an index mismatch between CGGlyph and NSGlyph such that they aren't
    interchangeable.

    - Keith
  • On Sep 1, 2007, at 10:49 AM, Keith Duncan wrote:

    >> NSGlyph is not an object, it's an int.  Try casting them to a
    >> NSGlyph (no asterisk)
    >
    > Actually NSGlyph is an unsigned integer, whereas CGGlyph is an
    > unsigned short. However I have a buffer (C style array) of CGGlyphs.
    >
    > The method I was using was -[NSBezierPath's
    > appendBezierPathWithGlyphs:count:inFont:] which expects a buffer of
    > NSGlyphs. So you see my cast was correct it just seems that there is
    > an index mismatch between CGGlyph and NSGlyph such that they aren't
    > interchangeable.

    Ah.. I see.  I believe that NSGlyph and CGGlyph should store the same
    value, but your problem is that they store them in differently sized
    chunks so that when you create arrays of the chunks, they don't line
    up properly.

    Both NSGlyph and CGGlyph simply represent the glyph index of a
    particular graphic in the font.  The most direct solution to your
    problem would be to simply allocate a local array large enough to hold
    NSGlyph values and then simply trans-coding the array of glyph IDs
    from CGGlyph to NSGlyph so that you get the properly sized array.

    Unfortunately, the other way to go from a CGGlyph to a path would be
    to use Core Text and CTFontCreatePathForGlyph which does not exist in
    Tiger.  Still, in that case, you'd have to use something like
    CGPathApply or a similar mechanism to get an NSBezierPath that you
    could append to other NSBezierPaths.

    Scott
  • On Sep 1, 2007, at 8:49 AM, Keith Duncan wrote:

    >> NSGlyph is not an object, it's an int.  Try casting them to a
    >> NSGlyph (no asterisk)
    >
    > Actually NSGlyph is an unsigned integer, whereas CGGlyph is an
    > unsigned short. However I have a buffer (C style array) of CGGlyphs.
    >
    > The method I was using was -[NSBezierPath's
    > appendBezierPathWithGlyphs:count:inFont:] which expects a buffer of
    > NSGlyphs. So you see my cast was correct it just seems that there
    > is an index mismatch between CGGlyph and NSGlyph such that they
    > aren't interchangeable.

    Actually your cast doesn't help and is in fact wrong since it
    prevents the compiler from seeing your error.

    If you have an C array of CGGlyphs then each array slot is 2 bytes
    wide and casting wont change how the memory is allocated or
    populated. The appendBezierPathWithGlyphs:count:inFont: method
    expects a C array of NSGlyphs (4 byte slots).

    So if you stated you have 10 glyphs then it is expecting an array 40
    bytes long but you are only giving it one that is 20 bytes long.
    Additionally each time it reads a glyph it was actually reading two
    CGGlyphs which is obviously not what you want.

    Anyway consider using appendBezierPathWithPackedGlyphs: with a NULL
    terminated CGGlyphs array (not ideal...).

    -Shawn
  • > Actually your cast doesn't help and is in fact wrong since it
    > prevents the compiler from seeing your error.

    I appreciate this, it was simply a stab in the dark since I remember
    reading somewhere (in Apple docs) that they are interchangeable. It
    should infact read that the value is interchangeable NOT the type.

    I'll file a bug when I find the page.

    > If you have an C array of CGGlyphs then each array slot is 2 bytes
    > wide and casting wont change how the memory is allocated or
    > populated. The appendBezierPathWithGlyphs:count:inFont: method
    > expects a C array of NSGlyphs (4 byte slots).

    This explains the behavior I'm getting, the bezier path only contains
    every second glyph!

    - Keith
  • Rather than attempting to transcode the entire array into a local
    NSGlyph array which would require iteration anyway I decided to
    iterate over the array and append the glyphs on a per index basis
    using -[NSBezierPath appendGlyph:inFont:] which is working fine. OK so
    it's a message send per loop iteration but it's still pretty speedy.

    Getting the raw CGGlyphs myself and appending them, rather than
    getting NSGlyphs from an NSLayoutManager object is speedier and has
    provided the speed up I was looking for. Since this is a category
    method I don't actually have a text storage or layout manager object
    and was having to allocate them both everytime the method ran.

    - Keith
  • On 1 Sep 2007, at 20:26, Keith Duncan wrote:

    > Getting the raw CGGlyphs myself and appending them, rather than
    > getting NSGlyphs from an NSLayoutManager object is speedier and has
    > provided the speed up I was looking for. Since this is a category
    > method I don't actually have a text storage or layout manager
    > object and was having to allocate them both everytime the method ran.

    Though by doing this, you might be losing a lot of typographic
    support that you get for free with NSLayoutManager.  Of course, it
    depends on how you're getting the raw glyphs in the first place.

    You can always allocate and set up the text system ahead of time,
    then use that one copy to generate the glyphs you need (i.e. you
    don't need to do it on every method call).

    Kind regards,

    Alastair.

    --
    http://alastairs-place.net
  • On Sep 1, 2007, at 11:37 AM, Keith Duncan wrote:

    > I appreciate this, it was simply a stab in the dark since I
    > remember reading somewhere (in Apple docs) that they are
    > interchangeable. It should infact read that the value is
    > interchangeable NOT the type.

    For valid glyphs in the font, NSGlyph and CGGlyph do use the same
    numerical values.  NSGlyph also has some special defined values
    (NSControlGlyph and NSNullGlyph) with particular meanings for the
    Cocoa text system:  NSControlGlyph is used in the glyph stream to
    represent control characters and attachments that end up not being
    represented by visible glyphs, and NSNullGlyph is used as padding in
    the glyph stream in cases where that is useful and desirable to keep
    the numerical indexes for glyphs and characters in line.  These
    values are not likely to be understood in the same way outside of the
    Cocoa text system, so they should not be carried over to CGGlyphs.

    Douglas Davidson
previous month september 2007 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
Go to today