ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.134
Committed: Fri Aug 4 16:49:58 2006 UTC (17 years, 9 months ago) by root
Branch: MAIN
Changes since 1.133: +2 -0 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.133 render (CFPlus::Layout self, float x, float y)
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     self->r, self->g, self->b, self->a
1036     );
1037 root 1.11
1038 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Texture
1039 root 1.11
1040     void
1041 root 1.113 pad2pot (SV *data_, SV *w_, SV *h_)
1042     CODE:
1043     {
1044     int ow = SvIV (w_);
1045     int oh = SvIV (h_);
1046    
1047     if (ow && oh)
1048     {
1049     int nw = minpot (ow);
1050     int nh = minpot (oh);
1051    
1052     if (nw != ow || nh != oh)
1053     {
1054     if (SvOK (data_))
1055     {
1056     STRLEN datalen;
1057     char *data = SvPVbyte (data_, datalen);
1058     int bpp = datalen / (ow * oh);
1059     SV *result_ = sv_2mortal (newSV (nw * nh * bpp));
1060    
1061     SvPOK_only (result_);
1062     SvCUR_set (result_, nw * nh * bpp);
1063    
1064     memset (SvPVX (result_), 0, nw * nh * bpp);
1065     while (oh--)
1066     memcpy (SvPVX (result_) + oh * nw * bpp, data + oh * ow * bpp, ow * bpp);
1067    
1068     sv_setsv (data_, result_);
1069     }
1070    
1071     sv_setiv (w_, nw);
1072     sv_setiv (h_, nh);
1073     }
1074     }
1075     }
1076    
1077     void
1078 root 1.114 draw_quad (SV *self, float x, float y, float w = 0., float h = 0.)
1079 root 1.12 PROTOTYPE: $$$;$$
1080 root 1.76 ALIAS:
1081     draw_quad_alpha = 1
1082     draw_quad_alpha_premultiplied = 2
1083 root 1.11 CODE:
1084     {
1085 root 1.12 HV *hv = (HV *)SvRV (self);
1086 root 1.37 float s = SvNV (*hv_fetch (hv, "s", 1, 1));
1087     float t = SvNV (*hv_fetch (hv, "t", 1, 1));
1088 root 1.12 int name = SvIV (*hv_fetch (hv, "name", 4, 1));
1089    
1090     if (items < 5)
1091     {
1092 root 1.18 w = SvNV (*hv_fetch (hv, "w", 1, 1));
1093     h = SvNV (*hv_fetch (hv, "h", 1, 1));
1094 root 1.12 }
1095    
1096 root 1.76 if (ix)
1097     {
1098     glEnable (GL_BLEND);
1099 root 1.103
1100     if (ix == 2)
1101     glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1102     else
1103     gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1104 root 1.104 GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
1105 root 1.103
1106 root 1.86 glEnable (GL_ALPHA_TEST);
1107     glAlphaFunc (GL_GREATER, 0.01f);
1108 root 1.76 }
1109    
1110 root 1.12 glBindTexture (GL_TEXTURE_2D, name);
1111 root 1.76
1112 root 1.12 glBegin (GL_QUADS);
1113 root 1.37 glTexCoord2f (0, 0); glVertex2f (x , y );
1114     glTexCoord2f (0, t); glVertex2f (x , y + h);
1115     glTexCoord2f (s, t); glVertex2f (x + w, y + h);
1116     glTexCoord2f (s, 0); glVertex2f (x + w, y );
1117 root 1.12 glEnd ();
1118 root 1.76
1119     if (ix)
1120 root 1.86 {
1121     glDisable (GL_ALPHA_TEST);
1122     glDisable (GL_BLEND);
1123     }
1124 root 1.11 }
1125 root 1.28
1126 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Map
1127 root 1.28
1128 root 1.133 CFPlus::Map
1129 root 1.28 new (SV *class, int map_width, int map_height)
1130     CODE:
1131     New (0, RETVAL, 1, struct map);
1132 root 1.42 RETVAL->x = 0;
1133     RETVAL->y = 0;
1134     RETVAL->w = map_width;
1135     RETVAL->h = map_height;
1136     RETVAL->ox = 0;
1137     RETVAL->oy = 0;
1138 root 1.30 RETVAL->faces = 8192;
1139     Newz (0, RETVAL->face, RETVAL->faces, mapface);
1140 root 1.42 RETVAL->texs = 8192;
1141     Newz (0, RETVAL->tex, RETVAL->texs, maptex);
1142 root 1.28 RETVAL->rows = 0;
1143     RETVAL->row = 0;
1144     OUTPUT:
1145     RETVAL
1146    
1147     void
1148 root 1.133 DESTROY (CFPlus::Map self)
1149 root 1.28 CODE:
1150     {
1151 root 1.30 map_clear (self);
1152 root 1.28 Safefree (self->face);
1153 root 1.111 Safefree (self->tex);
1154 root 1.29 Safefree (self);
1155     }
1156    
1157     void
1158 root 1.133 clear (CFPlus::Map self)
1159 root 1.30 CODE:
1160     map_clear (self);
1161    
1162     void
1163 root 1.133 set_face (CFPlus::Map self, int face, int texid)
1164 root 1.29 CODE:
1165     {
1166 root 1.42 while (self->faces <= face)
1167 root 1.28 {
1168 root 1.30 Append (mapface, self->face, self->faces, self->faces);
1169 root 1.29 self->faces *= 2;
1170     }
1171 root 1.28
1172 root 1.42 self->face [face] = texid;
1173     }
1174    
1175     void
1176 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)
1177 root 1.42 CODE:
1178     {
1179     while (self->texs <= texid)
1180     {
1181     Append (maptex, self->tex, self->texs, self->texs);
1182     self->texs *= 2;
1183     }
1184    
1185 root 1.48 {
1186     maptex *tex = self->tex + texid;
1187 root 1.39
1188 root 1.48 tex->name = name;
1189     tex->w = w;
1190     tex->h = h;
1191     tex->s = s;
1192     tex->t = t;
1193     tex->r = r;
1194     tex->g = g;
1195     tex->b = b;
1196     tex->a = a;
1197     }
1198 root 1.95
1199     // somewhat hackish, but for textures that require it, it really
1200     // improves the look, and most others don't suffer.
1201     glBindTexture (GL_TEXTURE_2D, name);
1202 root 1.99 //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1203     //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1204     // use uglier nearest interpolation because linear suffers
1205     // from transparent color bleeding and ugly wrapping effects.
1206     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1207 root 1.29 }
1208    
1209 root 1.42 int
1210 root 1.133 ox (CFPlus::Map self)
1211 root 1.42 ALIAS:
1212     oy = 1
1213 root 1.101 x = 2
1214     y = 3
1215 root 1.102 w = 4
1216     h = 5
1217 root 1.42 CODE:
1218     switch (ix)
1219     {
1220     case 0: RETVAL = self->ox; break;
1221     case 1: RETVAL = self->oy; break;
1222 root 1.101 case 2: RETVAL = self->x; break;
1223     case 3: RETVAL = self->y; break;
1224 root 1.102 case 4: RETVAL = self->w; break;
1225     case 5: RETVAL = self->h; break;
1226 root 1.42 }
1227     OUTPUT:
1228     RETVAL
1229    
1230 root 1.29 void
1231 root 1.133 scroll (CFPlus::Map self, int dx, int dy)
1232 root 1.43 CODE:
1233     {
1234 root 1.44 if (dx > 0)
1235     map_blank (self, self->x, self->y, dx - 1, self->h);
1236     else if (dx < 0)
1237     map_blank (self, self->x + self->w + dx + 1, self->y, 1 - dx, self->h);
1238    
1239     if (dy > 0)
1240     map_blank (self, self->x, self->y, self->w, dy - 1);
1241     else if (dy < 0)
1242     map_blank (self, self->x, self->y + self->h + dy + 1, self->w, 1 - dy);
1243 root 1.43
1244 root 1.44 self->ox += dx; self->x += dx;
1245     self->oy += dy; self->y += dy;
1246 root 1.43
1247     while (self->y < 0)
1248     {
1249     Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y);
1250    
1251     self->rows += MAP_EXTEND_Y;
1252     self->y += MAP_EXTEND_Y;
1253     }
1254 root 1.44 }
1255 root 1.43
1256 root 1.44 void
1257 root 1.133 map1a_update (CFPlus::Map self, SV *data_)
1258 root 1.44 CODE:
1259     {
1260 root 1.30 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
1261     uint8_t *data_end = (uint8_t *)SvEND (data_);
1262 root 1.48 mapcell *cell;
1263     int x, y, flags;
1264 root 1.43
1265 root 1.29 while (data < data_end)
1266     {
1267 root 1.48 flags = (data [0] << 8) + data [1]; data += 2;
1268 root 1.30
1269 root 1.120 x = self->x + ((flags >> 10) & 63);
1270     y = self->y + ((flags >> 4) & 63);
1271 root 1.29
1272 root 1.48 cell = map_get_cell (self, x, y);
1273 root 1.29
1274     if (flags & 15)
1275     {
1276 root 1.45 if (cell->darkness < 0)
1277 root 1.29 {
1278     cell->darkness = 0;
1279     cell->face [0] = 0;
1280     cell->face [1] = 0;
1281     cell->face [2] = 0;
1282     }
1283 root 1.45
1284 root 1.29 cell->darkness = flags & 8 ? *data++ : 255;
1285    
1286 root 1.42 //TODO: don't trust server data to be in-range(!)
1287    
1288 root 1.29 if (flags & 4)
1289     {
1290 root 1.42 cell->face [0] = self->face [(data [0] << 8) + data [1]]; data += 2;
1291 root 1.29 }
1292    
1293     if (flags & 2)
1294     {
1295 root 1.42 cell->face [1] = self->face [(data [0] << 8) + data [1]]; data += 2;
1296 root 1.29 }
1297    
1298     if (flags & 1)
1299     {
1300 root 1.42 cell->face [2] = self->face [(data [0] << 8) + data [1]]; data += 2;
1301 root 1.29 }
1302     }
1303     else
1304 root 1.31 cell->darkness = -1;
1305 root 1.29 }
1306 root 1.28 }
1307    
1308 root 1.40 SV *
1309 root 1.133 mapmap (CFPlus::Map self, int x0, int y0, int w, int h)
1310 root 1.40 CODE:
1311     {
1312 root 1.55 int x1, x;
1313     int y1, y;
1314 root 1.40 int z;
1315     SV *map_sv = newSV (w * h * sizeof (uint32_t));
1316     uint32_t *map = (uint32_t *)SvPVX (map_sv);
1317    
1318     SvPOK_only (map_sv);
1319     SvCUR_set (map_sv, w * h * sizeof (uint32_t));
1320    
1321 root 1.55 x0 += self->x; x1 = x0 + w;
1322     y0 += self->y; y1 = y0 + h;
1323 root 1.40
1324     for (y = y0; y < y1; y++)
1325     {
1326     maprow *row = 0 <= y && y < self->rows
1327     ? self->row + y
1328     : 0;
1329    
1330     for (x = x0; x < x1; x++)
1331     {
1332     int r = 32, g = 32, b = 32, a = 192;
1333    
1334     if (row && row->c0 <= x && x < row->c1)
1335     {
1336     mapcell *cell = row->col + (x - row->c0);
1337    
1338     for (z = 0; z <= 0; z++)
1339     {
1340 root 1.42 mapface face = cell->face [z];
1341 root 1.40
1342     if (face)
1343     {
1344 root 1.42 maptex tex = self->tex [face];
1345 root 1.40 int a0 = 255 - tex.a;
1346     int a1 = tex.a;
1347    
1348     r = (r * a0 + tex.r * a1) / 255;
1349     g = (g * a0 + tex.g * a1) / 255;
1350     b = (b * a0 + tex.b * a1) / 255;
1351     a = (a * a0 + tex.a * a1) / 255;
1352     }
1353     }
1354     }
1355    
1356     *map++ = (r )
1357     | (g << 8)
1358     | (b << 16)
1359     | (a << 24);
1360     }
1361     }
1362    
1363     RETVAL = map_sv;
1364     }
1365     OUTPUT:
1366     RETVAL
1367    
1368 root 1.30 void
1369 root 1.133 draw (CFPlus::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1370 root 1.116 CODE:
1371 root 1.30 {
1372 root 1.48 int vx, vy;
1373     int x, y, z;
1374     int last_name;
1375     mapface face;
1376    
1377 root 1.120 vx = self->x + self->w / 2 - sw / 2 - shift_x;
1378     vy = self->y + self->h / 2 - sh / 2 - shift_y;
1379 root 1.38
1380 root 1.42 /*
1381     int vx = self->vx = self->w >= sw
1382     ? self->x + (self->w - sw) / 2
1383     : MIN (self->x, MAX (self->x + self->w - sw + 1, self->vx));
1384    
1385     int vy = self->vy = self->h >= sh
1386     ? self->y + (self->h - sh) / 2
1387     : MIN (self->y, MAX (self->y + self->h - sh + 1, self->vy));
1388     */
1389 root 1.30
1390     glColor4ub (255, 255, 255, 255);
1391    
1392 root 1.117 glEnable (GL_BLEND);
1393 root 1.30 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1394     glEnable (GL_TEXTURE_2D);
1395     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1396    
1397 root 1.48 glBegin (GL_QUADS);
1398 root 1.30
1399 root 1.48 last_name = 0;
1400 root 1.30
1401     for (z = 0; z < 3; z++)
1402     for (y = 0; y < sh; y++)
1403     if (0 <= y + vy && y + vy < self->rows)
1404     {
1405     maprow *row = self->row + (y + vy);
1406    
1407     for (x = 0; x < sw; x++)
1408     if (row->c0 <= x + vx && x + vx < row->c1)
1409     {
1410     mapcell *cell = row->col + (x + vx - row->c0);
1411 root 1.32
1412 root 1.48 face = cell->face [z];
1413 root 1.30
1414     if (face)
1415     {
1416 root 1.42 maptex tex = self->tex [face];
1417 root 1.30
1418     int px = (x + 1) * 32 - tex.w;
1419     int py = (y + 1) * 32 - tex.h;
1420    
1421     if (last_name != tex.name)
1422     {
1423     glEnd ();
1424     last_name = tex.name;
1425     glBindTexture (GL_TEXTURE_2D, last_name);
1426     glBegin (GL_QUADS);
1427     }
1428    
1429     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1430     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1431     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1432     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1433     }
1434     }
1435     }
1436    
1437     glEnd ();
1438 root 1.32
1439 root 1.34 glDisable (GL_TEXTURE_2D);
1440     glDisable (GL_BLEND);
1441 root 1.116 }
1442    
1443     void
1444 root 1.133 draw_magicmap (CFPlus::Map self, int dx, int dy, int w, int h, unsigned char *data)
1445 root 1.117 CODE:
1446     {
1447     static float color[16][3] = {
1448 root 1.123 { 0.00F, 0.00F, 0.00F },
1449     { 1.00F, 1.00F, 1.00F },
1450     { 0.00F, 0.00F, 0.55F },
1451     { 1.00F, 0.00F, 0.00F },
1452    
1453     { 1.00F, 0.54F, 0.00F },
1454     { 0.11F, 0.56F, 1.00F },
1455     { 0.93F, 0.46F, 0.00F },
1456     { 0.18F, 0.54F, 0.34F },
1457    
1458     { 0.56F, 0.73F, 0.56F },
1459     { 0.80F, 0.80F, 0.80F },
1460     { 0.55F, 0.41F, 0.13F },
1461     { 0.99F, 0.77F, 0.26F },
1462    
1463     { 0.74F, 0.65F, 0.41F },
1464    
1465     { 0.00F, 1.00F, 1.00F },
1466     { 1.00F, 0.00F, 1.00F },
1467     { 1.00F, 1.00F, 0.00F },
1468 root 1.117 };
1469    
1470     int x, y;
1471    
1472     glEnable (GL_TEXTURE_2D);
1473     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1474     glEnable (GL_BLEND);
1475     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1476     glBegin (GL_QUADS);
1477    
1478     for (y = 0; y < h; y++)
1479     for (x = 0; x < w; x++)
1480     {
1481     unsigned char m = data [x + y * w];
1482    
1483 root 1.118 if (m)
1484     {
1485     float *c = color [m & 15];
1486    
1487     float tx1 = m & 0x40 ? 0.5 : 0.;
1488     float tx2 = tx1 + 0.5;
1489    
1490     glColor4f (c[0], c[1], c[2], 0.75);
1491     glTexCoord2f (tx1, 0.); glVertex2i (x , y );
1492     glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1);
1493     glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1);
1494     glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y );
1495     }
1496 root 1.117 }
1497    
1498     glEnd ();
1499     glDisable (GL_BLEND);
1500     glDisable (GL_TEXTURE_2D);
1501     }
1502    
1503     void
1504 root 1.133 fow_texture (CFPlus::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1505 root 1.116 PPCODE:
1506     {
1507     int vx, vy;
1508     int x, y;
1509     int sw4 = (sw + 3) & ~3;
1510     SV *darkness_sv = sv_2mortal (newSV (sw4 * sh));
1511     uint8_t *darkness = (uint8_t *)SvPVX (darkness_sv);
1512    
1513     memset (darkness, 255, sw4 * sh);
1514     SvPOK_only (darkness_sv);
1515     SvCUR_set (darkness_sv, sw4 * sh);
1516    
1517     vx = self->x + (self->w - sw + 1) / 2 - shift_x;
1518     vy = self->y + (self->h - sh + 1) / 2 - shift_y;
1519    
1520     for (y = 0; y < sh; y++)
1521     if (0 <= y + vy && y + vy < self->rows)
1522     {
1523     maprow *row = self->row + (y + vy);
1524    
1525     for (x = 0; x < sw; x++)
1526     if (row->c0 <= x + vx && x + vx < row->c1)
1527     {
1528     mapcell *cell = row->col + (x + vx - row->c0);
1529    
1530     darkness[y * sw4 + x] = cell->darkness < 0
1531     ? 255 - FOW_DARKNESS
1532     : 255 - cell->darkness;
1533     }
1534     }
1535 root 1.34
1536 root 1.32 EXTEND (SP, 3);
1537     PUSHs (sv_2mortal (newSViv (sw4)));
1538     PUSHs (sv_2mortal (newSViv (sh)));
1539     PUSHs (darkness_sv);
1540 root 1.30 }
1541    
1542 root 1.42 SV *
1543 root 1.133 get_rect (CFPlus::Map self, int x0, int y0, int w, int h)
1544 root 1.42 CODE:
1545     {
1546     int x, y, x1, y1;
1547     SV *data_sv = newSV (w * h * 7 + 5);
1548     uint8_t *data = (uint8_t *)SvPVX (data_sv);
1549    
1550     *data++ = 0; /* version 0 format */
1551     *data++ = w >> 8; *data++ = w;
1552     *data++ = h >> 8; *data++ = h;
1553    
1554     // we need to do this 'cause we don't keep an absolute coord system for rows
1555 root 1.55 // TODO: treat rows as we treat columns
1556 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1557     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1558    
1559     x0 += self->x - self->ox;
1560     y0 += self->y - self->oy;
1561    
1562     x1 = x0 + w;
1563     y1 = y0 + h;
1564    
1565     for (y = y0; y < y1; y++)
1566     {
1567     maprow *row = 0 <= y && y < self->rows
1568     ? self->row + y
1569     : 0;
1570    
1571     for (x = x0; x < x1; x++)
1572     {
1573     if (row && row->c0 <= x && x < row->c1)
1574     {
1575     mapcell *cell = row->col + (x - row->c0);
1576     uint8_t flags = 0;
1577    
1578     if (cell->face [0]) flags |= 1;
1579     if (cell->face [1]) flags |= 2;
1580     if (cell->face [2]) flags |= 4;
1581    
1582     *data++ = flags;
1583    
1584     if (flags & 1)
1585     {
1586     *data++ = cell->face [0] >> 8;
1587     *data++ = cell->face [0];
1588     }
1589    
1590     if (flags & 2)
1591     {
1592     *data++ = cell->face [1] >> 8;
1593     *data++ = cell->face [1];
1594     }
1595    
1596     if (flags & 4)
1597     {
1598     *data++ = cell->face [2] >> 8;
1599     *data++ = cell->face [2];
1600     }
1601     }
1602     else
1603     *data++ = 0;
1604     }
1605     }
1606    
1607     SvPOK_only (data_sv);
1608     SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
1609     RETVAL = data_sv;
1610     }
1611     OUTPUT:
1612     RETVAL
1613    
1614     void
1615 root 1.133 set_rect (CFPlus::Map self, int x0, int y0, uint8_t *data)
1616 root 1.42 PPCODE:
1617     {
1618     int x, y, z;
1619 root 1.48 int w, h;
1620 root 1.42 int x1, y1;
1621    
1622     if (*data++ != 0)
1623     return; /* version mismatch */
1624    
1625 root 1.48 w = *data++ << 8; w |= *data++;
1626     h = *data++ << 8; h |= *data++;
1627 root 1.42
1628     // we need to do this 'cause we don't keep an absolute coord system for rows
1629 root 1.55 // TODO: treat rows as we treat columns
1630 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1631     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1632    
1633     x0 += self->x - self->ox;
1634     y0 += self->y - self->oy;
1635    
1636     x1 = x0 + w;
1637     y1 = y0 + h;
1638    
1639     for (y = y0; y < y1; y++)
1640     {
1641     maprow *row = map_get_row (self, y);
1642    
1643     for (x = x0; x < x1; x++)
1644     {
1645     uint8_t flags = *data++;
1646    
1647     if (flags)
1648     {
1649     mapface face[3] = { 0, 0, 0 };
1650    
1651     mapcell *cell = row_get_cell (row, x);
1652    
1653     if (flags & 1) { face[0] = *data++ << 8; face[0] |= *data++; }
1654     if (flags & 2) { face[1] = *data++ << 8; face[1] |= *data++; }
1655     if (flags & 4) { face[2] = *data++ << 8; face[2] |= *data++; }
1656    
1657     if (cell->darkness <= 0)
1658     {
1659     cell->darkness = -1;
1660    
1661     for (z = 0; z <= 2; z++)
1662     {
1663     cell->face[z] = face[z];
1664    
1665     if (face[z] && (face[z] >= self->texs || !self->tex[face [z]].name))
1666     XPUSHs (sv_2mortal (newSViv (face[z])));
1667     }
1668     }
1669     }
1670     }
1671     }
1672     }
1673    
1674 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::MixChunk
1675 root 1.52
1676 root 1.133 CFPlus::MixChunk
1677 root 1.52 new_from_file (SV *class, char *path)
1678     CODE:
1679     RETVAL = Mix_LoadWAV (path);
1680     OUTPUT:
1681     RETVAL
1682    
1683     void
1684 root 1.133 DESTROY (CFPlus::MixChunk self)
1685 root 1.52 CODE:
1686     Mix_FreeChunk (self);
1687    
1688     int
1689 root 1.133 volume (CFPlus::MixChunk self, int volume = -1)
1690 root 1.52 CODE:
1691     RETVAL = Mix_VolumeChunk (self, volume);
1692     OUTPUT:
1693     RETVAL
1694    
1695     int
1696 root 1.133 play (CFPlus::MixChunk self, int channel = -1, int loops = 0, int ticks = -1)
1697 root 1.52 CODE:
1698     RETVAL = Mix_PlayChannelTimed (channel, self, loops, ticks);
1699     OUTPUT:
1700     RETVAL
1701    
1702 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::MixMusic
1703 root 1.52
1704     int
1705     volume (int volume = -1)
1706     CODE:
1707     RETVAL = Mix_VolumeMusic (volume);
1708     OUTPUT:
1709     RETVAL
1710    
1711 root 1.133 CFPlus::MixMusic
1712 root 1.52 new_from_file (SV *class, char *path)
1713     CODE:
1714     RETVAL = Mix_LoadMUS (path);
1715     OUTPUT:
1716     RETVAL
1717    
1718     void
1719 root 1.133 DESTROY (CFPlus::MixMusic self)
1720 root 1.52 CODE:
1721     Mix_FreeMusic (self);
1722    
1723     int
1724 root 1.133 play (CFPlus::MixMusic self, int loops = -1)
1725 root 1.52 CODE:
1726     RETVAL = Mix_PlayMusic (self, loops);
1727     OUTPUT:
1728     RETVAL
1729    
1730 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::OpenGL
1731 root 1.54
1732     BOOT:
1733     {
1734 root 1.133 HV *stash = gv_stashpv ("CFPlus::OpenGL", 1);
1735 root 1.54 static const struct {
1736     const char *name;
1737     IV iv;
1738     } *civ, const_iv[] = {
1739     # define const_iv(name) { # name, (IV)name }
1740     const_iv (GL_COLOR_MATERIAL),
1741     const_iv (GL_SMOOTH),
1742     const_iv (GL_FLAT),
1743 root 1.69 const_iv (GL_DITHER),
1744 root 1.54 const_iv (GL_BLEND),
1745 root 1.89 const_iv (GL_CULL_FACE),
1746 root 1.69 const_iv (GL_SCISSOR_TEST),
1747 root 1.89 const_iv (GL_DEPTH_TEST),
1748     const_iv (GL_ALPHA_TEST),
1749     const_iv (GL_NORMALIZE),
1750     const_iv (GL_RESCALE_NORMAL),
1751 root 1.119 const_iv (GL_FRONT),
1752     const_iv (GL_BACK),
1753 root 1.54 const_iv (GL_AND),
1754 root 1.67 const_iv (GL_ONE),
1755     const_iv (GL_ZERO),
1756 root 1.54 const_iv (GL_SRC_ALPHA),
1757 root 1.104 const_iv (GL_DST_ALPHA),
1758 root 1.54 const_iv (GL_ONE_MINUS_SRC_ALPHA),
1759 root 1.67 const_iv (GL_ONE_MINUS_DST_ALPHA),
1760 root 1.104 const_iv (GL_SRC_ALPHA_SATURATE),
1761 root 1.54 const_iv (GL_RGB),
1762     const_iv (GL_RGBA),
1763 root 1.115 const_iv (GL_RGBA4),
1764     const_iv (GL_RGBA8),
1765     const_iv (GL_RGB5_A1),
1766 root 1.54 const_iv (GL_UNSIGNED_BYTE),
1767 root 1.89 const_iv (GL_UNSIGNED_SHORT),
1768     const_iv (GL_UNSIGNED_INT),
1769 root 1.54 const_iv (GL_ALPHA),
1770 root 1.86 const_iv (GL_INTENSITY),
1771 root 1.76 const_iv (GL_LUMINANCE),
1772 root 1.86 const_iv (GL_LUMINANCE_ALPHA),
1773 root 1.54 const_iv (GL_FLOAT),
1774     const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
1775     const_iv (GL_COMPILE),
1776     const_iv (GL_TEXTURE_1D),
1777     const_iv (GL_TEXTURE_2D),
1778     const_iv (GL_TEXTURE_ENV),
1779     const_iv (GL_TEXTURE_MAG_FILTER),
1780     const_iv (GL_TEXTURE_MIN_FILTER),
1781     const_iv (GL_TEXTURE_ENV_MODE),
1782     const_iv (GL_TEXTURE_WRAP_S),
1783     const_iv (GL_TEXTURE_WRAP_T),
1784 root 1.98 const_iv (GL_REPEAT),
1785 root 1.54 const_iv (GL_CLAMP),
1786 root 1.98 const_iv (GL_CLAMP_TO_EDGE),
1787 root 1.54 const_iv (GL_NEAREST),
1788     const_iv (GL_LINEAR),
1789 root 1.57 const_iv (GL_NEAREST_MIPMAP_NEAREST),
1790     const_iv (GL_LINEAR_MIPMAP_NEAREST),
1791     const_iv (GL_NEAREST_MIPMAP_LINEAR),
1792     const_iv (GL_LINEAR_MIPMAP_LINEAR),
1793     const_iv (GL_GENERATE_MIPMAP),
1794 root 1.54 const_iv (GL_MODULATE),
1795 root 1.69 const_iv (GL_DECAL),
1796 root 1.54 const_iv (GL_REPLACE),
1797 root 1.89 const_iv (GL_DEPTH_BUFFER_BIT),
1798 root 1.54 const_iv (GL_COLOR_BUFFER_BIT),
1799     const_iv (GL_PROJECTION),
1800     const_iv (GL_MODELVIEW),
1801     const_iv (GL_COLOR_LOGIC_OP),
1802 root 1.69 const_iv (GL_SEPARABLE_2D),
1803 root 1.54 const_iv (GL_CONVOLUTION_2D),
1804     const_iv (GL_CONVOLUTION_BORDER_MODE),
1805     const_iv (GL_CONSTANT_BORDER),
1806     const_iv (GL_LINES),
1807 root 1.89 const_iv (GL_LINE_LOOP),
1808 root 1.54 const_iv (GL_QUADS),
1809 root 1.89 const_iv (GL_QUAD_STRIP),
1810     const_iv (GL_TRIANGLES),
1811     const_iv (GL_TRIANGLE_STRIP),
1812     const_iv (GL_TRIANGLE_FAN),
1813 root 1.54 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
1814     const_iv (GL_FASTEST),
1815 root 1.89 const_iv (GL_V2F),
1816     const_iv (GL_V3F),
1817     const_iv (GL_T2F_V3F),
1818     const_iv (GL_T2F_N3F_V3F),
1819 root 1.54 # undef const_iv
1820     };
1821    
1822     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1823     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1824     }
1825    
1826 root 1.97 char *
1827     gl_vendor ()
1828     CODE:
1829     RETVAL = (char *)glGetString (GL_VENDOR);
1830     OUTPUT:
1831     RETVAL
1832    
1833     char *
1834     gl_version ()
1835     CODE:
1836     RETVAL = (char *)glGetString (GL_VERSION);
1837     OUTPUT:
1838     RETVAL
1839    
1840     char *
1841     gl_extensions ()
1842     CODE:
1843     RETVAL = (char *)glGetString (GL_EXTENSIONS);
1844     OUTPUT:
1845     RETVAL
1846    
1847 root 1.54 int glGetError ()
1848    
1849 root 1.114 void glFinish ()
1850    
1851 root 1.54 void glClear (int mask)
1852    
1853     void glClearColor (float r, float g, float b, float a = 1.0)
1854     PROTOTYPE: @
1855    
1856     void glEnable (int cap)
1857    
1858     void glDisable (int cap)
1859    
1860     void glShadeModel (int mode)
1861    
1862     void glHint (int target, int mode)
1863    
1864     void glBlendFunc (int sfactor, int dfactor)
1865    
1866 root 1.103 void glBlendFuncSeparate (int sa, int da, int saa, int daa)
1867     CODE:
1868     gl_BlendFuncSeparate (sa, da, saa, daa);
1869    
1870 root 1.89 void glDepthMask (int flag)
1871    
1872 root 1.54 void glLogicOp (int opcode)
1873    
1874 root 1.68 void glColorMask (int red, int green, int blue, int alpha)
1875    
1876 root 1.54 void glMatrixMode (int mode)
1877    
1878     void glPushMatrix ()
1879    
1880     void glPopMatrix ()
1881    
1882     void glLoadIdentity ()
1883    
1884 root 1.119 void glDrawBuffer (int buffer)
1885    
1886     void glReadBuffer (int buffer)
1887    
1888 root 1.90 # near_ and far_ are due to microsofts buggy "c" compiler
1889     void glFrustum (double left, double right, double bottom, double top, double near_, double far_)
1890    
1891     # near_ and far_ are due to microsofts buggy "c" compiler
1892 root 1.64 void glOrtho (double left, double right, double bottom, double top, double near_, double far_)
1893 root 1.54
1894     void glViewport (int x, int y, int width, int height)
1895    
1896 root 1.69 void glScissor (int x, int y, int width, int height)
1897    
1898 root 1.54 void glTranslate (float x, float y, float z = 0.)
1899     CODE:
1900     glTranslatef (x, y, z);
1901    
1902 root 1.62 void glScale (float x, float y, float z = 1.)
1903 root 1.54 CODE:
1904     glScalef (x, y, z);
1905    
1906     void glRotate (float angle, float x, float y, float z)
1907     CODE:
1908     glRotatef (angle, x, y, z);
1909    
1910     void glBegin (int mode)
1911    
1912     void glEnd ()
1913    
1914     void glColor (float r, float g, float b, float a = 1.0)
1915     PROTOTYPE: @
1916 root 1.103 ALIAS:
1917     glColor_premultiply = 1
1918 root 1.54 CODE:
1919 root 1.103 if (ix)
1920     {
1921     r *= a;
1922     g *= a;
1923     b *= a;
1924     }
1925 root 1.90 // microsoft visual "c" rounds instead of truncating...
1926 root 1.130 glColor4f (r, g, b, a);
1927 root 1.54
1928 root 1.89 void glInterleavedArrays (int format, int stride, char *data)
1929    
1930     void glDrawElements (int mode, int count, int type, char *indices)
1931    
1932     # 1.2 void glDrawRangeElements (int mode, int start, int end
1933    
1934 root 1.91 void glRasterPos (float x, float y, float z = 0.)
1935     CODE:
1936     glRasterPos3f (0, 0, z);
1937     glBitmap (0, 0, 0, 0, x, y, 0);
1938    
1939 root 1.54 void glVertex (float x, float y, float z = 0.)
1940     CODE:
1941     glVertex3f (x, y, z);
1942    
1943     void glTexCoord (float s, float t)
1944     CODE:
1945     glTexCoord2f (s, t);
1946    
1947     void glTexEnv (int target, int pname, float param)
1948     CODE:
1949     glTexEnvf (target, pname, param);
1950    
1951     void glTexParameter (int target, int pname, float param)
1952     CODE:
1953     glTexParameterf (target, pname, param);
1954    
1955     void glBindTexture (int target, int name)
1956    
1957     void glConvolutionParameter (int target, int pname, float params)
1958     CODE:
1959 root 1.103 if (gl.ConvolutionParameterf)
1960     gl.ConvolutionParameterf (target, pname, params);
1961 root 1.54
1962     void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
1963 root 1.64 CODE:
1964 root 1.103 if (gl.ConvolutionFilter2D)
1965     gl.ConvolutionFilter2D (target, internalformat, width, height, format, type, data);
1966 root 1.54
1967 root 1.69 void glSeparableFilter2D (int target, int internalformat, int width, int height, int format, int type, char *row, char *column)
1968     CODE:
1969 root 1.103 if (gl.SeparableFilter2D)
1970     gl.SeparableFilter2D (target, internalformat, width, height, format, type, row, column);
1971 root 1.69
1972 root 1.54 void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data)
1973    
1974     void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
1975    
1976 root 1.91 void glDrawPixels (int width, int height, int format, int type, char *pixels)
1977 root 1.68
1978     void glCopyPixels (int x, int y, int width, int height, int type = GL_COLOR)
1979    
1980 root 1.54 int glGenTexture ()
1981     CODE:
1982     {
1983     GLuint name;
1984     glGenTextures (1, &name);
1985     RETVAL = name;
1986     }
1987     OUTPUT:
1988     RETVAL
1989    
1990     void glDeleteTexture (int name)
1991     CODE:
1992     {
1993     GLuint name_ = name;
1994     glDeleteTextures (1, &name_);
1995     }
1996    
1997     int glGenList ()
1998     CODE:
1999     RETVAL = glGenLists (1);
2000     OUTPUT:
2001     RETVAL
2002    
2003     void glDeleteList (int list)
2004     CODE:
2005     glDeleteLists (list, 1);
2006    
2007     void glNewList (int list, int mode = GL_COMPILE)
2008    
2009     void glEndList ()
2010    
2011     void glCallList (int list)
2012    
2013 root 1.89