ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.140
Committed: Mon Aug 14 03:41:25 2006 UTC (17 years, 9 months ago) by root
Branch: MAIN
Changes since 1.139: +0 -2 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.48 #ifdef _WIN32
2 root 1.131 # define WIN32_LEAN_AND_MEAN
3 root 1.79 # define _WIN32_WINNT 0x0500 // needed to get win2000 api calls
4 root 1.48 # include <malloc.h>
5 root 1.79 # include <windows.h>
6 root 1.75 # pragma warning(disable:4244)
7 root 1.48 #endif
8    
9 root 1.1 #include "EXTERN.h"
10     #include "perl.h"
11     #include "XSUB.h"
12    
13 root 1.131 #ifdef _WIN32
14     # undef pipe
15     #endif
16    
17 root 1.80 #include <math.h>
18 root 1.5 #include <string.h>
19 root 1.25 #include <stdio.h>
20 root 1.111 #include <stdlib.h>
21 root 1.5
22 root 1.2 #include <SDL.h>
23 root 1.76 #include <SDL_endian.h>
24 root 1.23 #include <SDL_image.h>
25 root 1.52 #include <SDL_mixer.h>
26 root 1.3 #include <SDL_opengl.h>
27 root 1.5
28 root 1.124 #define PANGO_ENABLE_BACKEND
29     #define G_DISABLE_CAST_CHECKS
30    
31 root 1.30 #include <glib/gmacros.h>
32    
33 root 1.5 #include <pango/pango.h>
34    
35 root 1.48 #ifndef _WIN32
36     # include <sys/types.h>
37     # include <sys/socket.h>
38     # include <netinet/in.h>
39     # include <netinet/tcp.h>
40     # include <inttypes.h>
41     #else
42     typedef unsigned char uint8_t;
43     typedef unsigned short uint16_t;
44     typedef unsigned int uint32_t;
45     typedef signed char int8_t;
46     typedef signed short int16_t;
47     typedef signed int int32_t;
48     #endif
49 root 1.28
50 root 1.121 #define OBJ_STR "\xef\xbf\xbc" /* U+FFFC, objetc replacement character */
51    
52 root 1.29 #define FOW_DARKNESS 32
53    
54     #define MAP_EXTEND_X 32
55     #define MAP_EXTEND_Y 512
56    
57 root 1.63 #define MIN_FONT_HEIGHT 10
58 root 1.58
59 root 1.127 #if 0
60 root 1.124 # define PARACHUTE SDL_INIT_NOPARACHUTE
61     #else
62     # define PARACHUTE 0
63     #endif
64    
65 root 1.103 static struct
66     {
67     #define GL_FUNC(ptr,name) ptr name;
68     #include "glfunc.h"
69     #undef GL_FUNC
70     } gl;
71    
72     static void gl_BlendFuncSeparate (GLenum sa, GLenum da, GLenum saa, GLenum daa)
73     {
74     if (gl.BlendFuncSeparate)
75     gl.BlendFuncSeparate (sa, da, saa, daa);
76     else if (gl.BlendFuncSeparateEXT)
77     gl.BlendFuncSeparateEXT (sa, da, saa, daa);
78     else
79     glBlendFunc (sa, da);
80     }
81 root 1.64
82 root 1.124 #include "texcache.c"
83    
84     #include "pango-font.c"
85     #include "pango-fontmap.c"
86     #include "pango-render.c"
87    
88 root 1.133 typedef Mix_Chunk *CFPlus__MixChunk;
89     typedef Mix_Music *CFPlus__MixMusic;
90 root 1.52
91 root 1.133 typedef PangoFontDescription *CFPlus__Font;
92 root 1.2
93 root 1.121 static int
94     shape_attr_p (PangoLayoutRun *run)
95     {
96     GSList *attrs = run->item->analysis.extra_attrs;
97    
98     while (attrs)
99     {
100     PangoAttribute *attr = attrs->data;
101    
102     if (attr->klass->type == PANGO_ATTR_SHAPE)
103     return 1;
104    
105     attrs = attrs->next;
106     }
107    
108     return 0;
109     }
110    
111 root 1.14 typedef struct cf_layout {
112 root 1.124 PangoLayout *pl;
113 root 1.76 float r, g, b, a; // default color for rgba mode
114 root 1.14 int base_height;
115 root 1.133 CFPlus__Font font;
116     } *CFPlus__Layout;
117 root 1.14
118 root 1.133 static CFPlus__Font default_font;
119 root 1.124 static PangoContext *opengl_context;
120     static PangoFontMap *opengl_fontmap;
121 root 1.61
122 root 1.14 static void
123 root 1.19 substitute_func (FcPattern *pattern, gpointer data)
124     {
125 root 1.108 FcPatternAddBool (pattern, FC_HINTING, 1);
126 root 1.110 #ifdef FC_HINT_STYLE
127 root 1.109 FcPatternAddBool (pattern, FC_HINT_STYLE, FC_HINT_FULL);
128 root 1.110 #endif
129 root 1.82 FcPatternAddBool (pattern, FC_AUTOHINT, 0);
130 root 1.19 }
131    
132     static void
133 root 1.133 layout_update_font (CFPlus__Layout self)
134 root 1.17 {
135 root 1.19 /* use a random scale factor to account for unknown descenders, 0.8 works
136     * reasonably well with bitstream vera
137     */
138 root 1.61 PangoFontDescription *font = self->font ? self->font : default_font;
139 root 1.46
140 root 1.61 pango_font_description_set_absolute_size (font,
141     MAX (MIN_FONT_HEIGHT, self->base_height) * (PANGO_SCALE * 8 / 10));
142 root 1.58
143 root 1.61 pango_layout_set_font_description (self->pl, font);
144 root 1.17 }
145    
146     static void
147 root 1.133 layout_get_pixel_size (CFPlus__Layout self, int *w, int *h)
148 root 1.14 {
149 root 1.139 PangoRectangle rect;
150 root 1.14
151 root 1.139 // get_pixel_* wrongly rounds down
152     pango_layout_get_extents (self->pl, 0, &rect);
153 root 1.76
154 root 1.139 rect.width = (rect.width + PANGO_SCALE - 1) / PANGO_SCALE;
155     rect.height = (rect.height + PANGO_SCALE - 1) / PANGO_SCALE;
156    
157     if (!rect.width) rect.width = 1;
158     if (!rect.height) rect.height = 1;
159    
160     *w = rect.width;
161     *h = rect.height;
162 root 1.14 }
163    
164 root 1.42 typedef uint16_t mapface;
165    
166 root 1.28 typedef struct {
167 root 1.30 GLint name;
168     int w, h;
169     float s, t;
170 root 1.39 uint8_t r, g, b, a;
171 root 1.42 } maptex;
172 root 1.30
173     typedef struct {
174 root 1.29 int16_t darkness;
175 root 1.42 mapface face[3];
176 root 1.28 } mapcell;
177    
178     typedef struct {
179 root 1.30 int32_t c0, c1;
180 root 1.28 mapcell *col;
181     } maprow;
182    
183     typedef struct map {
184     int x, y, w, h;
185 root 1.42 int ox, oy; /* offset to virtual global coordinate system */
186 root 1.28 int faces;
187 root 1.30 mapface *face;
188 root 1.28
189 root 1.42 int texs;
190     maptex *tex;
191    
192 root 1.48 int32_t rows;
193 root 1.28 maprow *row;
194 root 1.133 } *CFPlus__Map;
195 root 1.28
196 root 1.30 static char *
197     prepend (char *ptr, int sze, int inc)
198     {
199     char *p;
200    
201     New (0, p, sze + inc, char);
202     Zero (p, inc, char);
203     Move (ptr, p + inc, sze, char);
204     Safefree (ptr);
205    
206     return p;
207     }
208    
209     static char *
210     append (char *ptr, int sze, int inc)
211     {
212     Renew (ptr, sze + inc, char);
213     Zero (ptr + sze, inc, char);
214    
215     return ptr;
216     }
217    
218     #define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
219     #define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
220    
221 root 1.42 static maprow *
222 root 1.133 map_get_row (CFPlus__Map self, int y)
223 root 1.42 {
224     if (0 > y)
225     {
226     int extend = - y + MAP_EXTEND_Y;
227     Prepend (maprow, self->row, self->rows, extend);
228    
229     self->rows += extend;
230     self->y += extend;
231     y += extend;
232     }
233     else if (y >= self->rows)
234     {
235     int extend = y - self->rows + MAP_EXTEND_Y;
236     Append (maprow, self->row, self->rows, extend);
237     self->rows += extend;
238     }
239    
240     return self->row + y;
241     }
242    
243     static mapcell *
244     row_get_cell (maprow *row, int x)
245     {
246     if (!row->col)
247     {
248     Newz (0, row->col, MAP_EXTEND_X, mapcell);
249     row->c0 = x - MAP_EXTEND_X / 4;
250     row->c1 = row->c0 + MAP_EXTEND_X;
251     }
252    
253     if (row->c0 > x)
254     {
255     int extend = row->c0 - x + MAP_EXTEND_X;
256     Prepend (mapcell, row->col, row->c1 - row->c0, extend);
257     row->c0 -= extend;
258     }
259     else if (x >= row->c1)
260     {
261     int extend = x - row->c1 + MAP_EXTEND_X;
262     Append (mapcell, row->col, row->c1 - row->c0, extend);
263     row->c1 += extend;
264     }
265    
266     return row->col + (x - row->c0);
267     }
268    
269     static mapcell *
270 root 1.133 map_get_cell (CFPlus__Map self, int x, int y)
271 root 1.42 {
272     return row_get_cell (map_get_row (self, y), x);
273     }
274    
275 root 1.30 static void
276 root 1.133 map_clear (CFPlus__Map self)
277 root 1.30 {
278     int r;
279    
280     for (r = 0; r < self->rows; r++)
281     Safefree (self->row[r].col);
282    
283     Safefree (self->row);
284    
285     self->x = 0;
286     self->y = 0;
287 root 1.42 self->ox = 0;
288     self->oy = 0;
289 root 1.30 self->row = 0;
290     self->rows = 0;
291     }
292    
293 root 1.29 static void
294 root 1.133 map_blank (CFPlus__Map self, int x0, int y0, int w, int h)
295 root 1.29 {
296     int x, y;
297 root 1.48 maprow *row;
298 root 1.29
299     for (y = y0; y < y0 + h; y++)
300 root 1.30 if (y >= 0)
301     {
302     if (y >= self->rows)
303     break;
304    
305 root 1.48 row = self->row + y;
306 root 1.30
307     for (x = x0; x < x0 + w; x++)
308     if (x >= row->c0)
309     {
310     if (x >= row->c1)
311     break;
312 root 1.29
313 root 1.31 row->col[x - row->c0].darkness = -1;
314 root 1.30 }
315     }
316 root 1.29 }
317    
318 root 1.56 static void
319 root 1.75 music_finished (void)
320 root 1.56 {
321     SDL_UserEvent ev;
322    
323     ev.type = SDL_USEREVENT;
324     ev.code = 0;
325     ev.data1 = 0;
326     ev.data2 = 0;
327    
328 root 1.57 SDL_PushEvent ((SDL_Event *)&ev);
329 root 1.56 }
330    
331 root 1.71 static void
332     channel_finished (int channel)
333     {
334     SDL_UserEvent ev;
335    
336     ev.type = SDL_USEREVENT;
337     ev.code = 1;
338 root 1.74 ev.data1 = (void *)(long)channel;
339 root 1.71 ev.data2 = 0;
340    
341     SDL_PushEvent ((SDL_Event *)&ev);
342     }
343    
344 root 1.113 static unsigned int
345     minpot (unsigned int n)
346     {
347     if (!n)
348     return 0;
349    
350     --n;
351    
352     n |= n >> 1;
353     n |= n >> 2;
354     n |= n >> 4;
355     n |= n >> 8;
356     n |= n >> 16;
357    
358     return n + 1;
359     }
360    
361 root 1.133 MODULE = CFPlus PACKAGE = CFPlus
362 root 1.1
363 root 1.11 PROTOTYPES: ENABLE
364    
365 root 1.5 BOOT:
366     {
367 root 1.133 HV *stash = gv_stashpv ("CFPlus", 1);
368 root 1.51 static const struct {
369     const char *name;
370     IV iv;
371     } *civ, const_iv[] = {
372     # define const_iv(name) { # name, (IV)name }
373     const_iv (SDL_ACTIVEEVENT),
374     const_iv (SDL_KEYDOWN),
375     const_iv (SDL_KEYUP),
376     const_iv (SDL_MOUSEMOTION),
377     const_iv (SDL_MOUSEBUTTONDOWN),
378     const_iv (SDL_MOUSEBUTTONUP),
379     const_iv (SDL_JOYAXISMOTION),
380     const_iv (SDL_JOYBALLMOTION),
381     const_iv (SDL_JOYHATMOTION),
382     const_iv (SDL_JOYBUTTONDOWN),
383     const_iv (SDL_JOYBUTTONUP),
384     const_iv (SDL_QUIT),
385     const_iv (SDL_SYSWMEVENT),
386     const_iv (SDL_EVENT_RESERVEDA),
387     const_iv (SDL_EVENT_RESERVEDB),
388     const_iv (SDL_VIDEORESIZE),
389     const_iv (SDL_VIDEOEXPOSE),
390     const_iv (SDL_USEREVENT),
391     const_iv (SDLK_KP0),
392     const_iv (SDLK_KP1),
393     const_iv (SDLK_KP2),
394     const_iv (SDLK_KP3),
395     const_iv (SDLK_KP4),
396     const_iv (SDLK_KP5),
397     const_iv (SDLK_KP6),
398     const_iv (SDLK_KP7),
399     const_iv (SDLK_KP8),
400     const_iv (SDLK_KP9),
401     const_iv (SDLK_KP_PERIOD),
402     const_iv (SDLK_KP_DIVIDE),
403     const_iv (SDLK_KP_MULTIPLY),
404     const_iv (SDLK_KP_MINUS),
405     const_iv (SDLK_KP_PLUS),
406     const_iv (SDLK_KP_ENTER),
407     const_iv (SDLK_KP_EQUALS),
408     const_iv (SDLK_UP),
409     const_iv (SDLK_DOWN),
410     const_iv (SDLK_RIGHT),
411     const_iv (SDLK_LEFT),
412     const_iv (SDLK_INSERT),
413     const_iv (SDLK_HOME),
414     const_iv (SDLK_END),
415     const_iv (SDLK_PAGEUP),
416     const_iv (SDLK_PAGEDOWN),
417     const_iv (SDLK_F1),
418     const_iv (SDLK_F2),
419     const_iv (SDLK_F3),
420     const_iv (SDLK_F4),
421     const_iv (SDLK_F5),
422     const_iv (SDLK_F6),
423     const_iv (SDLK_F7),
424     const_iv (SDLK_F8),
425     const_iv (SDLK_F9),
426     const_iv (SDLK_F10),
427     const_iv (SDLK_F11),
428     const_iv (SDLK_F12),
429     const_iv (SDLK_F13),
430     const_iv (SDLK_F14),
431     const_iv (SDLK_F15),
432     const_iv (SDLK_NUMLOCK),
433     const_iv (SDLK_CAPSLOCK),
434     const_iv (SDLK_SCROLLOCK),
435     const_iv (SDLK_RSHIFT),
436     const_iv (SDLK_LSHIFT),
437     const_iv (SDLK_RCTRL),
438     const_iv (SDLK_LCTRL),
439     const_iv (SDLK_RALT),
440     const_iv (SDLK_LALT),
441     const_iv (SDLK_RMETA),
442     const_iv (SDLK_LMETA),
443     const_iv (SDLK_LSUPER),
444     const_iv (SDLK_RSUPER),
445     const_iv (SDLK_MODE),
446     const_iv (SDLK_COMPOSE),
447     const_iv (SDLK_HELP),
448     const_iv (SDLK_PRINT),
449     const_iv (SDLK_SYSREQ),
450     const_iv (SDLK_BREAK),
451     const_iv (SDLK_MENU),
452     const_iv (SDLK_POWER),
453     const_iv (SDLK_EURO),
454     const_iv (SDLK_UNDO),
455     const_iv (KMOD_NONE),
456     const_iv (KMOD_LSHIFT),
457     const_iv (KMOD_RSHIFT),
458     const_iv (KMOD_LCTRL),
459     const_iv (KMOD_RCTRL),
460     const_iv (KMOD_LALT),
461     const_iv (KMOD_RALT),
462     const_iv (KMOD_LMETA),
463     const_iv (KMOD_RMETA),
464     const_iv (KMOD_NUM),
465     const_iv (KMOD_CAPS),
466     const_iv (KMOD_MODE),
467     const_iv (KMOD_CTRL),
468     const_iv (KMOD_SHIFT),
469     const_iv (KMOD_ALT),
470     const_iv (KMOD_META)
471     # undef const_iv
472     };
473    
474     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
475     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
476 root 1.79 }
477 root 1.51
478 root 1.129 int
479     in_destruct ()
480     CODE:
481     RETVAL = PL_main_cv == Nullcv;
482     OUTPUT:
483     RETVAL
484    
485 root 1.116 NV floor (NV x)
486    
487     NV ceil (NV x)
488    
489 root 1.79 void
490     pango_init ()
491     CODE:
492     {
493 root 1.124 opengl_fontmap = pango_opengl_font_map_new ();
494     pango_opengl_font_map_set_default_substitute ((PangoOpenGLFontMap *)opengl_fontmap, substitute_func, 0, 0);
495     opengl_context = pango_opengl_font_map_create_context ((PangoOpenGLFontMap *)opengl_fontmap);
496 root 1.5 }
497    
498 root 1.51 int
499 root 1.124 SDL_Init (U32 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | PARACHUTE)
500 root 1.51
501     void
502     SDL_Quit ()
503    
504     void
505     SDL_ListModes ()
506     PPCODE:
507     {
508     SDL_Rect **m;
509    
510     SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5);
511     SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5);
512     SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5);
513 root 1.88 SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 1);
514 root 1.51
515 root 1.88 SDL_GL_SetAttribute (SDL_GL_BUFFER_SIZE, 15);
516 root 1.115 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 0);
517 root 1.85
518 root 1.51 SDL_GL_SetAttribute (SDL_GL_ACCUM_RED_SIZE, 0);
519     SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0);
520     SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE, 0);
521     SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0);
522    
523     SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
524 root 1.134 #if SDL_VERSION_ATLEAST(1,2,10)
525 root 1.131 SDL_GL_SetAttribute (SDL_GL_ACCELERATED_VISUAL, 1);
526     SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1);
527 root 1.134 #endif
528 root 1.51
529 root 1.53 SDL_EnableUNICODE (1);
530     SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
531    
532 root 1.51 m = SDL_ListModes (0, SDL_FULLSCREEN | SDL_OPENGL);
533    
534     if (m && m != (SDL_Rect **)-1)
535     while (*m)
536     {
537     AV *av = newAV ();
538     av_push (av, newSViv ((*m)->w));
539     av_push (av, newSViv ((*m)->h));
540     XPUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
541    
542     ++m;
543     }
544     }
545    
546 root 1.88 char *
547     SDL_GetError ()
548    
549 root 1.51 int
550     SDL_SetVideoMode (int w, int h, int fullscreen)
551     CODE:
552     RETVAL = !!SDL_SetVideoMode (
553     w, h, 0, SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0)
554     );
555 root 1.103 if (RETVAL)
556     {
557     SDL_WM_SetCaption ("Crossfire+ Client " VERSION, "Crossfire+");
558     # define GL_FUNC(ptr,name) gl.name = (ptr)SDL_GL_GetProcAddress ("gl" # name);
559     # include "glfunc.h"
560     # undef GL_FUNC
561     }
562 root 1.51 OUTPUT:
563     RETVAL
564    
565 root 1.53 void
566 root 1.54 SDL_GL_SwapBuffers ()
567    
568 root 1.94 char *
569     SDL_GetKeyName (int sym)
570    
571 root 1.54 void
572 root 1.53 SDL_PollEvent ()
573     PPCODE:
574     {
575     SDL_Event ev;
576    
577     while (SDL_PollEvent (&ev))
578     {
579     HV *hv = newHV ();
580     hv_store (hv, "type", 4, newSViv (ev.type), 0);
581 root 1.70
582 root 1.53 switch (ev.type)
583     {
584     case SDL_KEYDOWN:
585     case SDL_KEYUP:
586     hv_store (hv, "state", 5, newSViv (ev.key.state), 0);
587     hv_store (hv, "sym", 3, newSViv (ev.key.keysym.sym), 0);
588     hv_store (hv, "mod", 3, newSViv (ev.key.keysym.mod), 0);
589     hv_store (hv, "unicode", 7, newSViv (ev.key.keysym.unicode), 0);
590     break;
591    
592     case SDL_ACTIVEEVENT:
593     hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0);
594     hv_store (hv, "state", 5, newSViv (ev.active.state), 0);
595     break;
596    
597     case SDL_MOUSEMOTION:
598 root 1.94 hv_store (hv, "mod", 3, newSViv (SDL_GetModState ()), 0);
599 root 1.93
600 root 1.53 hv_store (hv, "state", 5, newSViv (ev.motion.state), 0);
601     hv_store (hv, "x", 1, newSViv (ev.motion.x), 0);
602     hv_store (hv, "y", 1, newSViv (ev.motion.y), 0);
603     hv_store (hv, "xrel", 4, newSViv (ev.motion.xrel), 0);
604     hv_store (hv, "yrel", 4, newSViv (ev.motion.yrel), 0);
605     break;
606    
607     case SDL_MOUSEBUTTONDOWN:
608     case SDL_MOUSEBUTTONUP:
609 root 1.94 hv_store (hv, "mod", 3, newSViv (SDL_GetModState ()), 0);
610 root 1.93
611 root 1.53 hv_store (hv, "button", 6, newSViv (ev.button.button), 0);
612     hv_store (hv, "state", 5, newSViv (ev.button.state), 0);
613     hv_store (hv, "x", 1, newSViv (ev.button.x), 0);
614     hv_store (hv, "y", 1, newSViv (ev.button.y), 0);
615 root 1.70 break;
616 root 1.72
617     case SDL_USEREVENT:
618     hv_store (hv, "code", 4, newSViv (ev.user.code), 0);
619     hv_store (hv, "data1", 5, newSViv ((IV)ev.user.data1), 0);
620     hv_store (hv, "data2", 5, newSViv ((IV)ev.user.data2), 0);
621     break;
622 root 1.53 }
623    
624 root 1.133 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("CFPlus::UI::Event", 1))));
625 root 1.53 }
626     }
627 root 1.52
628     int
629 root 1.73 Mix_OpenAudio (int frequency = 48000, int format = MIX_DEFAULT_FORMAT, int channels = 1, int chunksize = 2048)
630 root 1.56 POSTCALL:
631     Mix_HookMusicFinished (music_finished);
632 root 1.71 Mix_ChannelFinished (channel_finished);
633 root 1.52
634     void
635     Mix_CloseAudio ()
636    
637     int
638     Mix_AllocateChannels (int numchans = -1)
639    
640 root 1.10 void
641     lowdelay (int fd, int val = 1)
642     CODE:
643 root 1.48 #ifndef _WIN32
644 root 1.10 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof (val));
645 root 1.48 #endif
646 root 1.10
647 root 1.5 void
648 root 1.13 add_font (char *file)
649     CODE:
650 root 1.129 FcConfigAppFontAddFile (0, (const FcChar8 *)file);
651 root 1.13
652     void
653 root 1.23 load_image_inline (SV *image_)
654     ALIAS:
655     load_image_file = 1
656     PPCODE:
657     {
658     STRLEN image_len;
659     char *image = (char *)SvPVbyte (image_, image_len);
660     SDL_Surface *surface, *surface2;
661     SDL_PixelFormat fmt;
662     SDL_RWops *rw = ix
663     ? SDL_RWFromFile (image, "r")
664     : SDL_RWFromConstMem (image, image_len);
665    
666     if (!rw)
667 root 1.41 croak ("load_image: %s", SDL_GetError ());
668 root 1.23
669     surface = IMG_Load_RW (rw, 1);
670     if (!surface)
671 root 1.41 croak ("load_image: %s", SDL_GetError ());
672 root 1.23
673     fmt.palette = NULL;
674     fmt.BitsPerPixel = 32;
675     fmt.BytesPerPixel = 4;
676 root 1.49 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
677 root 1.23 fmt.Rmask = 0x000000ff;
678     fmt.Gmask = 0x0000ff00;
679     fmt.Bmask = 0x00ff0000;
680     fmt.Amask = 0xff000000;
681 root 1.49 #else
682     fmt.Rmask = 0xff000000;
683     fmt.Gmask = 0x00ff0000;
684     fmt.Bmask = 0x0000ff00;
685     fmt.Amask = 0x000000ff;
686     #endif
687 root 1.23 fmt.Rloss = 0;
688     fmt.Gloss = 0;
689     fmt.Bloss = 0;
690     fmt.Aloss = 0;
691     fmt.Rshift = 0;
692     fmt.Gshift = 8;
693     fmt.Bshift = 16;
694     fmt.Ashift = 24;
695     fmt.colorkey = 0;
696     fmt.alpha = 0;
697    
698     surface2 = SDL_ConvertSurface (surface, &fmt, SDL_SWSURFACE);
699    
700 root 1.39 assert (surface2->pitch == surface2->w * 4);
701    
702 root 1.129 SDL_LockSurface (surface2);
703     EXTEND (SP, 6);
704 root 1.23 PUSHs (sv_2mortal (newSViv (surface2->w)));
705     PUSHs (sv_2mortal (newSViv (surface2->h)));
706     PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch)));
707 root 1.116 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
708 root 1.23 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
709 root 1.49 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
710 root 1.129 SDL_UnlockSurface (surface2);
711 root 1.23
712     SDL_FreeSurface (surface);
713     SDL_FreeSurface (surface2);
714     }
715    
716 root 1.25 void
717 root 1.39 average (int x, int y, uint32_t *data)
718     PPCODE:
719     {
720     uint32_t r = 0, g = 0, b = 0, a = 0;
721    
722     x = y = x * y;
723    
724     while (x--)
725     {
726     uint32_t p = *data++;
727    
728     r += (p ) & 255;
729     g += (p >> 8) & 255;
730     b += (p >> 16) & 255;
731     a += (p >> 24) & 255;
732     }
733    
734     EXTEND (SP, 4);
735 root 1.40 PUSHs (sv_2mortal (newSViv (r / y)));
736     PUSHs (sv_2mortal (newSViv (g / y)));
737     PUSHs (sv_2mortal (newSViv (b / y)));
738     PUSHs (sv_2mortal (newSViv (a / y)));
739 root 1.39 }
740    
741     void
742 root 1.66 error (char *message)
743     CODE:
744 root 1.86 fprintf (stderr, "ERROR: %s\n", message);
745 root 1.66 #ifdef _WIN32
746 root 1.86 MessageBox (0, message, "Crossfire+ Error", MB_OK | MB_ICONERROR);
747 root 1.66 #endif
748    
749     void
750 root 1.25 fatal (char *message)
751     CODE:
752 root 1.86 fprintf (stderr, "FATAL: %s\n", message);
753 root 1.50 #ifdef _WIN32
754 root 1.86 MessageBox (0, message, "Crossfire+ Fatal Error", MB_OK | MB_ICONERROR);
755 root 1.25 #endif
756 root 1.112 _exit (1);
757 root 1.111
758     void
759     _exit (int retval)
760     CODE:
761 root 1.112 _exit (retval);
762 root 1.25
763 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Font
764 root 1.61
765 root 1.133 CFPlus::Font
766 root 1.70 new_from_file (SV *class, char *path, int id = 0)
767 root 1.61 CODE:
768     {
769     int count;
770 root 1.70 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count);
771 root 1.61 RETVAL = pango_fc_font_description_from_pattern (pattern, 0);
772     FcPatternDestroy (pattern);
773     }
774     OUTPUT:
775     RETVAL
776    
777     void
778 root 1.133 DESTROY (CFPlus::Font self)
779 root 1.61 CODE:
780     pango_font_description_free (self);
781    
782     void
783 root 1.133 make_default (CFPlus::Font self)
784 root 1.61 CODE:
785     default_font = self;
786    
787 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Layout
788 root 1.14
789 root 1.124 void
790 root 1.129 reset_glyph_cache ()
791 root 1.124 CODE:
792     tc_clear ();
793    
794 root 1.133 CFPlus::Layout
795 root 1.128 new (SV *class)
796 root 1.14 CODE:
797     New (0, RETVAL, 1, struct cf_layout);
798 root 1.76
799 root 1.124 RETVAL->pl = pango_layout_new (opengl_context);
800 root 1.76 RETVAL->r = 1.;
801     RETVAL->g = 1.;
802     RETVAL->b = 1.;
803     RETVAL->a = 1.;
804     RETVAL->base_height = MIN_FONT_HEIGHT;
805     RETVAL->font = 0;
806    
807 root 1.14 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
808 root 1.76 layout_update_font (RETVAL);
809 root 1.14 OUTPUT:
810     RETVAL
811    
812     void
813 root 1.133 DESTROY (CFPlus::Layout self)
814 root 1.14 CODE:
815     g_object_unref (self->pl);
816     Safefree (self);
817 root 1.13
818 root 1.8 void
819 root 1.133 set_text (CFPlus::Layout self, SV *text_)
820 root 1.35 CODE:
821     {
822     STRLEN textlen;
823     char *text = SvPVutf8 (text_, textlen);
824    
825     pango_layout_set_text (self->pl, text, textlen);
826     }
827    
828     void
829 root 1.133 set_markup (CFPlus::Layout self, SV *text_)
830 root 1.14 CODE:
831 root 1.5 {
832     STRLEN textlen;
833     char *text = SvPVutf8 (text_, textlen);
834 root 1.14
835     pango_layout_set_markup (self->pl, text, textlen);
836     }
837    
838 root 1.121 void
839 root 1.133 set_shapes (CFPlus::Layout self, ...)
840 root 1.121 CODE:
841     {
842     PangoAttrList *attrs = 0;
843     const char *text = pango_layout_get_text (self->pl);
844     const char *pos = text;
845 root 1.122 int arg = 4;
846 root 1.121
847     while (arg < items && (pos = strstr (pos, OBJ_STR)))
848     {
849 root 1.122 PangoRectangle inkrect, rect;
850 root 1.121 PangoAttribute *attr;
851    
852 root 1.122 int x = SvIV (ST (arg - 3));
853     int y = SvIV (ST (arg - 2));
854 root 1.121 int w = SvIV (ST (arg - 1));
855 root 1.122 int h = SvIV (ST (arg ));
856 root 1.121
857 root 1.122 inkrect.x = 0;
858     inkrect.y = 0;
859     inkrect.width = 0;
860     inkrect.height = 0;
861    
862     rect.x = x * PANGO_SCALE;
863     rect.y = y * PANGO_SCALE;
864     rect.width = w * PANGO_SCALE;
865 root 1.121 rect.height = h * PANGO_SCALE;
866    
867     if (!attrs)
868     attrs = pango_layout_get_attributes (self->pl);
869    
870 root 1.122 attr = pango_attr_shape_new (&inkrect, &rect);
871 root 1.121 attr->start_index = pos - text;
872     attr->end_index = attr->start_index + sizeof (OBJ_STR) - 1;
873     pango_attr_list_insert (attrs, attr);
874    
875 root 1.122 arg += 4;
876 root 1.121 pos += sizeof (OBJ_STR) - 1;
877     }
878    
879     if (attrs)
880     pango_layout_set_attributes (self->pl, attrs);
881     }
882    
883     void
884 root 1.133 get_shapes (CFPlus::Layout self)
885 root 1.121 PPCODE:
886     {
887     PangoLayoutIter *iter = pango_layout_get_iter (self->pl);
888    
889     do
890     {
891     PangoLayoutRun *run = pango_layout_iter_get_run (iter);
892    
893     if (run && shape_attr_p (run))
894     {
895     PangoRectangle extents;
896     pango_layout_iter_get_run_extents (iter, 0, &extents);
897    
898 root 1.129 EXTEND (SP, 2);
899 root 1.121 PUSHs (sv_2mortal (newSViv (PANGO_PIXELS (extents.x))));
900     PUSHs (sv_2mortal (newSViv (PANGO_PIXELS (extents.y))));
901     }
902     }
903     while (pango_layout_iter_next_run (iter));
904    
905     pango_layout_iter_free (iter);
906     }
907    
908     int
909 root 1.133 has_wrapped (CFPlus::Layout self)
910 root 1.121 CODE:
911     {
912     int lines = 1;
913     const char *text = pango_layout_get_text (self->pl);
914    
915     while (*text)
916     lines += *text++ == '\n';
917    
918     RETVAL = lines < pango_layout_get_line_count (self->pl);
919     }
920     OUTPUT:
921     RETVAL
922    
923 root 1.46 SV *
924 root 1.133 get_text (CFPlus::Layout self)
925 root 1.46 CODE:
926 root 1.47 RETVAL = newSVpv (pango_layout_get_text (self->pl), 0);
927 root 1.107 sv_utf8_decode (RETVAL);
928 root 1.46 OUTPUT:
929     RETVAL
930    
931 root 1.14 void
932 root 1.133 set_foreground (CFPlus::Layout self, float r, float g, float b, float a = 1.)
933 root 1.76 CODE:
934     self->r = r;
935     self->g = g;
936     self->b = b;
937     self->a = a;
938    
939     void
940 root 1.133 set_font (CFPlus::Layout self, CFPlus::Font font = 0)
941 root 1.61 CODE:
942     if (self->font != font)
943     {
944     self->font = font;
945     layout_update_font (self);
946     }
947    
948     void
949 root 1.133 set_height (CFPlus::Layout self, int base_height)
950 root 1.16 CODE:
951 root 1.61 if (self->base_height != base_height)
952     {
953     self->base_height = base_height;
954     layout_update_font (self);
955     }
956 root 1.16
957     void
958 root 1.133 set_width (CFPlus::Layout self, int max_width = -1)
959 root 1.14 CODE:
960     pango_layout_set_width (self->pl, max_width < 0 ? max_width : max_width * PANGO_SCALE);
961    
962     void
963 root 1.133 set_indent (CFPlus::Layout self, int indent)
964 root 1.84 CODE:
965     pango_layout_set_indent (self->pl, indent * PANGO_SCALE);
966    
967     void
968 root 1.133 set_spacing (CFPlus::Layout self, int spacing)
969 root 1.84 CODE:
970     pango_layout_set_spacing (self->pl, spacing * PANGO_SCALE);
971    
972     void
973 root 1.133 set_ellipsise (CFPlus::Layout self, int ellipsise)
974 root 1.84 CODE:
975     pango_layout_set_ellipsize (self->pl,
976     ellipsise == 1 ? PANGO_ELLIPSIZE_START
977     : ellipsise == 2 ? PANGO_ELLIPSIZE_MIDDLE
978     : ellipsise == 3 ? PANGO_ELLIPSIZE_END
979     : PANGO_ELLIPSIZE_NONE
980     );
981    
982     void
983 root 1.133 set_single_paragraph_mode (CFPlus::Layout self, int spm)
984 root 1.84 CODE:
985     pango_layout_set_single_paragraph_mode (self->pl, !!spm);
986    
987     void
988 root 1.133 size (CFPlus::Layout self)
989 root 1.14 PPCODE:
990     {
991     int w, h;
992    
993     layout_get_pixel_size (self, &w, &h);
994    
995     EXTEND (SP, 2);
996     PUSHs (sv_2mortal (newSViv (w)));
997     PUSHs (sv_2mortal (newSViv (h)));
998     }
999    
1000 root 1.17 int
1001 root 1.133 descent (CFPlus::Layout self)
1002 root 1.122 CODE:
1003     {
1004     PangoRectangle rect;
1005     PangoLayoutLine *line = pango_layout_get_line (self->pl, 0);
1006     pango_layout_line_get_pixel_extents (line, 0, &rect);
1007     RETVAL = PANGO_DESCENT (rect);
1008     }
1009     OUTPUT:
1010     RETVAL
1011    
1012     int
1013 root 1.133 xy_to_index (CFPlus::Layout self, int x, int y)
1014 root 1.17 CODE:
1015     {
1016     int index, trailing;
1017     pango_layout_xy_to_index (self->pl, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing);
1018     RETVAL = index;
1019     }
1020     OUTPUT:
1021     RETVAL
1022    
1023     void
1024 root 1.133 cursor_pos (CFPlus::Layout self, int index)
1025 root 1.17 PPCODE:
1026     {
1027     PangoRectangle strong_pos;
1028     pango_layout_get_cursor_pos (self->pl, index, &strong_pos, 0);
1029 root 1.30
1030 root 1.17 EXTEND (SP, 3);
1031     PUSHs (sv_2mortal (newSViv (strong_pos.x / PANGO_SCALE)));
1032     PUSHs (sv_2mortal (newSViv (strong_pos.y / PANGO_SCALE)));
1033     PUSHs (sv_2mortal (newSViv (strong_pos.height / PANGO_SCALE)));
1034     }
1035    
1036 root 1.14 void
1037 root 1.135 render (CFPlus::Layout self, float x, float y, int flags = 0)
1038 root 1.14 PPCODE:
1039 root 1.124 pango_opengl_render_layout_subpixel (
1040     self->pl,
1041     x * PANGO_SCALE, y * PANGO_SCALE,
1042 root 1.135 self->r, self->g, self->b, self->a,
1043     flags
1044 root 1.124 );
1045 root 1.11
1046 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Texture
1047 root 1.11
1048     void
1049 root 1.113 pad2pot (SV *data_, SV *w_, SV *h_)
1050     CODE:
1051     {
1052     int ow = SvIV (w_);
1053     int oh = SvIV (h_);
1054    
1055     if (ow && oh)
1056     {
1057     int nw = minpot (ow);
1058     int nh = minpot (oh);
1059    
1060     if (nw != ow || nh != oh)
1061     {
1062     if (SvOK (data_))
1063     {
1064     STRLEN datalen;
1065     char *data = SvPVbyte (data_, datalen);
1066     int bpp = datalen / (ow * oh);
1067     SV *result_ = sv_2mortal (newSV (nw * nh * bpp));
1068    
1069     SvPOK_only (result_);
1070     SvCUR_set (result_, nw * nh * bpp);
1071    
1072     memset (SvPVX (result_), 0, nw * nh * bpp);
1073     while (oh--)
1074     memcpy (SvPVX (result_) + oh * nw * bpp, data + oh * ow * bpp, ow * bpp);
1075    
1076     sv_setsv (data_, result_);
1077     }
1078    
1079     sv_setiv (w_, nw);
1080     sv_setiv (h_, nh);
1081     }
1082     }
1083     }
1084    
1085     void
1086 root 1.114 draw_quad (SV *self, float x, float y, float w = 0., float h = 0.)
1087 root 1.12 PROTOTYPE: $$$;$$
1088 root 1.76 ALIAS:
1089     draw_quad_alpha = 1
1090     draw_quad_alpha_premultiplied = 2
1091 root 1.11 CODE:
1092     {
1093 root 1.12 HV *hv = (HV *)SvRV (self);
1094 root 1.37 float s = SvNV (*hv_fetch (hv, "s", 1, 1));
1095     float t = SvNV (*hv_fetch (hv, "t", 1, 1));
1096 root 1.12 int name = SvIV (*hv_fetch (hv, "name", 4, 1));
1097    
1098     if (items < 5)
1099     {
1100 root 1.18 w = SvNV (*hv_fetch (hv, "w", 1, 1));
1101     h = SvNV (*hv_fetch (hv, "h", 1, 1));
1102 root 1.12 }
1103    
1104 root 1.76 if (ix)
1105     {
1106     glEnable (GL_BLEND);
1107 root 1.103
1108     if (ix == 2)
1109     glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1110     else
1111     gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1112 root 1.104 GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
1113 root 1.103
1114 root 1.86 glEnable (GL_ALPHA_TEST);
1115     glAlphaFunc (GL_GREATER, 0.01f);
1116 root 1.76 }
1117    
1118 root 1.12 glBindTexture (GL_TEXTURE_2D, name);
1119 root 1.76
1120 root 1.12 glBegin (GL_QUADS);
1121 root 1.37 glTexCoord2f (0, 0); glVertex2f (x , y );
1122     glTexCoord2f (0, t); glVertex2f (x , y + h);
1123     glTexCoord2f (s, t); glVertex2f (x + w, y + h);
1124     glTexCoord2f (s, 0); glVertex2f (x + w, y );
1125 root 1.12 glEnd ();
1126 root 1.76
1127     if (ix)
1128 root 1.86 {
1129     glDisable (GL_ALPHA_TEST);
1130     glDisable (GL_BLEND);
1131     }
1132 root 1.11 }
1133 root 1.28
1134 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Map
1135 root 1.28
1136 root 1.133 CFPlus::Map
1137 root 1.28 new (SV *class, int map_width, int map_height)
1138     CODE:
1139     New (0, RETVAL, 1, struct map);
1140 root 1.42 RETVAL->x = 0;
1141     RETVAL->y = 0;
1142     RETVAL->w = map_width;
1143     RETVAL->h = map_height;
1144     RETVAL->ox = 0;
1145     RETVAL->oy = 0;
1146 root 1.30 RETVAL->faces = 8192;
1147     Newz (0, RETVAL->face, RETVAL->faces, mapface);
1148 root 1.42 RETVAL->texs = 8192;
1149     Newz (0, RETVAL->tex, RETVAL->texs, maptex);
1150 root 1.28 RETVAL->rows = 0;
1151     RETVAL->row = 0;
1152     OUTPUT:
1153     RETVAL
1154    
1155     void
1156 root 1.133 DESTROY (CFPlus::Map self)
1157 root 1.28 CODE:
1158     {
1159 root 1.30 map_clear (self);
1160 root 1.28 Safefree (self->face);
1161 root 1.111 Safefree (self->tex);
1162 root 1.29 Safefree (self);
1163     }
1164    
1165     void
1166 root 1.133 clear (CFPlus::Map self)
1167 root 1.30 CODE:
1168     map_clear (self);
1169    
1170     void
1171 root 1.133 set_face (CFPlus::Map self, int face, int texid)
1172 root 1.29 CODE:
1173     {
1174 root 1.42 while (self->faces <= face)
1175 root 1.28 {
1176 root 1.30 Append (mapface, self->face, self->faces, self->faces);
1177 root 1.29 self->faces *= 2;
1178     }
1179 root 1.28
1180 root 1.42 self->face [face] = texid;
1181     }
1182    
1183     void
1184 root 1.133 set_texture (CFPlus::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a)
1185 root 1.42 CODE:
1186     {
1187     while (self->texs <= texid)
1188     {
1189     Append (maptex, self->tex, self->texs, self->texs);
1190     self->texs *= 2;
1191     }
1192    
1193 root 1.48 {
1194     maptex *tex = self->tex + texid;
1195 root 1.39
1196 root 1.48 tex->name = name;
1197     tex->w = w;
1198     tex->h = h;
1199     tex->s = s;
1200     tex->t = t;
1201     tex->r = r;
1202     tex->g = g;
1203     tex->b = b;
1204     tex->a = a;
1205     }
1206 root 1.95
1207     // somewhat hackish, but for textures that require it, it really
1208     // improves the look, and most others don't suffer.
1209     glBindTexture (GL_TEXTURE_2D, name);
1210 root 1.99 //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1211     //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1212     // use uglier nearest interpolation because linear suffers
1213     // from transparent color bleeding and ugly wrapping effects.
1214     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1215 root 1.29 }
1216    
1217 root 1.42 int
1218 root 1.133 ox (CFPlus::Map self)
1219 root 1.42 ALIAS:
1220     oy = 1
1221 root 1.101 x = 2
1222     y = 3
1223 root 1.102 w = 4
1224     h = 5
1225 root 1.42 CODE:
1226     switch (ix)
1227     {
1228     case 0: RETVAL = self->ox; break;
1229     case 1: RETVAL = self->oy; break;
1230 root 1.101 case 2: RETVAL = self->x; break;
1231     case 3: RETVAL = self->y; break;
1232 root 1.102 case 4: RETVAL = self->w; break;
1233     case 5: RETVAL = self->h; break;
1234 root 1.42 }
1235     OUTPUT:
1236     RETVAL
1237    
1238 root 1.29 void
1239 root 1.133 scroll (CFPlus::Map self, int dx, int dy)
1240 root 1.43 CODE:
1241     {
1242 root 1.44 if (dx > 0)
1243     map_blank (self, self->x, self->y, dx - 1, self->h);
1244     else if (dx < 0)
1245     map_blank (self, self->x + self->w + dx + 1, self->y, 1 - dx, self->h);
1246    
1247     if (dy > 0)
1248     map_blank (self, self->x, self->y, self->w, dy - 1);
1249     else if (dy < 0)
1250     map_blank (self, self->x, self->y + self->h + dy + 1, self->w, 1 - dy);
1251 root 1.43
1252 root 1.44 self->ox += dx; self->x += dx;
1253     self->oy += dy; self->y += dy;
1254 root 1.43
1255     while (self->y < 0)
1256     {
1257     Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y);
1258    
1259     self->rows += MAP_EXTEND_Y;
1260     self->y += MAP_EXTEND_Y;
1261     }
1262 root 1.44 }
1263 root 1.43
1264 root 1.44 void
1265 root 1.133 map1a_update (CFPlus::Map self, SV *data_)
1266 root 1.44 CODE:
1267     {
1268 root 1.30 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
1269     uint8_t *data_end = (uint8_t *)SvEND (data_);
1270 root 1.48 mapcell *cell;
1271     int x, y, flags;
1272 root 1.43
1273 root 1.29 while (data < data_end)
1274     {
1275 root 1.48 flags = (data [0] << 8) + data [1]; data += 2;
1276 root 1.30
1277 root 1.120 x = self->x + ((flags >> 10) & 63);
1278     y = self->y + ((flags >> 4) & 63);
1279 root 1.29
1280 root 1.48 cell = map_get_cell (self, x, y);
1281 root 1.29
1282     if (flags & 15)
1283     {
1284 root 1.45 if (cell->darkness < 0)
1285 root 1.29 {
1286     cell->darkness = 0;
1287     cell->face [0] = 0;
1288     cell->face [1] = 0;
1289     cell->face [2] = 0;
1290     }
1291 root 1.45
1292 root 1.29 cell->darkness = flags & 8 ? *data++ : 255;
1293    
1294 root 1.42 //TODO: don't trust server data to be in-range(!)
1295    
1296 root 1.29 if (flags & 4)
1297     {
1298 root 1.42 cell->face [0] = self->face [(data [0] << 8) + data [1]]; data += 2;
1299 root 1.29 }
1300    
1301     if (flags & 2)
1302     {
1303 root 1.42 cell->face [1] = self->face [(data [0] << 8) + data [1]]; data += 2;
1304 root 1.29 }
1305    
1306     if (flags & 1)
1307     {
1308 root 1.42 cell->face [2] = self->face [(data [0] << 8) + data [1]]; data += 2;
1309 root 1.29 }
1310     }
1311     else
1312 root 1.31 cell->darkness = -1;
1313 root 1.29 }
1314 root 1.28 }
1315    
1316 root 1.40 SV *
1317 root 1.133 mapmap (CFPlus::Map self, int x0, int y0, int w, int h)
1318 root 1.40 CODE:
1319     {
1320 root 1.55 int x1, x;
1321     int y1, y;
1322 root 1.40 int z;
1323     SV *map_sv = newSV (w * h * sizeof (uint32_t));
1324     uint32_t *map = (uint32_t *)SvPVX (map_sv);
1325    
1326     SvPOK_only (map_sv);
1327     SvCUR_set (map_sv, w * h * sizeof (uint32_t));
1328    
1329 root 1.55 x0 += self->x; x1 = x0 + w;
1330     y0 += self->y; y1 = y0 + h;
1331 root 1.40
1332     for (y = y0; y < y1; y++)
1333     {
1334     maprow *row = 0 <= y && y < self->rows
1335     ? self->row + y
1336     : 0;
1337    
1338     for (x = x0; x < x1; x++)
1339     {
1340     int r = 32, g = 32, b = 32, a = 192;
1341    
1342     if (row && row->c0 <= x && x < row->c1)
1343     {
1344     mapcell *cell = row->col + (x - row->c0);
1345    
1346     for (z = 0; z <= 0; z++)
1347     {
1348 root 1.42 mapface face = cell->face [z];
1349 root 1.40
1350     if (face)
1351     {
1352 root 1.42 maptex tex = self->tex [face];
1353 root 1.40 int a0 = 255 - tex.a;
1354     int a1 = tex.a;
1355    
1356     r = (r * a0 + tex.r * a1) / 255;
1357     g = (g * a0 + tex.g * a1) / 255;
1358     b = (b * a0 + tex.b * a1) / 255;
1359     a = (a * a0 + tex.a * a1) / 255;
1360     }
1361     }
1362     }
1363    
1364     *map++ = (r )
1365     | (g << 8)
1366     | (b << 16)
1367     | (a << 24);
1368     }
1369     }
1370    
1371     RETVAL = map_sv;
1372     }
1373     OUTPUT:
1374     RETVAL
1375    
1376 root 1.30 void
1377 root 1.133 draw (CFPlus::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1378 root 1.116 CODE:
1379 root 1.30 {
1380 root 1.48 int vx, vy;
1381     int x, y, z;
1382     int last_name;
1383     mapface face;
1384    
1385 root 1.120 vx = self->x + self->w / 2 - sw / 2 - shift_x;
1386     vy = self->y + self->h / 2 - sh / 2 - shift_y;
1387 root 1.38
1388 root 1.42 /*
1389     int vx = self->vx = self->w >= sw
1390     ? self->x + (self->w - sw) / 2
1391     : MIN (self->x, MAX (self->x + self->w - sw + 1, self->vx));
1392    
1393     int vy = self->vy = self->h >= sh
1394     ? self->y + (self->h - sh) / 2
1395     : MIN (self->y, MAX (self->y + self->h - sh + 1, self->vy));
1396     */
1397 root 1.30
1398     glColor4ub (255, 255, 255, 255);
1399    
1400 root 1.117 glEnable (GL_BLEND);
1401 root 1.30 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1402     glEnable (GL_TEXTURE_2D);
1403     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1404    
1405 root 1.48 glBegin (GL_QUADS);
1406 root 1.30
1407 root 1.48 last_name = 0;
1408 root 1.30
1409     for (z = 0; z < 3; z++)
1410     for (y = 0; y < sh; y++)
1411     if (0 <= y + vy && y + vy < self->rows)
1412     {
1413     maprow *row = self->row + (y + vy);
1414    
1415     for (x = 0; x < sw; x++)
1416     if (row->c0 <= x + vx && x + vx < row->c1)
1417     {
1418     mapcell *cell = row->col + (x + vx - row->c0);
1419 root 1.32
1420 root 1.48 face = cell->face [z];
1421 root 1.30
1422     if (face)
1423     {
1424 root 1.42 maptex tex = self->tex [face];
1425 root 1.30
1426     int px = (x + 1) * 32 - tex.w;
1427     int py = (y + 1) * 32 - tex.h;
1428    
1429     if (last_name != tex.name)
1430     {
1431     glEnd ();
1432     last_name = tex.name;
1433     glBindTexture (GL_TEXTURE_2D, last_name);
1434     glBegin (GL_QUADS);
1435     }
1436    
1437     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1438     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1439     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1440     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1441     }
1442     }
1443     }
1444    
1445     glEnd ();
1446 root 1.32
1447 root 1.34 glDisable (GL_TEXTURE_2D);
1448     glDisable (GL_BLEND);
1449 root 1.116 }
1450    
1451     void
1452 root 1.133 draw_magicmap (CFPlus::Map self, int dx, int dy, int w, int h, unsigned char *data)
1453 root 1.117 CODE:
1454     {
1455     static float color[16][3] = {
1456 root 1.123 { 0.00F, 0.00F, 0.00F },
1457     { 1.00F, 1.00F, 1.00F },
1458     { 0.00F, 0.00F, 0.55F },
1459     { 1.00F, 0.00F, 0.00F },
1460    
1461     { 1.00F, 0.54F, 0.00F },
1462     { 0.11F, 0.56F, 1.00F },
1463     { 0.93F, 0.46F, 0.00F },
1464     { 0.18F, 0.54F, 0.34F },
1465    
1466     { 0.56F, 0.73F, 0.56F },
1467     { 0.80F, 0.80F, 0.80F },
1468     { 0.55F, 0.41F, 0.13F },
1469     { 0.99F, 0.77F, 0.26F },
1470    
1471     { 0.74F, 0.65F, 0.41F },
1472    
1473     { 0.00F, 1.00F, 1.00F },
1474     { 1.00F, 0.00F, 1.00F },
1475     { 1.00F, 1.00F, 0.00F },
1476 root 1.117 };
1477    
1478     int x, y;
1479    
1480     glEnable (GL_TEXTURE_2D);
1481     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1482     glEnable (GL_BLEND);
1483     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1484     glBegin (GL_QUADS);
1485    
1486     for (y = 0; y < h; y++)
1487     for (x = 0; x < w; x++)
1488     {
1489     unsigned char m = data [x + y * w];
1490    
1491 root 1.118 if (m)
1492     {
1493     float *c = color [m & 15];
1494    
1495     float tx1 = m & 0x40 ? 0.5 : 0.;
1496     float tx2 = tx1 + 0.5;
1497    
1498     glColor4f (c[0], c[1], c[2], 0.75);
1499     glTexCoord2f (tx1, 0.); glVertex2i (x , y );
1500     glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1);
1501     glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1);
1502     glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y );
1503     }
1504 root 1.117 }
1505    
1506     glEnd ();
1507     glDisable (GL_BLEND);
1508     glDisable (GL_TEXTURE_2D);
1509     }
1510    
1511     void
1512 root 1.133 fow_texture (CFPlus::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1513 root 1.116 PPCODE:
1514     {
1515     int vx, vy;
1516     int x, y;
1517     int sw4 = (sw + 3) & ~3;
1518     SV *darkness_sv = sv_2mortal (newSV (sw4 * sh));
1519     uint8_t *darkness = (uint8_t *)SvPVX (darkness_sv);
1520    
1521     memset (darkness, 255, sw4 * sh);
1522     SvPOK_only (darkness_sv);
1523     SvCUR_set (darkness_sv, sw4 * sh);
1524    
1525     vx = self->x + (self->w - sw + 1) / 2 - shift_x;
1526     vy = self->y + (self->h - sh + 1) / 2 - shift_y;
1527    
1528     for (y = 0; y < sh; y++)
1529     if (0 <= y + vy && y + vy < self->rows)
1530     {
1531     maprow *row = self->row + (y + vy);
1532    
1533     for (x = 0; x < sw; x++)
1534     if (row->c0 <= x + vx && x + vx < row->c1)
1535     {
1536     mapcell *cell = row->col + (x + vx - row->c0);
1537    
1538     darkness[y * sw4 + x] = cell->darkness < 0
1539     ? 255 - FOW_DARKNESS
1540     : 255 - cell->darkness;
1541     }
1542     }
1543 root 1.34
1544 root 1.32 EXTEND (SP, 3);
1545     PUSHs (sv_2mortal (newSViv (sw4)));
1546     PUSHs (sv_2mortal (newSViv (sh)));
1547     PUSHs (darkness_sv);
1548 root 1.30 }
1549    
1550 root 1.42 SV *
1551 root 1.133 get_rect (CFPlus::Map self, int x0, int y0, int w, int h)
1552 root 1.42 CODE:
1553     {
1554     int x, y, x1, y1;
1555     SV *data_sv = newSV (w * h * 7 + 5);
1556     uint8_t *data = (uint8_t *)SvPVX (data_sv);
1557    
1558     *data++ = 0; /* version 0 format */
1559     *data++ = w >> 8; *data++ = w;
1560     *data++ = h >> 8; *data++ = h;
1561    
1562     // we need to do this 'cause we don't keep an absolute coord system for rows
1563 root 1.55 // TODO: treat rows as we treat columns
1564 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1565     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1566    
1567     x0 += self->x - self->ox;
1568     y0 += self->y - self->oy;
1569    
1570     x1 = x0 + w;
1571     y1 = y0 + h;
1572    
1573     for (y = y0; y < y1; y++)
1574     {
1575     maprow *row = 0 <= y && y < self->rows
1576     ? self->row + y
1577     : 0;
1578    
1579     for (x = x0; x < x1; x++)
1580     {
1581     if (row && row->c0 <= x && x < row->c1)
1582     {
1583     mapcell *cell = row->col + (x - row->c0);
1584     uint8_t flags = 0;
1585    
1586     if (cell->face [0]) flags |= 1;
1587     if (cell->face [1]) flags |= 2;
1588     if (cell->face [2]) flags |= 4;
1589    
1590     *data++ = flags;
1591    
1592     if (flags & 1)
1593     {
1594     *data++ = cell->face [0] >> 8;
1595     *data++ = cell->face [0];
1596     }
1597    
1598     if (flags & 2)
1599     {
1600     *data++ = cell->face [1] >> 8;
1601     *data++ = cell->face [1];
1602     }
1603    
1604     if (flags & 4)
1605     {
1606     *data++ = cell->face [2] >> 8;
1607     *data++ = cell->face [2];
1608     }
1609     }
1610     else
1611     *data++ = 0;
1612     }
1613     }
1614    
1615     SvPOK_only (data_sv);
1616     SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
1617     RETVAL = data_sv;
1618     }
1619     OUTPUT:
1620     RETVAL
1621    
1622     void
1623 root 1.133 set_rect (CFPlus::Map self, int x0, int y0, uint8_t *data)
1624 root 1.42 PPCODE:
1625     {
1626     int x, y, z;
1627 root 1.48 int w, h;
1628 root 1.42 int x1, y1;
1629    
1630     if (*data++ != 0)
1631     return; /* version mismatch */
1632    
1633 root 1.48 w = *data++ << 8; w |= *data++;
1634     h = *data++ << 8; h |= *data++;
1635 root 1.42
1636     // we need to do this 'cause we don't keep an absolute coord system for rows
1637 root 1.55 // TODO: treat rows as we treat columns
1638 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1639     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1640    
1641     x0 += self->x - self->ox;
1642     y0 += self->y - self->oy;
1643    
1644     x1 = x0 + w;
1645     y1 = y0 + h;
1646    
1647     for (y = y0; y < y1; y++)
1648     {
1649     maprow *row = map_get_row (self, y);
1650    
1651     for (x = x0; x < x1; x++)
1652     {
1653     uint8_t flags = *data++;
1654    
1655     if (flags)
1656     {
1657     mapface face[3] = { 0, 0, 0 };
1658    
1659     mapcell *cell = row_get_cell (row, x);
1660    
1661     if (flags & 1) { face[0] = *data++ << 8; face[0] |= *data++; }
1662     if (flags & 2) { face[1] = *data++ << 8; face[1] |= *data++; }
1663     if (flags & 4) { face[2] = *data++ << 8; face[2] |= *data++; }
1664    
1665     if (cell->darkness <= 0)
1666     {
1667     cell->darkness = -1;
1668    
1669     for (z = 0; z <= 2; z++)
1670     {
1671     cell->face[z] = face[z];
1672    
1673     if (face[z] && (face[z] >= self->texs || !self->tex[face [z]].name))
1674     XPUSHs (sv_2mortal (newSViv (face[z])));
1675     }
1676     }
1677     }
1678     }
1679     }
1680     }
1681    
1682 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::MixChunk
1683 root 1.52
1684 root 1.133 CFPlus::MixChunk
1685 root 1.52 new_from_file (SV *class, char *path)
1686     CODE:
1687     RETVAL = Mix_LoadWAV (path);
1688     OUTPUT:
1689     RETVAL
1690    
1691     void
1692 root 1.133 DESTROY (CFPlus::MixChunk self)
1693 root 1.52 CODE:
1694     Mix_FreeChunk (self);
1695    
1696     int
1697 root 1.133 volume (CFPlus::MixChunk self, int volume = -1)
1698 root 1.52 CODE:
1699     RETVAL = Mix_VolumeChunk (self, volume);
1700     OUTPUT:
1701     RETVAL
1702    
1703     int
1704 root 1.133 play (CFPlus::MixChunk self, int channel = -1, int loops = 0, int ticks = -1)
1705 root 1.52 CODE:
1706     RETVAL = Mix_PlayChannelTimed (channel, self, loops, ticks);
1707     OUTPUT:
1708     RETVAL
1709    
1710 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::MixMusic
1711 root 1.52
1712     int
1713     volume (int volume = -1)
1714     CODE:
1715     RETVAL = Mix_VolumeMusic (volume);
1716     OUTPUT:
1717     RETVAL
1718    
1719 root 1.133 CFPlus::MixMusic
1720 root 1.52 new_from_file (SV *class, char *path)
1721     CODE:
1722     RETVAL = Mix_LoadMUS (path);
1723     OUTPUT:
1724     RETVAL
1725    
1726     void
1727 root 1.133 DESTROY (CFPlus::MixMusic self)
1728 root 1.52 CODE:
1729     Mix_FreeMusic (self);
1730    
1731     int
1732 root 1.133 play (CFPlus::MixMusic self, int loops = -1)
1733 root 1.52 CODE:
1734     RETVAL = Mix_PlayMusic (self, loops);
1735     OUTPUT:
1736     RETVAL
1737    
1738 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::OpenGL
1739 root 1.54
1740     BOOT:
1741     {
1742 root 1.133 HV *stash = gv_stashpv ("CFPlus::OpenGL", 1);
1743 root 1.54 static const struct {
1744     const char *name;
1745     IV iv;
1746     } *civ, const_iv[] = {
1747     # define const_iv(name) { # name, (IV)name }
1748     const_iv (GL_COLOR_MATERIAL),
1749     const_iv (GL_SMOOTH),
1750     const_iv (GL_FLAT),
1751 root 1.69 const_iv (GL_DITHER),
1752 root 1.54 const_iv (GL_BLEND),
1753 root 1.89 const_iv (GL_CULL_FACE),
1754 root 1.69 const_iv (GL_SCISSOR_TEST),
1755 root 1.89 const_iv (GL_DEPTH_TEST),
1756     const_iv (GL_ALPHA_TEST),
1757     const_iv (GL_NORMALIZE),
1758     const_iv (GL_RESCALE_NORMAL),
1759 root 1.119 const_iv (GL_FRONT),
1760     const_iv (GL_BACK),
1761 root 1.54 const_iv (GL_AND),
1762 root 1.67 const_iv (GL_ONE),
1763     const_iv (GL_ZERO),
1764 root 1.54 const_iv (GL_SRC_ALPHA),
1765 root 1.104 const_iv (GL_DST_ALPHA),
1766 root 1.54 const_iv (GL_ONE_MINUS_SRC_ALPHA),
1767 root 1.67 const_iv (GL_ONE_MINUS_DST_ALPHA),
1768 root 1.104 const_iv (GL_SRC_ALPHA_SATURATE),
1769 root 1.54 const_iv (GL_RGB),
1770     const_iv (GL_RGBA),
1771 root 1.115 const_iv (GL_RGBA4),
1772     const_iv (GL_RGBA8),
1773     const_iv (GL_RGB5_A1),
1774 root 1.54 const_iv (GL_UNSIGNED_BYTE),
1775 root 1.89 const_iv (GL_UNSIGNED_SHORT),
1776     const_iv (GL_UNSIGNED_INT),
1777 root 1.54 const_iv (GL_ALPHA),
1778 root 1.86 const_iv (GL_INTENSITY),
1779 root 1.76 const_iv (GL_LUMINANCE),
1780 root 1.86 const_iv (GL_LUMINANCE_ALPHA),
1781 root 1.54 const_iv (GL_FLOAT),
1782     const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
1783     const_iv (GL_COMPILE),
1784     const_iv (GL_TEXTURE_1D),
1785     const_iv (GL_TEXTURE_2D),
1786     const_iv (GL_TEXTURE_ENV),
1787     const_iv (GL_TEXTURE_MAG_FILTER),
1788     const_iv (GL_TEXTURE_MIN_FILTER),
1789     const_iv (GL_TEXTURE_ENV_MODE),
1790     const_iv (GL_TEXTURE_WRAP_S),
1791     const_iv (GL_TEXTURE_WRAP_T),
1792 root 1.98 const_iv (GL_REPEAT),
1793 root 1.54 const_iv (GL_CLAMP),
1794 root 1.98 const_iv (GL_CLAMP_TO_EDGE),
1795 root 1.54 const_iv (GL_NEAREST),
1796     const_iv (GL_LINEAR),
1797 root 1.57 const_iv (GL_NEAREST_MIPMAP_NEAREST),
1798     const_iv (GL_LINEAR_MIPMAP_NEAREST),
1799     const_iv (GL_NEAREST_MIPMAP_LINEAR),
1800     const_iv (GL_LINEAR_MIPMAP_LINEAR),
1801     const_iv (GL_GENERATE_MIPMAP),
1802 root 1.54 const_iv (GL_MODULATE),
1803 root 1.69 const_iv (GL_DECAL),
1804 root 1.54 const_iv (GL_REPLACE),
1805 root 1.89 const_iv (GL_DEPTH_BUFFER_BIT),
1806 root 1.54 const_iv (GL_COLOR_BUFFER_BIT),
1807     const_iv (GL_PROJECTION),
1808     const_iv (GL_MODELVIEW),
1809     const_iv (GL_COLOR_LOGIC_OP),
1810 root 1.69 const_iv (GL_SEPARABLE_2D),
1811 root 1.54 const_iv (GL_CONVOLUTION_2D),
1812     const_iv (GL_CONVOLUTION_BORDER_MODE),
1813     const_iv (GL_CONSTANT_BORDER),
1814     const_iv (GL_LINES),
1815 root 1.138 const_iv (GL_LINE_STRIP),
1816 root 1.89 const_iv (GL_LINE_LOOP),
1817 root 1.54 const_iv (GL_QUADS),
1818 root 1.89 const_iv (GL_QUAD_STRIP),
1819     const_iv (GL_TRIANGLES),
1820     const_iv (GL_TRIANGLE_STRIP),
1821     const_iv (GL_TRIANGLE_FAN),
1822 root 1.54 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
1823     const_iv (GL_FASTEST),
1824 root 1.89 const_iv (GL_V2F),
1825     const_iv (GL_V3F),
1826     const_iv (GL_T2F_V3F),
1827     const_iv (GL_T2F_N3F_V3F),
1828 root 1.54 # undef const_iv
1829     };
1830    
1831     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1832     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1833     }
1834    
1835 root 1.97 char *
1836     gl_vendor ()
1837     CODE:
1838     RETVAL = (char *)glGetString (GL_VENDOR);
1839     OUTPUT:
1840     RETVAL
1841    
1842     char *
1843     gl_version ()
1844     CODE:
1845     RETVAL = (char *)glGetString (GL_VERSION);
1846     OUTPUT:
1847     RETVAL
1848    
1849     char *
1850     gl_extensions ()
1851     CODE:
1852     RETVAL = (char *)glGetString (GL_EXTENSIONS);
1853     OUTPUT:
1854     RETVAL
1855    
1856 root 1.54 int glGetError ()
1857    
1858 root 1.114 void glFinish ()
1859    
1860 root 1.54 void glClear (int mask)
1861    
1862     void glClearColor (float r, float g, float b, float a = 1.0)
1863     PROTOTYPE: @
1864    
1865     void glEnable (int cap)
1866    
1867     void glDisable (int cap)
1868    
1869     void glShadeModel (int mode)
1870    
1871     void glHint (int target, int mode)
1872    
1873     void glBlendFunc (int sfactor, int dfactor)
1874    
1875 root 1.103 void glBlendFuncSeparate (int sa, int da, int saa, int daa)
1876     CODE:
1877     gl_BlendFuncSeparate (sa, da, saa, daa);
1878    
1879 root 1.89 void glDepthMask (int flag)
1880    
1881 root 1.54 void glLogicOp (int opcode)
1882    
1883 root 1.68 void glColorMask (int red, int green, int blue, int alpha)
1884    
1885 root 1.54 void glMatrixMode (int mode)
1886    
1887     void glPushMatrix ()
1888    
1889     void glPopMatrix ()
1890    
1891     void glLoadIdentity ()
1892    
1893 root 1.119 void glDrawBuffer (int buffer)
1894    
1895     void glReadBuffer (int buffer)
1896    
1897 root 1.90 # near_ and far_ are due to microsofts buggy "c" compiler
1898     void glFrustum (double left, double right, double bottom, double top, double near_, double far_)
1899    
1900     # near_ and far_ are due to microsofts buggy "c" compiler
1901 root 1.64 void glOrtho (double left, double right, double bottom, double top, double near_, double far_)
1902 root 1.54
1903     void glViewport (int x, int y, int width, int height)
1904    
1905 root 1.69 void glScissor (int x, int y, int width, int height)
1906    
1907 root 1.54 void glTranslate (float x, float y, float z = 0.)
1908     CODE:
1909     glTranslatef (x, y, z);
1910    
1911 root 1.62 void glScale (float x, float y, float z = 1.)
1912 root 1.54 CODE:
1913     glScalef (x, y, z);
1914    
1915     void glRotate (float angle, float x, float y, float z)
1916     CODE:
1917     glRotatef (angle, x, y, z);
1918    
1919     void glBegin (int mode)
1920    
1921     void glEnd ()
1922    
1923     void glColor (float r, float g, float b, float a = 1.0)
1924     PROTOTYPE: @
1925 root 1.103 ALIAS:
1926     glColor_premultiply = 1
1927 root 1.54 CODE:
1928 root 1.103 if (ix)
1929     {
1930     r *= a;
1931     g *= a;
1932     b *= a;
1933     }
1934 root 1.90 // microsoft visual "c" rounds instead of truncating...
1935 root 1.130 glColor4f (r, g, b, a);
1936 root 1.54
1937 root 1.89 void glInterleavedArrays (int format, int stride, char *data)
1938    
1939     void glDrawElements (int mode, int count, int type, char *indices)
1940    
1941     # 1.2 void glDrawRangeElements (int mode, int start, int end
1942    
1943 root 1.91 void glRasterPos (float x, float y, float z = 0.)
1944     CODE:
1945     glRasterPos3f (0, 0, z);
1946     glBitmap (0, 0, 0, 0, x, y, 0);
1947    
1948 root 1.54 void glVertex (float x, float y, float z = 0.)
1949     CODE:
1950     glVertex3f (x, y, z);
1951    
1952     void glTexCoord (float s, float t)
1953     CODE:
1954     glTexCoord2f (s, t);
1955    
1956     void glTexEnv (int target, int pname, float param)
1957     CODE:
1958     glTexEnvf (target, pname, param);
1959    
1960     void glTexParameter (int target, int pname, float param)
1961     CODE:
1962     glTexParameterf (target, pname, param);
1963    
1964     void glBindTexture (int target, int name)
1965    
1966     void glConvolutionParameter (int target, int pname, float params)
1967     CODE:
1968 root 1.103 if (gl.ConvolutionParameterf)
1969     gl.ConvolutionParameterf (target, pname, params);
1970 root 1.54
1971     void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
1972 root 1.64 CODE:
1973 root 1.103 if (gl.ConvolutionFilter2D)
1974     gl.ConvolutionFilter2D (target, internalformat, width, height, format, type, data);
1975 root 1.54
1976 root 1.69 void glSeparableFilter2D (int target, int internalformat, int width, int height, int format, int type, char *row, char *column)
1977     CODE:
1978 root 1.103 if (gl.SeparableFilter2D)
1979     gl.SeparableFilter2D (target, internalformat, width, height, format, type, row, column);
1980 root 1.69
1981 root 1.54 void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data)
1982    
1983     void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
1984    
1985 root 1.91 void glDrawPixels (int width, int height, int format, int type, char *pixels)
1986 root 1.68
1987     void glCopyPixels (int x, int y, int width, int height, int type = GL_COLOR)
1988    
1989 root 1.54 int glGenTexture ()
1990     CODE:
1991     {
1992     GLuint name;
1993     glGenTextures (1, &name);
1994     RETVAL = name;
1995     }
1996     OUTPUT:
1997     RETVAL
1998    
1999     void glDeleteTexture (int name)
2000     CODE:
2001     {
2002     GLuint name_ = name;
2003     glDeleteTextures (1, &name_);
2004     }
2005    
2006     int glGenList ()
2007     CODE:
2008     RETVAL = glGenLists (1);
2009     OUTPUT:
2010     RETVAL
2011    
2012     void glDeleteList (int list)
2013     CODE:
2014     glDeleteLists (list, 1);
2015    
2016     void glNewList (int list, int mode = GL_COMPILE)
2017    
2018     void glEndList ()
2019    
2020     void glCallList (int list)
2021