File: SCREENFillArc.c

package info (click to toggle)
psychtoolbox-3 3.0.19.14.dfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 86,796 kB
  • sloc: ansic: 176,245; cpp: 20,103; objc: 5,393; sh: 2,753; python: 1,397; php: 384; makefile: 193; java: 113
file content (227 lines) | stat: -rw-r--r-- 8,899 bytes parent folder | download | duplicates (5)
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/*
	SCREENFillArc.cpp		
 
	Draw a filled arc, like a part of a pie-chart.
 
	AUTHORS:
 
	Allen.Ingling@nyu.edu                   awi
	mario.kleiner at tuebingen.mpg.de       mk
 
	PLATFORMS:
	
	Should compile and work for all platforms.
 
	NOTES:
 
	HISTORY:
 
	12/11/05        mk		Created. Derived from Allen Inglings gluDisc.   
 
	TO DO:
 
 */


#include "Screen.h"

// The routine that does the real work - see at bottom of file:
void PsychRenderArc(unsigned int mode);

PsychError SCREENDrawArc(void)
{
    // If you change useString then also change the corresponding synopsis string in ScreenSynopsis.c
    static char useString[] = "Screen('DrawArc',windowPtr,[color],[rect],startAngle,arcAngle)";
    //                                          1         2       3      4          5
    static char synopsisString[] = 
        "Draw an arc inscribed within the rect. 'color' is the clut index (scalar "
        "or [r g b] triplet) that you want to poke into each pixel; default produces "
        "black with the standard CLUT for this window's pixelSize. Default 'rect' is "
        "entire window. Angles are measured clockwise from vertical.";
    static char seeAlsoString[] = "FrameArc FillArc";	
	
    //all sub functions should have these two lines
    PsychPushHelp(useString, synopsisString,seeAlsoString);
    if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};
    
    //check for superfluous arguments
    PsychErrorExit(PsychCapNumInputArgs(5));        //The maximum number of inputs
    PsychErrorExit(PsychRequireNumInputArgs(3));    //The minimum number of inputs
    PsychErrorExit(PsychCapNumOutputArgs(0));       //The maximum number of outputs
	
    // Render arc of type 1 - Just the outline.
    PsychRenderArc(1);
    
    return(PsychError_none);
}

PsychError SCREENFrameArc(void)
{
    // If you change useString then also change the corresponding synopsis string in ScreenSynopsis.c
    static char useString[] = "Screen('FrameArc',windowPtr,[color],[rect],startAngle,arcAngle, [penWidth], [penHeight], [penMode])";
    //                                          1         2       3      4          5           6           7           8
    static char synopsisString[] = 
        "Draw an arc inscribed within the rect. 'color' is the clut index (scalar "
        "or [r g b] triplet) that you want to poke into each pixel; default produces "
        "black with the standard CLUT for this window's pixelSize. Default 'rect' is "
        "entire window. Angles are measured clockwise from vertical. 'penWidth' and "
        "'penHeight' are the width and height of the pen to use. penWidth must equal "
        "penHeight and the 'penMode' argument is currently ignored.";
    static char seeAlsoString[] = "DrawArc FillArc";	
    
    //all sub functions should have these two lines
    PsychPushHelp(useString, synopsisString,seeAlsoString);
    if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};
    
    //check for superfluous arguments
    PsychErrorExit(PsychCapNumInputArgs(8));        //The maximum number of inputs
    PsychErrorExit(PsychRequireNumInputArgs(3));    //The minimum number of inputs
    PsychErrorExit(PsychCapNumOutputArgs(0));       //The maximum number of outputs
    
    // Render arc of type 2 - Just the outline with penWidth.
    PsychRenderArc(2);
    
    return(PsychError_none);
}


PsychError SCREENFillArc(void)  
{	
	// If you change useString then also change the corresponding synopsis string in ScreenSynopsis.c
	static char useString[] = "Screen('FillArc',windowPtr,[color],[rect],startAngle,arcAngle)";
	//                                          1         2       3      4          5
	static char synopsisString[] = 
		"Draw a filled arc inscribed within the rect. 'color' is the clut index (scalar "
		"or [r g b a] triplet) that you want to poke into each pixel; default produces "
        "black with the standard CLUT for this window's pixelSize. Default 'rect' is "
		"entire window. Angles are measured clockwise from vertical.";
	static char seeAlsoString[] = "DrawArc FrameArc";	
	
	//all sub functions should have these two lines
	PsychPushHelp(useString, synopsisString,seeAlsoString);
	if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};
	
	//check for superfluous arguments
	PsychErrorExit(PsychCapNumInputArgs(5));        //The maximum number of inputs
	PsychErrorExit(PsychRequireNumInputArgs(3));    //The minimum number of inputs
	PsychErrorExit(PsychCapNumOutputArgs(0));       //The maximum number of outputs
	
	// Render arc of type 3 - Filled arc.
	PsychRenderArc(3);
	
	return(PsychError_none);
}

