2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #import <Cocoa/Cocoa.h>
26 #import "DrawBackground.h"
28 DrawBackground
::DrawBackground()
32 void DrawBackground
::draw(CGContextRef cgc
, CGRect inRect
)
34 CGContextSaveGState(cgc
);
35 drawSelf(cgc
, inRect
);
36 CGContextRestoreGState(cgc
);
39 void DrawBackground
::drawSelf(CGContextRef cgc
, CGRect inRect
)
43 SolidColorBackground
::SolidColorBackground(SCColor inColor
)
48 void SolidColorBackground
::drawSelf(CGContextRef cgc
, CGRect inRect
)
50 CGContextSetRGBFillColor(cgc
, mColor.red
, mColor.green
, mColor.blue
, mColor.alpha
);
51 CGContextFillRect(cgc
, inRect
);
54 GradientBackground
::GradientBackground(SCColor inStartColor
, SCColor inEndColor
, int inDirection
, int inSteps
)
55 : mStartColor(inStartColor
), mEndColor(inEndColor
), mDirection(inDirection
), mSteps(inSteps
)
59 void hPaintGradient(CGContextRef cgc
, CGRect bounds
, SCColor startColor
, SCColor endColor
, int numSteps
);
60 void vPaintGradient(CGContextRef cgc
, CGRect bounds
, SCColor startColor
, SCColor endColor
, int numSteps
);
62 void GradientBackground
::drawSelf(CGContextRef cgc
, CGRect inRect
)
66 if (mDirection
== grad_Narrow
) {
67 isHorizontal
= inRect.size.width
< inRect.size.height
;
68 } else if (mDirection
== grad_Wide
) {
69 isHorizontal
= inRect.size.width
> inRect.size.height
;
71 isHorizontal
= mDirection
== grad_Horizontal
;
75 hPaintGradient(cgc
, inRect
, mStartColor
, mEndColor
, mSteps
);
77 vPaintGradient(cgc
, inRect
, mStartColor
, mEndColor
, mSteps
);
82 HiliteGradientBackground
::HiliteGradientBackground(SCColor inStartColor
, SCColor inEndColor
, int inDirection
, int inSteps
, float inFrac
)
83 : GradientBackground(inStartColor
, inEndColor
, inDirection
, inSteps
), mFrac(inFrac
), mFrac1(1.
- inFrac
)
88 void HiliteGradientBackground
::drawSelf(CGContextRef cgc
, CGRect inRect
)
92 if (mDirection
== grad_Narrow
) {
93 isHorizontal
= inRect.size.width
< inRect.size.height
;
94 } else if (mDirection
== grad_Wide
) {
95 isHorizontal
= inRect.size.width
> inRect.size.height
;
97 isHorizontal
= mDirection
== grad_Horizontal
;
100 CGRect rectA
= inRect
;
101 CGRect rectB
= inRect
;
104 rectA.size.width
*= mFrac
;
105 rectB.origin.x
+= rectA.size.width
;
106 rectB.size.width
*= mFrac1
;
107 hPaintGradient(cgc
, rectA
, mStartColor
, mEndColor
, (int)(mSteps
* mFrac
));
108 hPaintGradient(cgc
, rectB
, mEndColor
, mStartColor
, (int)(mSteps
* mFrac1
));
110 rectA.size.height
*= mFrac
;
111 rectB.origin.y
+= rectA.size.height
;
112 rectB.size.height
*= mFrac1
;
113 vPaintGradient(cgc
, rectA
, mStartColor
, mEndColor
, (int)(mSteps
* mFrac
));
114 vPaintGradient(cgc
, rectB
, mEndColor
, mStartColor
, (int)(mSteps
* mFrac1
));
121 void ScaleRectInRect( NSRect
*bounds
, NSSize
*origSize
, NSRect
*destRect
);
122 inline void ScaleRectInRect( NSRect
*bounds
, NSSize
*origSize
, NSRect
*destRect
)
124 float imgRatio
= (*origSize
).width
/ (*origSize
).height
;
125 //float maxDim = ( (*origSize).width > (*origSize).height) ? (*origSize).width : (*origSize).height;
127 if( imgRatio
< 1.0f
)
129 (*destRect
).size.height
= (*bounds
).size.height
;
130 (*destRect
).size.width
= (*destRect
).size.height
* imgRatio
;
131 if( (*destRect
).size.width
> (*bounds
).size.width
) { // clip and resize
132 (*destRect
).size.width
= (*bounds
).size.width
;
133 (*destRect
).size.height
= (*destRect
).size.width
/ imgRatio
;
138 (*destRect
).size.width
= (*bounds
).size.width
;
139 (*destRect
).size.height
= (*destRect
).size.width
/ imgRatio
;
140 if( (*destRect
).size.height
> (*bounds
).size.height
) { // clip and resize
141 (*destRect
).size.height
= (*bounds
).size.height
;
142 (*destRect
).size.width
= (*destRect
).size.height
* imgRatio
;
146 destRect
->origin.x
= bounds
->origin.x
+ ((bounds
->size.width
- destRect
->size.width
) * 0.5f
);
147 destRect
->origin.y
= bounds
->origin.y
+ ((bounds
->size.height
- destRect
->size.height
) * 0.5f
);
150 SCImageBackground
::SCImageBackground(SCImage
* inSCImage
, NSRect inFromRect
, int inTileMode
, float inFraction
)
151 : mSCImage(inSCImage
), mFromRect(inFromRect
), mTileMode(inTileMode
), mFraction(inFraction
)
153 [mSCImage retain
]; // in case
155 // convert sc rect to image coordinates + clipping
158 w
= [mSCImage size
].width
;
159 h
= [mSCImage size
].height
;
161 mSwappedYOrigin
= sc_clip(h
- (mFromRect.origin.y
+ mFromRect.size.height
), 0, h
);
162 mOriginalYOrigin
= sc_clip(mFromRect.origin.y
, 0, h
);
164 mFromRect.origin.x
= sc_clip(mFromRect.origin.x
, 0, w
);
166 if((mFromRect.origin.x
+ mFromRect.size.width
) > w
)
167 mFromRect.size.width
= w
- mFromRect.origin.x
;
169 if((mFromRect.origin.y
+ mFromRect.size.height
) > h
)
170 mFromRect.size.height
= h
- mFromRect.origin.y
;
174 void SCImageBackground
::rebuildCache(CGContextRef cgc
)
176 if([mSCImage isSynced
])
179 [mSCImage syncRepresentations
];
181 if([mSCImage isAccelerated
]) { // build CIImage
182 // no cache for now -> may be see with CGLayer conversion
185 CGLayerRef layer
= CGLayerCreateWithContext(cgc
, CGSizeMake([mSCImage size
].width
, [mSCImage size
].height
), NULL
);
187 NSLog(@
"SCImageBackground::rebuildCache failed Creating valid CGLayerRef");
189 ctx
= CGLayerGetContext(layer
);
191 [NSGraphicsContext saveGraphicsState
];
192 NSGraphicsContext
*layerCtx
= [NSGraphicsContext contextWithGraphicsPort
:ctx flipped
:NO
];
193 [NSGraphicsContext setCurrentContext
:layerCtx
];
194 CGContextSaveGState(ctx
);
195 CGContextTranslateCTM(ctx
, 0, mFromRect.size.height
);
196 CGContextScaleCTM(ctx
, 1, -1.0f
);
197 [mSCImage drawInRect
:NSMakeRect(0.f
, 0.f
, mFromRect.size.width
, mFromRect.size.height
) fromRect
:mFromRect operation
:NSCompositeSourceOver fraction
:mFraction
];
198 CGContextSaveRestoreGState(ctx
);
199 [NSGraphicsContext restoreGraphicsState
];
204 void SCImageBackground
::drawSelf(CGContextRef cgc
, CGRect inRect
)
207 1 - fixed to left, fixed to top ---> topLeft
208 2 - horizontally tile, fixed to top ---> top + tilex
209 3 - fixed to right, fixed to top ---> topRight
210 4 - fixed to left, vertically tile ---> left + tiley
211 5 - horizontally tile, vertically tile ---> tilexy
212 6 - fixed to right, vertically tile --> right + tiley
213 7 - fixed to left, fixed to bottom --> bottomLeft
214 8 - horizontally tile, fixed to bottom --> bottom + tiley
215 9 - fixed to right, fixed to bottom ---> bottomRight
216 10 - fit ---> scale to fit in the view rect (meaning a full drawRect instead
217 of a drawAtPoint with tile options)
219 12 - center , fixed to top
220 13 - center , fixed to bottom
221 14 - fixed to left, center
222 15 - fixed to right, center
225 // printf("SCImageBackground::drawSelf x: %f\t y: %f\t width: %f\t height: %f\n",
226 // inRect.origin.x, inRect.origin.y, inRect.size.width, inRect.size.height);
228 CGContextSaveGState(cgc
);
229 CGContextClipToRect(cgc
, inRect
);
231 #if SCIMAGE_BACKGROUND_DEBUG
232 extern double GetTimeOfDay();
233 double past
= GetTimeOfDay();
236 NSRect destinationRect
= NSMakeRect(inRect.origin.x
, inRect.origin.y
, mFromRect.size.width
, mFromRect.size.height
);
243 destinationRect.size.width
= inRect.size.width
;
244 destinationRect.origin.y
+= (mTileMode
== 2 ?
0 : inRect.size.height
- mFromRect.size.height
);
245 [mSCImage tileInSCRect
:destinationRect fromRect
:mFromRect operation
:NSCompositeSourceOver fraction
:mFraction
];
251 destinationRect.size
= NSMakeSize(inRect.size.width
, inRect.size.height
);
252 [mSCImage tileInSCRect
:destinationRect fromRect
:mFromRect operation
:NSCompositeSourceOver fraction
:mFraction
];
259 destinationRect.size.height
= inRect.size.height
;
260 destinationRect.origin.x
+= (mTileMode
== 4 ?
0 : (inRect.size.width
- mFromRect.size.width
));
261 [mSCImage tileInSCRect
:destinationRect fromRect
:mFromRect operation
:NSCompositeSourceOver fraction
:mFraction
];
266 destinationRect.origin.x
+= inRect.size.width
- mFromRect.size.width
;
270 destinationRect.origin.x
+= inRect.size.width
- mFromRect.size.width
;
271 destinationRect.origin.y
+= inRect.size.height
- mFromRect.size.height
;
275 destinationRect.origin.y
+= inRect.size.height
- mFromRect.size.height
;
280 destinationRect.size
= *(NSSize
*)&inRect.size
;
283 case 11: // center x - center y + scale
284 ScaleRectInRect((NSRect
*)&inRect
, &mFromRect.size
, (NSRect
*)&destinationRect
);
287 case 12: // center - fixed to top
288 destinationRect.origin.x
+= ((inRect.size.width
- destinationRect.size.width
) * 0.5);
291 case 13: // center - fixed to bottom
292 destinationRect.origin.x
+= ((inRect.size.width
- destinationRect.size.width
) * 0.5);
293 destinationRect.origin.y
+= inRect.size.height
- mFromRect.size.height
;
296 case 14: // fixed to left - center
297 destinationRect.origin.y
+= ((inRect.size.height
- destinationRect.size.height
) * 0.5);
300 case 15: // fixed to right - center
301 destinationRect.origin.y
+= ((inRect.size.height
- destinationRect.size.height
) * 0.5);
302 destinationRect.origin.x
+= (inRect.size.width
- destinationRect.size.width
);
306 destinationRect.origin.x
+= ((inRect.size.width
- destinationRect.size.width
) * 0.5);
307 destinationRect.origin.y
+= ((inRect.size.height
- destinationRect.size.height
) * 0.5);
314 [mSCImage drawInSCRect
:destinationRect fromRect
:mFromRect operation
:NSCompositeSourceOver fraction
:mFraction
];
317 #if SCIMAGE_BACKGROUND_DEBUG
318 NSLog(@
"SCImageBackground (%p) SCImage Time To Render: %f", this, GetTimeOfDay() - past
);
321 CGContextRestoreGState(cgc
);
324 SCImageBackground
::~
SCImageBackground()
326 #if SCIMAGE_BACKGROUND_DEBUG
327 NSLog(@
"SCImageBackground (%p) release SCImage (%p)", this, mSCImage
);
335 CGPatternCreate(void *info
, CGRect bounds
, CGAffineTransform matrix
, float xStep
, float yStep
, CGPatternTiling tiling
, int isColored
, const CGPatternCallbacks
*callbacks
)
336 struct CGPatternCallbacks
{
337 unsigned int version
;
338 void (*drawPattern
)(void *info
, CGContextRef c
);
339 void (*releaseInfo
)(void *info
);
341 typedef struct CGPatternCallbacks CGPatternCallbacks
;
348 static void drawPattern(void *info
, CGContextRef c
)
350 TiledBackground
*tb
= (TiledBackground
*)info
;
354 CGPatternCallbacks callbacks
;
355 callbacks.version
= 0;
356 callbacks.drawPattern
= drawPattern
;
357 callbacks.releaseInfo
= releaseInfo
;
359 CGPatternCreate(this, tileBounds
, CGAffineTransformIdentity
,
360 tileBounds.size.width
, tileBounds.size.height
, kCGPatternTilingConstantSpacing
, YES
, callbacks
);