ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.165
Committed: Fri Dec 8 14:59:54 2006 UTC (17 years, 5 months ago) by root
Branch: MAIN
Changes since 1.164: +41 -1 lines
Log Message:
implement a somewhat hack multiline text editor

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