1 #ifdef WIN32
2 #include <windows.h>
3 #endif
4 #ifdef __APPLE__
5 #include <OpenGL/gl.h>
6 #else
7 #include <GL/gl.h>
8 #endif
9 #include "mgl2/opengl.h"
10 #include "mgl2/mgl_cf.h"
11 #include <algorithm>
12 //-----------------------------------------------------------------------------
13 /// Create mglGraph object in OpenGL mode.
mgl_create_graph_gl()14 HMGL MGL_EXPORT mgl_create_graph_gl()
15 {	return new mglCanvasGL;	}
16 /// Create mglGraph object in OpenGL mode.
mgl_create_graph_gl_()17 uintptr_t MGL_EXPORT mgl_create_graph_gl_()
18 {	return uintptr_t(new mglCanvasGL);	}
19 //-----------------------------------------------------------------------------
mglCanvasGL()20 mglCanvasGL::mglCanvasGL() : mglCanvas(1,1)
21 {	Clf();	Zoom(0,0,1,1);	set(MGL_FULL_CURV);	limit_pm1=true;	}
22 //-----------------------------------------------------------------------------
~mglCanvasGL()23 mglCanvasGL::~mglCanvasGL(){}
24 //-----------------------------------------------------------------------------
set_pen(unsigned style,mreal width,mreal pos)25 void set_pen(unsigned style, mreal width, mreal pos)
26 {
27 	if(style==0)	return;
28 	unsigned long pdef = style*0x100010001;
29 	pdef >>= long(32*pos)%32;	// NOTE try to bypass OpenGL limitations
30 	style = pdef & 0xffff;
31 	width *= 20;
32 	if(style!=0xffff)
33 	{
34 		glEnable(GL_LINE_STIPPLE);
35 		glLineStipple(int(width+0.5),style);
36 	}
37 	else	glDisable(GL_LINE_STIPPLE);
38 	if(width>1)	glLineWidth(width);	// NOTE bypass bug on some drivers, where width>1 must be
39 	else		glLineWidth(1);
40 }
41 //-----------------------------------------------------------------------------
Finish()42 void mglCanvasGL::Finish()
43 {
44 #if MGL_USE_DOUBLE
45 #define MGL_GL_TYPE	GL_DOUBLE
46 #else
47 #define MGL_GL_TYPE	GL_FLOAT
48 #endif
49 
50 	// Try to add smoothing
51 	glEnable(GL_LINE_SMOOTH);
52 	glEnable(GL_POLYGON_SMOOTH);
53 	glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
54 	glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
55 	glEnable(GL_BLEND);
56 	if((Flag&3)==1)	glBlendFunc(GL_DST_COLOR, GL_ZERO);
57 	else if((Flag&3)==2) glBlendFunc(GL_SRC_ALPHA, GL_ONE);
58 	else glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
59 
60 	if(Prm.size()>0)
61 	{
62 		PreparePrim(0);
63 /*		glVertexPointer(3, MGL_GL_TYPE, sizeof(mglPnt), &(Pnt[0].x));	// something wrong with arrays
64 		glNormalPointer(MGL_GL_TYPE, sizeof(mglPnt), &(Pnt[0].u));
65 		glColorPointer(4, MGL_GL_TYPE, sizeof(mglPnt), &(Pnt[0].r));
66 		glEnableClientState(GL_VERTEX_ARRAY);
67 		glEnableClientState(GL_NORMAL_ARRAY);
68 		glEnableClientState(GL_COLOR_ARRAY);*/
69 
70 		int pdef=PDef;
71 		mreal ss=pPos, ww=PenWidth;
72 		mglPrim p;
73 		for(size_t i=0;i<Prm.size();i++)
74 		{
75 			p=GetPrm(i);	PDef=p.n3;	pPos=p.s;	PenWidth=p.w;
76 			long n1=p.n1, n2=p.n2, n3=p.n3, n4=p.n4;
77 			mglDrawReg d;	d.set(this,1,1,0);
78 			switch(p.type)
79 			{
80 /*			case 0:	mark_draw(Pnt[n1],n4,p.s,0);	break;
81 			case 1:	line_draw(n1,n2);	break;
82 			case 2:	trig_draw(n1,n2,n3);	break;
83 			case 3:	quad_draw(n1,n2,n3,n4);	break;*/
84 			case 0:	mark_draw(Pnt[n1],n4,p.s,&d);	break;
85 			case 1:	line_draw(Pnt[n1],Pnt[n2],&d);	break;
86 			case 2:	trig_draw(Pnt[n1],Pnt[n2],Pnt[n3],true,&d);	break;
87 			case 3:	quad_draw(Pnt[n1],Pnt[n2],Pnt[n3],Pnt[n4],&d);	break;
88 			case 4:	glyph_draw(p,&d);	break;
89 			}
90 		}
91 		PDef=pdef;	pPos=ss;	PenWidth=ww;
92 	}
93 	glFinish();
94 }
95 //-----------------------------------------------------------------------------
Alpha(bool enable)96 bool mglCanvasGL::Alpha(bool enable)
97 {
98 	if(enable)
99 	{
100 		set(MGL_ENABLE_ALPHA);
101 		glDisable(GL_DEPTH_TEST);
102 		glEnable(GL_ALPHA_TEST);
103 		glEnable(GL_BLEND);
104 		if((Flag&3)==1)	glBlendFunc(GL_DST_COLOR, GL_ZERO);
105 		else if((Flag&3)==2) glBlendFunc(GL_SRC_ALPHA, GL_ONE);
106 		else glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
107 	}
108 	else
109 	{
110 		clr(MGL_ENABLE_ALPHA);
111 		glEnable(GL_DEPTH_TEST);
112 		glDisable(GL_ALPHA_TEST);
113 //		glDisable(GL_BLEND);
114 	}
115 	return mglCanvas::Alpha(enable);
116 }
117 //-----------------------------------------------------------------------------
AddLight(int n,mglPoint r,mglPoint d,char cc,mreal br,mreal ap)118 void mglCanvasGL::AddLight(int n,mglPoint r,mglPoint d,char cc, mreal br,mreal ap)
119 {
120 	mglColor c(cc);
121 	float amb[4],dif[4],spc[4], pos[4];
122 	bool inf = mgl_isnan(r.x);
123 	if(n<0 || n>7)	{	SetWarn(mglWarnLId,"AddLight");	return;	}
124 	if(c.Valid())
125 	{
126 		spc[0] = br*c.r;	spc[1] = br*c.g;	spc[2] = br*c.b;
127 		amb[0] = AmbBr*c.r;	amb[1] = AmbBr*c.g;	amb[2] = AmbBr*c.b;
128 	}
129 	else
130 	{
131 		spc[0] = spc[1] = spc[2] = br;
132 		amb[0] = amb[1] = amb[2] = AmbBr;
133 	}
134 	dif[0] = dif[1] = dif[2] = DifBr;
135 	dif[3] = amb[3] = spc[3] = 1.;
136 	if(inf)
137 	{	pos[0] = d.x;	pos[1] = d.y;	pos[2] = d.z;	pos[3] = 0;	}
138 	else
139 	{	pos[0] = r.x;	pos[1] = r.y;	pos[2] = r.z;	pos[3] = 1;	}
140 
141 	glShadeModel(GL_SMOOTH);
142 	glLightfv(GL_LIGHT0+n, GL_AMBIENT, amb);
143 	glLightfv(GL_LIGHT0+n, GL_DIFFUSE, dif);
144 	glLightfv(GL_LIGHT0+n, GL_SPECULAR, spc);
145 	glLightfv(GL_LIGHT0+n, GL_POSITION, pos);
146 	if(!inf)
147 	{
148 //		ap = 90-180*atan(fabs(ap))/M_PI;
149 //		float dir[4]={d.x, d.y, d.z, 0};
150 //		glLightfv(GL_LIGHT0+n, GL_SPOT_DIRECTION, dir);
151 //		glLightf(GL_LIGHT0+n, GL_SPOT_CUTOFF, ap);
152 	}
153 	glEnable(GL_LIGHT0+n);
154 }
155 //-----------------------------------------------------------------------------
Light(int n,bool enable)156 void mglCanvasGL::Light(int n, bool enable)
157 {
158 	if(enable)	glEnable(GL_LIGHT0+n);
159 	else		glDisable(GL_LIGHT0+n);
160 }
161 //-----------------------------------------------------------------------------
Light(bool enable)162 bool mglCanvasGL::Light(bool enable)
163 {
164 	if(enable)	{	glEnable(GL_LIGHTING);	glEnable(GL_NORMALIZE);}
165 	else		{	glDisable(GL_LIGHTING);	glDisable(GL_NORMALIZE);	}
166 	return mglCanvas::Light(enable);
167 }
168 //-----------------------------------------------------------------------------
LightScale(const mglMatrix * M)169 void mglCanvasGL::LightScale(const mglMatrix *M)
170 {
171 	mglCanvas::LightScale(M);
172 	GLenum ll[8] = {GL_LIGHT0,GL_LIGHT1,GL_LIGHT2,GL_LIGHT3,GL_LIGHT4,
173 			GL_LIGHT5,GL_LIGHT6,GL_LIGHT7};
174 	float pos[4]={0,0,0,0};
175 	for(int i=0;i<8;i++)	// NOTE only global light is used in OpenGL mode
176 	{
177 		pos[0] = light[i].p.x;
178 		pos[1] = light[i].p.y;
179 		pos[2] = light[i].p.z;
180 		if(light[i].n)	glLightfv(ll[i], GL_POSITION, pos);
181 	}
182 }
183 //-----------------------------------------------------------------------------
Zoom(mreal x1,mreal y1,mreal x2,mreal y2)184 void mglCanvasGL::Zoom(mreal x1, mreal y1, mreal x2, mreal y2)
185 {
186 	glMatrixMode(GL_PROJECTION);//GL_PROJECTION GL_VIEWPORT GL_MODELVIEW
187 	glLoadIdentity();
188 	glScaled(x2-x1,y2-y1,1);
189 	glTranslated((x1+x2-1)/2,(y1+y2-1)/2,0);
190 }
191 //-----------------------------------------------------------------------------
View(mreal TetX,mreal TetY,mreal TetZ)192 void mglCanvasGL::View(mreal TetX,mreal TetY,mreal TetZ)
193 {
194 	glMatrixMode(GL_PROJECTION);//GL_PROJECTION GL_VIEWPORT GL_MODELVIEW
195 	glRotated(TetX,1.,0.,0.);
196 	glRotated(TetY,0.,1.,0.);
197 	glRotated(TetZ,0.,0.,1.);
198 }
199 //-----------------------------------------------------------------------------
Fog(mreal d,mreal)200 void mglCanvasGL::Fog(mreal d, mreal)
201 {
202 	if(d>0)
203 	{
204 		float back[4]={BDef[0]/255.f,BDef[1]/255.f,BDef[2]/255.f,BDef[3]/255.f};
205 		glFogf(GL_FOG_MODE,GL_EXP);
206 		glFogf(GL_FOG_DENSITY,5*d);
207 		glFogfv(GL_FOG_COLOR,back);
208 		glEnable(GL_FOG);
209 	}
210 	else	glDisable(GL_FOG);
211 }
212 //-----------------------------------------------------------------------------
Clf(mglColor Back)213 void mglCanvasGL::Clf(mglColor Back)
214 {
215 	mglCanvas::Clf(Back);
216 	if(Back==NC)	Back.Set(BDef[0]/255.,BDef[1]/255.,BDef[2]/255.);
217 	gl_clf(Back);
218 }
219 //-----------------------------------------------------------------------------
Clf(const char * col)220 void mglCanvasGL::Clf(const char *col)
221 {
222 	mglCanvas::Clf(col);
223 	gl_clf(mglColor(BDef[0]/255.,BDef[1]/255.,BDef[2]/255.));
224 }
225 //-----------------------------------------------------------------------------
gl_clf(mglColor Back)226 void mglCanvasGL::gl_clf(mglColor Back)
227 {
228 	if(Back==NC)	Back = WC;
229 //	glDepthFunc(GL_LESS);
230 	glDepthFunc(GL_GREATER);
231 	glClearColor(Back.r,Back.g,Back.b,1.);
232 	glClearDepth(-10.);
233 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
234 	glEnable(GL_COLOR_MATERIAL);
235 
236 	glMatrixMode(GL_MODELVIEW);//GL_MODELVIEW GL_VIEWPORT GL_PROJECTION
237 	glLoadIdentity();
238 	glScaled(2,2,2);
239 	glTranslated(-0.5,-0.5,-0.5);
240 
241 //	float dif[4]={DifBr,DifBr,DifBr,1};
242 //	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, dif);
243 	float spc[4]={1,1,1,1};
244 	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spc);
245 	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, DifBr);
246 }
247 //-----------------------------------------------------------------------------
248 /*void mglCanvasGL::EndFrame()
249 {
250 //	mglGraph::EndFrame();
251 	glEndList();
252 }
253 //-----------------------------------------------------------------------------
254 int mglCanvasGL::NewFrame()
255 {
256 	Clf();	Identity();
257 	glNewList(CurFrameId,GL_COMPILE);
258 	CurFrameId++;
259 	return CurFrameId-1;
260 }*/
261 //-----------------------------------------------------------------------------
GetRGBLines(long & width,long & height,unsigned char * & f,bool alpha)262 unsigned char **mglCanvasGL::GetRGBLines(long &width, long &height, unsigned char *&f, bool alpha)
263 {
264 	long x, y, d = alpha ? 4:3;
265 	GLint w[4];
266 	glGetIntegerv(GL_VIEWPORT,w);
267 	x=w[0];	y=w[1];	width=w[2];	height=w[3];
268 	unsigned char **p;
269 
270 	p = (unsigned char **)malloc(height * sizeof(unsigned char *));
271 	f = (unsigned char *) malloc(width*height * sizeof(unsigned char)*d);
272 	for(long i=0;i<height;i++)	p[i] = f+d*width*(height-1-i);
273 	glReadBuffer(GL_FRONT);
274 	glPixelStorei(GL_PACK_ALIGNMENT, 1);
275 	glReadPixels(x, y, width, height, alpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, f);
276 	return p;
277 }
278 //-----------------------------------------------------------------------------
quad_draw(long k1,long k2,long k3,long k4)279 void mglCanvasGL::quad_draw(long k1, long k2, long k3, long k4)
280 {
281 	glBegin(GL_QUADS);
282 	glArrayElement(k1);	glArrayElement(k2);
283 	glArrayElement(k4);	glArrayElement(k3);
284 	glEnd();
285 }
286 //-----------------------------------------------------------------------------
trig_draw(long k1,long k2,long k3)287 void mglCanvasGL::trig_draw(long k1, long k2, long k3)
288 {
289 	glBegin(GL_TRIANGLES);
290 	glArrayElement(k1);	glArrayElement(k2);	glArrayElement(k3);
291 	glEnd();
292 }
293 //-----------------------------------------------------------------------------
line_draw(long k1,long k2)294 void mglCanvasGL::line_draw(long k1, long k2)
295 {
296 	if(PDef==0)	return;
297 	set_pen(PDef,PenWidth, pPos);
298 	glBegin(GL_LINES);
299 	glArrayElement(k1);	glArrayElement(k2);
300 	glEnd();
301 }
302 //-----------------------------------------------------------------------------
quad_draw(const mglPnt & p1,const mglPnt & p2,const mglPnt & p3,const mglPnt & p4,const mglDrawReg *)303 void mglCanvasGL::quad_draw(const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, const mglPnt &p4, const mglDrawReg *)
304 {
305 	glBegin(GL_QUADS);
306 	glNormal3f(p1.u,p1.v,p1.w);	glColor4f(p1.r,p1.g,p1.b,p1.a);	glVertex3f(p1.x,p1.y,p1.z);
307 	glNormal3f(p2.u,p2.v,p2.w);	glColor4f(p2.r,p2.g,p2.b,p2.a);	glVertex3f(p2.x,p2.y,p2.z);
308 	glNormal3f(p4.u,p4.v,p4.w);	glColor4f(p4.r,p4.g,p4.b,p4.a);	glVertex3f(p4.x,p4.y,p4.z);
309 	glNormal3f(p3.u,p3.v,p3.w);	glColor4f(p3.r,p3.g,p3.b,p3.a);	glVertex3f(p3.x,p3.y,p3.z);
310 	glEnd();
311 }
312 //-----------------------------------------------------------------------------
trig_draw(const mglPnt & p1,const mglPnt & p2,const mglPnt & p3,bool,const mglDrawReg *)313 void mglCanvasGL::trig_draw(const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, bool, const mglDrawReg *)
314 {
315 	glBegin(GL_TRIANGLES);
316 	glNormal3f(p1.u,p1.v,p1.w);	glColor4f(p1.r,p1.g,p1.b,p1.a);	glVertex3f(p1.x,p1.y,p1.z);
317 	glNormal3f(p2.u,p2.v,p2.w);	glColor4f(p2.r,p2.g,p2.b,p2.a);	glVertex3f(p2.x,p2.y,p2.z);
318 	glNormal3f(p3.u,p3.v,p3.w);	glColor4f(p3.r,p3.g,p3.b,p3.a);	glVertex3f(p3.x,p3.y,p3.z);
319 	glEnd();
320 }
321 //-----------------------------------------------------------------------------
line_draw(const mglPnt & p1,const mglPnt & p2,const mglDrawReg *)322 void mglCanvasGL::line_draw(const mglPnt &p1, const mglPnt &p2, const mglDrawReg *)
323 {
324 	if(PDef==0)	return;
325 	set_pen(PDef,PenWidth, pPos);
326 	glBegin(GL_LINES);
327 	glColor4f(p1.r,p1.g,p1.b,p1.a);	glVertex3f(p1.x,p1.y,p1.z);
328 	glColor4f(p2.r,p2.g,p2.b,p2.a);	glVertex3f(p2.x,p2.y,p2.z);
329 	glEnd();
330 }
331 //-----------------------------------------------------------------------------
pnt_draw(const mglPnt & p1,const mglDrawReg *)332 void mglCanvasGL::pnt_draw(const mglPnt &p1, const mglDrawReg *)
333 {
334 	glBegin(GL_POINTS);
335 	glColor4f(p1.r,p1.g,p1.b,p1.a);	glVertex3f(p1.x,p1.y,p1.z);
336 	glEnd();
337 }
338 //-----------------------------------------------------------------------------
mark_draw(const mglPnt & q,char type,mreal size,mglDrawReg * d)339 void mglCanvasGL::mark_draw(const mglPnt &q, char type, mreal size, mglDrawReg *d)
340 {
341 	mglPnt p0=q,p1=q,p2=q,p3=q;
342 	mreal ss=fabs(size);
343 
344 	if(type=='.' || ss==0)
345 	{
346 		if(d)	d->PenWidth = ss?ss:sqrt(font_factor/400);
347 		pnt_draw(q,d);
348 	}
349 	else
350 	{
351 		if(d)
352 		{
353 			d->PDef = MGL_SOLID_MASK;	d->angle = 0;
354 			d->PenWidth*=fabs(50*size);
355 			if(d->PenWidth<1)	d->PenWidth=1;
356 		}
357 		if(!strchr("xsSoO",type))	ss *= 1.1;
358 		switch(type)
359 		{
360 		case 'P':
361 			p0.x = q.x-ss;	p0.y = q.y-ss;	p1.x = q.x+ss;	p1.y = q.y-ss;
362 			p2.x = q.x+ss;	p2.y = q.y+ss;	p3.x = q.x-ss;	p3.y = q.y+ss;
363 			line_draw(p0,p1,d);	line_draw(p1,p2,d);
364 			line_draw(p2,p3,d);	line_draw(p3,p0,d);
365 		case '+':
366 			p0.x = q.x-ss;	p0.y = q.y;	p1.x = q.x+ss;	p1.y = q.y;	line_draw(p0,p1,d);
367 			p2.x = q.x;	p2.y = q.y-ss;	p3.x = q.x;	p3.y = q.y+ss;	line_draw(p2,p3,d);
368 			break;
369 		case 'X':
370 			p0.x = q.x-ss;	p0.y = q.y-ss;	p1.x = q.x+ss;	p1.y = q.y-ss;
371 			p2.x = q.x+ss;	p2.y = q.y+ss;	p3.x = q.x-ss;	p3.y = q.y+ss;
372 			line_draw(p0,p1,d);	line_draw(p1,p2,d);
373 			line_draw(p2,p3,d);	line_draw(p3,p0,d);
374 		case 'x':
375 			p0.x = q.x-ss;	p0.y = q.y-ss;	p1.x = q.x+ss;	p1.y = q.y+ss;	line_draw(p0,p1,d);
376 			p2.x = q.x+ss;	p2.y = q.y-ss;	p3.x = q.x-ss;	p3.y = q.y+ss;	line_draw(p2,p3,d);
377 			break;
378 		case 'S':
379 			p0.x = q.x-ss;	p0.y = q.y-ss;	p1.x = q.x-ss;	p1.y = q.y+ss;
380 			p2.x= q.x+ss;	p2.y= q.y+ss;	p3.x = q.x+ss;	p3.y = q.y-ss;
381 			quad_draw(p0,p1,p3,p2,d);
382 		case 's':
383 			p0.x = q.x-ss;	p0.y = q.y-ss;	p1.x = q.x+ss;	p1.y = q.y-ss;
384 			p2.x = q.x+ss;	p2.y = q.y+ss;	p3.x = q.x-ss;	p3.y = q.y+ss;
385 			line_draw(p0,p1,d);	line_draw(p1,p2,d);
386 			line_draw(p2,p3,d);	line_draw(p3,p0,d);
387 			break;
388 		case 'D':
389 			p0.x = q.x;	p0.y = q.y-ss;	p1.x = q.x+ss;	p1.y = q.y;
390 			p2.x= q.x;	p2.y= q.y+ss;	p3.x = q.x-ss;	p3.y = q.y;
391 			quad_draw(p0,p1,p3,p2,d);
392 		case 'd':
393 			p0.x = q.x;	p0.y = q.y-ss;	p1.x = q.x+ss;	p1.y = q.y;
394 			p2.x = q.x;	p2.y = q.y+ss;	p3.x = q.x-ss;	p3.y = q.y;
395 			line_draw(p0,p1,d);	line_draw(p1,p2,d);
396 			line_draw(p2,p3,d);	line_draw(p3,p0,d);
397 			break;
398 		case 'Y':
399 			p1.x = q.x;	p1.y = q.y-ss;	line_draw(q,p1,d);
400 			p2.x = q.x-0.8*ss;	p2.y = q.y+0.6*ss;	line_draw(q,p2,d);
401 			p3.x = q.x+0.8*ss;	p3.y = q.y+0.6*ss;	line_draw(q,p3,d);
402 			break;
403 		case '*':
404 			p0.x = q.x-ss;		p0.y = q.y;
405 			p1.x = q.x+ss;		p1.y = q.y;	line_draw(p0,p1,d);
406 			p0.x = q.x-0.6*ss;	p0.y = q.y-0.8*ss;
407 			p1.x = q.x+0.6*ss;	p1.y = q.y+0.8*ss;	line_draw(p0,p1,d);
408 			p0.x = q.x-0.6*ss;	p0.y = q.y+0.8*ss;
409 			p1.x = q.x+0.6*ss;	p1.y = q.y-0.8*ss;	line_draw(p0,p1,d);
410 			break;
411 		case 'T':
412 			p0.x = q.x-ss;	p0.y = q.y-ss/2;
413 			p1.x = q.x+ss;	p1.y = q.y-ss/2;
414 			p2.x= q.x;		p2.y= q.y+ss;
415 			trig_draw(p0,p1,p2,false,d);
416 		case '^':
417 			p0.x = q.x-ss;	p0.y = q.y-ss/2;
418 			p1.x = q.x+ss;	p1.y = q.y-ss/2;
419 			p2.x= q.x;		p2.y= q.y+ss;
420 			line_draw(p0,p1,d);	line_draw(p1,p2,d);
421 			line_draw(p2,p0,d);	break;
422 		case 'V':
423 			p0.x = q.x-ss;	p0.y = q.y+ss/2;
424 			p1.x = q.x+ss;	p1.y = q.y+ss/2;
425 			p2.x= q.x;		p2.y= q.y-ss;
426 			trig_draw(p0,p1,p2,false,d);
427 		case 'v':
428 			p0.x = q.x-ss;	p0.y = q.y+ss/2;
429 			p1.x = q.x+ss;	p1.y = q.y+ss/2;
430 			p2.x= q.x;		p2.y= q.y-ss;
431 			line_draw(p0,p1,d);	line_draw(p1,p2,d);
432 			line_draw(p2,p0,d);	break;
433 		case 'L':
434 			p0.x = q.x+ss/2;	p0.y = q.y+ss;
435 			p1.x = q.x+ss/2;	p1.y = q.y-ss;
436 			p2.x= q.x-ss;		p2.y= q.y;
437 			trig_draw(p0,p1,p2,false,d);
438 		case '<':
439 			p0.x = q.x+ss/2;	p0.y = q.y+ss;
440 			p1.x = q.x+ss/2;	p1.y = q.y-ss;
441 			p2.x= q.x-ss;		p2.y= q.y;
442 			line_draw(p0,p1,d);	line_draw(p1,p2,d);
443 			line_draw(p2,p0,d);	break;
444 		case 'R':
445 			p0.x = q.x-ss/2;	p0.y = q.y+ss;
446 			p1.x = q.x-ss/2;	p1.y = q.y-ss;
447 			p2.x= q.x+ss;		p2.y= q.y;
448 			trig_draw(p0,p1,p2,false,d);
449 		case '>':
450 			p0.x = q.x-ss/2;	p0.y = q.y+ss;
451 			p1.x = q.x-ss/2;	p1.y = q.y-ss;
452 			p2.x= q.x+ss;		p2.y= q.y;
453 			line_draw(p0,p1,d);	line_draw(p1,p2,d);
454 			line_draw(p2,p0,d);	break;
455 		case 'O':
456 /*			for(long j=long(-ss);j<=long(ss);j++)	for(long i=long(-ss);i<=long(ss);i++)
457 			{
458 				long x=long(q.x)+i, y=long(q.y)+j;
459 				if(i*i+j*j>=ss*ss || !d || x<d->x1 || x>d->x2 || y<d->y1 || y>d->y2)	continue;
460 				if(cs[3])	pnt_plot(x,y,q.z+1,cs,d->ObjId);
461 			}*/
462 		case 'o':
463 			for(long i=0;i<=20;i++)	// TODO copy from mark_pix()?!
464 			{
465 				p0 = p1;	p1.x = q.x+ss*cos(i*M_PI/10);	p1.y = q.y+ss*sin(i*M_PI/10);
466 				if(i>0)	line_draw(p0,p1,d);
467 			}
468 			break;
469 		case 'C':
470 			pnt_draw(q,d);
471 			for(long i=0;i<=20;i++)
472 			{
473 				p0 = p1;	p1.x = q.x+ss*cos(i*M_PI/10);	p1.y = q.y+ss*sin(i*M_PI/10);
474 				if(i>0)	line_draw(p0,p1,d);
475 			}
476 			break;
477 		}
478 	}
479 }
480 //-----------------------------------------------------------------------------
glyph_fill(mreal phi,const mglPnt & pp,mreal f,const mglGlyph & g,const mglDrawReg * d)481 void mglCanvasGL::glyph_fill(mreal phi, const mglPnt &pp, mreal f, const mglGlyph &g, const mglDrawReg *d)
482 {
483 	if(!g.trig || g.nt<=0)	return;
484 	const mreal co=cos(phi*M_PI/180), si=sin(phi*M_PI/180);
485 	mglPnt q0=pp, q1=pp, q2=pp;
486 	q0.u=q0.v=q1.u=q1.v=q2.u=q2.v=NAN;
487 	for(long ik=0;ik<g.nt;ik++)
488 	{
489 		long ii = 6*ik;	mreal x, y;
490 		x = pp.u+g.trig[ii]*f;	y = pp.v+g.trig[ii+1]*f;
491 		q0.x = pp.x+(x*co+y*si)/2;	q0.y = pp.y+(y*co-x*si)/2;	ii+=2;
492 		x = pp.u+g.trig[ii]*f;	y = pp.v+g.trig[ii+1]*f;
493 		q1.x = pp.x+(x*co+y*si)/2;	q1.y = pp.y+(y*co-x*si)/2;	ii+=2;
494 		x = pp.u+g.trig[ii]*f;	y = pp.v+g.trig[ii+1]*f;
495 		q2.x = pp.x+(x*co+y*si)/2;	q2.y = pp.y+(y*co-x*si)/2;
496 		trig_draw(q0,q1,q2,false,d);
497 	}
498 }
499 //-----------------------------------------------------------------------------
500