ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.135
Committed: Sun Aug 13 15:14:17 2006 UTC (17 years, 9 months ago) by root
Branch: MAIN
Changes since 1.134: +3 -2 lines
Log Message:
*** empty log message ***

File Contents

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