ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.208
Committed: Sat Jul 21 16:07:53 2007 UTC (16 years, 9 months ago) by root
Branch: MAIN
Changes since 1.207: +20 -11 lines
Log Message:
the beginning of a (very simple) canvas widget

File Contents

# User Rev Content
1 root 1.48 #ifdef _WIN32
2 root 1.131 # define WIN32_LEAN_AND_MEAN
3 root 1.170 # define NTDDI_VERSION NTDDI_WIN2K // needed to get win2000 api calls
4 root 1.48 # include <malloc.h>
5 root 1.79 # include <windows.h>
6 root 1.157 # include <wininet.h>
7 root 1.75 # pragma warning(disable:4244)
8 root 1.162 # pragma warning(disable:4761)
9 root 1.48 #endif
10    
11 root 1.193 //#define DEBUG 1
12     #if DEBUG
13     # include <valgrind/memcheck.h>
14     #endif
15    
16 root 1.1 #include "EXTERN.h"
17     #include "perl.h"
18     #include "XSUB.h"
19    
20 root 1.131 #ifdef _WIN32
21     # undef pipe
22     #endif
23    
24 root 1.168 #include <assert.h>
25 root 1.80 #include <math.h>
26 root 1.5 #include <string.h>
27 root 1.25 #include <stdio.h>
28 root 1.111 #include <stdlib.h>
29 root 1.5
30 root 1.2 #include <SDL.h>
31 root 1.202 #include <SDL_thread.h>
32 root 1.76 #include <SDL_endian.h>
33 root 1.23 #include <SDL_image.h>
34 root 1.52 #include <SDL_mixer.h>
35 root 1.3 #include <SDL_opengl.h>
36 root 1.5
37 root 1.124 #define PANGO_ENABLE_BACKEND
38     #define G_DISABLE_CAST_CHECKS
39    
40 root 1.30 #include <glib/gmacros.h>
41    
42 root 1.5 #include <pango/pango.h>
43    
44 root 1.48 #ifndef _WIN32
45     # include <sys/types.h>
46     # include <sys/socket.h>
47     # include <netinet/in.h>
48     # include <netinet/tcp.h>
49     # include <inttypes.h>
50     #endif
51 root 1.28
52 root 1.162 #define OBJ_STR "\xef\xbf\xbc" /* U+FFFC, object replacement character */
53 root 1.121
54 root 1.29 #define FOW_DARKNESS 32
55    
56     #define MAP_EXTEND_X 32
57     #define MAP_EXTEND_Y 512
58    
59 root 1.63 #define MIN_FONT_HEIGHT 10
60 root 1.58
61 root 1.127 #if 0
62 root 1.124 # define PARACHUTE SDL_INIT_NOPARACHUTE
63     #else
64     # define PARACHUTE 0
65     #endif
66    
67 root 1.188 static AV *texture_av;
68    
69 root 1.103 static struct
70     {
71     #define GL_FUNC(ptr,name) ptr name;
72     #include "glfunc.h"
73     #undef GL_FUNC
74     } gl;
75    
76 root 1.192 static void
77     gl_BlendFuncSeparate (GLenum sa, GLenum da, GLenum saa, GLenum daa)
78 root 1.103 {
79     if (gl.BlendFuncSeparate)
80     gl.BlendFuncSeparate (sa, da, saa, daa);
81     else if (gl.BlendFuncSeparateEXT)
82     gl.BlendFuncSeparateEXT (sa, da, saa, daa);
83     else
84     glBlendFunc (sa, da);
85     }
86 root 1.64
87 root 1.192 static GLuint
88     gen_texture ()
89     {
90     GLuint name;
91    
92     if (AvFILL (texture_av) >= 0)
93     name = (GLuint)(size_t)av_pop (texture_av);
94     else
95     glGenTextures (1, &name);
96    
97     return name;
98     }
99    
100     static void
101     del_texture (GLuint name)
102     {
103     /* make a half-assed attempt at returning the memory used by the texture */
104     /* textures are frequently being reused by cfplus anyway */
105     /*glBindTexture (GL_TEXTURE_2D, name);*/
106     /*glTexImage2D (GL_TEXTURE_2D, 0, GL_ALPHA, 0, 0, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);*/
107     av_push (texture_av, (SV *)(size_t)name);
108     glDeleteTextures (1, &name);
109     }
110    
111 root 1.124 #include "texcache.c"
112    
113     #include "pango-font.c"
114     #include "pango-fontmap.c"
115     #include "pango-render.c"
116    
117 root 1.133 typedef Mix_Chunk *CFPlus__MixChunk;
118     typedef Mix_Music *CFPlus__MixMusic;
119 root 1.52
120 root 1.133 typedef PangoFontDescription *CFPlus__Font;
121 root 1.2
122 root 1.121 static int
123     shape_attr_p (PangoLayoutRun *run)
124     {
125     GSList *attrs = run->item->analysis.extra_attrs;
126    
127     while (attrs)
128     {
129     PangoAttribute *attr = attrs->data;
130    
131     if (attr->klass->type == PANGO_ATTR_SHAPE)
132     return 1;
133    
134     attrs = attrs->next;
135     }
136    
137     return 0;
138     }
139    
140 root 1.14 typedef struct cf_layout {
141 root 1.124 PangoLayout *pl;
142 root 1.76 float r, g, b, a; // default color for rgba mode
143 root 1.14 int base_height;
144 root 1.133 CFPlus__Font font;
145     } *CFPlus__Layout;
146 root 1.14
147 root 1.133 static CFPlus__Font default_font;
148 root 1.124 static PangoContext *opengl_context;
149     static PangoFontMap *opengl_fontmap;
150 root 1.61
151 root 1.14 static void
152 root 1.19 substitute_func (FcPattern *pattern, gpointer data)
153     {
154 root 1.108 FcPatternAddBool (pattern, FC_HINTING, 1);
155 root 1.110 #ifdef FC_HINT_STYLE
156 root 1.109 FcPatternAddBool (pattern, FC_HINT_STYLE, FC_HINT_FULL);
157 root 1.110 #endif
158 root 1.82 FcPatternAddBool (pattern, FC_AUTOHINT, 0);
159 root 1.19 }
160    
161     static void
162 root 1.133 layout_update_font (CFPlus__Layout self)
163 root 1.17 {
164 root 1.19 /* use a random scale factor to account for unknown descenders, 0.8 works
165     * reasonably well with bitstream vera
166     */
167 root 1.61 PangoFontDescription *font = self->font ? self->font : default_font;
168 root 1.46
169 root 1.61 pango_font_description_set_absolute_size (font,
170     MAX (MIN_FONT_HEIGHT, self->base_height) * (PANGO_SCALE * 8 / 10));
171 root 1.58
172 root 1.61 pango_layout_set_font_description (self->pl, font);
173 root 1.17 }
174    
175     static void
176 root 1.133 layout_get_pixel_size (CFPlus__Layout self, int *w, int *h)
177 root 1.14 {
178 root 1.139 PangoRectangle rect;
179 root 1.14
180 root 1.139 // get_pixel_* wrongly rounds down
181     pango_layout_get_extents (self->pl, 0, &rect);
182 root 1.76
183 root 1.139 rect.width = (rect.width + PANGO_SCALE - 1) / PANGO_SCALE;
184     rect.height = (rect.height + PANGO_SCALE - 1) / PANGO_SCALE;
185    
186     if (!rect.width) rect.width = 1;
187     if (!rect.height) rect.height = 1;
188    
189     *w = rect.width;
190     *h = rect.height;
191 root 1.14 }
192    
193 root 1.174 typedef uint16_t tileid;
194     typedef uint16_t faceid;
195 root 1.42
196 root 1.28 typedef struct {
197 root 1.174 int name;
198 root 1.30 int w, h;
199     float s, t;
200 root 1.39 uint8_t r, g, b, a;
201 root 1.176 tileid smoothtile;
202     uint8_t smoothlevel;
203 root 1.42 } maptex;
204 root 1.30
205     typedef struct {
206 root 1.153 uint32_t player;
207 root 1.174 tileid tile[3];
208 root 1.142 uint16_t darkness;
209 root 1.176 uint8_t stat_width, stat_hp, flags, smoothmax;
210 root 1.28 } mapcell;
211    
212     typedef struct {
213 root 1.30 int32_t c0, c1;
214 root 1.28 mapcell *col;
215     } maprow;
216    
217     typedef struct map {
218     int x, y, w, h;
219 root 1.42 int ox, oy; /* offset to virtual global coordinate system */
220 root 1.174 int faces; tileid *face2tile; // [faceid]
221     int texs; maptex *tex; // [tileid]
222 root 1.42
223 root 1.48 int32_t rows;
224 root 1.28 maprow *row;
225 root 1.133 } *CFPlus__Map;
226 root 1.28
227 root 1.30 static char *
228     prepend (char *ptr, int sze, int inc)
229     {
230     char *p;
231    
232     New (0, p, sze + inc, char);
233     Zero (p, inc, char);
234     Move (ptr, p + inc, sze, char);
235     Safefree (ptr);
236    
237     return p;
238     }
239    
240     static char *
241     append (char *ptr, int sze, int inc)
242     {
243     Renew (ptr, sze + inc, char);
244     Zero (ptr + sze, inc, char);
245    
246     return ptr;
247     }
248    
249     #define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
250     #define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
251    
252 root 1.174 static void
253     need_facenum (struct map *self, faceid face)
254     {
255     while (self->faces <= face)
256     {
257     Append (tileid, self->face2tile, self->faces, self->faces);
258     self->faces *= 2;
259     }
260     }
261    
262     static void
263     need_texid (struct map *self, int texid)
264     {
265     while (self->texs <= texid)
266     {
267     Append (maptex, self->tex, self->texs, self->texs);
268     self->texs *= 2;
269     }
270     }
271    
272 root 1.42 static maprow *
273 root 1.133 map_get_row (CFPlus__Map self, int y)
274 root 1.42 {
275     if (0 > y)
276     {
277     int extend = - y + MAP_EXTEND_Y;
278     Prepend (maprow, self->row, self->rows, extend);
279    
280     self->rows += extend;
281     self->y += extend;
282     y += extend;
283     }
284     else if (y >= self->rows)
285     {
286     int extend = y - self->rows + MAP_EXTEND_Y;
287     Append (maprow, self->row, self->rows, extend);
288     self->rows += extend;
289     }
290    
291     return self->row + y;
292     }
293    
294     static mapcell *
295     row_get_cell (maprow *row, int x)
296     {
297     if (!row->col)
298     {
299     Newz (0, row->col, MAP_EXTEND_X, mapcell);
300     row->c0 = x - MAP_EXTEND_X / 4;
301     row->c1 = row->c0 + MAP_EXTEND_X;
302     }
303    
304     if (row->c0 > x)
305     {
306     int extend = row->c0 - x + MAP_EXTEND_X;
307     Prepend (mapcell, row->col, row->c1 - row->c0, extend);
308     row->c0 -= extend;
309     }
310     else if (x >= row->c1)
311     {
312     int extend = x - row->c1 + MAP_EXTEND_X;
313     Append (mapcell, row->col, row->c1 - row->c0, extend);
314     row->c1 += extend;
315     }
316    
317     return row->col + (x - row->c0);
318     }
319    
320     static mapcell *
321 root 1.133 map_get_cell (CFPlus__Map self, int x, int y)
322 root 1.42 {
323     return row_get_cell (map_get_row (self, y), x);
324     }
325    
326 root 1.30 static void
327 root 1.133 map_clear (CFPlus__Map self)
328 root 1.30 {
329     int r;
330    
331     for (r = 0; r < self->rows; r++)
332     Safefree (self->row[r].col);
333    
334     Safefree (self->row);
335    
336     self->x = 0;
337     self->y = 0;
338 root 1.42 self->ox = 0;
339     self->oy = 0;
340 root 1.30 self->row = 0;
341     self->rows = 0;
342     }
343    
344 root 1.29 static void
345 root 1.133 map_blank (CFPlus__Map self, int x0, int y0, int w, int h)
346 root 1.29 {
347     int x, y;
348 root 1.48 maprow *row;
349 root 1.146 mapcell *cell;
350 root 1.29
351     for (y = y0; y < y0 + h; y++)
352 root 1.30 if (y >= 0)
353     {
354     if (y >= self->rows)
355     break;
356    
357 root 1.48 row = self->row + y;
358 root 1.30
359     for (x = x0; x < x0 + w; x++)
360     if (x >= row->c0)
361     {
362     if (x >= row->c1)
363     break;
364 root 1.29
365 root 1.146 cell = row->col + x - row->c0;
366    
367     cell->darkness = 0;
368     cell->stat_hp = 0;
369 root 1.154 cell->flags = 0;
370     cell->player = 0;
371 root 1.30 }
372     }
373 root 1.29 }
374    
375 root 1.176 typedef struct {
376     tileid tile;
377     uint8_t x, y, level;
378     } smooth_key;
379    
380     static void
381     smooth_or_bits (HV *hv, smooth_key *key, IV bits)
382     {
383 root 1.181 SV **sv = hv_fetch (hv, (char *)key, sizeof (*key), 1);
384 root 1.176
385     if (SvIOK (*sv))
386     SvIV_set (*sv, SvIVX (*sv) | bits);
387     else
388     sv_setiv (*sv, bits);
389     }
390    
391 root 1.56 static void
392 root 1.75 music_finished (void)
393 root 1.56 {
394     SDL_UserEvent ev;
395    
396     ev.type = SDL_USEREVENT;
397     ev.code = 0;
398     ev.data1 = 0;
399     ev.data2 = 0;
400    
401 root 1.57 SDL_PushEvent ((SDL_Event *)&ev);
402 root 1.56 }
403    
404 root 1.71 static void
405     channel_finished (int channel)
406     {
407     SDL_UserEvent ev;
408    
409     ev.type = SDL_USEREVENT;
410     ev.code = 1;
411 root 1.74 ev.data1 = (void *)(long)channel;
412 root 1.71 ev.data2 = 0;
413    
414     SDL_PushEvent ((SDL_Event *)&ev);
415     }
416    
417 root 1.113 static unsigned int
418     minpot (unsigned int n)
419     {
420     if (!n)
421     return 0;
422    
423     --n;
424    
425     n |= n >> 1;
426     n |= n >> 2;
427     n |= n >> 4;
428     n |= n >> 8;
429     n |= n >> 16;
430    
431     return n + 1;
432     }
433    
434 root 1.167 /* SDL should provide this, really. */
435     #define SDLK_MODIFIER_MIN 300
436     #define SDLK_MODIFIER_MAX 314
437    
438 root 1.207 /******************************************************************************/
439    
440     static int
441     within_widget (SV *widget, NV x, NV y)
442     {
443     HV *self;
444     SV **svp;
445     NV wx, ww, wy, wh;
446    
447     if (!SvROK (widget))
448     return 0;
449    
450     self = (HV *)SvRV (widget);
451    
452     if (SvTYPE (self) != SVt_PVHV)
453     return 0;
454    
455     svp = hv_fetch (self, "y", 1, 0); wy = svp ? SvNV (*svp) : 0.;
456     if (y < wy)
457     return 0;
458    
459     svp = hv_fetch (self, "h", 1, 0); wh = svp ? SvNV (*svp) : 0.;
460     if (y >= wy + wh)
461     return 0;
462    
463     svp = hv_fetch (self, "x", 1, 0); wx = svp ? SvNV (*svp) : 0.;
464     if (x < wx)
465     return 0;
466    
467     svp = hv_fetch (self, "w", 1, 0); ww = svp ? SvNV (*svp) : 0.;
468     if (x >= wx + ww)
469     return 0;
470    
471     svp = hv_fetch (self, "can_events", sizeof ("can_events") - 1, 0);
472     if (!svp || !SvTRUE (*svp))
473     return 0;
474    
475     return 1;
476     }
477    
478 root 1.133 MODULE = CFPlus PACKAGE = CFPlus
479 root 1.1
480 root 1.11 PROTOTYPES: ENABLE
481    
482 root 1.5 BOOT:
483     {
484 root 1.133 HV *stash = gv_stashpv ("CFPlus", 1);
485 root 1.51 static const struct {
486     const char *name;
487     IV iv;
488     } *civ, const_iv[] = {
489     # define const_iv(name) { # name, (IV)name }
490 root 1.167 const_iv (SDLK_MODIFIER_MIN),
491     const_iv (SDLK_MODIFIER_MAX),
492    
493 root 1.51 const_iv (SDL_ACTIVEEVENT),
494     const_iv (SDL_KEYDOWN),
495     const_iv (SDL_KEYUP),
496     const_iv (SDL_MOUSEMOTION),
497     const_iv (SDL_MOUSEBUTTONDOWN),
498     const_iv (SDL_MOUSEBUTTONUP),
499     const_iv (SDL_JOYAXISMOTION),
500     const_iv (SDL_JOYBALLMOTION),
501     const_iv (SDL_JOYHATMOTION),
502     const_iv (SDL_JOYBUTTONDOWN),
503     const_iv (SDL_JOYBUTTONUP),
504     const_iv (SDL_QUIT),
505     const_iv (SDL_SYSWMEVENT),
506     const_iv (SDL_EVENT_RESERVEDA),
507     const_iv (SDL_EVENT_RESERVEDB),
508     const_iv (SDL_VIDEORESIZE),
509     const_iv (SDL_VIDEOEXPOSE),
510     const_iv (SDL_USEREVENT),
511 root 1.167
512     const_iv (SDL_APPINPUTFOCUS),
513     const_iv (SDL_APPMOUSEFOCUS),
514     const_iv (SDL_APPACTIVE),
515    
516 root 1.51 const_iv (SDLK_KP0),
517     const_iv (SDLK_KP1),
518     const_iv (SDLK_KP2),
519     const_iv (SDLK_KP3),
520     const_iv (SDLK_KP4),
521     const_iv (SDLK_KP5),
522     const_iv (SDLK_KP6),
523     const_iv (SDLK_KP7),
524     const_iv (SDLK_KP8),
525     const_iv (SDLK_KP9),
526     const_iv (SDLK_KP_PERIOD),
527     const_iv (SDLK_KP_DIVIDE),
528     const_iv (SDLK_KP_MULTIPLY),
529     const_iv (SDLK_KP_MINUS),
530     const_iv (SDLK_KP_PLUS),
531     const_iv (SDLK_KP_ENTER),
532     const_iv (SDLK_KP_EQUALS),
533     const_iv (SDLK_UP),
534     const_iv (SDLK_DOWN),
535     const_iv (SDLK_RIGHT),
536     const_iv (SDLK_LEFT),
537     const_iv (SDLK_INSERT),
538     const_iv (SDLK_HOME),
539     const_iv (SDLK_END),
540     const_iv (SDLK_PAGEUP),
541     const_iv (SDLK_PAGEDOWN),
542     const_iv (SDLK_F1),
543     const_iv (SDLK_F2),
544     const_iv (SDLK_F3),
545     const_iv (SDLK_F4),
546     const_iv (SDLK_F5),
547     const_iv (SDLK_F6),
548     const_iv (SDLK_F7),
549     const_iv (SDLK_F8),
550     const_iv (SDLK_F9),
551     const_iv (SDLK_F10),
552     const_iv (SDLK_F11),
553     const_iv (SDLK_F12),
554     const_iv (SDLK_F13),
555     const_iv (SDLK_F14),
556     const_iv (SDLK_F15),
557     const_iv (SDLK_NUMLOCK),
558     const_iv (SDLK_CAPSLOCK),
559     const_iv (SDLK_SCROLLOCK),
560     const_iv (SDLK_RSHIFT),
561     const_iv (SDLK_LSHIFT),
562     const_iv (SDLK_RCTRL),
563     const_iv (SDLK_LCTRL),
564     const_iv (SDLK_RALT),
565     const_iv (SDLK_LALT),
566     const_iv (SDLK_RMETA),
567     const_iv (SDLK_LMETA),
568     const_iv (SDLK_LSUPER),
569     const_iv (SDLK_RSUPER),
570     const_iv (SDLK_MODE),
571     const_iv (SDLK_COMPOSE),
572     const_iv (SDLK_HELP),
573     const_iv (SDLK_PRINT),
574     const_iv (SDLK_SYSREQ),
575     const_iv (SDLK_BREAK),
576     const_iv (SDLK_MENU),
577     const_iv (SDLK_POWER),
578     const_iv (SDLK_EURO),
579     const_iv (SDLK_UNDO),
580 root 1.167
581 root 1.51 const_iv (KMOD_NONE),
582 root 1.167 const_iv (KMOD_SHIFT),
583 root 1.51 const_iv (KMOD_LSHIFT),
584     const_iv (KMOD_RSHIFT),
585 root 1.167 const_iv (KMOD_CTRL),
586 root 1.51 const_iv (KMOD_LCTRL),
587     const_iv (KMOD_RCTRL),
588 root 1.167 const_iv (KMOD_ALT),
589 root 1.51 const_iv (KMOD_LALT),
590     const_iv (KMOD_RALT),
591 root 1.167 const_iv (KMOD_META),
592 root 1.51 const_iv (KMOD_LMETA),
593     const_iv (KMOD_RMETA),
594     const_iv (KMOD_NUM),
595     const_iv (KMOD_CAPS),
596     const_iv (KMOD_MODE),
597     # undef const_iv
598     };
599    
600     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
601     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
602 root 1.167
603     assert (SDLK_MODIFIER_MIN == SDLK_NUMLOCK);
604     assert (SDLK_MODIFIER_MAX == SDLK_COMPOSE);
605 root 1.79 }
606 root 1.51
607 root 1.168 void
608     weaken (SV *rv)
609     PROTOTYPE: $
610     CODE:
611     sv_rvweaken (rv);
612    
613 root 1.129 int
614     in_destruct ()
615     CODE:
616     RETVAL = PL_main_cv == Nullcv;
617     OUTPUT:
618     RETVAL
619    
620 root 1.116 NV floor (NV x)
621    
622     NV ceil (NV x)
623    
624 root 1.79 void
625     pango_init ()
626     CODE:
627     {
628 root 1.124 opengl_fontmap = pango_opengl_font_map_new ();
629     pango_opengl_font_map_set_default_substitute ((PangoOpenGLFontMap *)opengl_fontmap, substitute_func, 0, 0);
630     opengl_context = pango_opengl_font_map_create_context ((PangoOpenGLFontMap *)opengl_fontmap);
631 root 1.5 }
632    
633 root 1.200 char *
634     SDL_GetError ()
635    
636 root 1.51 int
637 root 1.124 SDL_Init (U32 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | PARACHUTE)
638 root 1.51
639     void
640     SDL_Quit ()
641    
642     void
643 root 1.200 SDL_ListModes (int rgb, int alpha)
644 root 1.51 PPCODE:
645     {
646     SDL_Rect **m;
647    
648 root 1.200 SDL_GL_SetAttribute (SDL_GL_RED_SIZE , rgb);
649     SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, rgb);
650     SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE , rgb);
651     SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, alpha);
652 root 1.51
653 root 1.88 SDL_GL_SetAttribute (SDL_GL_BUFFER_SIZE, 15);
654 root 1.200 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE , 0);
655 root 1.85
656 root 1.200 SDL_GL_SetAttribute (SDL_GL_ACCUM_RED_SIZE , 0);
657 root 1.51 SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0);
658 root 1.200 SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE , 0);
659 root 1.51 SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0);
660    
661     SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
662 root 1.134 #if SDL_VERSION_ATLEAST(1,2,10)
663 root 1.131 SDL_GL_SetAttribute (SDL_GL_ACCELERATED_VISUAL, 1);
664     SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1);
665 root 1.134 #endif
666 root 1.51
667     m = SDL_ListModes (0, SDL_FULLSCREEN | SDL_OPENGL);
668    
669     if (m && m != (SDL_Rect **)-1)
670     while (*m)
671     {
672 root 1.200 if ((*m)->w >= 640 && (*m)->h >= 480)
673     {
674     AV *av = newAV ();
675     av_push (av, newSViv ((*m)->w));
676     av_push (av, newSViv ((*m)->h));
677     av_push (av, newSViv (rgb));
678     av_push (av, newSViv (alpha));
679     XPUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
680     }
681 root 1.51
682     ++m;
683     }
684     }
685    
686     int
687 root 1.200 SDL_SetVideoMode (int w, int h, int rgb, int alpha, int fullscreen)
688 root 1.51 CODE:
689 root 1.200 {
690     SDL_EnableUNICODE (1);
691     SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
692    
693     SDL_GL_SetAttribute (SDL_GL_RED_SIZE , rgb);
694     SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, rgb);
695     SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE , rgb);
696     SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, alpha);
697    
698 root 1.51 RETVAL = !!SDL_SetVideoMode (
699     w, h, 0, SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0)
700     );
701 root 1.200
702 root 1.103 if (RETVAL)
703     {
704 root 1.188 av_clear (texture_av);
705    
706 root 1.103 SDL_WM_SetCaption ("Crossfire+ Client " VERSION, "Crossfire+");
707 root 1.200 #define GL_FUNC(ptr,name) gl.name = (ptr)SDL_GL_GetProcAddress ("gl" # name);
708     #include "glfunc.h"
709     #undef GL_FUNC
710 root 1.103 }
711 root 1.200 }
712 root 1.51 OUTPUT:
713     RETVAL
714    
715 root 1.53 void
716 root 1.54 SDL_GL_SwapBuffers ()
717    
718 root 1.94 char *
719     SDL_GetKeyName (int sym)
720    
721 root 1.198 int
722     SDL_GetAppState ()
723    
724 root 1.54 void
725 root 1.197 poll_events ()
726 root 1.53 PPCODE:
727     {
728     SDL_Event ev;
729    
730 root 1.197 SDL_PumpEvents ();
731     while (SDL_PeepEvents (&ev, 1, SDL_GETEVENT, SDL_ALLEVENTS) > 0)
732 root 1.53 {
733     HV *hv = newHV ();
734     hv_store (hv, "type", 4, newSViv (ev.type), 0);
735 root 1.70
736 root 1.53 switch (ev.type)
737     {
738     case SDL_KEYDOWN:
739     case SDL_KEYUP:
740     hv_store (hv, "state", 5, newSViv (ev.key.state), 0);
741     hv_store (hv, "sym", 3, newSViv (ev.key.keysym.sym), 0);
742     hv_store (hv, "mod", 3, newSViv (ev.key.keysym.mod), 0);
743 root 1.167 hv_store (hv, "cmod", 4, newSViv (SDL_GetModState ()), 0); /* current mode */
744 root 1.53 hv_store (hv, "unicode", 7, newSViv (ev.key.keysym.unicode), 0);
745     break;
746    
747     case SDL_ACTIVEEVENT:
748     hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0);
749     hv_store (hv, "state", 5, newSViv (ev.active.state), 0);
750     break;
751    
752     case SDL_MOUSEMOTION:
753 root 1.196 {
754     int state = ev.motion.state;
755     int x = ev.motion.x;
756     int y = ev.motion.y;
757     int xrel = ev.motion.xrel;
758     int yrel = ev.motion.yrel;
759    
760     /* do simplistic event compression */
761     while (SDL_PeepEvents (&ev, 1, SDL_PEEKEVENT, SDL_EVENTMASK (SDL_MOUSEMOTION)) > 0
762     && state == ev.motion.state)
763     {
764     xrel += ev.motion.xrel;
765     yrel += ev.motion.yrel;
766     x = ev.motion.x;
767     y = ev.motion.y;
768     SDL_PeepEvents (&ev, 1, SDL_GETEVENT, SDL_EVENTMASK (SDL_MOUSEMOTION));
769     }
770 root 1.93
771 root 1.196 hv_store (hv, "mod", 3, newSViv (SDL_GetModState ()), 0);
772     hv_store (hv, "state", 5, newSViv (state), 0);
773     hv_store (hv, "x", 1, newSViv (x), 0);
774     hv_store (hv, "y", 1, newSViv (y), 0);
775     hv_store (hv, "xrel", 4, newSViv (xrel), 0);
776     hv_store (hv, "yrel", 4, newSViv (yrel), 0);
777     }
778 root 1.53 break;
779    
780     case SDL_MOUSEBUTTONDOWN:
781     case SDL_MOUSEBUTTONUP:
782 root 1.94 hv_store (hv, "mod", 3, newSViv (SDL_GetModState ()), 0);
783 root 1.93
784 root 1.53 hv_store (hv, "button", 6, newSViv (ev.button.button), 0);
785     hv_store (hv, "state", 5, newSViv (ev.button.state), 0);
786     hv_store (hv, "x", 1, newSViv (ev.button.x), 0);
787     hv_store (hv, "y", 1, newSViv (ev.button.y), 0);
788 root 1.70 break;
789 root 1.72
790     case SDL_USEREVENT:
791     hv_store (hv, "code", 4, newSViv (ev.user.code), 0);
792     hv_store (hv, "data1", 5, newSViv ((IV)ev.user.data1), 0);
793     hv_store (hv, "data2", 5, newSViv ((IV)ev.user.data2), 0);
794     break;
795 root 1.53 }
796    
797 root 1.133 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("CFPlus::UI::Event", 1))));
798 root 1.53 }
799     }
800 root 1.52
801     int
802 root 1.73 Mix_OpenAudio (int frequency = 48000, int format = MIX_DEFAULT_FORMAT, int channels = 1, int chunksize = 2048)
803 root 1.56 POSTCALL:
804     Mix_HookMusicFinished (music_finished);
805 root 1.71 Mix_ChannelFinished (channel_finished);
806 root 1.52
807     void
808     Mix_CloseAudio ()
809    
810     int
811     Mix_AllocateChannels (int numchans = -1)
812    
813 root 1.10 void
814     lowdelay (int fd, int val = 1)
815     CODE:
816 root 1.179 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (void *)&val, sizeof (val));
817 root 1.10
818 root 1.5 void
819 root 1.157 win32_proxy_info ()
820     PPCODE:
821     {
822     #ifdef _WIN32
823     char buffer[2048];
824     DWORD buflen;
825    
826     EXTEND (SP, 3);
827    
828     buflen = sizeof (buffer);
829     if (InternetQueryOption (0, INTERNET_OPTION_PROXY, (void *)buffer, &buflen))
830     if (((INTERNET_PROXY_INFO *)buffer)->dwAccessType == INTERNET_OPEN_TYPE_PROXY)
831     {
832     PUSHs (newSVpv (((INTERNET_PROXY_INFO *)buffer)->lpszProxy, 0));
833    
834     buflen = sizeof (buffer);
835     if (InternetQueryOption (0, INTERNET_OPTION_PROXY_USERNAME, (void *)buffer, &buflen))
836     {
837     PUSHs (newSVpv (buffer, 0));
838    
839     buflen = sizeof (buffer);
840     if (InternetQueryOption (0, INTERNET_OPTION_PROXY_PASSWORD, (void *)buffer, &buflen))
841     PUSHs (newSVpv (buffer, 0));
842     }
843     }
844     #endif
845     }
846    
847     void
848 root 1.13 add_font (char *file)
849     CODE:
850 root 1.129 FcConfigAppFontAddFile (0, (const FcChar8 *)file);
851 root 1.13
852     void
853 root 1.23 load_image_inline (SV *image_)
854     ALIAS:
855     load_image_file = 1
856     PPCODE:
857     {
858     STRLEN image_len;
859     char *image = (char *)SvPVbyte (image_, image_len);
860     SDL_Surface *surface, *surface2;
861     SDL_PixelFormat fmt;
862     SDL_RWops *rw = ix
863     ? SDL_RWFromFile (image, "r")
864     : SDL_RWFromConstMem (image, image_len);
865    
866     if (!rw)
867 root 1.41 croak ("load_image: %s", SDL_GetError ());
868 root 1.23
869     surface = IMG_Load_RW (rw, 1);
870     if (!surface)
871 root 1.41 croak ("load_image: %s", SDL_GetError ());
872 root 1.23
873     fmt.palette = NULL;
874     fmt.BitsPerPixel = 32;
875     fmt.BytesPerPixel = 4;
876 root 1.49 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
877 root 1.23 fmt.Rmask = 0x000000ff;
878     fmt.Gmask = 0x0000ff00;
879     fmt.Bmask = 0x00ff0000;
880     fmt.Amask = 0xff000000;
881 root 1.49 #else
882     fmt.Rmask = 0xff000000;
883     fmt.Gmask = 0x00ff0000;
884     fmt.Bmask = 0x0000ff00;
885     fmt.Amask = 0x000000ff;
886     #endif
887 root 1.23 fmt.Rloss = 0;
888     fmt.Gloss = 0;
889     fmt.Bloss = 0;
890     fmt.Aloss = 0;
891     fmt.Rshift = 0;
892     fmt.Gshift = 8;
893     fmt.Bshift = 16;
894     fmt.Ashift = 24;
895     fmt.colorkey = 0;
896     fmt.alpha = 0;
897    
898     surface2 = SDL_ConvertSurface (surface, &fmt, SDL_SWSURFACE);
899    
900 root 1.39 assert (surface2->pitch == surface2->w * 4);
901    
902 root 1.129 SDL_LockSurface (surface2);
903     EXTEND (SP, 6);
904 root 1.23 PUSHs (sv_2mortal (newSViv (surface2->w)));
905     PUSHs (sv_2mortal (newSViv (surface2->h)));
906     PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch)));
907 root 1.116 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
908 root 1.23 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
909 root 1.49 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
910 root 1.129 SDL_UnlockSurface (surface2);
911 root 1.23
912     SDL_FreeSurface (surface);
913     SDL_FreeSurface (surface2);
914     }
915    
916 root 1.25 void
917 root 1.39 average (int x, int y, uint32_t *data)
918     PPCODE:
919     {
920     uint32_t r = 0, g = 0, b = 0, a = 0;
921    
922     x = y = x * y;
923    
924     while (x--)
925     {
926     uint32_t p = *data++;
927    
928     r += (p ) & 255;
929     g += (p >> 8) & 255;
930     b += (p >> 16) & 255;
931     a += (p >> 24) & 255;
932     }
933    
934     EXTEND (SP, 4);
935 root 1.40 PUSHs (sv_2mortal (newSViv (r / y)));
936     PUSHs (sv_2mortal (newSViv (g / y)));
937     PUSHs (sv_2mortal (newSViv (b / y)));
938     PUSHs (sv_2mortal (newSViv (a / y)));
939 root 1.39 }
940    
941     void
942 root 1.66 error (char *message)
943     CODE:
944 root 1.86 fprintf (stderr, "ERROR: %s\n", message);
945 root 1.66 #ifdef _WIN32
946 root 1.86 MessageBox (0, message, "Crossfire+ Error", MB_OK | MB_ICONERROR);
947 root 1.66 #endif
948    
949     void
950 root 1.25 fatal (char *message)
951     CODE:
952 root 1.86 fprintf (stderr, "FATAL: %s\n", message);
953 root 1.50 #ifdef _WIN32
954 root 1.86 MessageBox (0, message, "Crossfire+ Fatal Error", MB_OK | MB_ICONERROR);
955 root 1.25 #endif
956 root 1.112 _exit (1);
957 root 1.111
958     void
959 root 1.158 _exit (int retval = 0)
960 root 1.111 CODE:
961 root 1.161 #ifdef WIN32
962     ExitThread (retval); // unclean, please beam me up
963     #else
964 root 1.112 _exit (retval);
965 root 1.161 #endif
966 root 1.25
967 root 1.193 void
968     debug ()
969     CODE:
970     {
971     #if DEBUG
972     VALGRIND_DO_LEAK_CHECK;
973     #endif
974     }
975    
976 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Font
977 root 1.61
978 root 1.205 PROTOTYPES: DISABLE
979    
980 root 1.133 CFPlus::Font
981 root 1.70 new_from_file (SV *class, char *path, int id = 0)
982 root 1.61 CODE:
983     {
984     int count;
985 root 1.70 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count);
986 root 1.61 RETVAL = pango_fc_font_description_from_pattern (pattern, 0);
987     FcPatternDestroy (pattern);
988     }
989     OUTPUT:
990     RETVAL
991    
992     void
993 root 1.133 DESTROY (CFPlus::Font self)
994 root 1.61 CODE:
995     pango_font_description_free (self);
996    
997     void
998 root 1.133 make_default (CFPlus::Font self)
999 root 1.205 PROTOTYPE: $
1000 root 1.61 CODE:
1001     default_font = self;
1002    
1003 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Layout
1004 root 1.14
1005 root 1.205 PROTOTYPES: DISABLE
1006    
1007 root 1.124 void
1008 root 1.129 reset_glyph_cache ()
1009 root 1.205 PROTOTYPE:
1010 root 1.124 CODE:
1011     tc_clear ();
1012    
1013 root 1.133 CFPlus::Layout
1014 root 1.128 new (SV *class)
1015 root 1.14 CODE:
1016     New (0, RETVAL, 1, struct cf_layout);
1017 root 1.76
1018 root 1.124 RETVAL->pl = pango_layout_new (opengl_context);
1019 root 1.76 RETVAL->r = 1.;
1020     RETVAL->g = 1.;
1021     RETVAL->b = 1.;
1022     RETVAL->a = 1.;
1023     RETVAL->base_height = MIN_FONT_HEIGHT;
1024     RETVAL->font = 0;
1025    
1026 root 1.14 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
1027 root 1.76 layout_update_font (RETVAL);
1028 root 1.14 OUTPUT:
1029     RETVAL
1030    
1031     void
1032 root 1.133 DESTROY (CFPlus::Layout self)
1033 root 1.14 CODE:
1034     g_object_unref (self->pl);
1035     Safefree (self);
1036 root 1.13
1037 root 1.8 void
1038 root 1.133 set_text (CFPlus::Layout self, SV *text_)
1039 root 1.35 CODE:
1040     {
1041     STRLEN textlen;
1042     char *text = SvPVutf8 (text_, textlen);
1043    
1044     pango_layout_set_text (self->pl, text, textlen);
1045     }
1046    
1047     void
1048 root 1.133 set_markup (CFPlus::Layout self, SV *text_)
1049 root 1.14 CODE:
1050 root 1.5 {
1051     STRLEN textlen;
1052     char *text = SvPVutf8 (text_, textlen);
1053 root 1.14
1054     pango_layout_set_markup (self->pl, text, textlen);
1055     }
1056    
1057 root 1.121 void
1058 root 1.133 set_shapes (CFPlus::Layout self, ...)
1059 root 1.121 CODE:
1060     {
1061     PangoAttrList *attrs = 0;
1062     const char *text = pango_layout_get_text (self->pl);
1063     const char *pos = text;
1064 root 1.122 int arg = 4;
1065 root 1.121
1066     while (arg < items && (pos = strstr (pos, OBJ_STR)))
1067     {
1068 root 1.122 PangoRectangle inkrect, rect;
1069 root 1.121 PangoAttribute *attr;
1070    
1071 root 1.122 int x = SvIV (ST (arg - 3));
1072     int y = SvIV (ST (arg - 2));
1073 root 1.121 int w = SvIV (ST (arg - 1));
1074 root 1.122 int h = SvIV (ST (arg ));
1075 root 1.121
1076 root 1.122 inkrect.x = 0;
1077     inkrect.y = 0;
1078     inkrect.width = 0;
1079     inkrect.height = 0;
1080    
1081     rect.x = x * PANGO_SCALE;
1082     rect.y = y * PANGO_SCALE;
1083     rect.width = w * PANGO_SCALE;
1084 root 1.121 rect.height = h * PANGO_SCALE;
1085    
1086     if (!attrs)
1087     attrs = pango_layout_get_attributes (self->pl);
1088    
1089 root 1.122 attr = pango_attr_shape_new (&inkrect, &rect);
1090 root 1.121 attr->start_index = pos - text;
1091     attr->end_index = attr->start_index + sizeof (OBJ_STR) - 1;
1092     pango_attr_list_insert (attrs, attr);
1093    
1094 root 1.122 arg += 4;
1095 root 1.121 pos += sizeof (OBJ_STR) - 1;
1096     }
1097    
1098     if (attrs)
1099     pango_layout_set_attributes (self->pl, attrs);
1100     }
1101    
1102     void
1103 root 1.133 get_shapes (CFPlus::Layout self)
1104 root 1.121 PPCODE:
1105     {
1106     PangoLayoutIter *iter = pango_layout_get_iter (self->pl);
1107    
1108     do
1109     {
1110     PangoLayoutRun *run = pango_layout_iter_get_run (iter);
1111    
1112     if (run && shape_attr_p (run))
1113     {
1114     PangoRectangle extents;
1115     pango_layout_iter_get_run_extents (iter, 0, &extents);
1116    
1117 root 1.129 EXTEND (SP, 2);
1118 root 1.121 PUSHs (sv_2mortal (newSViv (PANGO_PIXELS (extents.x))));
1119     PUSHs (sv_2mortal (newSViv (PANGO_PIXELS (extents.y))));
1120     }
1121     }
1122     while (pango_layout_iter_next_run (iter));
1123    
1124     pango_layout_iter_free (iter);
1125     }
1126    
1127     int
1128 root 1.133 has_wrapped (CFPlus::Layout self)
1129 root 1.121 CODE:
1130     {
1131     int lines = 1;
1132     const char *text = pango_layout_get_text (self->pl);
1133    
1134     while (*text)
1135     lines += *text++ == '\n';
1136    
1137     RETVAL = lines < pango_layout_get_line_count (self->pl);
1138     }
1139     OUTPUT:
1140     RETVAL
1141    
1142 root 1.46 SV *
1143 root 1.133 get_text (CFPlus::Layout self)
1144 root 1.46 CODE:
1145 root 1.47 RETVAL = newSVpv (pango_layout_get_text (self->pl), 0);
1146 root 1.107 sv_utf8_decode (RETVAL);
1147 root 1.46 OUTPUT:
1148     RETVAL
1149    
1150 root 1.14 void
1151 root 1.133 set_foreground (CFPlus::Layout self, float r, float g, float b, float a = 1.)
1152 root 1.76 CODE:
1153     self->r = r;
1154     self->g = g;
1155     self->b = b;
1156     self->a = a;
1157    
1158     void
1159 root 1.133 set_font (CFPlus::Layout self, CFPlus::Font font = 0)
1160 root 1.61 CODE:
1161     if (self->font != font)
1162     {
1163     self->font = font;
1164     layout_update_font (self);
1165     }
1166    
1167     void
1168 root 1.133 set_height (CFPlus::Layout self, int base_height)
1169 root 1.16 CODE:
1170 root 1.61 if (self->base_height != base_height)
1171     {
1172     self->base_height = base_height;
1173     layout_update_font (self);
1174     }
1175 root 1.16
1176     void
1177 root 1.133 set_width (CFPlus::Layout self, int max_width = -1)
1178 root 1.14 CODE:
1179     pango_layout_set_width (self->pl, max_width < 0 ? max_width : max_width * PANGO_SCALE);
1180    
1181     void
1182 root 1.133 set_indent (CFPlus::Layout self, int indent)
1183 root 1.84 CODE:
1184     pango_layout_set_indent (self->pl, indent * PANGO_SCALE);
1185    
1186     void
1187 root 1.133 set_spacing (CFPlus::Layout self, int spacing)
1188 root 1.84 CODE:
1189     pango_layout_set_spacing (self->pl, spacing * PANGO_SCALE);
1190    
1191     void
1192 root 1.133 set_ellipsise (CFPlus::Layout self, int ellipsise)
1193 root 1.84 CODE:
1194     pango_layout_set_ellipsize (self->pl,
1195     ellipsise == 1 ? PANGO_ELLIPSIZE_START
1196     : ellipsise == 2 ? PANGO_ELLIPSIZE_MIDDLE
1197     : ellipsise == 3 ? PANGO_ELLIPSIZE_END
1198     : PANGO_ELLIPSIZE_NONE
1199     );
1200    
1201     void
1202 root 1.133 set_single_paragraph_mode (CFPlus::Layout self, int spm)
1203 root 1.84 CODE:
1204     pango_layout_set_single_paragraph_mode (self->pl, !!spm);
1205    
1206     void
1207 root 1.133 size (CFPlus::Layout self)
1208 root 1.14 PPCODE:
1209     {
1210     int w, h;
1211    
1212     layout_get_pixel_size (self, &w, &h);
1213    
1214     EXTEND (SP, 2);
1215     PUSHs (sv_2mortal (newSViv (w)));
1216     PUSHs (sv_2mortal (newSViv (h)));
1217     }
1218    
1219 root 1.17 int
1220 root 1.133 descent (CFPlus::Layout self)
1221 root 1.122 CODE:
1222     {
1223     PangoRectangle rect;
1224     PangoLayoutLine *line = pango_layout_get_line (self->pl, 0);
1225     pango_layout_line_get_pixel_extents (line, 0, &rect);
1226     RETVAL = PANGO_DESCENT (rect);
1227     }
1228     OUTPUT:
1229     RETVAL
1230    
1231     int
1232 root 1.133 xy_to_index (CFPlus::Layout self, int x, int y)
1233 root 1.17 CODE:
1234     {
1235     int index, trailing;
1236     pango_layout_xy_to_index (self->pl, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing);
1237 root 1.165 RETVAL = index + trailing;
1238 root 1.17 }
1239     OUTPUT:
1240     RETVAL
1241    
1242     void
1243 root 1.133 cursor_pos (CFPlus::Layout self, int index)
1244 root 1.17 PPCODE:
1245     {
1246     PangoRectangle strong_pos;
1247     pango_layout_get_cursor_pos (self->pl, index, &strong_pos, 0);
1248 root 1.30
1249 root 1.17 EXTEND (SP, 3);
1250     PUSHs (sv_2mortal (newSViv (strong_pos.x / PANGO_SCALE)));
1251     PUSHs (sv_2mortal (newSViv (strong_pos.y / PANGO_SCALE)));
1252     PUSHs (sv_2mortal (newSViv (strong_pos.height / PANGO_SCALE)));
1253     }
1254    
1255 root 1.14 void
1256 root 1.165 index_to_line_x (CFPlus::Layout self, int index, int trailing = 0)
1257     PPCODE:
1258     {
1259     int line, x;
1260    
1261     pango_layout_index_to_line_x (self->pl, index, trailing, &line, &x);
1262     /* pango bug: line is between 1..numlines, not 0..numlines-1 */
1263    
1264     EXTEND (SP, 2);
1265     PUSHs (sv_2mortal (newSViv (line - 1)));
1266     PUSHs (sv_2mortal (newSViv (x / PANGO_SCALE)));
1267     }
1268    
1269     void
1270     line_x_to_index (CFPlus::Layout self, int line, int x)
1271     PPCODE:
1272     {
1273     PangoLayoutLine *lp;
1274     int index, trailing;
1275    
1276     if (line < 0)
1277     XSRETURN_EMPTY;
1278    
1279     if (!(lp = pango_layout_get_line (self->pl, line)))
1280     XSRETURN_EMPTY; /* do better */
1281    
1282 root 1.166 pango_layout_line_x_to_index (lp, x * PANGO_SCALE, &index, &trailing);
1283 root 1.165
1284     EXTEND (SP, 2);
1285     if (GIMME_V == G_SCALAR)
1286     PUSHs (sv_2mortal (newSViv (index + trailing)));
1287     else
1288     {
1289     PUSHs (sv_2mortal (newSViv (index)));
1290     PUSHs (sv_2mortal (newSViv (trailing)));
1291     }
1292     }
1293    
1294     void
1295 root 1.135 render (CFPlus::Layout self, float x, float y, int flags = 0)
1296 root 1.14 PPCODE:
1297 root 1.124 pango_opengl_render_layout_subpixel (
1298     self->pl,
1299     x * PANGO_SCALE, y * PANGO_SCALE,
1300 root 1.135 self->r, self->g, self->b, self->a,
1301     flags
1302 root 1.124 );
1303 root 1.11
1304 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Texture
1305 root 1.11
1306 root 1.205 PROTOTYPES: ENABLE
1307    
1308 root 1.199 int minpot (int n)
1309    
1310 root 1.11 void
1311 root 1.203 pad (SV *data_, int ow, int oh, int nw, int nh)
1312 root 1.113 CODE:
1313     {
1314 root 1.203 if ((nw != ow || nh != oh) && SvOK (data_))
1315 root 1.113 {
1316 root 1.203 STRLEN datalen;
1317     char *data = SvPVbyte (data_, datalen);
1318     int bpp = datalen / (ow * oh);
1319     SV *result_ = sv_2mortal (newSV (nw * nh * bpp));
1320    
1321     SvPOK_only (result_);
1322     SvCUR_set (result_, nw * nh * bpp);
1323    
1324     memset (SvPVX (result_), 0, nw * nh * bpp);
1325     while (oh--)
1326     memcpy (SvPVX (result_) + oh * nw * bpp, data + oh * ow * bpp, ow * bpp);
1327 root 1.113
1328 root 1.203 sv_setsv (data_, result_);
1329 root 1.113 }
1330     }
1331    
1332     void
1333 root 1.114 draw_quad (SV *self, float x, float y, float w = 0., float h = 0.)
1334 root 1.12 PROTOTYPE: $$$;$$
1335 root 1.76 ALIAS:
1336     draw_quad_alpha = 1
1337     draw_quad_alpha_premultiplied = 2
1338 root 1.11 CODE:
1339     {
1340 root 1.12 HV *hv = (HV *)SvRV (self);
1341 root 1.37 float s = SvNV (*hv_fetch (hv, "s", 1, 1));
1342     float t = SvNV (*hv_fetch (hv, "t", 1, 1));
1343 root 1.12 int name = SvIV (*hv_fetch (hv, "name", 4, 1));
1344    
1345     if (items < 5)
1346     {
1347 root 1.18 w = SvNV (*hv_fetch (hv, "w", 1, 1));
1348     h = SvNV (*hv_fetch (hv, "h", 1, 1));
1349 root 1.12 }
1350    
1351 root 1.76 if (ix)
1352     {
1353     glEnable (GL_BLEND);
1354 root 1.103
1355     if (ix == 2)
1356     glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1357     else
1358     gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1359 root 1.104 GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
1360 root 1.103
1361 root 1.86 glEnable (GL_ALPHA_TEST);
1362     glAlphaFunc (GL_GREATER, 0.01f);
1363 root 1.76 }
1364    
1365 root 1.12 glBindTexture (GL_TEXTURE_2D, name);
1366 root 1.76
1367 root 1.12 glBegin (GL_QUADS);
1368 root 1.37 glTexCoord2f (0, 0); glVertex2f (x , y );
1369     glTexCoord2f (0, t); glVertex2f (x , y + h);
1370     glTexCoord2f (s, t); glVertex2f (x + w, y + h);
1371     glTexCoord2f (s, 0); glVertex2f (x + w, y );
1372 root 1.12 glEnd ();
1373 root 1.76
1374     if (ix)
1375 root 1.86 {
1376     glDisable (GL_ALPHA_TEST);
1377     glDisable (GL_BLEND);
1378     }
1379 root 1.11 }
1380 root 1.28
1381 root 1.199 IV texture_valid_2d (GLint internalformat, GLsizei w, GLsizei h, GLenum format, GLenum type)
1382     CODE:
1383     {
1384     GLint width;
1385     glTexImage2D (GL_PROXY_TEXTURE_2D, 0, internalformat, w, h, 0, format, type, 0);
1386     glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
1387     RETVAL = width > 0;
1388     }
1389     OUTPUT:
1390     RETVAL
1391    
1392 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Map
1393 root 1.28
1394 root 1.205 PROTOTYPES: DISABLE
1395    
1396 root 1.133 CFPlus::Map
1397 root 1.164 new (SV *class)
1398 root 1.28 CODE:
1399     New (0, RETVAL, 1, struct map);
1400 root 1.42 RETVAL->x = 0;
1401     RETVAL->y = 0;
1402 root 1.164 RETVAL->w = 0;
1403     RETVAL->h = 0;
1404 root 1.42 RETVAL->ox = 0;
1405     RETVAL->oy = 0;
1406 root 1.174 RETVAL->faces = 8192; Newz (0, RETVAL->face2tile, RETVAL->faces, tileid);
1407     RETVAL->texs = 8192; Newz (0, RETVAL->tex , RETVAL->texs , maptex);
1408 root 1.28 RETVAL->rows = 0;
1409     RETVAL->row = 0;
1410     OUTPUT:
1411     RETVAL
1412    
1413     void
1414 root 1.133 DESTROY (CFPlus::Map self)
1415 root 1.28 CODE:
1416     {
1417 root 1.30 map_clear (self);
1418 root 1.174 Safefree (self->face2tile);
1419 root 1.111 Safefree (self->tex);
1420 root 1.29 Safefree (self);
1421     }
1422    
1423     void
1424 root 1.164 resize (CFPlus::Map self, int map_width, int map_height)
1425     CODE:
1426     self->w = map_width;
1427     self->h = map_height;
1428    
1429     void
1430 root 1.133 clear (CFPlus::Map self)
1431 root 1.30 CODE:
1432     map_clear (self);
1433    
1434     void
1435 root 1.174 set_tileid (CFPlus::Map self, int face, int tile)
1436 root 1.29 CODE:
1437     {
1438 root 1.174 need_facenum (self, face); self->face2tile [face] = tile;
1439     need_texid (self, tile);
1440 root 1.42 }
1441    
1442     void
1443 root 1.176 set_smooth (CFPlus::Map self, int face, int smooth, int level)
1444     CODE:
1445     {
1446     tileid texid;
1447     maptex *tex;
1448    
1449     if (face < 0 || face >= self->faces)
1450     return;
1451    
1452     if (smooth < 0 || smooth >= self->faces)
1453     return;
1454    
1455     texid = self->face2tile [face];
1456    
1457     if (!texid)
1458     return;
1459    
1460     tex = self->tex + texid;
1461     tex->smoothtile = self->face2tile [smooth];
1462     tex->smoothlevel = level;
1463     }
1464    
1465     void
1466 root 1.133 set_texture (CFPlus::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a)
1467 root 1.42 CODE:
1468     {
1469 root 1.174 need_texid (self, texid);
1470 root 1.42
1471 root 1.48 {
1472     maptex *tex = self->tex + texid;
1473 root 1.39
1474 root 1.48 tex->name = name;
1475     tex->w = w;
1476     tex->h = h;
1477     tex->s = s;
1478     tex->t = t;
1479     tex->r = r;
1480     tex->g = g;
1481     tex->b = b;
1482     tex->a = a;
1483     }
1484 root 1.95
1485     // somewhat hackish, but for textures that require it, it really
1486     // improves the look, and most others don't suffer.
1487     glBindTexture (GL_TEXTURE_2D, name);
1488 root 1.99 //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1489     //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1490     // use uglier nearest interpolation because linear suffers
1491     // from transparent color bleeding and ugly wrapping effects.
1492     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1493 root 1.29 }
1494    
1495 root 1.42 int
1496 root 1.133 ox (CFPlus::Map self)
1497 root 1.42 ALIAS:
1498     oy = 1
1499 root 1.101 x = 2
1500     y = 3
1501 root 1.102 w = 4
1502     h = 5
1503 root 1.42 CODE:
1504     switch (ix)
1505     {
1506     case 0: RETVAL = self->ox; break;
1507     case 1: RETVAL = self->oy; break;
1508 root 1.101 case 2: RETVAL = self->x; break;
1509     case 3: RETVAL = self->y; break;
1510 root 1.102 case 4: RETVAL = self->w; break;
1511     case 5: RETVAL = self->h; break;
1512 root 1.42 }
1513     OUTPUT:
1514     RETVAL
1515    
1516 root 1.29 void
1517 root 1.133 scroll (CFPlus::Map self, int dx, int dy)
1518 root 1.43 CODE:
1519     {
1520 root 1.44 if (dx > 0)
1521 root 1.154 map_blank (self, self->x, self->y, dx, self->h);
1522 root 1.44 else if (dx < 0)
1523 root 1.187 map_blank (self, self->x + self->w + dx, self->y, -dx, self->h);
1524 root 1.44
1525     if (dy > 0)
1526 root 1.154 map_blank (self, self->x, self->y, self->w, dy);
1527 root 1.44 else if (dy < 0)
1528 root 1.187 map_blank (self, self->x, self->y + self->h + dy, self->w, -dy);
1529 root 1.43
1530 root 1.44 self->ox += dx; self->x += dx;
1531     self->oy += dy; self->y += dy;
1532 root 1.43
1533     while (self->y < 0)
1534     {
1535     Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y);
1536    
1537     self->rows += MAP_EXTEND_Y;
1538     self->y += MAP_EXTEND_Y;
1539     }
1540 root 1.44 }
1541 root 1.43
1542 root 1.44 void
1543 root 1.141 map1a_update (CFPlus::Map self, SV *data_, int extmap)
1544 root 1.44 CODE:
1545     {
1546 root 1.30 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
1547     uint8_t *data_end = (uint8_t *)SvEND (data_);
1548 root 1.48 mapcell *cell;
1549     int x, y, flags;
1550 root 1.43
1551 root 1.150 while (data < data_end - 1)
1552 root 1.29 {
1553 root 1.48 flags = (data [0] << 8) + data [1]; data += 2;
1554 root 1.30
1555 root 1.120 x = self->x + ((flags >> 10) & 63);
1556     y = self->y + ((flags >> 4) & 63);
1557 root 1.29
1558 root 1.48 cell = map_get_cell (self, x, y);
1559 root 1.29
1560     if (flags & 15)
1561     {
1562 root 1.142 if (!cell->darkness)
1563 root 1.29 {
1564 root 1.154 memset (cell, 0, sizeof (*cell));
1565 root 1.142 cell->darkness = 256;
1566 root 1.29 }
1567 root 1.45
1568 root 1.142 //TODO: don't trust server data to be in-range(!)
1569    
1570 root 1.141 if (flags & 8)
1571     {
1572     if (extmap)
1573     {
1574     uint8_t ext, cmd;
1575    
1576     do
1577     {
1578     ext = *data++;
1579 root 1.144 cmd = ext & 0x3f;
1580 root 1.141
1581 root 1.147 if (cmd < 4)
1582 root 1.142 cell->darkness = 255 - ext * 64 + 1;
1583 root 1.147 else if (cmd == 5) // health
1584     {
1585     cell->stat_width = 1;
1586     cell->stat_hp = *data++;
1587     }
1588     else if (cmd == 6) // monster width
1589     cell->stat_width = *data++ + 1;
1590 root 1.169 else if (cmd == 0x47)
1591 root 1.153 {
1592 root 1.182 if (*data == 4)
1593     ; // decode player count
1594 root 1.153
1595     data += *data + 1;
1596     }
1597     else if (cmd == 8) // cell flags
1598     cell->flags = *data++;
1599 root 1.144 else if (ext & 0x40) // unknown, multibyte => skip
1600     data += *data + 1;
1601 root 1.147 else
1602     data++;
1603 root 1.141 }
1604 root 1.147 while (ext & 0x80);
1605 root 1.141 }
1606     else
1607 root 1.142 cell->darkness = *data++ + 1;
1608 root 1.141 }
1609 root 1.29
1610     if (flags & 4)
1611     {
1612 root 1.174 faceid face = (data [0] << 8) + data [1]; data += 2;
1613     need_facenum (self, face);
1614     cell->tile [0] = self->face2tile [face];
1615 root 1.29 }
1616    
1617     if (flags & 2)
1618     {
1619 root 1.174 faceid face = (data [0] << 8) + data [1]; data += 2;
1620     need_facenum (self, face);
1621     cell->tile [1] = self->face2tile [face];
1622 root 1.29 }
1623    
1624     if (flags & 1)
1625     {
1626 root 1.174 faceid face = (data [0] << 8) + data [1]; data += 2;
1627     need_facenum (self, face);
1628     cell->tile [2] = self->face2tile [face];
1629 root 1.29 }
1630     }
1631     else
1632 root 1.155 cell->darkness = 0;
1633 root 1.29 }
1634 root 1.28 }
1635    
1636 root 1.40 SV *
1637 root 1.133 mapmap (CFPlus::Map self, int x0, int y0, int w, int h)
1638 root 1.40 CODE:
1639     {
1640 root 1.55 int x1, x;
1641     int y1, y;
1642 root 1.40 int z;
1643     SV *map_sv = newSV (w * h * sizeof (uint32_t));
1644     uint32_t *map = (uint32_t *)SvPVX (map_sv);
1645    
1646     SvPOK_only (map_sv);
1647     SvCUR_set (map_sv, w * h * sizeof (uint32_t));
1648    
1649 root 1.55 x0 += self->x; x1 = x0 + w;
1650     y0 += self->y; y1 = y0 + h;
1651 root 1.40
1652     for (y = y0; y < y1; y++)
1653     {
1654     maprow *row = 0 <= y && y < self->rows
1655     ? self->row + y
1656     : 0;
1657    
1658     for (x = x0; x < x1; x++)
1659     {
1660     int r = 32, g = 32, b = 32, a = 192;
1661    
1662     if (row && row->c0 <= x && x < row->c1)
1663     {
1664     mapcell *cell = row->col + (x - row->c0);
1665    
1666     for (z = 0; z <= 0; z++)
1667     {
1668 root 1.174 maptex tex = self->tex [cell->tile [z]];
1669     int a0 = 255 - tex.a;
1670     int a1 = tex.a;
1671    
1672     r = (r * a0 + tex.r * a1) / 255;
1673     g = (g * a0 + tex.g * a1) / 255;
1674     b = (b * a0 + tex.b * a1) / 255;
1675     a = (a * a0 + tex.a * a1) / 255;
1676 root 1.40 }
1677     }
1678    
1679     *map++ = (r )
1680     | (g << 8)
1681     | (b << 16)
1682     | (a << 24);
1683     }
1684     }
1685    
1686     RETVAL = map_sv;
1687     }
1688     OUTPUT:
1689     RETVAL
1690    
1691 root 1.30 void
1692 root 1.171 draw (CFPlus::Map self, int mx, int my, int sw, int sh, int T)
1693 root 1.116 CODE:
1694 root 1.30 {
1695 root 1.176 HV *smooth = (HV *)sv_2mortal ((SV *)newHV ());
1696     uint32_t smooth_level[256 / 32]; // one bit for every possible smooth level
1697 root 1.178 static uint8_t smooth_max[256][256]; // egad, fats and wasteful on memory (64k)
1698 root 1.176 smooth_key skey;
1699 root 1.48 int x, y, z;
1700     int last_name;
1701    
1702 root 1.176 // thats current max. sorry.
1703     if (sw > 255) sw = 255;
1704     if (sh > 255) sh = 255;
1705    
1706     // clear key, in case of extra padding
1707     memset (&skey, 0, sizeof (skey));
1708    
1709 root 1.30 glColor4ub (255, 255, 255, 255);
1710    
1711 root 1.117 glEnable (GL_BLEND);
1712 root 1.30 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1713     glEnable (GL_TEXTURE_2D);
1714     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1715    
1716 root 1.48 glBegin (GL_QUADS);
1717 root 1.30
1718 root 1.48 last_name = 0;
1719 root 1.30
1720 root 1.164 mx += self->x;
1721     my += self->y;
1722    
1723 root 1.176 // first pass: determine smooth_max
1724     // rather ugly, if you ask me
1725     // could also be stored inside mapcell and updated on change
1726     memset (smooth_max, 0, sizeof (smooth_max));
1727    
1728     for (y = 0; y < sh; y++)
1729     if (0 <= y + my && y + my < self->rows)
1730     {
1731     maprow *row = self->row + (y + my);
1732    
1733     for (x = 0; x < sw; x++)
1734     if (row->c0 <= x + mx && x + mx < row->c1)
1735     {
1736     mapcell *cell = row->col + (x + mx - row->c0);
1737    
1738 root 1.177 smooth_max[x + 1][y + 1] =
1739     MAX (self->tex [cell->tile [0]].smoothlevel,
1740     MAX (self->tex [cell->tile [1]].smoothlevel,
1741     self->tex [cell->tile [2]].smoothlevel));
1742 root 1.176 }
1743     }
1744    
1745     for (z = 0; z <= 2; z++)
1746     {
1747 root 1.186 memset (smooth_level, 0, sizeof (smooth_level));
1748    
1749 root 1.176 for (y = 0; y < sh; y++)
1750     if (0 <= y + my && y + my < self->rows)
1751     {
1752     maprow *row = self->row + (y + my);
1753    
1754     for (x = 0; x < sw; x++)
1755     if (row->c0 <= x + mx && x + mx < row->c1)
1756     {
1757     mapcell *cell = row->col + (x + mx - row->c0);
1758     tileid tile = cell->tile [z];
1759    
1760     if (tile)
1761     {
1762     maptex tex = self->tex [tile];
1763     int px = (x + 1) * T - tex.w;
1764     int py = (y + 1) * T - tex.h;
1765    
1766     // suppressing texture state switches here
1767     // is only moderately effective, but worth the extra effort
1768     if (last_name != tex.name)
1769     {
1770     if (!tex.name)
1771     tex = self->tex [2]; /* missing, replace by noface */
1772    
1773     glEnd ();
1774     glBindTexture (GL_TEXTURE_2D, last_name = tex.name);
1775     glBegin (GL_QUADS);
1776     }
1777    
1778     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1779     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1780     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1781     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1782    
1783     if (cell->flags && z == 2)
1784     {
1785     if (cell->flags & 1)
1786     {
1787     maptex tex = self->tex [1];
1788     int px = x * T + T * 2 / 32;
1789     int py = y * T - T * 6 / 32;
1790    
1791     glEnd ();
1792     glBindTexture (GL_TEXTURE_2D, last_name = tex.name);
1793     glBegin (GL_QUADS);
1794    
1795     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1796     glTexCoord2f (0 , tex.t); glVertex2f (px , py + T);
1797     glTexCoord2f (tex.s, tex.t); glVertex2f (px + T, py + T);
1798     glTexCoord2f (tex.s, 0 ); glVertex2f (px + T, py );
1799     }
1800     }
1801    
1802     // update smooth hash
1803     if (tex.smoothtile)
1804     {
1805     skey.tile = tex.smoothtile;
1806     skey.level = tex.smoothlevel;
1807    
1808     smooth_level [tex.smoothlevel >> 5] |= ((uint32_t)1) << (tex.smoothlevel & 31);
1809 root 1.30
1810 root 1.176 // add bits to current tile and all neighbours. skey.x|y is
1811     // shifted +1|+1 so we always stay positive.
1812 root 1.30
1813 root 1.180 // bits is ___n cccc CCCC bbbb
1814     // n do not draw borders&corners
1815     // c draw these corners, but...
1816     // C ... not these
1817     // b draw these borders
1818    
1819     // borders: 1 ┃· 2 ━━ 4 ·┃ 8 ··
1820     // ┃· ·· ·┃ ━━
1821    
1822     // corners: 1 ┛· 2 ·┗ 4 ·· 8 ··
1823     // ·· ·· ·┏ ┓·
1824    
1825 root 1.176 // full tile
1826     skey.x = x + 1; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x1000);
1827    
1828     // borders
1829 root 1.180 skey.x = x + 2; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x0091);
1830     skey.x = x + 1; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0032);
1831 root 1.176 skey.x = x ; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x0064);
1832     skey.x = x + 1; skey.y = y ; smooth_or_bits (smooth, &skey, 0x00c8);
1833    
1834     // corners
1835     skey.x = x + 2; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0100);
1836     skey.x = x ; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0200);
1837     skey.x = x ; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0400);
1838     skey.x = x + 2; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0800);
1839     }
1840     }
1841     }
1842     }
1843 root 1.174
1844 root 1.186 // go through all smoothlevels, lowest to highest, then draw.
1845     // this is basically counting sort
1846 root 1.176 {
1847 root 1.186 int w, b;
1848 root 1.30
1849 root 1.186 for (w = 0; w < 256 / 32; ++w)
1850     {
1851     uint32_t smask = smooth_level [w];
1852     if (smask)
1853     for (b = 0; b < 32; ++b)
1854     if (smask & (((uint32_t)1) << b))
1855 root 1.176 {
1856 root 1.186 int level = (w << 5) | b;
1857     HE *he;
1858 root 1.153
1859 root 1.186 hv_iterinit (smooth);
1860     while ((he = hv_iternext (smooth)))
1861 root 1.153 {
1862 root 1.186 smooth_key *skey = (smooth_key *)HeKEY (he);
1863     IV bits = SvIVX (HeVAL (he));
1864 root 1.176
1865 root 1.186 if (!(bits & 0x1000)
1866     && skey->level == level
1867 root 1.191 && level > smooth_max [skey->x][skey->y])
1868 root 1.174 {
1869 root 1.186 maptex tex = self->tex [skey->tile];
1870     int px = (((int)skey->x) - 1) * T;
1871     int py = (((int)skey->y) - 1) * T;
1872     int border = bits & 15;
1873     int corner = (bits >> 8) & ~(bits >> 4) & 15;
1874     float dx = tex.s * .0625f; // 16 images/row
1875     float dy = tex.t * .5f ; // 2 images/column
1876    
1877     // this time naively avoiding texture state changes
1878     // save gobs of state changes.
1879     if (last_name != tex.name)
1880     {
1881     if (!tex.name)
1882     continue; // smoothing not yet available
1883    
1884     glEnd ();
1885     glBindTexture (GL_TEXTURE_2D, last_name = tex.name);
1886     glBegin (GL_QUADS);
1887     }
1888    
1889     if (border)
1890     {
1891     float ox = border * dx;
1892    
1893     glTexCoord2f (ox , 0.f ); glVertex2f (px , py );
1894     glTexCoord2f (ox , dy ); glVertex2f (px , py + T);
1895     glTexCoord2f (ox + dx, dy ); glVertex2f (px + T, py + T);
1896     glTexCoord2f (ox + dx, 0.f ); glVertex2f (px + T, py );
1897     }
1898    
1899     if (corner)
1900     {
1901     float ox = corner * dx;
1902    
1903     glTexCoord2f (ox , dy ); glVertex2f (px , py );
1904     glTexCoord2f (ox , dy * 2.f); glVertex2f (px , py + T);
1905     glTexCoord2f (ox + dx, dy * 2.f); glVertex2f (px + T, py + T);
1906     glTexCoord2f (ox + dx, dy ); glVertex2f (px + T, py );
1907     }
1908 root 1.174 }
1909 root 1.153 }
1910     }
1911 root 1.186 }
1912 root 1.176 }
1913    
1914 root 1.186 hv_clear (smooth);
1915     }
1916 root 1.30
1917     glEnd ();
1918 root 1.32
1919 root 1.34 glDisable (GL_TEXTURE_2D);
1920 root 1.152 glDisable (GL_BLEND);
1921 root 1.143
1922 root 1.145 // top layer: overlays such as the health bar
1923 root 1.143 for (y = 0; y < sh; y++)
1924 root 1.164 if (0 <= y + my && y + my < self->rows)
1925 root 1.143 {
1926 root 1.164 maprow *row = self->row + (y + my);
1927 root 1.143
1928     for (x = 0; x < sw; x++)
1929 root 1.164 if (row->c0 <= x + mx && x + mx < row->c1)
1930 root 1.143 {
1931 root 1.164 mapcell *cell = row->col + (x + mx - row->c0);
1932 root 1.143
1933 root 1.171 int px = x * T;
1934     int py = y * T;
1935 root 1.143
1936     if (cell->stat_hp)
1937     {
1938 root 1.171 int width = cell->stat_width * T;
1939 root 1.174 int thick = (sh * T / 32 + 27) / 28 + 1 + cell->stat_width;
1940 root 1.143
1941 root 1.152 glColor3ub (0, 0, 0);
1942 root 1.151 glRectf (px + 1, py - thick - 2,
1943     px + width - 1, py);
1944 root 1.147
1945 root 1.152 glColor3ub (cell->stat_hp, 255 - cell->stat_hp, 0);
1946 root 1.147 glRectf (px + 2,
1947 root 1.151 py - thick - 1,
1948     px + width - 2 - cell->stat_hp * (width - 4) / 255, py - 1);
1949 root 1.143 }
1950     }
1951     }
1952 root 1.116 }
1953    
1954     void
1955 root 1.133 draw_magicmap (CFPlus::Map self, int dx, int dy, int w, int h, unsigned char *data)
1956 root 1.117 CODE:
1957     {
1958     static float color[16][3] = {
1959 root 1.123 { 0.00F, 0.00F, 0.00F },
1960     { 1.00F, 1.00F, 1.00F },
1961     { 0.00F, 0.00F, 0.55F },
1962     { 1.00F, 0.00F, 0.00F },
1963    
1964     { 1.00F, 0.54F, 0.00F },
1965     { 0.11F, 0.56F, 1.00F },
1966     { 0.93F, 0.46F, 0.00F },
1967     { 0.18F, 0.54F, 0.34F },
1968    
1969     { 0.56F, 0.73F, 0.56F },
1970     { 0.80F, 0.80F, 0.80F },
1971     { 0.55F, 0.41F, 0.13F },
1972     { 0.99F, 0.77F, 0.26F },
1973    
1974     { 0.74F, 0.65F, 0.41F },
1975    
1976     { 0.00F, 1.00F, 1.00F },
1977     { 1.00F, 0.00F, 1.00F },
1978     { 1.00F, 1.00F, 0.00F },
1979 root 1.117 };
1980    
1981     int x, y;
1982    
1983     glEnable (GL_TEXTURE_2D);
1984     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1985     glEnable (GL_BLEND);
1986     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1987     glBegin (GL_QUADS);
1988    
1989     for (y = 0; y < h; y++)
1990     for (x = 0; x < w; x++)
1991     {
1992     unsigned char m = data [x + y * w];
1993    
1994 root 1.118 if (m)
1995     {
1996     float *c = color [m & 15];
1997    
1998     float tx1 = m & 0x40 ? 0.5 : 0.;
1999     float tx2 = tx1 + 0.5;
2000    
2001     glColor4f (c[0], c[1], c[2], 0.75);
2002     glTexCoord2f (tx1, 0.); glVertex2i (x , y );
2003     glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1);
2004     glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1);
2005     glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y );
2006     }
2007 root 1.117 }
2008    
2009     glEnd ();
2010     glDisable (GL_BLEND);
2011     glDisable (GL_TEXTURE_2D);
2012     }
2013    
2014     void
2015 root 1.204 fow_texture (CFPlus::Map self, int mx, int my, int sw, int sh)
2016 root 1.116 PPCODE:
2017     {
2018     int x, y;
2019 root 1.204 int sw1 = sw + 2;
2020     int sh1 = sh + 2;
2021     int sh3 = sh * 3;
2022     int sw34 = (sw * 3 + 3) & ~3;
2023     uint8_t *darkness1 = (uint8_t *)malloc (sw1 * sh1);
2024     SV *darkness3_sv = sv_2mortal (newSV (sw34 * sh3));
2025     uint8_t *darkness3 = (uint8_t *)SvPVX (darkness3_sv);
2026    
2027     SvPOK_only (darkness3_sv);
2028     SvCUR_set (darkness3_sv, sw34 * sh3);
2029 root 1.116
2030 root 1.204 mx += self->x - 1;
2031     my += self->y - 1;
2032 root 1.116
2033 root 1.204 memset (darkness1, 255, sw1 * sh1);
2034    
2035     for (y = 0; y < sh1; y++)
2036 root 1.164 if (0 <= y + my && y + my < self->rows)
2037 root 1.116 {
2038 root 1.164 maprow *row = self->row + (y + my);
2039 root 1.116
2040 root 1.204 for (x = 0; x < sw1; x++)
2041 root 1.164 if (row->c0 <= x + mx && x + mx < row->c1)
2042 root 1.116 {
2043 root 1.164 mapcell *cell = row->col + (x + mx - row->c0);
2044 root 1.116
2045 root 1.204 darkness1 [y * sw1 + x] = cell->darkness
2046 root 1.143 ? 255 - (cell->darkness - 1)
2047 root 1.142 : 255 - FOW_DARKNESS;
2048 root 1.116 }
2049     }
2050 root 1.34
2051 root 1.204 for (y = 0; y < sh; ++y)
2052     for (x = 0; x < sw; ++x)
2053     {
2054     uint8_t d11 = darkness1 [(y ) * sw1 + x ];
2055     uint8_t d21 = darkness1 [(y ) * sw1 + x + 1];
2056     uint8_t d31 = darkness1 [(y ) * sw1 + x + 2];
2057     uint8_t d12 = darkness1 [(y + 1) * sw1 + x ];
2058     uint8_t d22 = darkness1 [(y + 1) * sw1 + x + 1];
2059     uint8_t d32 = darkness1 [(y + 1) * sw1 + x + 2];
2060     uint8_t d13 = darkness1 [(y + 2) * sw1 + x ];
2061     uint8_t d23 = darkness1 [(y + 2) * sw1 + x + 1];
2062     uint8_t d33 = darkness1 [(y + 2) * sw1 + x + 2];
2063    
2064     uint8_t r11 = (d11 + d21 + d12) / 3;
2065     uint8_t r21 = d21;
2066     uint8_t r31 = (d21 + d31 + d32) / 3;
2067    
2068     uint8_t r12 = d12;
2069     uint8_t r22 = d22;
2070     uint8_t r32 = d32;
2071    
2072     uint8_t r13 = (d13 + d23 + d12) / 3;
2073     uint8_t r23 = d23;
2074     uint8_t r33 = (d23 + d33 + d32) / 3;
2075    
2076     darkness3 [(y * 3 ) * sw34 + (x * 3 )] = MAX (d22, r11);
2077     darkness3 [(y * 3 ) * sw34 + (x * 3 + 1)] = MAX (d22, r21);
2078     darkness3 [(y * 3 ) * sw34 + (x * 3 + 2)] = MAX (d22, r31);
2079     darkness3 [(y * 3 + 1) * sw34 + (x * 3 )] = MAX (d22, r12);
2080     darkness3 [(y * 3 + 1) * sw34 + (x * 3 + 1)] = MAX (d22, r22);
2081     darkness3 [(y * 3 + 1) * sw34 + (x * 3 + 2)] = MAX (d22, r32);
2082     darkness3 [(y * 3 + 2) * sw34 + (x * 3 )] = MAX (d22, r13);
2083     darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 1)] = MAX (d22, r23);
2084     darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 2)] = MAX (d22, r33);
2085     }
2086 root 1.201
2087 root 1.204 free (darkness1);
2088 root 1.201
2089 root 1.32 EXTEND (SP, 3);
2090 root 1.204 PUSHs (sv_2mortal (newSViv (sw34)));
2091     PUSHs (sv_2mortal (newSViv (sh3)));
2092     PUSHs (darkness3_sv);
2093 root 1.30 }
2094    
2095 root 1.42 SV *
2096 root 1.133 get_rect (CFPlus::Map self, int x0, int y0, int w, int h)
2097 root 1.42 CODE:
2098     {
2099     int x, y, x1, y1;
2100     SV *data_sv = newSV (w * h * 7 + 5);
2101     uint8_t *data = (uint8_t *)SvPVX (data_sv);
2102    
2103     *data++ = 0; /* version 0 format */
2104     *data++ = w >> 8; *data++ = w;
2105     *data++ = h >> 8; *data++ = h;
2106    
2107     // we need to do this 'cause we don't keep an absolute coord system for rows
2108 root 1.55 // TODO: treat rows as we treat columns
2109 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
2110     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
2111    
2112     x0 += self->x - self->ox;
2113     y0 += self->y - self->oy;
2114    
2115     x1 = x0 + w;
2116     y1 = y0 + h;
2117    
2118     for (y = y0; y < y1; y++)
2119     {
2120     maprow *row = 0 <= y && y < self->rows
2121     ? self->row + y
2122     : 0;
2123    
2124     for (x = x0; x < x1; x++)
2125     {
2126     if (row && row->c0 <= x && x < row->c1)
2127     {
2128     mapcell *cell = row->col + (x - row->c0);
2129     uint8_t flags = 0;
2130    
2131 root 1.174 if (cell->tile [0]) flags |= 1;
2132     if (cell->tile [1]) flags |= 2;
2133     if (cell->tile [2]) flags |= 4;
2134 root 1.42
2135     *data++ = flags;
2136    
2137     if (flags & 1)
2138     {
2139 root 1.174 tileid tile = cell->tile [0];
2140     *data++ = tile >> 8;
2141     *data++ = tile;
2142 root 1.42 }
2143    
2144     if (flags & 2)
2145     {
2146 root 1.174 tileid tile = cell->tile [1];
2147     *data++ = tile >> 8;
2148     *data++ = tile;
2149 root 1.42 }
2150    
2151     if (flags & 4)
2152     {
2153 root 1.174 tileid tile = cell->tile [2];
2154     *data++ = tile >> 8;
2155     *data++ = tile;
2156 root 1.42 }
2157     }
2158     else
2159     *data++ = 0;
2160     }
2161     }
2162    
2163     SvPOK_only (data_sv);
2164     SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
2165     RETVAL = data_sv;
2166     }
2167     OUTPUT:
2168     RETVAL
2169    
2170     void
2171 root 1.133 set_rect (CFPlus::Map self, int x0, int y0, uint8_t *data)
2172 root 1.42 PPCODE:
2173     {
2174     int x, y, z;
2175 root 1.48 int w, h;
2176 root 1.42 int x1, y1;
2177    
2178     if (*data++ != 0)
2179     return; /* version mismatch */
2180    
2181 root 1.48 w = *data++ << 8; w |= *data++;
2182     h = *data++ << 8; h |= *data++;
2183 root 1.42
2184     // we need to do this 'cause we don't keep an absolute coord system for rows
2185 root 1.55 // TODO: treat rows as we treat columns
2186 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
2187     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
2188    
2189     x0 += self->x - self->ox;
2190     y0 += self->y - self->oy;
2191    
2192     x1 = x0 + w;
2193     y1 = y0 + h;
2194    
2195     for (y = y0; y < y1; y++)
2196     {
2197     maprow *row = map_get_row (self, y);
2198    
2199     for (x = x0; x < x1; x++)
2200     {
2201     uint8_t flags = *data++;
2202    
2203     if (flags)
2204     {
2205     mapcell *cell = row_get_cell (row, x);
2206 root 1.174 tileid tile[3] = { 0, 0, 0 };
2207 root 1.42
2208 root 1.174 if (flags & 1) { tile[0] = *data++ << 8; tile[0] |= *data++; }
2209     if (flags & 2) { tile[1] = *data++ << 8; tile[1] |= *data++; }
2210     if (flags & 4) { tile[2] = *data++ << 8; tile[2] |= *data++; }
2211 root 1.42
2212 root 1.143 if (cell->darkness == 0)
2213 root 1.42 {
2214 root 1.142 cell->darkness = 0;
2215 root 1.42
2216     for (z = 0; z <= 2; z++)
2217     {
2218 root 1.174 tileid t = tile [z];
2219    
2220 root 1.175 if (t >= self->texs || (t && !self->tex [t].name))
2221 root 1.174 {
2222     XPUSHs (sv_2mortal (newSViv (t)));
2223     need_texid (self, t);
2224     }
2225 root 1.42
2226 root 1.174 cell->tile [z] = t;
2227 root 1.42 }
2228     }
2229     }
2230     }
2231     }
2232     }
2233    
2234 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::MixChunk
2235 root 1.52
2236 root 1.205 PROTOTYPES: DISABLE
2237    
2238 root 1.133 CFPlus::MixChunk
2239 root 1.52 new_from_file (SV *class, char *path)
2240     CODE:
2241     RETVAL = Mix_LoadWAV (path);
2242     OUTPUT:
2243     RETVAL
2244    
2245     void
2246 root 1.133 DESTROY (CFPlus::MixChunk self)
2247 root 1.52 CODE:
2248     Mix_FreeChunk (self);
2249    
2250     int
2251 root 1.133 volume (CFPlus::MixChunk self, int volume = -1)
2252 root 1.52 CODE:
2253     RETVAL = Mix_VolumeChunk (self, volume);
2254     OUTPUT:
2255     RETVAL
2256    
2257     int
2258 root 1.133 play (CFPlus::MixChunk self, int channel = -1, int loops = 0, int ticks = -1)
2259 root 1.52 CODE:
2260     RETVAL = Mix_PlayChannelTimed (channel, self, loops, ticks);
2261     OUTPUT:
2262     RETVAL
2263    
2264 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::MixMusic
2265 root 1.52
2266     int
2267     volume (int volume = -1)
2268 root 1.205 PROTOTYPE: ;$
2269 root 1.52 CODE:
2270     RETVAL = Mix_VolumeMusic (volume);
2271     OUTPUT:
2272     RETVAL
2273    
2274 root 1.194 int
2275     fade_out (int ms)
2276     CODE:
2277     RETVAL = Mix_FadeOutMusic (ms);
2278     OUTPUT:
2279     RETVAL
2280    
2281 root 1.133 CFPlus::MixMusic
2282 root 1.52 new_from_file (SV *class, char *path)
2283     CODE:
2284     RETVAL = Mix_LoadMUS (path);
2285     OUTPUT:
2286     RETVAL
2287    
2288     void
2289 root 1.133 DESTROY (CFPlus::MixMusic self)
2290 root 1.52 CODE:
2291     Mix_FreeMusic (self);
2292    
2293     int
2294 root 1.133 play (CFPlus::MixMusic self, int loops = -1)
2295 root 1.52 CODE:
2296     RETVAL = Mix_PlayMusic (self, loops);
2297     OUTPUT:
2298     RETVAL
2299    
2300 root 1.195 int
2301     fade_in_pos (CFPlus::MixMusic self, int loops, int ms, double position)
2302     CODE:
2303     RETVAL = Mix_FadeInMusicPos (self, loops, ms, position);
2304     OUTPUT:
2305     RETVAL
2306    
2307 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::OpenGL
2308 root 1.54
2309 root 1.205 PROTOTYPES: ENABLE
2310    
2311 root 1.54 BOOT:
2312     {
2313 root 1.133 HV *stash = gv_stashpv ("CFPlus::OpenGL", 1);
2314 root 1.54 static const struct {
2315     const char *name;
2316     IV iv;
2317     } *civ, const_iv[] = {
2318     # define const_iv(name) { # name, (IV)name }
2319 root 1.199 const_iv (GL_VENDOR),
2320     const_iv (GL_VERSION),
2321     const_iv (GL_EXTENSIONS),
2322 root 1.54 const_iv (GL_COLOR_MATERIAL),
2323     const_iv (GL_SMOOTH),
2324     const_iv (GL_FLAT),
2325 root 1.69 const_iv (GL_DITHER),
2326 root 1.54 const_iv (GL_BLEND),
2327 root 1.89 const_iv (GL_CULL_FACE),
2328 root 1.69 const_iv (GL_SCISSOR_TEST),
2329 root 1.89 const_iv (GL_DEPTH_TEST),
2330     const_iv (GL_ALPHA_TEST),
2331     const_iv (GL_NORMALIZE),
2332     const_iv (GL_RESCALE_NORMAL),
2333 root 1.119 const_iv (GL_FRONT),
2334     const_iv (GL_BACK),
2335 root 1.206 const_iv (GL_AUX0),
2336 root 1.54 const_iv (GL_AND),
2337 root 1.67 const_iv (GL_ONE),
2338     const_iv (GL_ZERO),
2339 root 1.54 const_iv (GL_SRC_ALPHA),
2340 root 1.104 const_iv (GL_DST_ALPHA),
2341 root 1.54 const_iv (GL_ONE_MINUS_SRC_ALPHA),
2342 root 1.67 const_iv (GL_ONE_MINUS_DST_ALPHA),
2343 root 1.104 const_iv (GL_SRC_ALPHA_SATURATE),
2344 root 1.54 const_iv (GL_RGB),
2345     const_iv (GL_RGBA),
2346 root 1.115 const_iv (GL_RGBA4),
2347     const_iv (GL_RGBA8),
2348     const_iv (GL_RGB5_A1),
2349 root 1.54 const_iv (GL_UNSIGNED_BYTE),
2350 root 1.89 const_iv (GL_UNSIGNED_SHORT),
2351     const_iv (GL_UNSIGNED_INT),
2352 root 1.54 const_iv (GL_ALPHA),
2353 root 1.86 const_iv (GL_INTENSITY),
2354 root 1.76 const_iv (GL_LUMINANCE),
2355 root 1.86 const_iv (GL_LUMINANCE_ALPHA),
2356 root 1.54 const_iv (GL_FLOAT),
2357     const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
2358     const_iv (GL_COMPILE),
2359 root 1.199 const_iv (GL_PROXY_TEXTURE_1D),
2360     const_iv (GL_PROXY_TEXTURE_2D),
2361 root 1.54 const_iv (GL_TEXTURE_1D),
2362     const_iv (GL_TEXTURE_2D),
2363     const_iv (GL_TEXTURE_ENV),
2364     const_iv (GL_TEXTURE_MAG_FILTER),
2365     const_iv (GL_TEXTURE_MIN_FILTER),
2366     const_iv (GL_TEXTURE_ENV_MODE),
2367     const_iv (GL_TEXTURE_WRAP_S),
2368     const_iv (GL_TEXTURE_WRAP_T),
2369 root 1.98 const_iv (GL_REPEAT),
2370 root 1.54 const_iv (GL_CLAMP),
2371 root 1.98 const_iv (GL_CLAMP_TO_EDGE),
2372 root 1.54 const_iv (GL_NEAREST),
2373     const_iv (GL_LINEAR),
2374 root 1.57 const_iv (GL_NEAREST_MIPMAP_NEAREST),
2375     const_iv (GL_LINEAR_MIPMAP_NEAREST),
2376     const_iv (GL_NEAREST_MIPMAP_LINEAR),
2377     const_iv (GL_LINEAR_MIPMAP_LINEAR),
2378     const_iv (GL_GENERATE_MIPMAP),
2379 root 1.54 const_iv (GL_MODULATE),
2380 root 1.69 const_iv (GL_DECAL),
2381 root 1.54 const_iv (GL_REPLACE),
2382 root 1.89 const_iv (GL_DEPTH_BUFFER_BIT),
2383 root 1.54 const_iv (GL_COLOR_BUFFER_BIT),
2384     const_iv (GL_PROJECTION),
2385     const_iv (GL_MODELVIEW),
2386     const_iv (GL_COLOR_LOGIC_OP),
2387 root 1.69 const_iv (GL_SEPARABLE_2D),
2388 root 1.54 const_iv (GL_CONVOLUTION_2D),
2389     const_iv (GL_CONVOLUTION_BORDER_MODE),
2390     const_iv (GL_CONSTANT_BORDER),
2391 root 1.208 const_iv (GL_POINTS),
2392 root 1.54 const_iv (GL_LINES),
2393 root 1.138 const_iv (GL_LINE_STRIP),
2394 root 1.89 const_iv (GL_LINE_LOOP),
2395 root 1.54 const_iv (GL_QUADS),
2396 root 1.89 const_iv (GL_QUAD_STRIP),
2397     const_iv (GL_TRIANGLES),
2398     const_iv (GL_TRIANGLE_STRIP),
2399     const_iv (GL_TRIANGLE_FAN),
2400 root 1.208 const_iv (GL_POLYGON),
2401 root 1.54 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
2402 root 1.206 const_iv (GL_POINT_SMOOTH_HINT),
2403     const_iv (GL_LINE_SMOOTH_HINT),
2404     const_iv (GL_POLYGON_SMOOTH_HINT),
2405     const_iv (GL_GENERATE_MIPMAP_HINT),
2406 root 1.54 const_iv (GL_FASTEST),
2407 root 1.206 const_iv (GL_DONT_CARE),
2408     const_iv (GL_NICEST),
2409 root 1.89 const_iv (GL_V2F),
2410     const_iv (GL_V3F),
2411     const_iv (GL_T2F_V3F),
2412     const_iv (GL_T2F_N3F_V3F),
2413 root 1.54 # undef const_iv
2414     };
2415    
2416     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
2417     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
2418 root 1.188
2419     texture_av = newAV ();
2420     AvREAL_off (texture_av);
2421 root 1.54 }
2422    
2423 root 1.97 char *
2424     gl_vendor ()
2425     CODE:
2426     RETVAL = (char *)glGetString (GL_VENDOR);
2427     OUTPUT:
2428     RETVAL
2429    
2430     char *
2431     gl_version ()
2432     CODE:
2433     RETVAL = (char *)glGetString (GL_VERSION);
2434     OUTPUT:
2435     RETVAL
2436    
2437     char *
2438     gl_extensions ()
2439     CODE:
2440     RETVAL = (char *)glGetString (GL_EXTENSIONS);
2441     OUTPUT:
2442     RETVAL
2443    
2444 root 1.201 const char *glGetString (GLenum pname)
2445 root 1.199
2446     GLint glGetInteger (GLenum pname)
2447     CODE:
2448     glGetIntegerv (pname, &RETVAL);
2449     OUTPUT:
2450     RETVAL
2451    
2452     GLdouble glGetDouble (GLenum pname)
2453     CODE:
2454     glGetDoublev (pname, &RETVAL);
2455     OUTPUT:
2456     RETVAL
2457    
2458 root 1.54 int glGetError ()
2459    
2460 root 1.114 void glFinish ()
2461    
2462 root 1.54 void glClear (int mask)
2463    
2464     void glClearColor (float r, float g, float b, float a = 1.0)
2465     PROTOTYPE: @
2466    
2467     void glEnable (int cap)
2468    
2469     void glDisable (int cap)
2470    
2471     void glShadeModel (int mode)
2472    
2473     void glHint (int target, int mode)
2474    
2475     void glBlendFunc (int sfactor, int dfactor)
2476    
2477 root 1.103 void glBlendFuncSeparate (int sa, int da, int saa, int daa)
2478     CODE:
2479     gl_BlendFuncSeparate (sa, da, saa, daa);
2480    
2481 root 1.89 void glDepthMask (int flag)
2482    
2483 root 1.54 void glLogicOp (int opcode)
2484    
2485 root 1.68 void glColorMask (int red, int green, int blue, int alpha)
2486    
2487 root 1.54 void glMatrixMode (int mode)
2488    
2489     void glPushMatrix ()
2490    
2491     void glPopMatrix ()
2492    
2493     void glLoadIdentity ()
2494    
2495 root 1.119 void glDrawBuffer (int buffer)
2496    
2497     void glReadBuffer (int buffer)
2498    
2499 root 1.90 # near_ and far_ are due to microsofts buggy "c" compiler
2500     void glFrustum (double left, double right, double bottom, double top, double near_, double far_)
2501    
2502     # near_ and far_ are due to microsofts buggy "c" compiler
2503 root 1.64 void glOrtho (double left, double right, double bottom, double top, double near_, double far_)
2504 root 1.54
2505 root 1.208 PROTOTYPES: DISABLE
2506    
2507 root 1.54 void glViewport (int x, int y, int width, int height)
2508    
2509 root 1.69 void glScissor (int x, int y, int width, int height)
2510    
2511 root 1.54 void glTranslate (float x, float y, float z = 0.)
2512     CODE:
2513     glTranslatef (x, y, z);
2514    
2515 root 1.62 void glScale (float x, float y, float z = 1.)
2516 root 1.54 CODE:
2517     glScalef (x, y, z);
2518    
2519     void glRotate (float angle, float x, float y, float z)
2520     CODE:
2521     glRotatef (angle, x, y, z);
2522    
2523     void glColor (float r, float g, float b, float a = 1.0)
2524 root 1.103 ALIAS:
2525     glColor_premultiply = 1
2526 root 1.54 CODE:
2527 root 1.103 if (ix)
2528     {
2529     r *= a;
2530     g *= a;
2531     b *= a;
2532     }
2533 root 1.90 // microsoft visual "c" rounds instead of truncating...
2534 root 1.130 glColor4f (r, g, b, a);
2535 root 1.54
2536 root 1.91 void glRasterPos (float x, float y, float z = 0.)
2537     CODE:
2538     glRasterPos3f (0, 0, z);
2539     glBitmap (0, 0, 0, 0, x, y, 0);
2540    
2541 root 1.54 void glVertex (float x, float y, float z = 0.)
2542     CODE:
2543     glVertex3f (x, y, z);
2544    
2545     void glTexCoord (float s, float t)
2546     CODE:
2547     glTexCoord2f (s, t);
2548    
2549 root 1.208 PROTOTYPES: ENABLE
2550    
2551     void glBegin (int mode)
2552    
2553     void glEnd ()
2554    
2555     void glPointSize (GLfloat size)
2556    
2557     void glLineWidth (GLfloat width)
2558    
2559     void glInterleavedArrays (int format, int stride, char *data)
2560    
2561     void glDrawElements (int mode, int count, int type, char *indices)
2562    
2563     # 1.2 void glDrawRangeElements (int mode, int start, int end
2564    
2565 root 1.54 void glTexEnv (int target, int pname, float param)
2566     CODE:
2567     glTexEnvf (target, pname, param);
2568    
2569     void glTexParameter (int target, int pname, float param)
2570     CODE:
2571     glTexParameterf (target, pname, param);
2572    
2573     void glBindTexture (int target, int name)
2574    
2575     void glConvolutionParameter (int target, int pname, float params)
2576     CODE:
2577 root 1.103 if (gl.ConvolutionParameterf)
2578     gl.ConvolutionParameterf (target, pname, params);
2579 root 1.54
2580     void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
2581 root 1.64 CODE:
2582 root 1.103 if (gl.ConvolutionFilter2D)
2583     gl.ConvolutionFilter2D (target, internalformat, width, height, format, type, data);
2584 root 1.54
2585 root 1.69 void glSeparableFilter2D (int target, int internalformat, int width, int height, int format, int type, char *row, char *column)
2586     CODE:
2587 root 1.103 if (gl.SeparableFilter2D)
2588     gl.SeparableFilter2D (target, internalformat, width, height, format, type, row, column);
2589 root 1.69
2590 root 1.54 void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data)
2591    
2592     void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
2593    
2594 root 1.91 void glDrawPixels (int width, int height, int format, int type, char *pixels)
2595 root 1.68
2596 root 1.199 void glPixelZoom (float x, float y)
2597    
2598 root 1.68 void glCopyPixels (int x, int y, int width, int height, int type = GL_COLOR)
2599    
2600 root 1.54 int glGenTexture ()
2601     CODE:
2602 root 1.192 RETVAL = gen_texture ();
2603 root 1.54 OUTPUT:
2604     RETVAL
2605    
2606     void glDeleteTexture (int name)
2607     CODE:
2608 root 1.192 del_texture (name);
2609    
2610 root 1.54 int glGenList ()
2611     CODE:
2612     RETVAL = glGenLists (1);
2613     OUTPUT:
2614     RETVAL
2615    
2616     void glDeleteList (int list)
2617     CODE:
2618     glDeleteLists (list, 1);
2619    
2620     void glNewList (int list, int mode = GL_COMPILE)
2621    
2622     void glEndList ()
2623    
2624     void glCallList (int list)
2625    
2626 root 1.207 MODULE = CFPlus PACKAGE = CFPlus::UI::Base
2627    
2628     PROTOTYPES: DISABLE
2629    
2630     void
2631     find_widget (SV *widget, NV x, NV y)
2632     PPCODE:
2633     {
2634     if (within_widget (widget, x, y))
2635     XPUSHs (widget);
2636     }
2637