ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.121
Committed: Fri Jun 23 20:28:19 2006 UTC (17 years, 10 months ago) by root
Branch: MAIN
Changes since 1.120: +98 -0 lines
Log Message:
faster textviewer, embeddable widgets, no scroll-to-bottom for docviewer

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     int arg = 2;
843    
844     while (arg < items && (pos = strstr (pos, OBJ_STR)))
845     {
846     PangoRectangle rect;
847     PangoAttribute *attr;
848    
849     int w = SvIV (ST (arg - 1));
850     int h = SvIV (ST (arg));
851    
852     arg += 2;
853    
854     rect.x = 0;
855     rect.y = -h * PANGO_SCALE;
856     rect.width = w * PANGO_SCALE;
857     rect.height = h * PANGO_SCALE;
858    
859     if (!attrs)
860     attrs = pango_layout_get_attributes (self->pl);
861    
862     attr = pango_attr_shape_new (&rect, &rect);
863     attr->start_index = pos - text;
864     attr->end_index = attr->start_index + sizeof (OBJ_STR) - 1;
865     pango_attr_list_insert (attrs, attr);
866    
867     pos += sizeof (OBJ_STR) - 1;
868     }
869    
870     if (attrs)
871     pango_layout_set_attributes (self->pl, attrs);
872     }
873    
874     void
875     get_shapes (CFClient::Layout self)
876     PPCODE:
877     {
878     PangoLayoutIter *iter = pango_layout_get_iter (self->pl);
879    
880     do
881     {
882     PangoLayoutRun *run = pango_layout_iter_get_run (iter);
883    
884     if (run && shape_attr_p (run))
885     {
886     PangoRectangle extents;
887     pango_layout_iter_get_run_extents (iter, 0, &extents);
888    
889     PUSHs (sv_2mortal (newSViv (PANGO_PIXELS (extents.x))));
890     PUSHs (sv_2mortal (newSViv (PANGO_PIXELS (extents.y))));
891     }
892     }
893     while (pango_layout_iter_next_run (iter));
894    
895     pango_layout_iter_free (iter);
896     }
897    
898     int
899     has_wrapped (CFClient::Layout self)
900     CODE:
901     {
902     int lines = 1;
903     const char *text = pango_layout_get_text (self->pl);
904    
905     while (*text)
906     lines += *text++ == '\n';
907    
908     RETVAL = lines < pango_layout_get_line_count (self->pl);
909     }
910     OUTPUT:
911     RETVAL
912    
913 root 1.46 SV *
914     get_text (CFClient::Layout self)
915     CODE:
916 root 1.47 RETVAL = newSVpv (pango_layout_get_text (self->pl), 0);
917 root 1.107 sv_utf8_decode (RETVAL);
918 root 1.46 OUTPUT:
919     RETVAL
920    
921 root 1.14 void
922 root 1.76 set_foreground (CFClient::Layout self, float r, float g, float b, float a = 1.)
923     CODE:
924     self->r = r;
925     self->g = g;
926     self->b = b;
927     self->a = a;
928    
929     void
930 root 1.61 set_font (CFClient::Layout self, CFClient::Font font = 0)
931     CODE:
932     if (self->font != font)
933     {
934     self->font = font;
935     layout_update_font (self);
936     }
937    
938     void
939 root 1.16 set_height (CFClient::Layout self, int base_height)
940     CODE:
941 root 1.61 if (self->base_height != base_height)
942     {
943     self->base_height = base_height;
944     layout_update_font (self);
945     }
946 root 1.16
947     void
948 root 1.15 set_width (CFClient::Layout self, int max_width = -1)
949 root 1.14 CODE:
950     pango_layout_set_width (self->pl, max_width < 0 ? max_width : max_width * PANGO_SCALE);
951    
952     void
953 root 1.84 set_indent (CFClient::Layout self, int indent)
954     CODE:
955     pango_layout_set_indent (self->pl, indent * PANGO_SCALE);
956    
957     void
958     set_spacing (CFClient::Layout self, int spacing)
959     CODE:
960     pango_layout_set_spacing (self->pl, spacing * PANGO_SCALE);
961    
962     void
963     set_ellipsise (CFClient::Layout self, int ellipsise)
964     CODE:
965     pango_layout_set_ellipsize (self->pl,
966     ellipsise == 1 ? PANGO_ELLIPSIZE_START
967     : ellipsise == 2 ? PANGO_ELLIPSIZE_MIDDLE
968     : ellipsise == 3 ? PANGO_ELLIPSIZE_END
969     : PANGO_ELLIPSIZE_NONE
970     );
971    
972     void
973     set_single_paragraph_mode (CFClient::Layout self, int spm)
974     CODE:
975     pango_layout_set_single_paragraph_mode (self->pl, !!spm);
976    
977     void
978 root 1.15 size (CFClient::Layout self)
979 root 1.14 PPCODE:
980     {
981     int w, h;
982    
983     layout_get_pixel_size (self, &w, &h);
984    
985     EXTEND (SP, 2);
986     PUSHs (sv_2mortal (newSViv (w)));
987     PUSHs (sv_2mortal (newSViv (h)));
988     }
989    
990 root 1.17 int
991     xy_to_index (CFClient::Layout self, int x, int y)
992     CODE:
993     {
994     int index, trailing;
995     pango_layout_xy_to_index (self->pl, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing);
996     RETVAL = index;
997     }
998     OUTPUT:
999     RETVAL
1000    
1001     void
1002     cursor_pos (CFClient::Layout self, int index)
1003     PPCODE:
1004     {
1005     PangoRectangle strong_pos;
1006     pango_layout_get_cursor_pos (self->pl, index, &strong_pos, 0);
1007 root 1.30
1008 root 1.17 EXTEND (SP, 3);
1009     PUSHs (sv_2mortal (newSViv (strong_pos.x / PANGO_SCALE)));
1010     PUSHs (sv_2mortal (newSViv (strong_pos.y / PANGO_SCALE)));
1011     PUSHs (sv_2mortal (newSViv (strong_pos.height / PANGO_SCALE)));
1012     }
1013    
1014 root 1.14 void
1015 root 1.15 render (CFClient::Layout self)
1016 root 1.14 PPCODE:
1017     {
1018 root 1.5 SV *retval;
1019     int w, h;
1020    
1021 root 1.14 layout_get_pixel_size (self, &w, &h);
1022 root 1.5
1023 root 1.76 if (self->rgba)
1024     {
1025     cairo_surface_t *surface;
1026     cairo_t *cairo;
1027    
1028     retval = newSV (w * h * 4);
1029     SvPOK_only (retval);
1030     SvCUR_set (retval, w * h * 4);
1031    
1032     memset (SvPVX (retval), 0, w * h * 4);
1033    
1034     surface = cairo_image_surface_create_for_data (
1035     (void*)SvPVX (retval), CAIRO_FORMAT_ARGB32, w, h, w * 4);
1036     cairo = cairo_create (surface);
1037     cairo_set_source_rgba (cairo, self->r, self->g, self->b, self->a);
1038    
1039     pango_cairo_show_layout (cairo, self->pl);
1040    
1041     cairo_destroy (cairo);
1042     cairo_surface_destroy (surface);
1043    
1044     // what a mess, and its premultiplied, too :(
1045     {
1046     uint32_t *p = (uint32_t *)SvPVX (retval);
1047     uint32_t *e = p + w * h;
1048 root 1.5
1049 root 1.76 while (p < e)
1050     {
1051     uint32_t rgba = *p;
1052     rgba = (rgba >> 24) | (rgba << 8);
1053 root 1.87 #if 0
1054     #ifdef _WIN32
1055     {//D
1056     uint8_t r = rgba >> 24;
1057     uint8_t g = rgba >> 16;
1058     uint8_t b = rgba >> 8;
1059     uint8_t a = rgba >> 0;
1060    
1061     rgba = (rgba & 0xffffff00) | a;
1062     }
1063     #endif
1064     #endif
1065 root 1.76 rgba = SDL_SwapBE32 (rgba);
1066     *p++ = rgba;
1067     }
1068     }
1069    
1070     EXTEND (SP, 5);
1071     PUSHs (sv_2mortal (newSViv (w)));
1072     PUSHs (sv_2mortal (newSViv (h)));
1073     PUSHs (sv_2mortal (retval));
1074 root 1.116 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
1075 root 1.76 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
1076     }
1077     else
1078     {
1079     FT_Bitmap bitmap;
1080    
1081     retval = newSV (w * h);
1082     SvPOK_only (retval);
1083     SvCUR_set (retval, w * h);
1084    
1085     bitmap.rows = h;
1086     bitmap.width = w;
1087     bitmap.pitch = w;
1088     bitmap.buffer = (unsigned char*)SvPVX (retval);
1089     bitmap.num_grays = 256;
1090     bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
1091    
1092     memset (bitmap.buffer, 0, w * h);
1093    
1094     pango_ft2_render_layout (&bitmap, self->pl, 0 * PANGO_SCALE, 0 * PANGO_SCALE);
1095 root 1.1
1096 root 1.76 EXTEND (SP, 5);
1097     PUSHs (sv_2mortal (newSViv (w)));
1098     PUSHs (sv_2mortal (newSViv (h)));
1099     PUSHs (sv_2mortal (retval));
1100     PUSHs (sv_2mortal (newSViv (GL_ALPHA)));
1101     PUSHs (sv_2mortal (newSViv (GL_ALPHA)));
1102     }
1103 root 1.5 }
1104 root 1.11
1105 root 1.15 MODULE = CFClient PACKAGE = CFClient::Texture
1106 root 1.11
1107     void
1108 root 1.113 pad2pot (SV *data_, SV *w_, SV *h_)
1109     CODE:
1110     {
1111     int ow = SvIV (w_);
1112     int oh = SvIV (h_);
1113    
1114     if (ow && oh)
1115     {
1116     int nw = minpot (ow);
1117     int nh = minpot (oh);
1118    
1119     if (nw != ow || nh != oh)
1120     {
1121     if (SvOK (data_))
1122     {
1123     STRLEN datalen;
1124     char *data = SvPVbyte (data_, datalen);
1125     int bpp = datalen / (ow * oh);
1126     SV *result_ = sv_2mortal (newSV (nw * nh * bpp));
1127    
1128     SvPOK_only (result_);
1129     SvCUR_set (result_, nw * nh * bpp);
1130    
1131     memset (SvPVX (result_), 0, nw * nh * bpp);
1132     while (oh--)
1133     memcpy (SvPVX (result_) + oh * nw * bpp, data + oh * ow * bpp, ow * bpp);
1134    
1135     sv_setsv (data_, result_);
1136     }
1137    
1138     sv_setiv (w_, nw);
1139     sv_setiv (h_, nh);
1140     }
1141     }
1142     }
1143    
1144     void
1145 root 1.114 draw_quad (SV *self, float x, float y, float w = 0., float h = 0.)
1146 root 1.12 PROTOTYPE: $$$;$$
1147 root 1.76 ALIAS:
1148     draw_quad_alpha = 1
1149     draw_quad_alpha_premultiplied = 2
1150 root 1.11 CODE:
1151     {
1152 root 1.12 HV *hv = (HV *)SvRV (self);
1153 root 1.37 float s = SvNV (*hv_fetch (hv, "s", 1, 1));
1154     float t = SvNV (*hv_fetch (hv, "t", 1, 1));
1155 root 1.12 int name = SvIV (*hv_fetch (hv, "name", 4, 1));
1156    
1157     if (items < 5)
1158     {
1159 root 1.18 w = SvNV (*hv_fetch (hv, "w", 1, 1));
1160     h = SvNV (*hv_fetch (hv, "h", 1, 1));
1161 root 1.12 }
1162    
1163 root 1.76 if (ix)
1164     {
1165     glEnable (GL_BLEND);
1166 root 1.103
1167     if (ix == 2)
1168     glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1169     else
1170     gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1171 root 1.104 GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
1172 root 1.103
1173 root 1.86 glEnable (GL_ALPHA_TEST);
1174     glAlphaFunc (GL_GREATER, 0.01f);
1175 root 1.76 }
1176    
1177 root 1.12 glBindTexture (GL_TEXTURE_2D, name);
1178 root 1.76
1179 root 1.12 glBegin (GL_QUADS);
1180 root 1.37 glTexCoord2f (0, 0); glVertex2f (x , y );
1181     glTexCoord2f (0, t); glVertex2f (x , y + h);
1182     glTexCoord2f (s, t); glVertex2f (x + w, y + h);
1183     glTexCoord2f (s, 0); glVertex2f (x + w, y );
1184 root 1.12 glEnd ();
1185 root 1.76
1186     if (ix)
1187 root 1.86 {
1188     glDisable (GL_ALPHA_TEST);
1189     glDisable (GL_BLEND);
1190     }
1191 root 1.11 }
1192 root 1.28
1193     MODULE = CFClient PACKAGE = CFClient::Map
1194    
1195     CFClient::Map
1196     new (SV *class, int map_width, int map_height)
1197     CODE:
1198     New (0, RETVAL, 1, struct map);
1199 root 1.42 RETVAL->x = 0;
1200     RETVAL->y = 0;
1201     RETVAL->w = map_width;
1202     RETVAL->h = map_height;
1203     RETVAL->ox = 0;
1204     RETVAL->oy = 0;
1205 root 1.30 RETVAL->faces = 8192;
1206     Newz (0, RETVAL->face, RETVAL->faces, mapface);
1207 root 1.42 RETVAL->texs = 8192;
1208     Newz (0, RETVAL->tex, RETVAL->texs, maptex);
1209 root 1.28 RETVAL->rows = 0;
1210     RETVAL->row = 0;
1211     OUTPUT:
1212     RETVAL
1213    
1214     void
1215     DESTROY (CFClient::Map self)
1216     CODE:
1217     {
1218 root 1.30 map_clear (self);
1219 root 1.28 Safefree (self->face);
1220 root 1.111 Safefree (self->tex);
1221 root 1.29 Safefree (self);
1222     }
1223    
1224     void
1225 root 1.30 clear (CFClient::Map self)
1226     CODE:
1227     map_clear (self);
1228    
1229     void
1230 root 1.42 set_face (CFClient::Map self, int face, int texid)
1231 root 1.29 CODE:
1232     {
1233 root 1.42 while (self->faces <= face)
1234 root 1.28 {
1235 root 1.30 Append (mapface, self->face, self->faces, self->faces);
1236 root 1.29 self->faces *= 2;
1237     }
1238 root 1.28
1239 root 1.42 self->face [face] = texid;
1240     }
1241    
1242     void
1243     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)
1244     CODE:
1245     {
1246     while (self->texs <= texid)
1247     {
1248     Append (maptex, self->tex, self->texs, self->texs);
1249     self->texs *= 2;
1250     }
1251    
1252 root 1.48 {
1253     maptex *tex = self->tex + texid;
1254 root 1.39
1255 root 1.48 tex->name = name;
1256     tex->w = w;
1257     tex->h = h;
1258     tex->s = s;
1259     tex->t = t;
1260     tex->r = r;
1261     tex->g = g;
1262     tex->b = b;
1263     tex->a = a;
1264     }
1265 root 1.95
1266     // somewhat hackish, but for textures that require it, it really
1267     // improves the look, and most others don't suffer.
1268     glBindTexture (GL_TEXTURE_2D, name);
1269 root 1.99 //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1270     //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1271     // use uglier nearest interpolation because linear suffers
1272     // from transparent color bleeding and ugly wrapping effects.
1273     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1274 root 1.29 }
1275    
1276 root 1.42 int
1277     ox (CFClient::Map self)
1278     ALIAS:
1279     oy = 1
1280 root 1.101 x = 2
1281     y = 3
1282 root 1.102 w = 4
1283     h = 5
1284 root 1.42 CODE:
1285     switch (ix)
1286     {
1287     case 0: RETVAL = self->ox; break;
1288     case 1: RETVAL = self->oy; break;
1289 root 1.101 case 2: RETVAL = self->x; break;
1290     case 3: RETVAL = self->y; break;
1291 root 1.102 case 4: RETVAL = self->w; break;
1292     case 5: RETVAL = self->h; break;
1293 root 1.42 }
1294     OUTPUT:
1295     RETVAL
1296    
1297 root 1.29 void
1298 root 1.43 scroll (CFClient::Map self, int dx, int dy)
1299     CODE:
1300     {
1301 root 1.44 if (dx > 0)
1302     map_blank (self, self->x, self->y, dx - 1, self->h);
1303     else if (dx < 0)
1304     map_blank (self, self->x + self->w + dx + 1, self->y, 1 - dx, self->h);
1305    
1306     if (dy > 0)
1307     map_blank (self, self->x, self->y, self->w, dy - 1);
1308     else if (dy < 0)
1309     map_blank (self, self->x, self->y + self->h + dy + 1, self->w, 1 - dy);
1310 root 1.43
1311 root 1.44 self->ox += dx; self->x += dx;
1312     self->oy += dy; self->y += dy;
1313 root 1.43
1314     while (self->y < 0)
1315     {
1316     Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y);
1317    
1318     self->rows += MAP_EXTEND_Y;
1319     self->y += MAP_EXTEND_Y;
1320     }
1321 root 1.44 }
1322 root 1.43
1323 root 1.44 void
1324     map1a_update (CFClient::Map self, SV *data_)
1325     CODE:
1326     {
1327 root 1.30 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
1328     uint8_t *data_end = (uint8_t *)SvEND (data_);
1329 root 1.48 mapcell *cell;
1330     int x, y, flags;
1331 root 1.43
1332 root 1.29 while (data < data_end)
1333     {
1334 root 1.48 flags = (data [0] << 8) + data [1]; data += 2;
1335 root 1.30
1336 root 1.120 x = self->x + ((flags >> 10) & 63);
1337     y = self->y + ((flags >> 4) & 63);
1338 root 1.29
1339 root 1.48 cell = map_get_cell (self, x, y);
1340 root 1.29
1341     if (flags & 15)
1342     {
1343 root 1.45 if (cell->darkness < 0)
1344 root 1.29 {
1345     cell->darkness = 0;
1346     cell->face [0] = 0;
1347     cell->face [1] = 0;
1348     cell->face [2] = 0;
1349     }
1350 root 1.45
1351 root 1.29 cell->darkness = flags & 8 ? *data++ : 255;
1352    
1353 root 1.42 //TODO: don't trust server data to be in-range(!)
1354    
1355 root 1.29 if (flags & 4)
1356     {
1357 root 1.42 cell->face [0] = self->face [(data [0] << 8) + data [1]]; data += 2;
1358 root 1.29 }
1359    
1360     if (flags & 2)
1361     {
1362 root 1.42 cell->face [1] = self->face [(data [0] << 8) + data [1]]; data += 2;
1363 root 1.29 }
1364    
1365     if (flags & 1)
1366     {
1367 root 1.42 cell->face [2] = self->face [(data [0] << 8) + data [1]]; data += 2;
1368 root 1.29 }
1369     }
1370     else
1371 root 1.31 cell->darkness = -1;
1372 root 1.29 }
1373 root 1.28 }
1374    
1375 root 1.40 SV *
1376 root 1.55 mapmap (CFClient::Map self, int x0, int y0, int w, int h)
1377 root 1.40 CODE:
1378     {
1379 root 1.55 int x1, x;
1380     int y1, y;
1381 root 1.40 int z;
1382     SV *map_sv = newSV (w * h * sizeof (uint32_t));
1383     uint32_t *map = (uint32_t *)SvPVX (map_sv);
1384    
1385     SvPOK_only (map_sv);
1386     SvCUR_set (map_sv, w * h * sizeof (uint32_t));
1387    
1388 root 1.55 x0 += self->x; x1 = x0 + w;
1389     y0 += self->y; y1 = y0 + h;
1390 root 1.40
1391     for (y = y0; y < y1; y++)
1392     {
1393     maprow *row = 0 <= y && y < self->rows
1394     ? self->row + y
1395     : 0;
1396    
1397     for (x = x0; x < x1; x++)
1398     {
1399     int r = 32, g = 32, b = 32, a = 192;
1400    
1401     if (row && row->c0 <= x && x < row->c1)
1402     {
1403     mapcell *cell = row->col + (x - row->c0);
1404    
1405     for (z = 0; z <= 0; z++)
1406     {
1407 root 1.42 mapface face = cell->face [z];
1408 root 1.40
1409     if (face)
1410     {
1411 root 1.42 maptex tex = self->tex [face];
1412 root 1.40 int a0 = 255 - tex.a;
1413     int a1 = tex.a;
1414    
1415     r = (r * a0 + tex.r * a1) / 255;
1416     g = (g * a0 + tex.g * a1) / 255;
1417     b = (b * a0 + tex.b * a1) / 255;
1418     a = (a * a0 + tex.a * a1) / 255;
1419     }
1420     }
1421     }
1422    
1423     *map++ = (r )
1424     | (g << 8)
1425     | (b << 16)
1426     | (a << 24);
1427     }
1428     }
1429    
1430     RETVAL = map_sv;
1431     }
1432     OUTPUT:
1433     RETVAL
1434    
1435 root 1.30 void
1436 root 1.38 draw (CFClient::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1437 root 1.116 CODE:
1438 root 1.30 {
1439 root 1.48 int vx, vy;
1440     int x, y, z;
1441     int last_name;
1442     mapface face;
1443    
1444 root 1.120 vx = self->x + self->w / 2 - sw / 2 - shift_x;
1445     vy = self->y + self->h / 2 - sh / 2 - shift_y;
1446 root 1.38
1447 root 1.42 /*
1448     int vx = self->vx = self->w >= sw
1449     ? self->x + (self->w - sw) / 2
1450     : MIN (self->x, MAX (self->x + self->w - sw + 1, self->vx));
1451    
1452     int vy = self->vy = self->h >= sh
1453     ? self->y + (self->h - sh) / 2
1454     : MIN (self->y, MAX (self->y + self->h - sh + 1, self->vy));
1455     */
1456 root 1.30
1457     glColor4ub (255, 255, 255, 255);
1458    
1459 root 1.117 glEnable (GL_BLEND);
1460 root 1.30 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1461     glEnable (GL_TEXTURE_2D);
1462     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1463    
1464 root 1.48 glBegin (GL_QUADS);
1465 root 1.30
1466 root 1.48 last_name = 0;
1467 root 1.30
1468     for (z = 0; z < 3; z++)
1469     for (y = 0; y < sh; y++)
1470     if (0 <= y + vy && y + vy < self->rows)
1471     {
1472     maprow *row = self->row + (y + vy);
1473    
1474     for (x = 0; x < sw; x++)
1475     if (row->c0 <= x + vx && x + vx < row->c1)
1476     {
1477     mapcell *cell = row->col + (x + vx - row->c0);
1478 root 1.32
1479 root 1.48 face = cell->face [z];
1480 root 1.30
1481     if (face)
1482     {
1483 root 1.42 maptex tex = self->tex [face];
1484 root 1.30
1485     int px = (x + 1) * 32 - tex.w;
1486     int py = (y + 1) * 32 - tex.h;
1487    
1488     if (last_name != tex.name)
1489     {
1490     glEnd ();
1491     last_name = tex.name;
1492     glBindTexture (GL_TEXTURE_2D, last_name);
1493     glBegin (GL_QUADS);
1494     }
1495    
1496     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1497     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1498     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1499     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1500     }
1501     }
1502     }
1503    
1504     glEnd ();
1505 root 1.32
1506 root 1.34 glDisable (GL_TEXTURE_2D);
1507     glDisable (GL_BLEND);
1508 root 1.116 }
1509    
1510     void
1511 root 1.117 draw_magicmap (CFClient::Map self, int dx, int dy, int w, int h, unsigned char *data)
1512     CODE:
1513     {
1514     static float color[16][3] = {
1515     { 0.00, 0.00, 0.00 },
1516     { 1.00, 1.00, 1.00 },
1517     { 0.00, 0.00, 0.55 },
1518     { 1.00, 0.00, 0.00 },
1519    
1520     { 1.00, 0.54, 0.00 },
1521     { 0.11, 0.56, 1.00 },
1522     { 0.93, 0.46, 0.00 },
1523     { 0.18, 0.54, 0.34 },
1524    
1525     { 0.56, 0.73, 0.56 },
1526     { 0.80, 0.80, 0.80 },
1527     { 0.55, 0.41, 0.13 },
1528     { 0.99, 0.77, 0.26 },
1529    
1530     { 0.74, 0.65, 0.41 },
1531    
1532     { 0.00, 1.00, 1.00 },
1533     { 1.00, 0.00, 1.00 },
1534     { 1.00, 1.00, 0.00 },
1535     };
1536    
1537     int x, y;
1538    
1539     glEnable (GL_TEXTURE_2D);
1540     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1541     glEnable (GL_BLEND);
1542     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1543     glBegin (GL_QUADS);
1544    
1545     for (y = 0; y < h; y++)
1546     for (x = 0; x < w; x++)
1547     {
1548     unsigned char m = data [x + y * w];
1549    
1550 root 1.118 if (m)
1551     {
1552     float *c = color [m & 15];
1553    
1554     float tx1 = m & 0x40 ? 0.5 : 0.;
1555     float tx2 = tx1 + 0.5;
1556    
1557     glColor4f (c[0], c[1], c[2], 0.75);
1558     glTexCoord2f (tx1, 0.); glVertex2i (x , y );
1559     glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1);
1560     glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1);
1561     glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y );
1562     }
1563 root 1.117 }
1564    
1565     glEnd ();
1566     glDisable (GL_BLEND);
1567     glDisable (GL_TEXTURE_2D);
1568     }
1569    
1570     void
1571 root 1.116 fow_texture (CFClient::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1572     PPCODE:
1573     {
1574     int vx, vy;
1575     int x, y;
1576     int sw4 = (sw + 3) & ~3;
1577     SV *darkness_sv = sv_2mortal (newSV (sw4 * sh));
1578     uint8_t *darkness = (uint8_t *)SvPVX (darkness_sv);
1579    
1580     memset (darkness, 255, sw4 * sh);
1581     SvPOK_only (darkness_sv);
1582     SvCUR_set (darkness_sv, sw4 * sh);
1583    
1584     vx = self->x + (self->w - sw + 1) / 2 - shift_x;
1585     vy = self->y + (self->h - sh + 1) / 2 - shift_y;
1586    
1587     for (y = 0; y < sh; y++)
1588     if (0 <= y + vy && y + vy < self->rows)
1589     {
1590     maprow *row = self->row + (y + vy);
1591    
1592     for (x = 0; x < sw; x++)
1593     if (row->c0 <= x + vx && x + vx < row->c1)
1594     {
1595     mapcell *cell = row->col + (x + vx - row->c0);
1596    
1597     darkness[y * sw4 + x] = cell->darkness < 0
1598     ? 255 - FOW_DARKNESS
1599     : 255 - cell->darkness;
1600     }
1601     }
1602 root 1.34
1603 root 1.32 EXTEND (SP, 3);
1604     PUSHs (sv_2mortal (newSViv (sw4)));
1605     PUSHs (sv_2mortal (newSViv (sh)));
1606     PUSHs (darkness_sv);
1607 root 1.30 }
1608    
1609 root 1.42 SV *
1610     get_rect (CFClient::Map self, int x0, int y0, int w, int h)
1611     CODE:
1612     {
1613     int x, y, x1, y1;
1614     SV *data_sv = newSV (w * h * 7 + 5);
1615     uint8_t *data = (uint8_t *)SvPVX (data_sv);
1616    
1617     *data++ = 0; /* version 0 format */
1618     *data++ = w >> 8; *data++ = w;
1619     *data++ = h >> 8; *data++ = h;
1620    
1621     // we need to do this 'cause we don't keep an absolute coord system for rows
1622 root 1.55 // TODO: treat rows as we treat columns
1623 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1624     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1625    
1626     x0 += self->x - self->ox;
1627     y0 += self->y - self->oy;
1628    
1629     x1 = x0 + w;
1630     y1 = y0 + h;
1631    
1632     for (y = y0; y < y1; y++)
1633     {
1634     maprow *row = 0 <= y && y < self->rows
1635     ? self->row + y
1636     : 0;
1637    
1638     for (x = x0; x < x1; x++)
1639     {
1640     if (row && row->c0 <= x && x < row->c1)
1641     {
1642     mapcell *cell = row->col + (x - row->c0);
1643     uint8_t flags = 0;
1644    
1645     if (cell->face [0]) flags |= 1;
1646     if (cell->face [1]) flags |= 2;
1647     if (cell->face [2]) flags |= 4;
1648    
1649     *data++ = flags;
1650    
1651     if (flags & 1)
1652     {
1653     *data++ = cell->face [0] >> 8;
1654     *data++ = cell->face [0];
1655     }
1656    
1657     if (flags & 2)
1658     {
1659     *data++ = cell->face [1] >> 8;
1660     *data++ = cell->face [1];
1661     }
1662    
1663     if (flags & 4)
1664     {
1665     *data++ = cell->face [2] >> 8;
1666     *data++ = cell->face [2];
1667     }
1668     }
1669     else
1670     *data++ = 0;
1671     }
1672     }
1673    
1674     SvPOK_only (data_sv);
1675     SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
1676     RETVAL = data_sv;
1677     }
1678     OUTPUT:
1679     RETVAL
1680    
1681     void
1682     set_rect (CFClient::Map self, int x0, int y0, uint8_t *data)
1683     PPCODE:
1684     {
1685     int x, y, z;
1686 root 1.48 int w, h;
1687 root 1.42 int x1, y1;
1688    
1689     if (*data++ != 0)
1690     return; /* version mismatch */
1691    
1692 root 1.48 w = *data++ << 8; w |= *data++;
1693     h = *data++ << 8; h |= *data++;
1694 root 1.42
1695     // we need to do this 'cause we don't keep an absolute coord system for rows
1696 root 1.55 // TODO: treat rows as we treat columns
1697 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1698     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1699    
1700     x0 += self->x - self->ox;
1701     y0 += self->y - self->oy;
1702    
1703     x1 = x0 + w;
1704     y1 = y0 + h;
1705    
1706     for (y = y0; y < y1; y++)
1707     {
1708     maprow *row = map_get_row (self, y);
1709    
1710     for (x = x0; x < x1; x++)
1711     {
1712     uint8_t flags = *data++;
1713    
1714     if (flags)
1715     {
1716     mapface face[3] = { 0, 0, 0 };
1717    
1718     mapcell *cell = row_get_cell (row, x);
1719    
1720     if (flags & 1) { face[0] = *data++ << 8; face[0] |= *data++; }
1721     if (flags & 2) { face[1] = *data++ << 8; face[1] |= *data++; }
1722     if (flags & 4) { face[2] = *data++ << 8; face[2] |= *data++; }
1723    
1724     if (cell->darkness <= 0)
1725     {
1726     cell->darkness = -1;
1727    
1728     for (z = 0; z <= 2; z++)
1729     {
1730     cell->face[z] = face[z];
1731    
1732     if (face[z] && (face[z] >= self->texs || !self->tex[face [z]].name))
1733     XPUSHs (sv_2mortal (newSViv (face[z])));
1734     }
1735     }
1736     }
1737     }
1738     }
1739     }
1740    
1741 root 1.52 MODULE = CFClient PACKAGE = CFClient::MixChunk
1742    
1743     CFClient::MixChunk
1744     new_from_file (SV *class, char *path)
1745     CODE:
1746     RETVAL = Mix_LoadWAV (path);
1747     OUTPUT:
1748     RETVAL
1749    
1750     void
1751     DESTROY (CFClient::MixChunk self)
1752     CODE:
1753     Mix_FreeChunk (self);
1754    
1755     int
1756     volume (CFClient::MixChunk self, int volume = -1)
1757     CODE:
1758     RETVAL = Mix_VolumeChunk (self, volume);
1759     OUTPUT:
1760     RETVAL
1761    
1762     int
1763     play (CFClient::MixChunk self, int channel = -1, int loops = 0, int ticks = -1)
1764     CODE:
1765     RETVAL = Mix_PlayChannelTimed (channel, self, loops, ticks);
1766     OUTPUT:
1767     RETVAL
1768    
1769     MODULE = CFClient PACKAGE = CFClient::MixMusic
1770    
1771     int
1772     volume (int volume = -1)
1773     CODE:
1774     RETVAL = Mix_VolumeMusic (volume);
1775     OUTPUT:
1776     RETVAL
1777    
1778     CFClient::MixMusic
1779     new_from_file (SV *class, char *path)
1780     CODE:
1781     RETVAL = Mix_LoadMUS (path);
1782     OUTPUT:
1783     RETVAL
1784    
1785     void
1786     DESTROY (CFClient::MixMusic self)
1787     CODE:
1788     Mix_FreeMusic (self);
1789    
1790     int
1791     play (CFClient::MixMusic self, int loops = -1)
1792     CODE:
1793     RETVAL = Mix_PlayMusic (self, loops);
1794     OUTPUT:
1795     RETVAL
1796    
1797 root 1.54 MODULE = CFClient PACKAGE = CFClient::OpenGL
1798    
1799     BOOT:
1800     {
1801     HV *stash = gv_stashpv ("CFClient::OpenGL", 1);
1802     static const struct {
1803     const char *name;
1804     IV iv;
1805     } *civ, const_iv[] = {
1806     # define const_iv(name) { # name, (IV)name }
1807     const_iv (GL_COLOR_MATERIAL),
1808     const_iv (GL_SMOOTH),
1809     const_iv (GL_FLAT),
1810 root 1.69 const_iv (GL_DITHER),
1811 root 1.54 const_iv (GL_BLEND),
1812 root 1.89 const_iv (GL_CULL_FACE),
1813 root 1.69 const_iv (GL_SCISSOR_TEST),
1814 root 1.89 const_iv (GL_DEPTH_TEST),
1815     const_iv (GL_ALPHA_TEST),
1816     const_iv (GL_NORMALIZE),
1817     const_iv (GL_RESCALE_NORMAL),
1818 root 1.119 const_iv (GL_FRONT),
1819     const_iv (GL_BACK),
1820 root 1.54 const_iv (GL_AND),
1821 root 1.67 const_iv (GL_ONE),
1822     const_iv (GL_ZERO),
1823 root 1.54 const_iv (GL_SRC_ALPHA),
1824 root 1.104 const_iv (GL_DST_ALPHA),
1825 root 1.54 const_iv (GL_ONE_MINUS_SRC_ALPHA),
1826 root 1.67 const_iv (GL_ONE_MINUS_DST_ALPHA),
1827 root 1.104 const_iv (GL_SRC_ALPHA_SATURATE),
1828 root 1.54 const_iv (GL_RGB),
1829     const_iv (GL_RGBA),
1830 root 1.115 const_iv (GL_RGBA4),
1831     const_iv (GL_RGBA8),
1832     const_iv (GL_RGB5_A1),
1833 root 1.54 const_iv (GL_UNSIGNED_BYTE),
1834 root 1.89 const_iv (GL_UNSIGNED_SHORT),
1835     const_iv (GL_UNSIGNED_INT),
1836 root 1.54 const_iv (GL_ALPHA),
1837 root 1.86 const_iv (GL_INTENSITY),
1838 root 1.76 const_iv (GL_LUMINANCE),
1839 root 1.86 const_iv (GL_LUMINANCE_ALPHA),
1840 root 1.54 const_iv (GL_FLOAT),
1841     const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
1842     const_iv (GL_COMPILE),
1843     const_iv (GL_TEXTURE_1D),
1844     const_iv (GL_TEXTURE_2D),
1845     const_iv (GL_TEXTURE_ENV),
1846     const_iv (GL_TEXTURE_MAG_FILTER),
1847     const_iv (GL_TEXTURE_MIN_FILTER),
1848     const_iv (GL_TEXTURE_ENV_MODE),
1849     const_iv (GL_TEXTURE_WRAP_S),
1850     const_iv (GL_TEXTURE_WRAP_T),
1851 root 1.98 const_iv (GL_REPEAT),
1852 root 1.54 const_iv (GL_CLAMP),
1853 root 1.98 const_iv (GL_CLAMP_TO_EDGE),
1854 root 1.54 const_iv (GL_NEAREST),
1855     const_iv (GL_LINEAR),
1856 root 1.57 const_iv (GL_NEAREST_MIPMAP_NEAREST),
1857     const_iv (GL_LINEAR_MIPMAP_NEAREST),
1858     const_iv (GL_NEAREST_MIPMAP_LINEAR),
1859     const_iv (GL_LINEAR_MIPMAP_LINEAR),
1860     const_iv (GL_GENERATE_MIPMAP),
1861 root 1.54 const_iv (GL_MODULATE),
1862 root 1.69 const_iv (GL_DECAL),
1863 root 1.54 const_iv (GL_REPLACE),
1864 root 1.89 const_iv (GL_DEPTH_BUFFER_BIT),
1865 root 1.54 const_iv (GL_COLOR_BUFFER_BIT),
1866     const_iv (GL_PROJECTION),
1867     const_iv (GL_MODELVIEW),
1868     const_iv (GL_COLOR_LOGIC_OP),
1869 root 1.69 const_iv (GL_SEPARABLE_2D),
1870 root 1.54 const_iv (GL_CONVOLUTION_2D),
1871     const_iv (GL_CONVOLUTION_BORDER_MODE),
1872     const_iv (GL_CONSTANT_BORDER),
1873     const_iv (GL_LINES),
1874 root 1.89 const_iv (GL_LINE_LOOP),
1875 root 1.54 const_iv (GL_QUADS),
1876 root 1.89 const_iv (GL_QUAD_STRIP),
1877     const_iv (GL_TRIANGLES),
1878     const_iv (GL_TRIANGLE_STRIP),
1879     const_iv (GL_TRIANGLE_FAN),
1880 root 1.54 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
1881     const_iv (GL_FASTEST),
1882 root 1.89 const_iv (GL_V2F),
1883     const_iv (GL_V3F),
1884     const_iv (GL_T2F_V3F),
1885     const_iv (GL_T2F_N3F_V3F),
1886 root 1.54 # undef const_iv
1887     };
1888    
1889     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1890     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1891     }
1892    
1893 root 1.97 char *
1894     gl_vendor ()
1895     CODE:
1896     RETVAL = (char *)glGetString (GL_VENDOR);
1897     OUTPUT:
1898     RETVAL
1899    
1900     char *
1901     gl_version ()
1902     CODE:
1903     RETVAL = (char *)glGetString (GL_VERSION);
1904     OUTPUT:
1905     RETVAL
1906    
1907     char *
1908     gl_extensions ()
1909     CODE:
1910     RETVAL = (char *)glGetString (GL_EXTENSIONS);
1911     OUTPUT:
1912     RETVAL
1913    
1914 root 1.54 int glGetError ()
1915    
1916 root 1.114 void glFinish ()
1917    
1918 root 1.54 void glClear (int mask)
1919    
1920     void glClearColor (float r, float g, float b, float a = 1.0)
1921     PROTOTYPE: @
1922    
1923     void glEnable (int cap)
1924    
1925     void glDisable (int cap)
1926    
1927     void glShadeModel (int mode)
1928    
1929     void glHint (int target, int mode)
1930    
1931     void glBlendFunc (int sfactor, int dfactor)
1932    
1933 root 1.103 void glBlendFuncSeparate (int sa, int da, int saa, int daa)
1934     CODE:
1935     gl_BlendFuncSeparate (sa, da, saa, daa);
1936    
1937 root 1.89 void glDepthMask (int flag)
1938    
1939 root 1.54 void glLogicOp (int opcode)
1940    
1941 root 1.68 void glColorMask (int red, int green, int blue, int alpha)
1942    
1943 root 1.54 void glMatrixMode (int mode)
1944    
1945     void glPushMatrix ()
1946    
1947     void glPopMatrix ()
1948    
1949     void glLoadIdentity ()
1950    
1951 root 1.119 void glDrawBuffer (int buffer)
1952    
1953     void glReadBuffer (int buffer)
1954    
1955 root 1.90 # near_ and far_ are due to microsofts buggy "c" compiler
1956     void glFrustum (double left, double right, double bottom, double top, double near_, double far_)
1957    
1958     # near_ and far_ are due to microsofts buggy "c" compiler
1959 root 1.64 void glOrtho (double left, double right, double bottom, double top, double near_, double far_)
1960 root 1.54
1961     void glViewport (int x, int y, int width, int height)
1962    
1963 root 1.69 void glScissor (int x, int y, int width, int height)
1964    
1965 root 1.54 void glTranslate (float x, float y, float z = 0.)
1966     CODE:
1967     glTranslatef (x, y, z);
1968    
1969 root 1.62 void glScale (float x, float y, float z = 1.)
1970 root 1.54 CODE:
1971     glScalef (x, y, z);
1972    
1973     void glRotate (float angle, float x, float y, float z)
1974     CODE:
1975     glRotatef (angle, x, y, z);
1976    
1977     void glBegin (int mode)
1978    
1979     void glEnd ()
1980    
1981     void glColor (float r, float g, float b, float a = 1.0)
1982     PROTOTYPE: @
1983 root 1.103 ALIAS:
1984     glColor_premultiply = 1
1985 root 1.54 CODE:
1986 root 1.103 if (ix)
1987     {
1988     r *= a;
1989     g *= a;
1990     b *= a;
1991     }
1992 root 1.90 // microsoft visual "c" rounds instead of truncating...
1993 root 1.100 glColor4ub (MIN ((int)(r * 256.f), 255),
1994     MIN ((int)(g * 256.f), 255),
1995     MIN ((int)(b * 256.f), 255),
1996     MIN ((int)(a * 256.f), 255));
1997 root 1.54
1998 root 1.89 void glInterleavedArrays (int format, int stride, char *data)
1999    
2000     void glDrawElements (int mode, int count, int type, char *indices)
2001    
2002     # 1.2 void glDrawRangeElements (int mode, int start, int end
2003    
2004 root 1.91 void glRasterPos (float x, float y, float z = 0.)
2005     CODE:
2006     glRasterPos3f (0, 0, z);
2007     glBitmap (0, 0, 0, 0, x, y, 0);
2008    
2009 root 1.54 void glVertex (float x, float y, float z = 0.)
2010     CODE:
2011     glVertex3f (x, y, z);
2012    
2013     void glTexCoord (float s, float t)
2014     CODE:
2015     glTexCoord2f (s, t);
2016    
2017     void glTexEnv (int target, int pname, float param)
2018     CODE:
2019     glTexEnvf (target, pname, param);
2020    
2021     void glTexParameter (int target, int pname, float param)
2022     CODE:
2023     glTexParameterf (target, pname, param);
2024    
2025     void glBindTexture (int target, int name)
2026    
2027     void glConvolutionParameter (int target, int pname, float params)
2028     CODE:
2029 root 1.103 if (gl.ConvolutionParameterf)
2030     gl.ConvolutionParameterf (target, pname, params);
2031 root 1.54
2032     void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
2033 root 1.64 CODE:
2034 root 1.103 if (gl.ConvolutionFilter2D)
2035     gl.ConvolutionFilter2D (target, internalformat, width, height, format, type, data);
2036 root 1.54
2037 root 1.69 void glSeparableFilter2D (int target, int internalformat, int width, int height, int format, int type, char *row, char *column)
2038     CODE:
2039 root 1.103 if (gl.SeparableFilter2D)
2040     gl.SeparableFilter2D (target, internalformat, width, height, format, type, row, column);
2041 root 1.69
2042 root 1.54 void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data)
2043    
2044     void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
2045    
2046 root 1.91 void glDrawPixels (int width, int height, int format, int type, char *pixels)
2047 root 1.68
2048     void glCopyPixels (int x, int y, int width, int height, int type = GL_COLOR)
2049    
2050 root 1.54 int glGenTexture ()
2051     CODE:
2052     {
2053     GLuint name;
2054     glGenTextures (1, &name);
2055     RETVAL = name;
2056     }
2057     OUTPUT:
2058     RETVAL
2059    
2060     void glDeleteTexture (int name)
2061     CODE:
2062     {
2063     GLuint name_ = name;
2064     glDeleteTextures (1, &name_);
2065     }
2066    
2067     int glGenList ()
2068     CODE:
2069     RETVAL = glGenLists (1);
2070     OUTPUT:
2071     RETVAL
2072    
2073     void glDeleteList (int list)
2074     CODE:
2075     glDeleteLists (list, 1);
2076    
2077     void glNewList (int list, int mode = GL_COMPILE)
2078    
2079     void glEndList ()
2080    
2081     void glCallList (int list)
2082    
2083 root 1.89