void PsychRenderArc(unsigned int mode)
{
	PsychColorType			color;
	PsychRectType           rect;
	double					*startAngle, *arcAngle, *penWidth, *penHeight;
	PsychWindowRecordType	*windowRecord;
	double					whiteValue;
	double                  dotSize = 1;
	psych_bool				isArgThere;
	GLUquadric              *diskQuadric = NULL;
	double cx, cy, w, h;
	
	//get the window record from the window record argument and get info from the window record
	PsychAllocInWindowRecordArg(kPsychUseDefaultArgPosition, TRUE, &windowRecord);
	
	//Get the color argument or use the default, then coerce to the form determened by the window depth.  
	isArgThere=PsychCopyInColorArg(kPsychUseDefaultArgPosition, FALSE, &color);
	if(!isArgThere){
		whiteValue=PsychGetWhiteValueFromWindow(windowRecord);
		PsychLoadColorStruct(&color, kPsychIndexColor, whiteValue ); //index mode will coerce to any other.
	}
 	PsychCoerceColorMode( &color);
	
	// Get the rect to which the object should be inscribed: Default is "full screen"
	PsychMakeRect(rect, 0, 0, PsychGetWidthFromRect(windowRecord->clientrect), PsychGetHeightFromRect(windowRecord->clientrect));
	PsychCopyInRectArg(3, FALSE, rect);
	if (IsPsychRectEmpty(rect)) return;
	
	w=PsychGetWidthFromRect(rect);
	h=PsychGetHeightFromRect(rect);
	
	PsychGetCenterFromRectAbsolute(rect, &cx, &cy);
	if (w==0 || h==0) PsychErrorExitMsg(PsychError_user, "Invalid rect (width or height equals zero) provided!");
	
	// Get start angle: 
	PsychAllocInDoubleArg(4, TRUE,  &startAngle);
	PsychAllocInDoubleArg(5, TRUE,  &arcAngle);
	
	if (mode==2) {
		// Get pen width and height:
		penWidth=NULL;
		penHeight=NULL;
		PsychAllocInDoubleArg(6, FALSE,  &penWidth);
		PsychAllocInDoubleArg(7, FALSE,  &penHeight);
		// Check if penWidth and penHeight spec'd. If so, they
		// need to be equal:
		if (penWidth && penHeight && (*penWidth!=*penHeight)) {
			PsychErrorExitMsg(PsychError_user, "penWidth and penHeight must be equal if both are specified!");
		}
		dotSize=1;
		if (penWidth) dotSize = *penWidth;
		if (penHeight) dotSize = *penHeight;
	}
	
	// Enable this windowRecords framebuffer as current drawingtarget:
	PsychSetDrawingTarget(windowRecord);
	
	// Set default drawshader:
	PsychSetShader(windowRecord, -1);
	
	PsychUpdateAlphaBlendingFactorLazily(windowRecord);
	PsychSetGLColor(&color,  windowRecord);
	
    if (PsychIsGLClassic(windowRecord)) {
        // Backup our modelview matrix:
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
	
        // Position disk at center of rect:
        glTranslated(cx, cy, 0);
	
        // Scale in order to fit to rect in case w!=h:
        glScaled(1.0, -h/w, 1.0);
	
        // Draw filled partial disk:
        diskQuadric=gluNewQuadric();
	
        switch (mode) {
		case 1: // One pixel thin arc: InnerRadius = OuterRadius - 1
			gluPartialDisk(diskQuadric, (w/2) - 1.0, w/2, (int) w, 2, *startAngle, *arcAngle);
			break;
		case 2: // dotSize thick arc:  InnerRadius = OuterRadius - dotsize
			gluPartialDisk(diskQuadric, (dotSize < (w/2)) ? (w/2) - dotSize : 0, w/2, (int) w, 2, *startAngle, *arcAngle);
			break;
		case 3: // Filled arc:
			gluPartialDisk(diskQuadric, 0, w/2, (int) w, 1, *startAngle, *arcAngle);
			break;
        }
	
        gluDeleteQuadric(diskQuadric);
	
        // Restore old matrix:
        glPopMatrix();
	}
    else {
        switch (mode) {
		case 1: // One pixel thin arc: InnerRadius = OuterRadius - 1
            PsychDrawDisc(windowRecord, (float) cx, (float) cy, (float) ((w/2) - 1.0), (float) w/2, (int) w, (float) 1, (float) -h / (float) w, (float) *startAngle, (float) *arcAngle);
			break;
		case 2: // dotSize thick arc:  InnerRadius = OuterRadius - dotsize
            PsychDrawDisc(windowRecord, (float) cx, (float) cy, (float) ((dotSize < (w/2)) ? (w/2) - dotSize : 0), (float) w / 2, (int) w, (float) 1, (float) -h/ (float) w, (float) *startAngle, (float) *arcAngle);
			break;
		case 3: // Filled arc:
            PsychDrawDisc(windowRecord, (float) cx, (float) cy, (float) 0, (float) w / 2, (int) w, (float) 1, (float) -h / (float) w, (float) *startAngle, (float) *arcAngle);
			break;
        }
    }

	// Mark end of drawing op. This is needed for single buffered drawing:
	PsychFlushGL(windowRecord);
	
	return;
}