[NSColor clearColor] and NSBezierPath: not compatible?

  • A look in the archives did not bring back any good answer.

    It looks like NSBezierPath fill method does not work with the
    clearColor.

    Filling with another color works fine.

    Is this a bug, a limitation or is there a workaround?

    From what I can see in the documentation, this limitation is not
    documented. (Mac OS X 10.3.9)
  • On 17 août 05, at 17:00, <gandreas...> wrote:

    >
    > On Aug 17, 2005, at 9:52 AM, Stephane Sudre wrote:
    >
    >> A look in the archives did not bring back any good answer.
    >>
    >> It looks like NSBezierPath fill method does not work with the
    >> clearColor.
    >>
    >> Filling with another color works fine.
    >
    > Well, [NSBezierPath fillRect: rect] works fine with clearColor, which
    > is suppose to be equivalent to [[NSBezierPath bezierPathWithRect:
    > rect] fill]
    >
    > So how are you determining that filling with the clearColor doesn't
    > work?

    I have a rounded rectangle build with a NSBezierPath.

    When I fill it with the clearColor, no drawing operation is performed,
    the drawings behind the rounded rectangle are still there.

    When I fill it with the [NSColor redColor], a red rounded rectangle is
    drawn.

    IMHO, the [NSBezierPath bezierPathWithRect: rect] is probably using an
    optimized path to fill the rectangle and somehow falls back to the
    NSRect drawing methods.
  • On Aug 17, 2005, at 9:52 AM, Stephane Sudre wrote:

    > A look in the archives did not bring back any good answer.
    >
    > It looks like NSBezierPath fill method does not work with the
    > clearColor.
    >
    > Filling with another color works fine.
    >

    Well, [NSBezierPath fillRect: rect] works fine with clearColor, which
    is suppose to be equivalent to [[NSBezierPath bezierPathWithRect:
    rect] fill]

    So how are you determining that filling with the clearColor doesn't
    work?

    Glenn Andreas                      <gandreas...>
      <http://www.gandreas.com/> wicked fun!
    Widgetarium | the quickest path to widgets
  • NSBezierPath uses the NSCompositeSourceOver operation, therefore
    clearColor does not do anything. You could change the graphics state
    in order to clear the path:

        NSGraphicsContext *context;
        context = [NSGraphicsContext currentContext];
        [context saveGraphicsState];
        [context setCompositingOperation:NSCompositeClear];
        [yourBezierPath fill];
        [context restoreGraphicsState];

    Hope this helps.

    Stefan

    On 17.08.2005, at 16:52, Stephane Sudre wrote:

    > A look in the archives did not bring back any good answer.
    >
    > It looks like NSBezierPath fill method does not work with the
    > clearColor.
    >
    > Filling with another color works fine.
    >
    > Is this a bug, a limitation or is there a workaround?
    >
    > From what I can see in the documentation, this limitation is not
    > documented. (Mac OS X 10.3.9)
  • On Aug 17, 2005, at 8:10 AM, Stephane Sudre wrote:
    > When I fill it with the clearColor, no drawing operation is
    > performed, the drawings behind the rounded rectangle are still there.

      This seems correct if you you filled with clear in s-over mode.
    You probably want copy mode instead of s-over.

      I'll certainly admit that it seems strange if +fillRect: and -fill
    use different compositing modes, but I don't see anything in the
    documentation about equivalence of [NSBezierPath fillRect: rect] and
    [[NSBezierPath bezierPathWithRect: rect] fill.

      I typically use the CG primitives for this; you might be able to
    set the compositing mode that NSBezierPath uses with -
    [NSGraphicsContext setCompositingOperation:] (10.4 API).

    -tim
  • On 17 août 05, at 17:18, Stefan Schüßler wrote:

    > NSBezierPath uses the NSCompositeSourceOver operation, therefore
    > clearColor does not do anything. You could change the graphics state
    > in order to clear the path:
    >
    > NSGraphicsContext *context;
    > context = [NSGraphicsContext currentContext];
    > [context saveGraphicsState];
    > [context setCompositingOperation:NSCompositeClear];
    > [yourBezierPath fill];
    > [context restoreGraphicsState];

    Thanks for the explanation.

    Sadly the setCompositingOperation: is only available on 10.4 and later.
    I will look for its sibling in CoreGraphic as suggested by Timothy.
  • On Aug 17, 2005, at 17:37:40, Stephane Sudre wrote:
    > On 17 août 05, at 17:18, Stefan Schüßler wrote:
    >
    > Thanks for the explanation.
    >
    > Sadly the setCompositingOperation: is only available on 10.4 and
    > later. I will look for its sibling in CoreGraphic as suggested by
    > Timothy.

      You could also set your path as the clip rect and then use
    NSRectFill() or whatever to force the area transparent. Clipping will
    take care of cutting off the corners.

    Cheers,
    -- M. Uli Kusterer
    http://www.zathras.de