ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.123
Committed: Wed Jun 28 23:41:11 2006 UTC (17 years, 10 months ago) by root
Branch: MAIN
Changes since 1.122: +20 -20 lines
Log Message:
hypocrasy

File Contents

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