ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.139
Committed: Mon Aug 14 03:04:17 2006 UTC (17 years, 9 months ago) by root
Branch: MAIN
Changes since 1.138: +13 -4 lines
Log Message:
work around pango rounding bug

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