ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.55
Committed: Thu Apr 20 08:11:56 2006 UTC (18 years ago) by root
Branch: MAIN
Changes since 1.54: +8 -7 lines
Log Message:
map overview rectangle

File Contents

# User Rev Content
1 root 1.48 #ifdef _WIN32
2     # include <malloc.h>
3     #endif
4    
5 root 1.1 #include "EXTERN.h"
6     #include "perl.h"
7     #include "XSUB.h"
8    
9 root 1.5 #include <string.h>
10 root 1.25 #include <stdio.h>
11 root 1.5
12 root 1.2 #include <SDL.h>
13 root 1.23 #include <SDL_image.h>
14 root 1.52 #include <SDL_mixer.h>
15 root 1.3 #include <SDL_opengl.h>
16 root 1.5
17 root 1.30 #include <glib/gmacros.h>
18    
19 root 1.5 #include <pango/pango.h>
20 root 1.10 #include <pango/pangofc-fontmap.h>
21 root 1.5 #include <pango/pangoft2.h>
22    
23 root 1.48 #ifndef _WIN32
24     # include <sys/types.h>
25     # include <sys/socket.h>
26     # include <netinet/in.h>
27     # include <netinet/tcp.h>
28     # include <inttypes.h>
29     #else
30     typedef unsigned char uint8_t;
31     typedef unsigned short uint16_t;
32     typedef unsigned int uint32_t;
33     typedef signed char int8_t;
34     typedef signed short int16_t;
35     typedef signed int int32_t;
36     #endif
37 root 1.28
38 root 1.29 #define FOW_DARKNESS 32
39    
40     #define MAP_EXTEND_X 32
41     #define MAP_EXTEND_Y 512
42    
43 root 1.52 typedef Mix_Chunk *CFClient__MixChunk;
44     typedef Mix_Music *CFClient__MixMusic;
45    
46 root 1.5 static PangoContext *context;
47     static PangoFontMap *fontmap;
48 root 1.2
49 root 1.14 typedef struct cf_layout {
50     PangoLayout *pl;
51     int base_height;
52 root 1.15 } *CFClient__Layout;
53 root 1.14
54     static void
55 root 1.19 substitute_func (FcPattern *pattern, gpointer data)
56     {
57 root 1.20 FcPatternAddBool (pattern, FC_HINTING , 1);
58 root 1.35 FcPatternAddBool (pattern, FC_AUTOHINT, 0);
59 root 1.19 }
60    
61     static void
62 root 1.17 layout_update (CFClient__Layout self)
63     {
64 root 1.19 /* use a random scale factor to account for unknown descenders, 0.8 works
65     * reasonably well with bitstream vera
66     */
67 root 1.17 PangoFontDescription *font = pango_context_get_font_description (context);
68 root 1.46
69     int height = self->base_height * (PANGO_SCALE * 8 / 10);
70    
71     if (pango_font_description_get_size (font) != height)
72     {
73     pango_font_description_set_absolute_size (font, height);
74     pango_layout_context_changed (self->pl);
75     }
76 root 1.17 }
77    
78     static void
79 root 1.15 layout_get_pixel_size (CFClient__Layout self, int *w, int *h)
80 root 1.14 {
81 root 1.19 layout_update (self);
82 root 1.16
83 root 1.14 pango_layout_get_pixel_size (self->pl, w, h);
84    
85     *w = (*w + 3) & ~3;
86     if (!*w) *w = 1;
87     if (!*h) *h = 1;
88     }
89    
90 root 1.42 typedef uint16_t mapface;
91    
92 root 1.28 typedef struct {
93 root 1.30 GLint name;
94     int w, h;
95     float s, t;
96 root 1.39 uint8_t r, g, b, a;
97 root 1.42 } maptex;
98 root 1.30
99     typedef struct {
100 root 1.29 int16_t darkness;
101 root 1.42 mapface face[3];
102 root 1.28 } mapcell;
103    
104     typedef struct {
105 root 1.30 int32_t c0, c1;
106 root 1.28 mapcell *col;
107     } maprow;
108    
109     typedef struct map {
110     int x, y, w, h;
111 root 1.42 int ox, oy; /* offset to virtual global coordinate system */
112 root 1.28 int faces;
113 root 1.30 mapface *face;
114 root 1.28
115 root 1.42 int texs;
116     maptex *tex;
117    
118 root 1.48 int32_t rows;
119 root 1.28 maprow *row;
120     } *CFClient__Map;
121    
122 root 1.30 static char *
123     prepend (char *ptr, int sze, int inc)
124     {
125     char *p;
126    
127     New (0, p, sze + inc, char);
128     Zero (p, inc, char);
129     Move (ptr, p + inc, sze, char);
130     Safefree (ptr);
131    
132     return p;
133     }
134    
135     static char *
136     append (char *ptr, int sze, int inc)
137     {
138     Renew (ptr, sze + inc, char);
139     Zero (ptr + sze, inc, char);
140    
141     return ptr;
142     }
143    
144     #define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
145     #define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
146    
147 root 1.42 static maprow *
148     map_get_row (CFClient__Map self, int y)
149     {
150     if (0 > y)
151     {
152     int extend = - y + MAP_EXTEND_Y;
153     Prepend (maprow, self->row, self->rows, extend);
154    
155     self->rows += extend;
156     self->y += extend;
157     y += extend;
158     }
159     else if (y >= self->rows)
160     {
161     int extend = y - self->rows + MAP_EXTEND_Y;
162     Append (maprow, self->row, self->rows, extend);
163     self->rows += extend;
164     }
165    
166     return self->row + y;
167     }
168    
169     static mapcell *
170     row_get_cell (maprow *row, int x)
171     {
172     if (!row->col)
173     {
174     Newz (0, row->col, MAP_EXTEND_X, mapcell);
175     row->c0 = x - MAP_EXTEND_X / 4;
176     row->c1 = row->c0 + MAP_EXTEND_X;
177     }
178    
179     if (row->c0 > x)
180     {
181     int extend = row->c0 - x + MAP_EXTEND_X;
182     Prepend (mapcell, row->col, row->c1 - row->c0, extend);
183     row->c0 -= extend;
184     }
185     else if (x >= row->c1)
186     {
187     int extend = x - row->c1 + MAP_EXTEND_X;
188     Append (mapcell, row->col, row->c1 - row->c0, extend);
189     row->c1 += extend;
190     }
191    
192     return row->col + (x - row->c0);
193     }
194    
195     static mapcell *
196     map_get_cell (CFClient__Map self, int x, int y)
197     {
198     return row_get_cell (map_get_row (self, y), x);
199     }
200    
201 root 1.30 static void
202     map_clear (CFClient__Map self)
203     {
204     int r;
205    
206     for (r = 0; r < self->rows; r++)
207     Safefree (self->row[r].col);
208    
209     Safefree (self->row);
210    
211     self->x = 0;
212     self->y = 0;
213 root 1.42 self->ox = 0;
214     self->oy = 0;
215 root 1.30 self->row = 0;
216     self->rows = 0;
217     }
218    
219 root 1.29 static void
220     map_blank (CFClient__Map self, int x0, int y0, int w, int h)
221     {
222     int x, y;
223 root 1.48 maprow *row;
224 root 1.29
225     for (y = y0; y < y0 + h; y++)
226 root 1.30 if (y >= 0)
227     {
228     if (y >= self->rows)
229     break;
230    
231 root 1.48 row = self->row + y;
232 root 1.30
233     for (x = x0; x < x0 + w; x++)
234     if (x >= row->c0)
235     {
236     if (x >= row->c1)
237     break;
238 root 1.29
239 root 1.31 row->col[x - row->c0].darkness = -1;
240 root 1.30 }
241     }
242 root 1.29 }
243    
244 root 1.15 MODULE = CFClient PACKAGE = CFClient
245 root 1.1
246 root 1.11 PROTOTYPES: ENABLE
247    
248 root 1.5 BOOT:
249     {
250 root 1.51 HV *stash = gv_stashpv ("CFClient", 1);
251     static const struct {
252     const char *name;
253     IV iv;
254     } *civ, const_iv[] = {
255     # define const_iv(name) { # name, (IV)name }
256     const_iv (SDL_ACTIVEEVENT),
257     const_iv (SDL_KEYDOWN),
258     const_iv (SDL_KEYUP),
259     const_iv (SDL_MOUSEMOTION),
260     const_iv (SDL_MOUSEBUTTONDOWN),
261     const_iv (SDL_MOUSEBUTTONUP),
262     const_iv (SDL_JOYAXISMOTION),
263     const_iv (SDL_JOYBALLMOTION),
264     const_iv (SDL_JOYHATMOTION),
265     const_iv (SDL_JOYBUTTONDOWN),
266     const_iv (SDL_JOYBUTTONUP),
267     const_iv (SDL_QUIT),
268     const_iv (SDL_SYSWMEVENT),
269     const_iv (SDL_EVENT_RESERVEDA),
270     const_iv (SDL_EVENT_RESERVEDB),
271     const_iv (SDL_VIDEORESIZE),
272     const_iv (SDL_VIDEOEXPOSE),
273     const_iv (SDL_USEREVENT),
274     const_iv (SDLK_KP0),
275     const_iv (SDLK_KP1),
276     const_iv (SDLK_KP2),
277     const_iv (SDLK_KP3),
278     const_iv (SDLK_KP4),
279     const_iv (SDLK_KP5),
280     const_iv (SDLK_KP6),
281     const_iv (SDLK_KP7),
282     const_iv (SDLK_KP8),
283     const_iv (SDLK_KP9),
284     const_iv (SDLK_KP_PERIOD),
285     const_iv (SDLK_KP_DIVIDE),
286     const_iv (SDLK_KP_MULTIPLY),
287     const_iv (SDLK_KP_MINUS),
288     const_iv (SDLK_KP_PLUS),
289     const_iv (SDLK_KP_ENTER),
290     const_iv (SDLK_KP_EQUALS),
291     const_iv (SDLK_UP),
292     const_iv (SDLK_DOWN),
293     const_iv (SDLK_RIGHT),
294     const_iv (SDLK_LEFT),
295     const_iv (SDLK_INSERT),
296     const_iv (SDLK_HOME),
297     const_iv (SDLK_END),
298     const_iv (SDLK_PAGEUP),
299     const_iv (SDLK_PAGEDOWN),
300     const_iv (SDLK_F1),
301     const_iv (SDLK_F2),
302     const_iv (SDLK_F3),
303     const_iv (SDLK_F4),
304     const_iv (SDLK_F5),
305     const_iv (SDLK_F6),
306     const_iv (SDLK_F7),
307     const_iv (SDLK_F8),
308     const_iv (SDLK_F9),
309     const_iv (SDLK_F10),
310     const_iv (SDLK_F11),
311     const_iv (SDLK_F12),
312     const_iv (SDLK_F13),
313     const_iv (SDLK_F14),
314     const_iv (SDLK_F15),
315     const_iv (SDLK_NUMLOCK),
316     const_iv (SDLK_CAPSLOCK),
317     const_iv (SDLK_SCROLLOCK),
318     const_iv (SDLK_RSHIFT),
319     const_iv (SDLK_LSHIFT),
320     const_iv (SDLK_RCTRL),
321     const_iv (SDLK_LCTRL),
322     const_iv (SDLK_RALT),
323     const_iv (SDLK_LALT),
324     const_iv (SDLK_RMETA),
325     const_iv (SDLK_LMETA),
326     const_iv (SDLK_LSUPER),
327     const_iv (SDLK_RSUPER),
328     const_iv (SDLK_MODE),
329     const_iv (SDLK_COMPOSE),
330     const_iv (SDLK_HELP),
331     const_iv (SDLK_PRINT),
332     const_iv (SDLK_SYSREQ),
333     const_iv (SDLK_BREAK),
334     const_iv (SDLK_MENU),
335     const_iv (SDLK_POWER),
336     const_iv (SDLK_EURO),
337     const_iv (SDLK_UNDO),
338     const_iv (KMOD_NONE),
339     const_iv (KMOD_LSHIFT),
340     const_iv (KMOD_RSHIFT),
341     const_iv (KMOD_LCTRL),
342     const_iv (KMOD_RCTRL),
343     const_iv (KMOD_LALT),
344     const_iv (KMOD_RALT),
345     const_iv (KMOD_LMETA),
346     const_iv (KMOD_RMETA),
347     const_iv (KMOD_NUM),
348     const_iv (KMOD_CAPS),
349     const_iv (KMOD_MODE),
350     const_iv (KMOD_CTRL),
351     const_iv (KMOD_SHIFT),
352     const_iv (KMOD_ALT),
353     const_iv (KMOD_META)
354     # undef const_iv
355     };
356    
357     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
358     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
359    
360     fontmap = pango_ft2_font_map_new ();
361     pango_ft2_font_map_set_default_substitute ((PangoFT2FontMap *)fontmap, substitute_func, 0, 0);
362     context = pango_ft2_font_map_create_context ((PangoFT2FontMap *)fontmap);
363 root 1.5 }
364    
365 root 1.51 int
366     SDL_Init (U32 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO)
367    
368     void
369     SDL_Quit ()
370    
371     void
372     SDL_ListModes ()
373     PPCODE:
374     {
375     SDL_Rect **m;
376    
377     SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5);
378     SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5);
379     SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5);
380     SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 1);
381    
382     SDL_GL_SetAttribute (SDL_GL_ACCUM_RED_SIZE, 0);
383     SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0);
384     SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE, 0);
385     SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0);
386    
387     SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
388     SDL_GL_SetAttribute (SDL_GL_BUFFER_SIZE, 15);
389     SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 0);
390    
391 root 1.53 SDL_EnableUNICODE (1);
392     SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
393    
394 root 1.51 m = SDL_ListModes (0, SDL_FULLSCREEN | SDL_OPENGL);
395    
396     if (m && m != (SDL_Rect **)-1)
397     while (*m)
398     {
399     AV *av = newAV ();
400     av_push (av, newSViv ((*m)->w));
401     av_push (av, newSViv ((*m)->h));
402     XPUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
403    
404     ++m;
405     }
406     }
407    
408     int
409     SDL_SetVideoMode (int w, int h, int fullscreen)
410     CODE:
411     RETVAL = !!SDL_SetVideoMode (
412     w, h, 0, SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0)
413     );
414     SDL_WM_SetCaption ("Crossfire+ Client " VERSION, "Crossfire+");
415     OUTPUT:
416     RETVAL
417    
418 root 1.53 void
419 root 1.54 SDL_GL_SwapBuffers ()
420    
421     void
422 root 1.53 SDL_PollEvent ()
423     PPCODE:
424     {
425     SDL_Event ev;
426    
427     while (SDL_PollEvent (&ev))
428     {
429     HV *hv = newHV ();
430     hv_store (hv, "type", 4, newSViv (ev.type), 0);
431     switch (ev.type)
432     {
433     case SDL_KEYDOWN:
434     case SDL_KEYUP:
435     hv_store (hv, "state", 5, newSViv (ev.key.state), 0);
436     hv_store (hv, "sym", 3, newSViv (ev.key.keysym.sym), 0);
437     hv_store (hv, "mod", 3, newSViv (ev.key.keysym.mod), 0);
438     hv_store (hv, "unicode", 7, newSViv (ev.key.keysym.unicode), 0);
439     break;
440    
441     case SDL_ACTIVEEVENT:
442     hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0);
443     hv_store (hv, "state", 5, newSViv (ev.active.state), 0);
444     break;
445    
446     case SDL_MOUSEMOTION:
447     hv_store (hv, "state", 5, newSViv (ev.motion.state), 0);
448     hv_store (hv, "x", 1, newSViv (ev.motion.x), 0);
449     hv_store (hv, "y", 1, newSViv (ev.motion.y), 0);
450     hv_store (hv, "xrel", 4, newSViv (ev.motion.xrel), 0);
451     hv_store (hv, "yrel", 4, newSViv (ev.motion.yrel), 0);
452     break;
453    
454     case SDL_MOUSEBUTTONDOWN:
455     case SDL_MOUSEBUTTONUP:
456     hv_store (hv, "button", 6, newSViv (ev.button.button), 0);
457     hv_store (hv, "state", 5, newSViv (ev.button.state), 0);
458     hv_store (hv, "x", 1, newSViv (ev.button.x), 0);
459     hv_store (hv, "y", 1, newSViv (ev.button.y), 0);
460     }
461    
462     XPUSHs (sv_2mortal (newRV_noinc ((SV *)hv)));
463     }
464     }
465 root 1.52
466     int
467     Mix_OpenAudio (int frequency = 22050, int format = MIX_DEFAULT_FORMAT, int channels = 1, int chunksize = 512)
468    
469     void
470     Mix_CloseAudio ()
471    
472     int
473     Mix_AllocateChannels (int numchans = -1)
474    
475 root 1.10 void
476     lowdelay (int fd, int val = 1)
477     CODE:
478 root 1.48 #ifndef _WIN32
479 root 1.10 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof (val));
480 root 1.48 #endif
481 root 1.10
482 root 1.3 char *
483 root 1.4 gl_version ()
484     CODE:
485 root 1.5 RETVAL = (char *)glGetString (GL_VERSION);
486 root 1.4 OUTPUT:
487     RETVAL
488    
489     char *
490 root 1.3 gl_extensions ()
491     CODE:
492 root 1.5 RETVAL = (char *)glGetString (GL_EXTENSIONS);
493 root 1.3 OUTPUT:
494     RETVAL
495    
496 root 1.5 void
497 root 1.13 add_font (char *file)
498     CODE:
499     FcConfigAppFontAddFile (0, (const FcChar8 *)file); /* no idea wether this is required */
500    
501     void
502 root 1.9 set_font (char *file)
503 root 1.8 CODE:
504     {
505 root 1.9 int count;
506     FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)file, 0, 0, &count);
507 root 1.10 PangoFontDescription *font = pango_fc_font_description_from_pattern (pattern, 0);
508 root 1.9 FcPatternDestroy (pattern);
509 root 1.8 pango_context_set_font_description (context, font);
510     }
511    
512 root 1.23 void
513     load_image_inline (SV *image_)
514     ALIAS:
515     load_image_file = 1
516     PPCODE:
517     {
518     STRLEN image_len;
519     char *image = (char *)SvPVbyte (image_, image_len);
520     SDL_Surface *surface, *surface2;
521     SDL_PixelFormat fmt;
522     SDL_RWops *rw = ix
523     ? SDL_RWFromFile (image, "r")
524     : SDL_RWFromConstMem (image, image_len);
525    
526     if (!rw)
527 root 1.41 croak ("load_image: %s", SDL_GetError ());
528 root 1.23
529     surface = IMG_Load_RW (rw, 1);
530     if (!surface)
531 root 1.41 croak ("load_image: %s", SDL_GetError ());
532 root 1.23
533     fmt.palette = NULL;
534     fmt.BitsPerPixel = 32;
535     fmt.BytesPerPixel = 4;
536 root 1.49 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
537 root 1.23 fmt.Rmask = 0x000000ff;
538     fmt.Gmask = 0x0000ff00;
539     fmt.Bmask = 0x00ff0000;
540     fmt.Amask = 0xff000000;
541 root 1.49 #else
542     fmt.Rmask = 0xff000000;
543     fmt.Gmask = 0x00ff0000;
544     fmt.Bmask = 0x0000ff00;
545     fmt.Amask = 0x000000ff;
546     #endif
547 root 1.23 fmt.Rloss = 0;
548     fmt.Gloss = 0;
549     fmt.Bloss = 0;
550     fmt.Aloss = 0;
551     fmt.Rshift = 0;
552     fmt.Gshift = 8;
553     fmt.Bshift = 16;
554     fmt.Ashift = 24;
555     fmt.colorkey = 0;
556     fmt.alpha = 0;
557    
558     surface2 = SDL_ConvertSurface (surface, &fmt, SDL_SWSURFACE);
559    
560 root 1.39 assert (surface2->pitch == surface2->w * 4);
561    
562 root 1.23 EXTEND (SP, 5);
563     PUSHs (sv_2mortal (newSViv (surface2->w)));
564     PUSHs (sv_2mortal (newSViv (surface2->h)));
565     SDL_LockSurface (surface2);
566     PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch)));
567     SDL_UnlockSurface (surface2);
568 root 1.24 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
569 root 1.23 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
570 root 1.49 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
571 root 1.23
572     SDL_FreeSurface (surface);
573     SDL_FreeSurface (surface2);
574     }
575    
576 root 1.25 void
577 root 1.39 average (int x, int y, uint32_t *data)
578     PPCODE:
579     {
580     uint32_t r = 0, g = 0, b = 0, a = 0;
581    
582     x = y = x * y;
583    
584     while (x--)
585     {
586     uint32_t p = *data++;
587    
588     r += (p ) & 255;
589     g += (p >> 8) & 255;
590     b += (p >> 16) & 255;
591     a += (p >> 24) & 255;
592     }
593    
594     EXTEND (SP, 4);
595 root 1.40 PUSHs (sv_2mortal (newSViv (r / y)));
596     PUSHs (sv_2mortal (newSViv (g / y)));
597     PUSHs (sv_2mortal (newSViv (b / y)));
598     PUSHs (sv_2mortal (newSViv (a / y)));
599 root 1.39 }
600    
601     void
602 root 1.25 fatal (char *message)
603     CODE:
604 root 1.50 #ifdef _WIN32
605 root 1.25 MessageBox (0, message, "Crossfire+ Fatal Error", MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
606     #else
607 root 1.40 fprintf (stderr, "FATAL: %s\n", message);
608 root 1.25 #endif
609     exit (1);
610    
611 root 1.15 MODULE = CFClient PACKAGE = CFClient::Layout
612 root 1.14
613 root 1.15 CFClient::Layout
614 root 1.14 new (SV *class, int base_height = 10)
615     CODE:
616     New (0, RETVAL, 1, struct cf_layout);
617     RETVAL->base_height = base_height;
618     RETVAL->pl = pango_layout_new (context);
619     pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
620     OUTPUT:
621     RETVAL
622    
623     void
624 root 1.15 DESTROY (CFClient::Layout self)
625 root 1.14 CODE:
626     g_object_unref (self->pl);
627     Safefree (self);
628 root 1.13
629 root 1.8 void
630 root 1.35 set_text (CFClient::Layout self, SV *text_)
631     CODE:
632     {
633     STRLEN textlen;
634     char *text = SvPVutf8 (text_, textlen);
635    
636     pango_layout_set_text (self->pl, text, textlen);
637     }
638    
639     void
640 root 1.15 set_markup (CFClient::Layout self, SV *text_)
641 root 1.14 CODE:
642 root 1.5 {
643     STRLEN textlen;
644     char *text = SvPVutf8 (text_, textlen);
645 root 1.14
646     pango_layout_set_markup (self->pl, text, textlen);
647     }
648    
649 root 1.46 SV *
650     get_text (CFClient::Layout self)
651     CODE:
652 root 1.47 RETVAL = newSVpv (pango_layout_get_text (self->pl), 0);
653 root 1.46 SvUTF8_on (RETVAL);
654     OUTPUT:
655     RETVAL
656    
657 root 1.14 void
658 root 1.16 set_height (CFClient::Layout self, int base_height)
659     CODE:
660     self->base_height = base_height;
661    
662     void
663 root 1.15 set_width (CFClient::Layout self, int max_width = -1)
664 root 1.14 CODE:
665     pango_layout_set_width (self->pl, max_width < 0 ? max_width : max_width * PANGO_SCALE);
666    
667     void
668 root 1.15 size (CFClient::Layout self)
669 root 1.14 PPCODE:
670     {
671     int w, h;
672    
673 root 1.17 layout_update (self);
674 root 1.14 layout_get_pixel_size (self, &w, &h);
675    
676     EXTEND (SP, 2);
677     PUSHs (sv_2mortal (newSViv (w)));
678     PUSHs (sv_2mortal (newSViv (h)));
679     }
680    
681 root 1.17 int
682     xy_to_index (CFClient::Layout self, int x, int y)
683     CODE:
684     {
685     int index, trailing;
686    
687     layout_update (self);
688     pango_layout_xy_to_index (self->pl, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing);
689    
690     RETVAL = index;
691     }
692     OUTPUT:
693     RETVAL
694    
695     void
696     cursor_pos (CFClient::Layout self, int index)
697     PPCODE:
698     {
699     PangoRectangle strong_pos;
700     layout_update (self);
701     pango_layout_get_cursor_pos (self->pl, index, &strong_pos, 0);
702 root 1.30
703 root 1.17 EXTEND (SP, 3);
704     PUSHs (sv_2mortal (newSViv (strong_pos.x / PANGO_SCALE)));
705     PUSHs (sv_2mortal (newSViv (strong_pos.y / PANGO_SCALE)));
706     PUSHs (sv_2mortal (newSViv (strong_pos.height / PANGO_SCALE)));
707     }
708    
709 root 1.14 void
710 root 1.15 render (CFClient::Layout self)
711 root 1.14 PPCODE:
712     {
713 root 1.5 SV *retval;
714     int w, h;
715     FT_Bitmap bitmap;
716    
717 root 1.17 layout_update (self);
718 root 1.14 layout_get_pixel_size (self, &w, &h);
719 root 1.5
720     retval = newSV (w * h);
721     SvPOK_only (retval);
722     SvCUR_set (retval, w * h);
723    
724     bitmap.rows = h;
725     bitmap.width = w;
726     bitmap.pitch = w;
727     bitmap.buffer = (unsigned char*)SvPVX (retval);
728     bitmap.num_grays = 256;
729     bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
730    
731     memset (bitmap.buffer, 0, w * h);
732    
733 root 1.14 pango_ft2_render_layout (&bitmap, self->pl, 0 * PANGO_SCALE, 0 * PANGO_SCALE);
734 root 1.1
735 root 1.5 EXTEND (SP, 3);
736     PUSHs (sv_2mortal (newSViv (w)));
737     PUSHs (sv_2mortal (newSViv (h)));
738     PUSHs (sv_2mortal (retval));
739     }
740 root 1.11
741 root 1.15 MODULE = CFClient PACKAGE = CFClient::Texture
742 root 1.11
743     void
744 root 1.37 draw_quad (SV *self, float x, float y, float w = 0, float h = 0)
745 root 1.12 PROTOTYPE: $$$;$$
746 root 1.11 CODE:
747     {
748 root 1.12 HV *hv = (HV *)SvRV (self);
749 root 1.37 float s = SvNV (*hv_fetch (hv, "s", 1, 1));
750     float t = SvNV (*hv_fetch (hv, "t", 1, 1));
751 root 1.12 int name = SvIV (*hv_fetch (hv, "name", 4, 1));
752 elmex 1.36 int wrap_mode = SvIV (*hv_fetch (hv, "wrap_mode", 9, 1));
753 root 1.12
754     if (items < 5)
755     {
756 root 1.18 w = SvNV (*hv_fetch (hv, "w", 1, 1));
757     h = SvNV (*hv_fetch (hv, "h", 1, 1));
758 root 1.12 }
759    
760     glBindTexture (GL_TEXTURE_2D, name);
761 elmex 1.36 if (wrap_mode) {
762     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
763     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
764     }
765 root 1.12 glBegin (GL_QUADS);
766 root 1.37 glTexCoord2f (0, 0); glVertex2f (x , y );
767     glTexCoord2f (0, t); glVertex2f (x , y + h);
768     glTexCoord2f (s, t); glVertex2f (x + w, y + h);
769     glTexCoord2f (s, 0); glVertex2f (x + w, y );
770 root 1.12 glEnd ();
771 root 1.11 }
772 root 1.28
773     MODULE = CFClient PACKAGE = CFClient::Map
774    
775     CFClient::Map
776     new (SV *class, int map_width, int map_height)
777     CODE:
778     New (0, RETVAL, 1, struct map);
779 root 1.42 RETVAL->x = 0;
780     RETVAL->y = 0;
781     RETVAL->w = map_width;
782     RETVAL->h = map_height;
783     RETVAL->ox = 0;
784     RETVAL->oy = 0;
785 root 1.30 RETVAL->faces = 8192;
786     Newz (0, RETVAL->face, RETVAL->faces, mapface);
787 root 1.42 RETVAL->texs = 8192;
788     Newz (0, RETVAL->tex, RETVAL->texs, maptex);
789 root 1.28 RETVAL->rows = 0;
790     RETVAL->row = 0;
791     OUTPUT:
792     RETVAL
793    
794     void
795     DESTROY (CFClient::Map self)
796     CODE:
797     {
798 root 1.30 map_clear (self);
799 root 1.28 Safefree (self->face);
800 root 1.29 Safefree (self);
801     }
802    
803     void
804 root 1.30 clear (CFClient::Map self)
805     CODE:
806     map_clear (self);
807    
808     void
809 root 1.42 set_face (CFClient::Map self, int face, int texid)
810 root 1.29 CODE:
811     {
812 root 1.42 while (self->faces <= face)
813 root 1.28 {
814 root 1.30 Append (mapface, self->face, self->faces, self->faces);
815 root 1.29 self->faces *= 2;
816     }
817 root 1.28
818 root 1.42 self->face [face] = texid;
819     }
820    
821     void
822     set_texture (CFClient::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a)
823     CODE:
824     {
825     while (self->texs <= texid)
826     {
827     Append (maptex, self->tex, self->texs, self->texs);
828     self->texs *= 2;
829     }
830    
831 root 1.48 {
832     maptex *tex = self->tex + texid;
833 root 1.39
834 root 1.48 tex->name = name;
835     tex->w = w;
836     tex->h = h;
837     tex->s = s;
838     tex->t = t;
839     tex->r = r;
840     tex->g = g;
841     tex->b = b;
842     tex->a = a;
843     }
844 root 1.29 }
845    
846 root 1.42 int
847     ox (CFClient::Map self)
848     ALIAS:
849     oy = 1
850     CODE:
851     switch (ix)
852     {
853     case 0: RETVAL = self->ox; break;
854     case 1: RETVAL = self->oy; break;
855     }
856     OUTPUT:
857     RETVAL
858    
859 root 1.29 void
860 root 1.43 scroll (CFClient::Map self, int dx, int dy)
861     CODE:
862     {
863 root 1.44 if (dx > 0)
864     map_blank (self, self->x, self->y, dx - 1, self->h);
865     else if (dx < 0)
866     map_blank (self, self->x + self->w + dx + 1, self->y, 1 - dx, self->h);
867    
868     if (dy > 0)
869     map_blank (self, self->x, self->y, self->w, dy - 1);
870     else if (dy < 0)
871     map_blank (self, self->x, self->y + self->h + dy + 1, self->w, 1 - dy);
872 root 1.43
873 root 1.44 self->ox += dx; self->x += dx;
874     self->oy += dy; self->y += dy;
875 root 1.43
876     while (self->y < 0)
877     {
878     Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y);
879    
880     self->rows += MAP_EXTEND_Y;
881     self->y += MAP_EXTEND_Y;
882     }
883 root 1.44 }
884 root 1.43
885 root 1.44 void
886     map1a_update (CFClient::Map self, SV *data_)
887     CODE:
888     {
889 root 1.30 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
890     uint8_t *data_end = (uint8_t *)SvEND (data_);
891 root 1.48 mapcell *cell;
892     int x, y, flags;
893 root 1.43
894 root 1.29 while (data < data_end)
895     {
896 root 1.48 flags = (data [0] << 8) + data [1]; data += 2;
897 root 1.30
898 root 1.48 x = ((flags >> 10) & 63) + self->x;
899     y = ((flags >> 4) & 63) + self->y;
900 root 1.29
901 root 1.48 cell = map_get_cell (self, x, y);
902 root 1.29
903     if (flags & 15)
904     {
905 root 1.45 if (cell->darkness < 0)
906 root 1.29 {
907     cell->darkness = 0;
908     cell->face [0] = 0;
909     cell->face [1] = 0;
910     cell->face [2] = 0;
911     }
912 root 1.45
913 root 1.29 cell->darkness = flags & 8 ? *data++ : 255;
914    
915 root 1.42 //TODO: don't trust server data to be in-range(!)
916    
917 root 1.29 if (flags & 4)
918     {
919 root 1.42 cell->face [0] = self->face [(data [0] << 8) + data [1]]; data += 2;
920 root 1.29 }
921    
922     if (flags & 2)
923     {
924 root 1.42 cell->face [1] = self->face [(data [0] << 8) + data [1]]; data += 2;
925 root 1.29 }
926    
927     if (flags & 1)
928     {
929 root 1.42 cell->face [2] = self->face [(data [0] << 8) + data [1]]; data += 2;
930 root 1.29 }
931     }
932     else
933 root 1.31 cell->darkness = -1;
934 root 1.29 }
935 root 1.28 }
936    
937 root 1.40 SV *
938 root 1.55 mapmap (CFClient::Map self, int x0, int y0, int w, int h)
939 root 1.40 CODE:
940     {
941 root 1.55 int x1, x;
942     int y1, y;
943 root 1.40 int z;
944     SV *map_sv = newSV (w * h * sizeof (uint32_t));
945     uint32_t *map = (uint32_t *)SvPVX (map_sv);
946    
947     SvPOK_only (map_sv);
948     SvCUR_set (map_sv, w * h * sizeof (uint32_t));
949    
950 root 1.55 x0 += self->x; x1 = x0 + w;
951     y0 += self->y; y1 = y0 + h;
952 root 1.40
953     for (y = y0; y < y1; y++)
954     {
955     maprow *row = 0 <= y && y < self->rows
956     ? self->row + y
957     : 0;
958    
959     for (x = x0; x < x1; x++)
960     {
961     int r = 32, g = 32, b = 32, a = 192;
962    
963     if (row && row->c0 <= x && x < row->c1)
964     {
965     mapcell *cell = row->col + (x - row->c0);
966    
967     for (z = 0; z <= 0; z++)
968     {
969 root 1.42 mapface face = cell->face [z];
970 root 1.40
971     if (face)
972     {
973 root 1.42 maptex tex = self->tex [face];
974 root 1.40 int a0 = 255 - tex.a;
975     int a1 = tex.a;
976    
977     r = (r * a0 + tex.r * a1) / 255;
978     g = (g * a0 + tex.g * a1) / 255;
979     b = (b * a0 + tex.b * a1) / 255;
980     a = (a * a0 + tex.a * a1) / 255;
981     }
982     }
983     }
984    
985     *map++ = (r )
986     | (g << 8)
987     | (b << 16)
988     | (a << 24);
989     }
990     }
991    
992     RETVAL = map_sv;
993     }
994     OUTPUT:
995     RETVAL
996    
997 root 1.30 void
998 root 1.38 draw (CFClient::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
999 root 1.32 PPCODE:
1000 root 1.30 {
1001 root 1.48 int vx, vy;
1002     int x, y, z;
1003     int last_name;
1004     mapface face;
1005 root 1.32 int sw4 = (sw + 3) & ~3;
1006     SV *darkness_sv = sv_2mortal (newSV (sw4 * sh));
1007 root 1.35 uint8_t *darkness = (uint8_t *)SvPVX (darkness_sv);
1008 root 1.48
1009 root 1.42 memset (darkness, 255, sw4 * sh);
1010 root 1.32 SvPOK_only (darkness_sv);
1011     SvCUR_set (darkness_sv, sw4 * sh);
1012    
1013 root 1.48 vx = self->x + (self->w - sw) / 2 - shift_x;
1014     vy = self->y + (self->h - sh) / 2 - shift_y;
1015 root 1.38
1016 root 1.42 /*
1017     int vx = self->vx = self->w >= sw
1018     ? self->x + (self->w - sw) / 2
1019     : MIN (self->x, MAX (self->x + self->w - sw + 1, self->vx));
1020    
1021     int vy = self->vy = self->h >= sh
1022     ? self->y + (self->h - sh) / 2
1023     : MIN (self->y, MAX (self->y + self->h - sh + 1, self->vy));
1024     */
1025 root 1.30
1026     glColor4ub (255, 255, 255, 255);
1027    
1028     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1029     glEnable (GL_BLEND);
1030     glEnable (GL_TEXTURE_2D);
1031     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1032    
1033 root 1.48 glBegin (GL_QUADS);
1034 root 1.30
1035 root 1.48 last_name = 0;
1036 root 1.30
1037     for (z = 0; z < 3; z++)
1038     for (y = 0; y < sh; y++)
1039     if (0 <= y + vy && y + vy < self->rows)
1040     {
1041     maprow *row = self->row + (y + vy);
1042    
1043     for (x = 0; x < sw; x++)
1044     if (row->c0 <= x + vx && x + vx < row->c1)
1045     {
1046     mapcell *cell = row->col + (x + vx - row->c0);
1047 root 1.32
1048     darkness[y * sw4 + x] = cell->darkness < 0
1049 root 1.33 ? 255 - FOW_DARKNESS
1050 root 1.32 : 255 - cell->darkness;
1051    
1052 root 1.48 face = cell->face [z];
1053 root 1.30
1054     if (face)
1055     {
1056 root 1.42 maptex tex = self->tex [face];
1057 root 1.30
1058     int px = (x + 1) * 32 - tex.w;
1059     int py = (y + 1) * 32 - tex.h;
1060    
1061     if (last_name != tex.name)
1062     {
1063     glEnd ();
1064     last_name = tex.name;
1065     glBindTexture (GL_TEXTURE_2D, last_name);
1066     glBegin (GL_QUADS);
1067     }
1068    
1069     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1070     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1071     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1072     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1073     }
1074     }
1075     }
1076    
1077     glEnd ();
1078 root 1.32
1079 root 1.34 glDisable (GL_TEXTURE_2D);
1080     glDisable (GL_BLEND);
1081    
1082 root 1.32 EXTEND (SP, 3);
1083     PUSHs (sv_2mortal (newSViv (sw4)));
1084     PUSHs (sv_2mortal (newSViv (sh)));
1085     PUSHs (darkness_sv);
1086 root 1.30 }
1087    
1088 root 1.42 SV *
1089     get_rect (CFClient::Map self, int x0, int y0, int w, int h)
1090     CODE:
1091     {
1092     int x, y, x1, y1;
1093     SV *data_sv = newSV (w * h * 7 + 5);
1094     uint8_t *data = (uint8_t *)SvPVX (data_sv);
1095    
1096     *data++ = 0; /* version 0 format */
1097     *data++ = w >> 8; *data++ = w;
1098     *data++ = h >> 8; *data++ = h;
1099    
1100     // we need to do this 'cause we don't keep an absolute coord system for rows
1101 root 1.55 // TODO: treat rows as we treat columns
1102 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1103     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1104    
1105     x0 += self->x - self->ox;
1106     y0 += self->y - self->oy;
1107    
1108     x1 = x0 + w;
1109     y1 = y0 + h;
1110    
1111     for (y = y0; y < y1; y++)
1112     {
1113     maprow *row = 0 <= y && y < self->rows
1114     ? self->row + y
1115     : 0;
1116    
1117     for (x = x0; x < x1; x++)
1118     {
1119     if (row && row->c0 <= x && x < row->c1)
1120     {
1121     mapcell *cell = row->col + (x - row->c0);
1122     uint8_t flags = 0;
1123    
1124     if (cell->face [0]) flags |= 1;
1125     if (cell->face [1]) flags |= 2;
1126     if (cell->face [2]) flags |= 4;
1127    
1128     *data++ = flags;
1129    
1130     if (flags & 1)
1131     {
1132     *data++ = cell->face [0] >> 8;
1133     *data++ = cell->face [0];
1134     }
1135    
1136     if (flags & 2)
1137     {
1138     *data++ = cell->face [1] >> 8;
1139     *data++ = cell->face [1];
1140     }
1141    
1142     if (flags & 4)
1143     {
1144     *data++ = cell->face [2] >> 8;
1145     *data++ = cell->face [2];
1146     }
1147     }
1148     else
1149     *data++ = 0;
1150     }
1151     }
1152    
1153     SvPOK_only (data_sv);
1154     SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
1155     RETVAL = data_sv;
1156     }
1157     OUTPUT:
1158     RETVAL
1159    
1160     void
1161     set_rect (CFClient::Map self, int x0, int y0, uint8_t *data)
1162     PPCODE:
1163     {
1164     int x, y, z;
1165 root 1.48 int w, h;
1166 root 1.42 int x1, y1;
1167    
1168     if (*data++ != 0)
1169     return; /* version mismatch */
1170    
1171 root 1.48 w = *data++ << 8; w |= *data++;
1172     h = *data++ << 8; h |= *data++;
1173 root 1.42
1174     // we need to do this 'cause we don't keep an absolute coord system for rows
1175 root 1.55 // TODO: treat rows as we treat columns
1176 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1177     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1178    
1179     x0 += self->x - self->ox;
1180     y0 += self->y - self->oy;
1181    
1182     x1 = x0 + w;
1183     y1 = y0 + h;
1184    
1185     for (y = y0; y < y1; y++)
1186     {
1187     maprow *row = map_get_row (self, y);
1188    
1189     for (x = x0; x < x1; x++)
1190     {
1191     uint8_t flags = *data++;
1192    
1193     if (flags)
1194     {
1195     mapface face[3] = { 0, 0, 0 };
1196    
1197     mapcell *cell = row_get_cell (row, x);
1198    
1199     if (flags & 1) { face[0] = *data++ << 8; face[0] |= *data++; }
1200     if (flags & 2) { face[1] = *data++ << 8; face[1] |= *data++; }
1201     if (flags & 4) { face[2] = *data++ << 8; face[2] |= *data++; }
1202    
1203     if (cell->darkness <= 0)
1204     {
1205     cell->darkness = -1;
1206    
1207     for (z = 0; z <= 2; z++)
1208     {
1209     cell->face[z] = face[z];
1210    
1211     if (face[z] && (face[z] >= self->texs || !self->tex[face [z]].name))
1212     XPUSHs (sv_2mortal (newSViv (face[z])));
1213     }
1214     }
1215     }
1216     }
1217     }
1218     }
1219    
1220 root 1.52 MODULE = CFClient PACKAGE = CFClient::MixChunk
1221    
1222     CFClient::MixChunk
1223     new_from_file (SV *class, char *path)
1224     CODE:
1225     RETVAL = Mix_LoadWAV (path);
1226     OUTPUT:
1227     RETVAL
1228    
1229     void
1230     DESTROY (CFClient::MixChunk self)
1231     CODE:
1232     Mix_FreeChunk (self);
1233    
1234     int
1235     volume (CFClient::MixChunk self, int volume = -1)
1236     CODE:
1237     RETVAL = Mix_VolumeChunk (self, volume);
1238     OUTPUT:
1239     RETVAL
1240    
1241     int
1242     play (CFClient::MixChunk self, int channel = -1, int loops = 0, int ticks = -1)
1243     CODE:
1244     RETVAL = Mix_PlayChannelTimed (channel, self, loops, ticks);
1245     OUTPUT:
1246     RETVAL
1247    
1248     MODULE = CFClient PACKAGE = CFClient::MixMusic
1249    
1250     int
1251     volume (int volume = -1)
1252     CODE:
1253     RETVAL = Mix_VolumeMusic (volume);
1254     OUTPUT:
1255     RETVAL
1256    
1257     CFClient::MixMusic
1258     new_from_file (SV *class, char *path)
1259     CODE:
1260     RETVAL = Mix_LoadMUS (path);
1261     OUTPUT:
1262     RETVAL
1263    
1264     void
1265     DESTROY (CFClient::MixMusic self)
1266     CODE:
1267     Mix_FreeMusic (self);
1268    
1269     int
1270     play (CFClient::MixMusic self, int loops = -1)
1271     CODE:
1272     RETVAL = Mix_PlayMusic (self, loops);
1273     OUTPUT:
1274     RETVAL
1275    
1276 root 1.54 MODULE = CFClient PACKAGE = CFClient::OpenGL
1277    
1278     BOOT:
1279     {
1280     HV *stash = gv_stashpv ("CFClient::OpenGL", 1);
1281     static const struct {
1282     const char *name;
1283     IV iv;
1284     } *civ, const_iv[] = {
1285     # define const_iv(name) { # name, (IV)name }
1286     const_iv (GL_COLOR_MATERIAL),
1287     const_iv (GL_SMOOTH),
1288     const_iv (GL_FLAT),
1289     const_iv (GL_BLEND),
1290     const_iv (GL_AND),
1291     const_iv (GL_SRC_ALPHA),
1292     const_iv (GL_ONE_MINUS_SRC_ALPHA),
1293     const_iv (GL_RGB),
1294     const_iv (GL_RGBA),
1295     const_iv (GL_UNSIGNED_BYTE),
1296     const_iv (GL_ALPHA4),
1297     const_iv (GL_ALPHA),
1298     const_iv (GL_FLOAT),
1299     const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
1300     const_iv (GL_COMPILE),
1301     const_iv (GL_TEXTURE_1D),
1302     const_iv (GL_TEXTURE_2D),
1303     const_iv (GL_TEXTURE_ENV),
1304     const_iv (GL_TEXTURE_MAG_FILTER),
1305     const_iv (GL_TEXTURE_MIN_FILTER),
1306     const_iv (GL_TEXTURE_ENV_MODE),
1307     const_iv (GL_TEXTURE_WRAP_S),
1308     const_iv (GL_TEXTURE_WRAP_T),
1309     const_iv (GL_CLAMP),
1310     const_iv (GL_REPEAT),
1311     const_iv (GL_NEAREST),
1312     const_iv (GL_LINEAR),
1313     const_iv (GL_MODULATE),
1314     const_iv (GL_REPLACE),
1315     const_iv (GL_COLOR_BUFFER_BIT),
1316     const_iv (GL_PROJECTION),
1317     const_iv (GL_MODELVIEW),
1318     const_iv (GL_COLOR_LOGIC_OP),
1319     const_iv (GL_CONVOLUTION_2D),
1320     const_iv (GL_CONVOLUTION_BORDER_MODE),
1321     const_iv (GL_CONSTANT_BORDER),
1322     const_iv (GL_LINES),
1323     const_iv (GL_QUADS),
1324 root 1.55 const_iv (GL_LINE_LOOP),
1325 root 1.54 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
1326     const_iv (GL_FASTEST),
1327     # undef const_iv
1328     };
1329    
1330     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1331     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1332     }
1333    
1334     int glGetError ()
1335    
1336     void glClear (int mask)
1337    
1338     void glClearColor (float r, float g, float b, float a = 1.0)
1339     PROTOTYPE: @
1340    
1341     void glEnable (int cap)
1342    
1343     void glDisable (int cap)
1344    
1345     void glShadeModel (int mode)
1346    
1347     void glHint (int target, int mode)
1348    
1349     void glBlendFunc (int sfactor, int dfactor)
1350    
1351     void glLogicOp (int opcode)
1352    
1353     void glMatrixMode (int mode)
1354    
1355     void glPushMatrix ()
1356    
1357     void glPopMatrix ()
1358    
1359     void glLoadIdentity ()
1360    
1361     void glOrtho (double left, double right, double bottom, double top, double near, double far)
1362    
1363     void glViewport (int x, int y, int width, int height)
1364    
1365     void glTranslate (float x, float y, float z = 0.)
1366     CODE:
1367     glTranslatef (x, y, z);
1368    
1369     void glScale (float x, float y, float z)
1370     CODE:
1371     glScalef (x, y, z);
1372    
1373     void glRotate (float angle, float x, float y, float z)
1374     CODE:
1375     glRotatef (angle, x, y, z);
1376    
1377     void glBegin (int mode)
1378    
1379     void glEnd ()
1380    
1381     void glColor (float r, float g, float b, float a = 1.0)
1382     PROTOTYPE: @
1383     CODE:
1384     glColor4f (r, g, b, a);
1385    
1386     void glVertex (float x, float y, float z = 0.)
1387     CODE:
1388     glVertex3f (x, y, z);
1389    
1390     void glTexCoord (float s, float t)
1391     CODE:
1392     glTexCoord2f (s, t);
1393    
1394     void glTexEnv (int target, int pname, float param)
1395     CODE:
1396     glTexEnvf (target, pname, param);
1397    
1398     void glTexParameter (int target, int pname, float param)
1399     CODE:
1400     glTexParameterf (target, pname, param);
1401    
1402     void glBindTexture (int target, int name)
1403    
1404     void glConvolutionParameter (int target, int pname, float params)
1405     CODE:
1406     glConvolutionParameterf (target, pname, params);
1407    
1408     void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
1409    
1410     void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data)
1411    
1412     void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
1413    
1414     int glGenTexture ()
1415     CODE:
1416     {
1417     GLuint name;
1418     glGenTextures (1, &name);
1419     RETVAL = name;
1420     }
1421     OUTPUT:
1422     RETVAL
1423    
1424     void glDeleteTexture (int name)
1425     CODE:
1426     {
1427     GLuint name_ = name;
1428     glDeleteTextures (1, &name_);
1429     }
1430    
1431     int glGenList ()
1432     CODE:
1433     RETVAL = glGenLists (1);
1434     OUTPUT:
1435     RETVAL
1436    
1437     void glDeleteList (int list)
1438     CODE:
1439     glDeleteLists (list, 1);
1440    
1441     void glNewList (int list, int mode = GL_COMPILE)
1442    
1443     void glEndList ()
1444    
1445     void glCallList (int list)
1446