Merge pull request #10 from gunyarakun/fix-invalid-return
[cocotron.git] / AppKit / NSGraphics.m
blob176b0c174b63c15948f390efa47cc6f76d56102c
1 /* Copyright (c) 2006-2007 Christopher J. W. Lloyd <cjwl@objc.net>
3 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
9 #import <AppKit/NSGraphics.h>
10 #import <AppKit/NSGraphicsContextFunctions.h>
11 #import <AppKit/NSColor.h>
12 #import <AppKit/NSView.h>
13 #import <AppKit/NSRaise.h>
15 #import <AppKit/NSDisplay.h>
16 #import <ApplicationServices/ApplicationServices.h>
18 #import "NSPoofAnimation.h"
20 const float NSBlack=0;
21 const float NSDarkGray=0.333;
22 const float NSLightGray=0.667;
23 const float NSWhite=1.0;
25 NSString * const NSDeviceBlackColorSpace=@"NSDeviceBlackColorSpace";
26 NSString * const NSDeviceWhiteColorSpace=@"NSDeviceWhiteColorSpace";
27 NSString * const NSDeviceRGBColorSpace=@"NSDeviceRGBColorSpace";
28 NSString * const NSDeviceCMYKColorSpace=@"NSDeviceCMYKColorSpace";
29 NSString * const NSCalibratedBlackColorSpace=@"NSCalibratedBlackColorSpace";
30 NSString * const NSCalibratedWhiteColorSpace=@"NSCalibratedWhiteColorSpace";
31 NSString * const NSCalibratedRGBColorSpace=@"NSCalibratedRGBColorSpace";
32 NSString * const NSNamedColorSpace=@"NSNamedColorSpace";
33 NSString * const NSPatternColorSpace=@"NSPatternColorSpace";
35 NSString * const NSDeviceIsScreen=@"NSDeviceIsScreen";
36 NSString * const NSDeviceIsPrinter=@"NSDeviceIsPrinter";
37 NSString * const NSDeviceSize=@"NSDeviceSize";
38 NSString * const NSDeviceResolution=@"NSDeviceResolution";
39 NSString * const NSDeviceColorSpaceName=@"NSDeviceColorSpaceName";
40 NSString * const NSDeviceBitsPerSample=@"NSDeviceBitsPerSample";
42 static inline CGBlendMode blendModeForCompositeOp(NSCompositingOperation op){
43    static CGBlendMode table[]={
44     kCGBlendModeClear,
45     kCGBlendModeCopy,
46     kCGBlendModeNormal,
47     kCGBlendModeSourceIn,
48     kCGBlendModeSourceOut,
49     kCGBlendModeSourceAtop,
50     kCGBlendModeDestinationOver,
51     kCGBlendModeDestinationIn,
52     kCGBlendModeDestinationOut,
53     kCGBlendModeDestinationAtop,
54     kCGBlendModeXOR,
55     kCGBlendModePlusDarker,
56     kCGBlendModeNormal, // FIXME: highlight
57     kCGBlendModePlusLighter,
58    };
60    if(op<NSCompositeClear || op>NSCompositePlusLighter)
61     return NSCompositeCopy;
62    
63    return table[op];
66 void NSRectClipList(const NSRect *rects, int count) {
67    CGContextRef graphicsPort=NSCurrentGraphicsPort();
69    CGContextClipToRects(graphicsPort,rects,count);
72 void NSRectClip(NSRect rect) {
73    CGContextRef graphicsPort=NSCurrentGraphicsPort();
75    CGContextClipToRect(graphicsPort,rect);
79 void NSRectFillListWithColors(const NSRect *rects,NSColor **colors,int count) {
80    CGContextRef context=NSCurrentGraphicsPort();
81    int i;
83    CGContextSaveGState(context);
84    CGContextSetBlendMode(context,kCGBlendModeCopy);
85    for(i=0;i<count;i++){
86     [colors[i] setFill];
87 // FIXME: the groove/button rect generating code can generate negative size rects which draw incorrectly
88 // this either needs to be fixed in the drawing or the rect generation
89     if(rects[i].size.width>0 && rects[i].size.height>0)
90      NSRectFill(rects[i]);
91    }
92    CGContextRestoreGState(context);
95 void NSRectFillListWithGrays(const NSRect *rects,const float *grays,int count) {
96    CGContextRef context=NSCurrentGraphicsPort();
97    int        i;
99    CGContextSaveGState(context);
100    CGContextSetBlendMode(context,kCGBlendModeCopy);
101    for(i=0;i<count;i++){
102     CGContextSetGrayFillColor(context,grays[i],1.0);
103 // FIXME: the groove/button rect generating code can generate negative size rects which draw incorrectly
104 // this either needs to be fixed in the drawing or the rect generation
105     if(rects[i].size.width>0 && rects[i].size.height>0)
106      CGContextFillRect(context,rects[i]);
107    }
108    CGContextRestoreGState(context);
111 void NSRectFillList(const NSRect *rects, int count) {
112    CGContextRef context=NSCurrentGraphicsPort();
113    CGContextSaveGState(context);
114    CGContextSetBlendMode(context,kCGBlendModeCopy);
115    CGContextFillRects(NSCurrentGraphicsPort(),rects,count);
116    CGContextRestoreGState(context);
119 void NSRectFill(NSRect rect) {
120    CGContextRef context=NSCurrentGraphicsPort();
121    CGContextSaveGState(context);
122    CGContextSetBlendMode(context,kCGBlendModeCopy);
123    CGContextFillRect(NSCurrentGraphicsPort(),rect);
124    CGContextRestoreGState(context);
127 void NSEraseRect(NSRect rect) {
128    CGContextRef context=NSCurrentGraphicsPort();
129    CGContextSaveGState(context);
130    [[NSColor whiteColor] setFill];
131    CGContextSetBlendMode(context,kCGBlendModeCopy);
132    CGContextFillRect(NSCurrentGraphicsPort(),rect);
133    CGContextRestoreGState(context);
136 void NSRectFillListUsingOperation(const NSRect *rects,int count,NSCompositingOperation operation) {
137    CGContextRef context=NSCurrentGraphicsPort();
138    CGContextSaveGState(context);
139    CGContextSetBlendMode(context,blendModeForCompositeOp(operation));
140    CGContextFillRects(NSCurrentGraphicsPort(),rects,count);
141    CGContextRestoreGState(context);
144 void NSRectFillUsingOperation(NSRect rect,NSCompositingOperation op) {
145    NSRectFillListUsingOperation(&rect,1,op);
148 void NSFrameRectWithWidth(NSRect rect,CGFloat width) {
149    NSFrameRectWithWidthUsingOperation(rect,width,NSCompositeCopy);
152 void NSFrameRectWithWidthUsingOperation(NSRect rect,CGFloat width,NSCompositingOperation operation) {
153    CGContextRef context=NSCurrentGraphicsPort();
154    CGContextSaveGState(context);
155    CGContextSetBlendMode(context,blendModeForCompositeOp(operation));
156    CGRect edge[4];
157    // left
158    edge[0].origin.x=rect.origin.x;
159    edge[0].origin.y=rect.origin.y;
160    edge[0].size.width=width;
161    edge[0].size.height=rect.size.height;
162    // right
163    edge[1].origin.x=NSMaxX(rect)-width;
164    edge[1].origin.y=rect.origin.y;
165    edge[1].size.width=width;
166    edge[1].size.height=rect.size.height;
167    // bottom
168    edge[2].origin.x=rect.origin.x+width;
169    edge[2].origin.y=rect.origin.y;
170    edge[2].size.width=rect.size.width-width*2;
171    edge[2].size.height=width;
172    // top
173    edge[3].origin.x=rect.origin.x+width;
174    edge[3].origin.y=NSMaxY(rect)-width;
175    edge[3].size.width=rect.size.width-width*2;
176    edge[3].size.height=width;
177    
178    CGContextFillRects(NSCurrentGraphicsPort(),edge,4);
179    CGContextRestoreGState(context);
182 void NSFrameRect(NSRect rect) {
183    CGContextStrokeRectWithWidth(NSCurrentGraphicsPort(),rect,1);
186 void NSDottedFrameRect(NSRect rect) {
187    [[NSColor blackColor] setFill];
188 /* Win32 has poor dashed line support...
190     DrawFocusRect produces dark spots for the gaps sometimes 
191     If we use a brush, it becomes black&white, not black&transparent
192     The PS_DOT pen is not a single pixel dot.
194     Fortunately this is not used heavily...
195  */
196    if(rect.size.width<=0 || rect.size.height<=0)
197     return;
198    {
199     NSRect rects[(int)rect.size.width+2+(int)rect.size.height+2];
200     int    count=0;
201     int    x,y,maxx=NSMaxX(rect),maxy=NSMaxY(rect);
202     BOOL   on=NO;
204     for(x=rect.origin.x;x<maxx;x++,on=!on)
205      if(on)
206       rects[count++]=NSMakeRect(x,rect.origin.y,1,1);
208     for(y=rect.origin.y;y<maxy;y++,on=!on)
209      if(on)
210       rects[count++]=NSMakeRect(maxx-1,y,1,1);
212     for(x=maxx;--x>=rect.origin.x;on=!on)
213      if(on)
214       rects[count++]=NSMakeRect(x,maxy,1,1);
216     for(y=maxy;--y>=rect.origin.y;on=!on)
217      if(on)
218       rects[count++]=NSMakeRect(rect.origin.x,y,1,1);
220     CGContextFillRects(NSCurrentGraphicsPort(),rects,count);
221    }
225 static NSRect NSDrawColorRects(NSRect boundsRect,NSRect clipRect,const NSRect *sides,NSColor **colors,int count) {
226    CGContextRef graphicsPort=NSCurrentGraphicsPort();
228    CGContextSaveGState(graphicsPort);
229    CGContextClipToRect(graphicsPort,clipRect);
230    NSRectFillListWithColors(sides,colors,count);
231    CGContextRestoreGState(graphicsPort);
233    return boundsRect;
236 void NSDrawButton(NSRect rect,NSRect clipRect) {
237    NSRect   rects[7];
238    NSColor *colors[7];
239    int      i;
241    for(i=0;i<7;i++)
242     rects[i]=rect;
244    if([[NSGraphicsContext currentContext] isFlipped]){
245     colors[0]=[NSColor blackColor];
246     rects[0].origin.y+=rect.size.height-1;
247     rects[0].size.height=1;
249     colors[1]=[NSColor blackColor];
250     rects[1].origin.x+=rect.size.width-1;
251     rects[1].size.width=1;
253     colors[2]=[NSColor darkGrayColor];
254     rects[2].origin.x+=1;
255     rects[2].size.width-=2;
256     rects[2].origin.y+=rect.size.height-2;
257     rects[2].size.height=1;
259     colors[3]=[NSColor darkGrayColor];
260     rects[3].origin.x+=rect.size.width-2;
261     rects[3].origin.y+=1;
262     rects[3].size.width=1;
263     rects[3].size.height-=2;
265     colors[4]=[NSColor whiteColor];
266     rects[4].size.height=1;
267     rects[4].size.width-=1;
269     colors[5]=[NSColor whiteColor];
270     rects[5].size.width=1;
271     rects[5].size.height-=1;
273     colors[6]=[NSColor controlColor];
274     rects[6].origin.x+=1;
275     rects[6].origin.y+=1;
276     rects[6].size.width-=3;
277     rects[6].size.height-=3;
278    }
279    else {
280     colors[0]=[NSColor blackColor];
281     rects[0].size.height=1;
283     colors[1]=[NSColor blackColor];
284     rects[1].origin.x+=rect.size.width-1;
285     rects[1].size.width=1;
287     colors[2]=[NSColor darkGrayColor];
288     rects[2].origin.x+=1;
289     rects[2].origin.y+=1;
290     rects[2].size.width-=2;
291     rects[2].size.height=1;
293     colors[3]=[NSColor darkGrayColor];
294     rects[3].origin.x+=rect.size.width-2;
295     rects[3].origin.y+=2;
296     rects[3].size.width=1;
297     rects[3].size.height-=2;
299     colors[4]=[NSColor whiteColor];
300     rects[4].origin.y+=1;
301     rects[4].size.width=1;
302     rects[4].size.height-=1;
304     colors[5]=[NSColor whiteColor];
305     rects[5].origin.y+=rect.size.height-1;
306     rects[5].size.width-=1;
307     rects[5].size.height=1;
309     colors[6]=[NSColor controlColor];
310     rects[6].origin.x+=1;
311     rects[6].origin.y+=2;
312     rects[6].size.width-=3;
313     rects[6].size.height-=3;
314    }
316    NSDrawColorRects(rect,clipRect,rects,colors,7);
319 void NSDrawGrayBezel(NSRect rect, NSRect clipRect) {
320     NSRect rects[4];
321     NSColor *colors[4];
322     int i;
324     for(i=0; i<4; i++)
325         rects[i]=rect;
327     if ([[NSGraphicsContext currentContext] isFlipped]) {
328         colors[0]=[NSColor whiteColor];
329         colors[1]=[NSColor controlShadowColor];
330         rects[1].size.width-=1;
331         rects[1].size.height-=1;
332         colors[2]=[NSColor blackColor];
333         rects[2].origin.x+=1;
334         rects[2].origin.y+=1;
335         rects[2].size.width-=3;
336         rects[2].size.height-=3;
337         colors[3]=[NSColor controlColor];
338         rects[3].origin.x+=2;
339         rects[3].origin.y+=2;
340         rects[3].size.width-=3;
341         rects[3].size.height-=3;
342     }
343     else {
344         colors[0]=[NSColor whiteColor];
345         colors[1]=[NSColor controlShadowColor];
346         rects[1].origin.y+=1;
347         rects[1].size.width-=1;
348         rects[1].size.height-=1;
349         colors[2]=[NSColor blackColor];
350         rects[2].origin.x+=1;
351         rects[2].origin.y+=2;
352         rects[2].size.width-=3;
353         rects[2].size.height-=3;
354         colors[3]=[NSColor controlColor];
355         rects[3].origin.x+=2;
356         rects[3].origin.y+=1;
357         rects[3].size.width-=3;
358         rects[3].size.height-=3;
359     }
361    NSDrawColorRects(rect,clipRect,rects,colors,4);
365 void NSDrawWhiteBezel(NSRect rect, NSRect clipRect) {
366     NSRect rects[7];
367     NSColor *colors[7];
368     int i;
370     for(i=0; i<7; i++)
371         rects[i]=rect;
373     if ([[NSGraphicsContext currentContext] isFlipped]) {
374         colors[0]=[NSColor whiteColor];
375         colors[1]=[NSColor controlShadowColor];
376         rects[1].size.height=1;
377         colors[2]=[NSColor controlShadowColor];
378         rects[2].size.width=1;
379         rects[2].size.height-=1;
380         colors[3]=[NSColor controlColor];
381         rects[3].origin.x+=1;
382         rects[3].origin.y+=1;
383         rects[3].size.width-=2;
384         rects[3].size.height-=2;
385         colors[4]=[NSColor blackColor];
386         rects[4].origin.x+=1;
387         rects[4].origin.y+=1;
388         rects[4].size.width-=2;
389         rects[4].size.height=1;
390         colors[5]=[NSColor blackColor];
391         rects[5].origin.x+=1;
392         rects[5].origin.y+=1;
393         rects[5].size.width=1;
394         rects[5].size.height-=3;
395         colors[6]=[NSColor whiteColor];
396         rects[6].origin.x+=2;
397         rects[6].origin.y+=2;
398         rects[6].size.width-=4;
399         rects[6].size.height-=4;
400     }
401     else {
402         colors[0]=[NSColor whiteColor];
403         colors[1]=[NSColor controlShadowColor];
404         rects[1].origin.y+=rect.size.height;
405         rects[1].size.height=1;
406         colors[2]=[NSColor controlShadowColor];
407         rects[2].size.width=1;
408         rects[2].origin.y+=1;
409         rects[2].size.height-=1;
410         colors[3]=[NSColor controlColor];
411         rects[3].origin.x+=1;
412         rects[3].origin.y+=1;
413         rects[3].size.width-=2;
414         rects[3].size.height-=2;
415         colors[4]=[NSColor blackColor];
416         rects[4].origin.x+=1;
417         rects[4].origin.y+=rect.size.height-1;
418         rects[4].size.width-=2;
419         rects[4].size.height=1;
420         colors[5]=[NSColor blackColor];
421         rects[5].origin.x+=1;
422         rects[5].origin.y+=2;
423         rects[5].size.width=1;
424         rects[5].size.height-=3;
425         colors[6]=[NSColor whiteColor];
426         rects[6].origin.x+=2;
427         rects[6].origin.y+=2;
428         rects[6].size.width-=4;
429         rects[6].size.height-=3;
430     }
432    NSDrawColorRects(rect,clipRect,rects,colors,7);
435 void NSDrawDarkBezel(NSRect rect,NSRect clipRect){
436    NSDrawGrayBezel(rect,clipRect);
439 void NSDrawLightBezel(NSRect rect,NSRect clipRect){
440    NSDrawWhiteBezel(rect,clipRect);
443 void NSDrawGroove(NSRect rect, NSRect clipRect) {
444     NSRect rects[4];
445     NSColor *colors[4];
446     int i;
448     for(i=0; i<4; i++)
449         rects[i]=rect;
451     if ([[NSGraphicsContext currentContext] isFlipped]) {
452         colors[0]=[NSColor controlShadowColor];
453         colors[1]=[NSColor whiteColor];
454         rects[1].origin.x+=1;
455         rects[1].origin.y+=1;
456         colors[2]=[NSColor controlShadowColor];
457         rects[2].origin.x+=2;
458         rects[2].origin.y+=2;
459         rects[2].size.width-=3;
460         rects[2].size.height-=3;
461         colors[3]=[NSColor controlColor];
462         rects[3].origin.x+=2;
463         rects[3].origin.y+=2;
464         rects[3].size.width-=4;
465         rects[3].size.height-=4;
466     }
467     else {
468         colors[0]=[NSColor controlShadowColor];
469         colors[1]=[NSColor whiteColor];
470         rects[1].origin.x+=1;
471         rects[1].size.height-=1;
472         colors[2]=[NSColor controlShadowColor];
473         rects[2].origin.x+=2;
474         rects[2].origin.y+=1;
475         rects[2].size.width-=3;
476         rects[2].size.height-=3;
477         colors[3]=[NSColor controlColor];
478         rects[3].origin.x+=2;
479         rects[3].origin.y+=2;
480         rects[3].size.width-=4;
481         rects[3].size.height-=4;
482     }
484    NSDrawColorRects(rect,clipRect,rects,colors,4);
487 void NSDrawWindowBackground(NSRect rect) {
488    [[NSColor windowBackgroundColor] setFill];
489    NSRectFill(rect);
492 NSRect NSDrawTiledRects(NSRect bounds,NSRect clip,const NSRectEdge *sides,const float *grays,int count) {
493    return bounds;
496 void NSHighlightRect(NSRect rect) {
497    [[NSColor highlightColor] setFill];
498    CGContextFillRect(NSCurrentGraphicsPort(),rect);
501 void NSCopyBits(int gState,NSRect rect,NSPoint point) {
502    CGContextCopyBits(NSCurrentGraphicsPort(),rect,point,gState);
505 void NSBeep() {
506    [[NSDisplay currentDisplay] beep];
509 void NSEnableScreenUpdates(void) {
512 void NSDisableScreenUpdates(void) {
515 void NSShowAnimationEffect(NSAnimationEffect effect,NSPoint center,NSSize size,id delegate,SEL didEndSelector,void *context) {
516     [NSPoofAnimation poofAtLocation:center size:size animationDelegate:delegate didEndSelector:didEndSelector contextInfo:context];