ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.59
Committed: Sun Apr 23 04:41:33 2006 UTC (18 years ago) by root
Branch: MAIN
Changes since 1.58: +7 -2 lines
Log Message:
fix font size allocation

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