NSImage inside(?) NSBezierPath

  • Hello,
    I've tried to make a simple custom NSView object as like event view in
    iPhoto 2008. I've created the rounded rectangle with the method listed
    above and tried to apply in it an NSImage.
    Unfortunatly the NSImage does not fill correctly because my NSView
    contains rounded angles while the image is a rectangle. Is there a way
    to put this image *inside* the closed path? Or is there another way to
    remove the borders of the image (it should be more diffucult I think).

    I would also add a shadow so I've used the code listed in ADC Ref Lib
    but it does not work because the shadow itself is inside my path and
    not outside it; is it normal?

    This is the creation code of the view (here the result with the
    problem: http://img178.imageshack.us/img178/2625/immagine2um5.png):

    - (void)drawRect:(NSRect)rect {
    [NSGraphicsContext saveGraphicsState];
    NSBezierPath * path = [self bezierPathWithRoundRectInRect:rect];
    [path stroke];
    [NSGraphicsContext restoreGraphicsState];
    }

    - (NSBezierPath *)bezierPathWithRoundRectInRect:(NSRect)aRect {


    NSBezierPath * path = [NSBezierPath bezierPath];
    [NSBezierPath setDefaultLineCapStyle: NSButtLineCapStyle];
    [NSBezierPath setDefaultLineWidth: 1];

    NSPoint topMid = NSMakePoint(NSMidX(aRect)+space, NSMaxY(aRect)-space);
    NSPoint topLeft = NSMakePoint(NSMinX(aRect)+space, NSMaxY(aRect)-space);
    NSPoint topRight = NSMakePoint(NSMaxX(aRect)-space, NSMaxY(aRect)-space);
    NSPoint bottomRight = NSMakePoint(NSMaxX(aRect)-space, NSMinY(aRect)+space);
    NSPoint originPoint = aRect.origin;
    originPoint.x+=space;
    originPoint.y+=space;

    [path moveToPoint:topMid];
    [path appendBezierPathWithArcFromPoint:topLeft toPoint:aRect.origin
    radius:radius];
    [path appendBezierPathWithArcFromPoint:originPoint
    toPoint:bottomRight radius:radius];
    [path appendBezierPathWithArcFromPoint:bottomRight toPoint:topRight
    radius:radius];
    [path appendBezierPathWithArcFromPoint:topRight toPoint:topLeft radius:radius];
    [path closePath];

    [[NSColor redColor] set];

    NSImage *im = [NSImage imageNamed:@"big"];
    [im drawInRect: [path controlPointBounds] fromRect: [path
    controlPointBounds] operation:NSCompositeSourceOver fraction:1];

    return (path);
    }
  • You need to alter the current graphics context's clipping path and
    then draw the image.

    Call -addClip on your round edged rectangle bezier path then draw the
    image.

    - Keith
  • Hell's Kitchen wrote:

    > Hello,
    > I've tried to make a simple custom NSView object as like event view in
    > iPhoto 2008. I've created the rounded rectangle with the method listed
    > above and tried to apply in it an NSImage.
    > Unfortunatly the NSImage does not fill correctly because my NSView
    > contains rounded angles while the image is a rectangle. Is there a way
    > to put this image *inside* the closed path? Or is there another way to
    > remove the borders of the image (it should be more diffucult I think).

    Just to clarify: You're looking for a way to clip the NSImage with
    the path?

    <http://developer.apple.com/documentation/Cocoa/Conceptual/
    CocoaDrawingGuide/GraphicsContexts/chapter_3_section_3.html#//
    apple_ref/doc/uid/TP40003290-CH203-BCIIADBC
    >

    > This is the creation code of the view (here the result with the
    > problem: http://img178.imageshack.us/img178/2625/immagine2um5.png):
    >
    > - (void)drawRect:(NSRect)rect {
    > [NSGraphicsContext saveGraphicsState];
    > NSBezierPath * path = [self bezierPathWithRoundRectInRect:rect];

    This is a problem. There's no guarantee that the rect argument
    represents the whole view.

    > [path stroke];
    > [NSGraphicsContext restoreGraphicsState];
    > }
    >
    > - (NSBezierPath *)bezierPathWithRoundRectInRect:(NSRect)aRect {
    > ...
    > NSImage *im = [NSImage imageNamed:@"big"];
    > [im drawInRect: [path controlPointBounds] fromRect: [path
    > controlPointBounds] operation:NSCompositeSourceOver fraction:1];

    I also think it's weird that a method that appears to be an
    NSBezierPath factory happens to draw in the current context as a side-
    effect. I'd make this purely a factory (and a category on
    NSBezierPath) and use the resulting path as a clipping path from
    within the view's drawRect:.
  • Hey,

    To aid in clarity I will code what has been suggested.

    - (void)drawRect:(NSRect)rect
    {
          NSRect bounds = [self bounds];
          NSBezierPath *path = [self bezierPathWithRoundRectInRect: bounds];

          [NSGraphicsContext saveGraphicsState];

          [[NSColor redColor] set];
          [path stroke];

          [path addClip];

          [image drawInRect: bounds fromRect: NSZeroRect fraction: 1.0
    operation: NSCompositeSourceOver];

          [NSGraphicsContext restoreGraphicsState];
    }

    I am writing all this from memory, it has been a while since I've
    needed to draw an image so the order of the draw parameters may not be
    correct. Passing NSZeroRect as the "fromRect" argument tells NSImage
    that you want to draw the whole image, this prevents you from call -
    [NSImage size] and making your own rect that is the same size as the
    image.

    Peace, Alan

    --
    My blog: cocoalatte.info

    // Things I've said -------------------------
    "Maturity resides in the mind."
    "Silence is the Universe's greatest gift."
    "When the World realizes that personal beliefs are not something to
    argue or fight over, it shall evolve."
  • On 13.09.2007, at 23:59, Alan Smith wrote:
    > Passing NSZeroRect as the "fromRect" argument tells NSImage
    > that you want to draw the whole image, this prevents you from call -
    > [NSImage size] and making your own rect that is the same size as the
    > image.

      Ooooo... neat! I never saw this in the docs. That'll save me a lot
    of annoying typing in the future :-)

    Cheers,
    -- M. Uli Kusterer
    http://www.zathras.de
  • On 9/14/07, Uli Kusterer <witness.of.teachtext...> wrote:
    > On 13.09.2007, at 23:59, Alan Smith wrote:
    >> Passing NSZeroRect as the "fromRect" argument tells NSImage
    >> that you want to draw the whole image, this prevents you from call -
    >> [NSImage size] and making your own rect that is the same size as the
    >> image.
    >
    > Ooooo... neat! I never saw this in the docs. That'll save me a lot
    > of annoying typing in the future :-)

      Ditto! Perhaps a quick note in the documentation feedback might see
    this added ...

    --
    I.S.
  • On Sep 14, 2007, at 2:26 PM, I. Savant wrote:

    > On 9/14/07, Uli Kusterer <witness.of.teachtext...> wrote:
    >> On 13.09.2007, at 23:59, Alan Smith wrote:
    >>> Passing NSZeroRect as the "fromRect" argument tells NSImage
    >>> that you want to draw the whole image, this prevents you from call -
    >>> [NSImage size] and making your own rect that is the same size as the
    >>> image.
    >>
    >> Ooooo... neat! I never saw this in the docs. That'll save me a lot
    >> of annoying typing in the future :-)
    >
    > Ditto! Perhaps a quick note in the documentation feedback might see
    > this added ...

    The NSImage Class Reference was updated in 2006 to mention this
    NSZeroRect tip.

    Xcode's API ref on drawInRect:fromRect:operation:fraction also
    mentions it.  Curiously though, this same named API in CIImage,
    doesn't mention the tip.  I would assume though that passing
    NSZeroRect would do the right thing.

    ___________________________________________________________
    Ricky A. Sharp        mailto:<rsharp...>
    Instant Interactive(tm)  http://www.instantinteractive.com
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