Tweak towards having an option to include sc3-plugins included in the win bundle...
[supercollider.git] / Source / app / DrawBackground.M
blob858f6e46ed7b87880e07c18a3aeebb0645aa4c2c
1 /*
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
21 #ifndef SC_IPHONE
22 #import <Cocoa/Cocoa.h>
23 #import "SCImage.h"
24 #endif
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)
44 : mColor(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)
64 bool isHorizontal;
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;
70 } else {
71 isHorizontal = mDirection == grad_Horizontal;
74 if (isHorizontal) {
75 hPaintGradient(cgc, inRect, mStartColor, mEndColor, mSteps);
76 } else {
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)
90 bool isHorizontal;
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;
96 } else {
97 isHorizontal = mDirection == grad_Horizontal;
100 CGRect rectA = inRect;
101 CGRect rectB = inRect;
103 if (isHorizontal) {
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));
109 } else {
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));
118 // SCImageBackground
119 #ifndef SC_IPHONE
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;
136 } else {
137 // width >= height
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
156 float w, h;
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;
173 #if 0
174 void SCImageBackground::rebuildCache(CGContextRef cgc)
176 if([mSCImage isSynced])
177 return;
179 [mSCImage syncRepresentations];
181 if([mSCImage isAccelerated]) { // build CIImage
182 // no cache for now -> may be see with CGLayer conversion
183 }else{
184 CGContextRef ctx;
185 CGLayerRef layer = CGLayerCreateWithContext(cgc, CGSizeMake([mSCImage size].width, [mSCImage size].height), NULL);
186 if(!layer) {
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];
202 #endif
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)
218 11 - center x y
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();
234 #endif
236 NSRect destinationRect = NSMakeRect(inRect.origin.x, inRect.origin.y, mFromRect.size.width, mFromRect.size.height);
238 switch(mTileMode)
240 case 2:
241 case 8:
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];
247 goto end1;
249 case 5:
251 destinationRect.size = NSMakeSize(inRect.size.width, inRect.size.height);
252 [mSCImage tileInSCRect:destinationRect fromRect:mFromRect operation:NSCompositeSourceOver fraction:mFraction];
254 goto end1;
256 case 4:
257 case 6:
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];
263 goto end1;
265 case 3:
266 destinationRect.origin.x += inRect.size.width - mFromRect.size.width;
267 break;
269 case 9:
270 destinationRect.origin.x += inRect.size.width - mFromRect.size.width;
271 destinationRect.origin.y += inRect.size.height - mFromRect.size.height;
272 break;
274 case 7:
275 destinationRect.origin.y += inRect.size.height - mFromRect.size.height;
276 break;
278 // center
279 case 10:
280 destinationRect.size = *(NSSize*)&inRect.size;
281 break;
283 case 11: // center x - center y + scale
284 ScaleRectInRect((NSRect*)&inRect, &mFromRect.size, (NSRect*)&destinationRect);
285 break;
287 case 12: // center - fixed to top
288 destinationRect.origin.x += ((inRect.size.width - destinationRect.size.width) * 0.5);
289 break;
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;
294 break;
296 case 14: // fixed to left - center
297 destinationRect.origin.y += ((inRect.size.height - destinationRect.size.height) * 0.5);
298 break;
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);
303 break;
305 case 16:
306 destinationRect.origin.x += ((inRect.size.width - destinationRect.size.width) * 0.5);
307 destinationRect.origin.y += ((inRect.size.height - destinationRect.size.height) * 0.5);
308 break;
310 case 1:
311 default:
312 break;
314 [mSCImage drawInSCRect:destinationRect fromRect:mFromRect operation:NSCompositeSourceOver fraction:mFraction];
316 end1:
317 #if SCIMAGE_BACKGROUND_DEBUG
318 NSLog(@"SCImageBackground (%p) SCImage Time To Render: %f", this, GetTimeOfDay() - past);
319 #endif
321 CGContextRestoreGState(cgc);
324 SCImageBackground::~SCImageBackground()
326 #if SCIMAGE_BACKGROUND_DEBUG
327 NSLog(@"SCImageBackground (%p) release SCImage (%p)", this, mSCImage);
328 #endif
329 [mSCImage release];
331 #endif
333 #if 0
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;
343 drawTile()
345 [mTile draw];
348 static void drawPattern(void *info, CGContextRef c)
350 TiledBackground *tb = (TiledBackground*)info;
351 tb->drawTile();
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);
362 #endif