ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.79
Committed: Sun May 14 22:24:14 2006 UTC (18 years ago) by root
Branch: MAIN
Changes since 1.78: +18 -6 lines
Log Message:
improved win32 support and enable auto-hinting (cairo enforces auto-hinting it seems, so be consistent)

File Contents

# Content
1 #ifdef _WIN32
2 # define _WIN32_WINNT 0x0500 // needed to get win2000 api calls
3 # include <malloc.h>
4 # include <windows.h>
5 # pragma warning(disable:4244)
6 #endif
7
8 #include "EXTERN.h"
9 #include "perl.h"
10 #include "XSUB.h"
11
12 #include <string.h>
13 #include <stdio.h>
14
15 #include <SDL.h>
16 #include <SDL_endian.h>
17 #include <SDL_image.h>
18 #include <SDL_mixer.h>
19 #include <SDL_opengl.h>
20
21 #include <glib/gmacros.h>
22
23 #include <pango/pango.h>
24 #include <pango/pangofc-fontmap.h>
25 #include <pango/pangoft2.h>
26 #include <pango/pangocairo.h>
27
28 #ifndef _WIN32
29 # include <sys/types.h>
30 # include <sys/socket.h>
31 # include <netinet/in.h>
32 # include <netinet/tcp.h>
33 # include <inttypes.h>
34 #else
35 typedef unsigned char uint8_t;
36 typedef unsigned short uint16_t;
37 typedef unsigned int uint32_t;
38 typedef signed char int8_t;
39 typedef signed short int16_t;
40 typedef signed int int32_t;
41 #endif
42
43 #include "glext.h"
44
45 #define FOW_DARKNESS 32
46
47 #define MAP_EXTEND_X 32
48 #define MAP_EXTEND_Y 512
49
50 #define MIN_FONT_HEIGHT 10
51
52 #define GL_CALL(type,func,args) \
53 { \
54 static int init_; \
55 static type fptr_; \
56 \
57 if (!init_) \
58 { \
59 init_ = 1; \
60 fptr_ = (type)SDL_GL_GetProcAddress (# func); \
61 } \
62 \
63 if (fptr_) \
64 fptr_ args; \
65 }
66
67 typedef Mix_Chunk *CFClient__MixChunk;
68 typedef Mix_Music *CFClient__MixMusic;
69
70 typedef PangoFontDescription *CFClient__Font;
71
72 typedef struct cf_layout {
73 PangoLayout *pl; // either derived from a cairo or ft2 context
74 int rgba; // wether we use rgba (cairo) or grayscale (ft2)
75 float r, g, b, a; // default color for rgba mode
76 int base_height;
77 CFClient__Font font;
78 } *CFClient__Layout;
79
80 static CFClient__Font default_font;
81 static PangoContext *ft2_context, *cairo_context;
82 static PangoFontMap *ft2_fontmap, *cairo_fontmap;
83
84 static void
85 substitute_func (FcPattern *pattern, gpointer data)
86 {
87 FcPatternAddBool (pattern, FC_HINTING , 1);
88 FcPatternAddBool (pattern, FC_AUTOHINT, 1);
89 }
90
91 static void
92 layout_update_font (CFClient__Layout self)
93 {
94 /* use a random scale factor to account for unknown descenders, 0.8 works
95 * reasonably well with bitstream vera
96 */
97 PangoFontDescription *font = self->font ? self->font : default_font;
98
99 pango_font_description_set_absolute_size (font,
100 MAX (MIN_FONT_HEIGHT, self->base_height) * (PANGO_SCALE * 8 / 10));
101
102 pango_layout_set_font_description (self->pl, font);
103 }
104
105 static void
106 layout_get_pixel_size (CFClient__Layout self, int *w, int *h)
107 {
108 pango_layout_get_pixel_size (self->pl, w, h);
109
110 if (!*w) *w = 1;
111 if (!*h) *h = 1;
112
113 *w = (*w + 3) & ~3;
114 }
115
116 typedef uint16_t mapface;
117
118 typedef struct {
119 GLint name;
120 int w, h;
121 float s, t;
122 uint8_t r, g, b, a;
123 } maptex;
124
125 typedef struct {
126 int16_t darkness;
127 mapface face[3];
128 } mapcell;
129
130 typedef struct {
131 int32_t c0, c1;
132 mapcell *col;
133 } maprow;
134
135 typedef struct map {
136 int x, y, w, h;
137 int ox, oy; /* offset to virtual global coordinate system */
138 int faces;
139 mapface *face;
140
141 int texs;
142 maptex *tex;
143
144 int32_t rows;
145 maprow *row;
146 } *CFClient__Map;
147
148 static char *
149 prepend (char *ptr, int sze, int inc)
150 {
151 char *p;
152
153 New (0, p, sze + inc, char);
154 Zero (p, inc, char);
155 Move (ptr, p + inc, sze, char);
156 Safefree (ptr);
157
158 return p;
159 }
160
161 static char *
162 append (char *ptr, int sze, int inc)
163 {
164 Renew (ptr, sze + inc, char);
165 Zero (ptr + sze, inc, char);
166
167 return ptr;
168 }
169
170 #define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
171 #define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
172
173 static maprow *
174 map_get_row (CFClient__Map self, int y)
175 {
176 if (0 > y)
177 {
178 int extend = - y + MAP_EXTEND_Y;
179 Prepend (maprow, self->row, self->rows, extend);
180
181 self->rows += extend;
182 self->y += extend;
183 y += extend;
184 }
185 else if (y >= self->rows)
186 {
187 int extend = y - self->rows + MAP_EXTEND_Y;
188 Append (maprow, self->row, self->rows, extend);
189 self->rows += extend;
190 }
191
192 return self->row + y;
193 }
194
195 static mapcell *
196 row_get_cell (maprow *row, int x)
197 {
198 if (!row->col)
199 {
200 Newz (0, row->col, MAP_EXTEND_X, mapcell);
201 row->c0 = x - MAP_EXTEND_X / 4;
202 row->c1 = row->c0 + MAP_EXTEND_X;
203 }
204
205 if (row->c0 > x)
206 {
207 int extend = row->c0 - x + MAP_EXTEND_X;
208 Prepend (mapcell, row->col, row->c1 - row->c0, extend);
209 row->c0 -= extend;
210 }
211 else if (x >= row->c1)
212 {
213 int extend = x - row->c1 + MAP_EXTEND_X;
214 Append (mapcell, row->col, row->c1 - row->c0, extend);
215 row->c1 += extend;
216 }
217
218 return row->col + (x - row->c0);
219 }
220
221 static mapcell *
222 map_get_cell (CFClient__Map self, int x, int y)
223 {
224 return row_get_cell (map_get_row (self, y), x);
225 }
226
227 static void
228 map_clear (CFClient__Map self)
229 {
230 int r;
231
232 for (r = 0; r < self->rows; r++)
233 Safefree (self->row[r].col);
234
235 Safefree (self->row);
236
237 self->x = 0;
238 self->y = 0;
239 self->ox = 0;
240 self->oy = 0;
241 self->row = 0;
242 self->rows = 0;
243 }
244
245 static void
246 map_blank (CFClient__Map self, int x0, int y0, int w, int h)
247 {
248 int x, y;
249 maprow *row;
250
251 for (y = y0; y < y0 + h; y++)
252 if (y >= 0)
253 {
254 if (y >= self->rows)
255 break;
256
257 row = self->row + y;
258
259 for (x = x0; x < x0 + w; x++)
260 if (x >= row->c0)
261 {
262 if (x >= row->c1)
263 break;
264
265 row->col[x - row->c0].darkness = -1;
266 }
267 }
268 }
269
270 static void
271 music_finished (void)
272 {
273 SDL_UserEvent ev;
274
275 ev.type = SDL_USEREVENT;
276 ev.code = 0;
277 ev.data1 = 0;
278 ev.data2 = 0;
279
280 SDL_PushEvent ((SDL_Event *)&ev);
281 }
282
283 static void
284 channel_finished (int channel)
285 {
286 SDL_UserEvent ev;
287
288 ev.type = SDL_USEREVENT;
289 ev.code = 1;
290 ev.data1 = (void *)(long)channel;
291 ev.data2 = 0;
292
293 SDL_PushEvent ((SDL_Event *)&ev);
294 }
295
296 MODULE = CFClient PACKAGE = CFClient
297
298 PROTOTYPES: ENABLE
299
300 BOOT:
301 {
302 HV *stash = gv_stashpv ("CFClient", 1);
303 static const struct {
304 const char *name;
305 IV iv;
306 } *civ, const_iv[] = {
307 # define const_iv(name) { # name, (IV)name }
308 const_iv (SDL_ACTIVEEVENT),
309 const_iv (SDL_KEYDOWN),
310 const_iv (SDL_KEYUP),
311 const_iv (SDL_MOUSEMOTION),
312 const_iv (SDL_MOUSEBUTTONDOWN),
313 const_iv (SDL_MOUSEBUTTONUP),
314 const_iv (SDL_JOYAXISMOTION),
315 const_iv (SDL_JOYBALLMOTION),
316 const_iv (SDL_JOYHATMOTION),
317 const_iv (SDL_JOYBUTTONDOWN),
318 const_iv (SDL_JOYBUTTONUP),
319 const_iv (SDL_QUIT),
320 const_iv (SDL_SYSWMEVENT),
321 const_iv (SDL_EVENT_RESERVEDA),
322 const_iv (SDL_EVENT_RESERVEDB),
323 const_iv (SDL_VIDEORESIZE),
324 const_iv (SDL_VIDEOEXPOSE),
325 const_iv (SDL_USEREVENT),
326 const_iv (SDLK_KP0),
327 const_iv (SDLK_KP1),
328 const_iv (SDLK_KP2),
329 const_iv (SDLK_KP3),
330 const_iv (SDLK_KP4),
331 const_iv (SDLK_KP5),
332 const_iv (SDLK_KP6),
333 const_iv (SDLK_KP7),
334 const_iv (SDLK_KP8),
335 const_iv (SDLK_KP9),
336 const_iv (SDLK_KP_PERIOD),
337 const_iv (SDLK_KP_DIVIDE),
338 const_iv (SDLK_KP_MULTIPLY),
339 const_iv (SDLK_KP_MINUS),
340 const_iv (SDLK_KP_PLUS),
341 const_iv (SDLK_KP_ENTER),
342 const_iv (SDLK_KP_EQUALS),
343 const_iv (SDLK_UP),
344 const_iv (SDLK_DOWN),
345 const_iv (SDLK_RIGHT),
346 const_iv (SDLK_LEFT),
347 const_iv (SDLK_INSERT),
348 const_iv (SDLK_HOME),
349 const_iv (SDLK_END),
350 const_iv (SDLK_PAGEUP),
351 const_iv (SDLK_PAGEDOWN),
352 const_iv (SDLK_F1),
353 const_iv (SDLK_F2),
354 const_iv (SDLK_F3),
355 const_iv (SDLK_F4),
356 const_iv (SDLK_F5),
357 const_iv (SDLK_F6),
358 const_iv (SDLK_F7),
359 const_iv (SDLK_F8),
360 const_iv (SDLK_F9),
361 const_iv (SDLK_F10),
362 const_iv (SDLK_F11),
363 const_iv (SDLK_F12),
364 const_iv (SDLK_F13),
365 const_iv (SDLK_F14),
366 const_iv (SDLK_F15),
367 const_iv (SDLK_NUMLOCK),
368 const_iv (SDLK_CAPSLOCK),
369 const_iv (SDLK_SCROLLOCK),
370 const_iv (SDLK_RSHIFT),
371 const_iv (SDLK_LSHIFT),
372 const_iv (SDLK_RCTRL),
373 const_iv (SDLK_LCTRL),
374 const_iv (SDLK_RALT),
375 const_iv (SDLK_LALT),
376 const_iv (SDLK_RMETA),
377 const_iv (SDLK_LMETA),
378 const_iv (SDLK_LSUPER),
379 const_iv (SDLK_RSUPER),
380 const_iv (SDLK_MODE),
381 const_iv (SDLK_COMPOSE),
382 const_iv (SDLK_HELP),
383 const_iv (SDLK_PRINT),
384 const_iv (SDLK_SYSREQ),
385 const_iv (SDLK_BREAK),
386 const_iv (SDLK_MENU),
387 const_iv (SDLK_POWER),
388 const_iv (SDLK_EURO),
389 const_iv (SDLK_UNDO),
390 const_iv (KMOD_NONE),
391 const_iv (KMOD_LSHIFT),
392 const_iv (KMOD_RSHIFT),
393 const_iv (KMOD_LCTRL),
394 const_iv (KMOD_RCTRL),
395 const_iv (KMOD_LALT),
396 const_iv (KMOD_RALT),
397 const_iv (KMOD_LMETA),
398 const_iv (KMOD_RMETA),
399 const_iv (KMOD_NUM),
400 const_iv (KMOD_CAPS),
401 const_iv (KMOD_MODE),
402 const_iv (KMOD_CTRL),
403 const_iv (KMOD_SHIFT),
404 const_iv (KMOD_ALT),
405 const_iv (KMOD_META)
406 # undef const_iv
407 };
408
409 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
410 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
411 }
412
413 void
414 pango_init ()
415 CODE:
416 {
417 // delayed, so it can pick up new fonts added by AddFontResourceEx
418 ft2_fontmap = pango_ft2_font_map_new ();
419 pango_ft2_font_map_set_default_substitute ((PangoFT2FontMap *)ft2_fontmap, substitute_func, 0, 0);
420 ft2_context = pango_ft2_font_map_create_context ((PangoFT2FontMap *)ft2_fontmap);
421
422 cairo_fontmap = pango_cairo_font_map_get_default ();
423 cairo_context = pango_cairo_font_map_create_context ((PangoCairoFontMap *)cairo_fontmap);
424 }
425
426 int
427 SDL_Init (U32 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO)
428
429 void
430 SDL_Quit ()
431
432 void
433 SDL_ListModes ()
434 PPCODE:
435 {
436 SDL_Rect **m;
437
438 SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5);
439 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5);
440 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5);
441 SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 1);
442
443 SDL_GL_SetAttribute (SDL_GL_ACCUM_RED_SIZE, 0);
444 SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0);
445 SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE, 0);
446 SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0);
447
448 SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
449 SDL_GL_SetAttribute (SDL_GL_BUFFER_SIZE, 15);
450 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 0);
451
452 SDL_EnableUNICODE (1);
453 SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
454
455 m = SDL_ListModes (0, SDL_FULLSCREEN | SDL_OPENGL);
456
457 if (m && m != (SDL_Rect **)-1)
458 while (*m)
459 {
460 AV *av = newAV ();
461 av_push (av, newSViv ((*m)->w));
462 av_push (av, newSViv ((*m)->h));
463 XPUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
464
465 ++m;
466 }
467 }
468
469 int
470 SDL_SetVideoMode (int w, int h, int fullscreen)
471 CODE:
472 RETVAL = !!SDL_SetVideoMode (
473 w, h, 0, SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0)
474 );
475 SDL_WM_SetCaption ("Crossfire+ Client " VERSION, "Crossfire+");
476 OUTPUT:
477 RETVAL
478
479 void
480 SDL_GL_SwapBuffers ()
481
482 void
483 SDL_PollEvent ()
484 PPCODE:
485 {
486 SDL_Event ev;
487
488 while (SDL_PollEvent (&ev))
489 {
490 HV *hv = newHV ();
491 hv_store (hv, "type", 4, newSViv (ev.type), 0);
492
493 switch (ev.type)
494 {
495 case SDL_KEYDOWN:
496 case SDL_KEYUP:
497 hv_store (hv, "state", 5, newSViv (ev.key.state), 0);
498 hv_store (hv, "sym", 3, newSViv (ev.key.keysym.sym), 0);
499 hv_store (hv, "mod", 3, newSViv (ev.key.keysym.mod), 0);
500 hv_store (hv, "unicode", 7, newSViv (ev.key.keysym.unicode), 0);
501 break;
502
503 case SDL_ACTIVEEVENT:
504 hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0);
505 hv_store (hv, "state", 5, newSViv (ev.active.state), 0);
506 break;
507
508 case SDL_MOUSEMOTION:
509 hv_store (hv, "state", 5, newSViv (ev.motion.state), 0);
510 hv_store (hv, "x", 1, newSViv (ev.motion.x), 0);
511 hv_store (hv, "y", 1, newSViv (ev.motion.y), 0);
512 hv_store (hv, "xrel", 4, newSViv (ev.motion.xrel), 0);
513 hv_store (hv, "yrel", 4, newSViv (ev.motion.yrel), 0);
514 break;
515
516 case SDL_MOUSEBUTTONDOWN:
517 case SDL_MOUSEBUTTONUP:
518 hv_store (hv, "button", 6, newSViv (ev.button.button), 0);
519 hv_store (hv, "state", 5, newSViv (ev.button.state), 0);
520 hv_store (hv, "x", 1, newSViv (ev.button.x), 0);
521 hv_store (hv, "y", 1, newSViv (ev.button.y), 0);
522 break;
523
524 case SDL_USEREVENT:
525 hv_store (hv, "code", 4, newSViv (ev.user.code), 0);
526 hv_store (hv, "data1", 5, newSViv ((IV)ev.user.data1), 0);
527 hv_store (hv, "data2", 5, newSViv ((IV)ev.user.data2), 0);
528 break;
529 }
530
531 XPUSHs (sv_2mortal (newRV_noinc ((SV *)hv)));
532 }
533 }
534
535 int
536 Mix_OpenAudio (int frequency = 48000, int format = MIX_DEFAULT_FORMAT, int channels = 1, int chunksize = 2048)
537 POSTCALL:
538 Mix_HookMusicFinished (music_finished);
539 Mix_ChannelFinished (channel_finished);
540
541 void
542 Mix_CloseAudio ()
543
544 int
545 Mix_AllocateChannels (int numchans = -1)
546
547 void
548 lowdelay (int fd, int val = 1)
549 CODE:
550 #ifndef _WIN32
551 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof (val));
552 #endif
553
554 char *
555 gl_version ()
556 CODE:
557 RETVAL = (char *)glGetString (GL_VERSION);
558 OUTPUT:
559 RETVAL
560
561 char *
562 gl_extensions ()
563 CODE:
564 RETVAL = (char *)glGetString (GL_EXTENSIONS);
565 OUTPUT:
566 RETVAL
567
568 void
569 add_font (char *file)
570 CODE:
571 FcConfigAppFontAddFile (0, (const FcChar8 *)file); /* no idea wether this is required */
572 #ifdef _WIN32
573 // cairo... sigh... requires win2000
574 AddFontResourceEx (file, FR_PRIVATE, 0);
575 #endif
576
577 void
578 load_image_inline (SV *image_)
579 ALIAS:
580 load_image_file = 1
581 PPCODE:
582 {
583 STRLEN image_len;
584 char *image = (char *)SvPVbyte (image_, image_len);
585 SDL_Surface *surface, *surface2;
586 SDL_PixelFormat fmt;
587 SDL_RWops *rw = ix
588 ? SDL_RWFromFile (image, "r")
589 : SDL_RWFromConstMem (image, image_len);
590
591 if (!rw)
592 croak ("load_image: %s", SDL_GetError ());
593
594 surface = IMG_Load_RW (rw, 1);
595 if (!surface)
596 croak ("load_image: %s", SDL_GetError ());
597
598 fmt.palette = NULL;
599 fmt.BitsPerPixel = 32;
600 fmt.BytesPerPixel = 4;
601 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
602 fmt.Rmask = 0x000000ff;
603 fmt.Gmask = 0x0000ff00;
604 fmt.Bmask = 0x00ff0000;
605 fmt.Amask = 0xff000000;
606 #else
607 fmt.Rmask = 0xff000000;
608 fmt.Gmask = 0x00ff0000;
609 fmt.Bmask = 0x0000ff00;
610 fmt.Amask = 0x000000ff;
611 #endif
612 fmt.Rloss = 0;
613 fmt.Gloss = 0;
614 fmt.Bloss = 0;
615 fmt.Aloss = 0;
616 fmt.Rshift = 0;
617 fmt.Gshift = 8;
618 fmt.Bshift = 16;
619 fmt.Ashift = 24;
620 fmt.colorkey = 0;
621 fmt.alpha = 0;
622
623 surface2 = SDL_ConvertSurface (surface, &fmt, SDL_SWSURFACE);
624
625 assert (surface2->pitch == surface2->w * 4);
626
627 EXTEND (SP, 5);
628 PUSHs (sv_2mortal (newSViv (surface2->w)));
629 PUSHs (sv_2mortal (newSViv (surface2->h)));
630 SDL_LockSurface (surface2);
631 PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch)));
632 SDL_UnlockSurface (surface2);
633 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
634 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
635 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
636
637 SDL_FreeSurface (surface);
638 SDL_FreeSurface (surface2);
639 }
640
641 void
642 average (int x, int y, uint32_t *data)
643 PPCODE:
644 {
645 uint32_t r = 0, g = 0, b = 0, a = 0;
646
647 x = y = x * y;
648
649 while (x--)
650 {
651 uint32_t p = *data++;
652
653 r += (p ) & 255;
654 g += (p >> 8) & 255;
655 b += (p >> 16) & 255;
656 a += (p >> 24) & 255;
657 }
658
659 EXTEND (SP, 4);
660 PUSHs (sv_2mortal (newSViv (r / y)));
661 PUSHs (sv_2mortal (newSViv (g / y)));
662 PUSHs (sv_2mortal (newSViv (b / y)));
663 PUSHs (sv_2mortal (newSViv (a / y)));
664 }
665
666 void
667 error (char *message)
668 CODE:
669 #ifdef _WIN32
670 MessageBox (0, message, "Crossfire+ Error", MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
671 #else
672 fprintf (stderr, "ERROR: %s\n", message);
673 #endif
674
675 void
676 fatal (char *message)
677 CODE:
678 #ifdef _WIN32
679 MessageBox (0, message, "Crossfire+ Fatal Error", MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
680 #else
681 fprintf (stderr, "FATAL: %s\n", message);
682 #endif
683 exit (1);
684
685 MODULE = CFClient PACKAGE = CFClient::Font
686
687 CFClient::Font
688 new_from_file (SV *class, char *path, int id = 0)
689 CODE:
690 {
691 int count;
692 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count);
693 RETVAL = pango_fc_font_description_from_pattern (pattern, 0);
694 FcPatternDestroy (pattern);
695 }
696 OUTPUT:
697 RETVAL
698
699 void
700 DESTROY (CFClient::Font self)
701 CODE:
702 pango_font_description_free (self);
703
704 void
705 make_default (CFClient::Font self)
706 CODE:
707 default_font = self;
708
709 MODULE = CFClient PACKAGE = CFClient::Layout
710
711 CFClient::Layout
712 new (SV *class, int rgba = 0)
713 CODE:
714 New (0, RETVAL, 1, struct cf_layout);
715
716 RETVAL->pl = pango_layout_new (rgba ? cairo_context : ft2_context);
717 RETVAL->rgba = rgba;
718 RETVAL->r = 1.;
719 RETVAL->g = 1.;
720 RETVAL->b = 1.;
721 RETVAL->a = 1.;
722 RETVAL->base_height = MIN_FONT_HEIGHT;
723 RETVAL->font = 0;
724
725 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
726 layout_update_font (RETVAL);
727 OUTPUT:
728 RETVAL
729
730 void
731 DESTROY (CFClient::Layout self)
732 CODE:
733 g_object_unref (self->pl);
734 Safefree (self);
735
736 int
737 is_rgba (CFClient::Layout self)
738 CODE:
739 RETVAL = self->rgba;
740 OUTPUT:
741 RETVAL
742
743 void
744 set_text (CFClient::Layout self, SV *text_)
745 CODE:
746 {
747 STRLEN textlen;
748 char *text = SvPVutf8 (text_, textlen);
749
750 pango_layout_set_text (self->pl, text, textlen);
751 }
752
753 void
754 set_markup (CFClient::Layout self, SV *text_)
755 CODE:
756 {
757 STRLEN textlen;
758 char *text = SvPVutf8 (text_, textlen);
759
760 pango_layout_set_markup (self->pl, text, textlen);
761 }
762
763 SV *
764 get_text (CFClient::Layout self)
765 CODE:
766 RETVAL = newSVpv (pango_layout_get_text (self->pl), 0);
767 SvUTF8_on (RETVAL);
768 OUTPUT:
769 RETVAL
770
771 void
772 set_foreground (CFClient::Layout self, float r, float g, float b, float a = 1.)
773 CODE:
774 self->r = r;
775 self->g = g;
776 self->b = b;
777 self->a = a;
778
779 void
780 set_font (CFClient::Layout self, CFClient::Font font = 0)
781 CODE:
782 if (self->font != font)
783 {
784 self->font = font;
785 layout_update_font (self);
786 }
787
788 void
789 set_height (CFClient::Layout self, int base_height)
790 CODE:
791 if (self->base_height != base_height)
792 {
793 self->base_height = base_height;
794 layout_update_font (self);
795 }
796
797 void
798 set_width (CFClient::Layout self, int max_width = -1)
799 CODE:
800 pango_layout_set_width (self->pl, max_width < 0 ? max_width : max_width * PANGO_SCALE);
801
802 void
803 size (CFClient::Layout self)
804 PPCODE:
805 {
806 int w, h;
807
808 layout_get_pixel_size (self, &w, &h);
809
810 EXTEND (SP, 2);
811 PUSHs (sv_2mortal (newSViv (w)));
812 PUSHs (sv_2mortal (newSViv (h)));
813 }
814
815 int
816 xy_to_index (CFClient::Layout self, int x, int y)
817 CODE:
818 {
819 int index, trailing;
820 pango_layout_xy_to_index (self->pl, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing);
821 RETVAL = index;
822 }
823 OUTPUT:
824 RETVAL
825
826 void
827 cursor_pos (CFClient::Layout self, int index)
828 PPCODE:
829 {
830 PangoRectangle strong_pos;
831 pango_layout_get_cursor_pos (self->pl, index, &strong_pos, 0);
832
833 EXTEND (SP, 3);
834 PUSHs (sv_2mortal (newSViv (strong_pos.x / PANGO_SCALE)));
835 PUSHs (sv_2mortal (newSViv (strong_pos.y / PANGO_SCALE)));
836 PUSHs (sv_2mortal (newSViv (strong_pos.height / PANGO_SCALE)));
837 }
838
839 void
840 render (CFClient::Layout self)
841 PPCODE:
842 {
843 SV *retval;
844 int w, h;
845
846 layout_get_pixel_size (self, &w, &h);
847
848 if (self->rgba)
849 {
850 cairo_surface_t *surface;
851 cairo_t *cairo;
852
853 retval = newSV (w * h * 4);
854 SvPOK_only (retval);
855 SvCUR_set (retval, w * h * 4);
856
857 memset (SvPVX (retval), 0, w * h * 4);
858
859 surface = cairo_image_surface_create_for_data (
860 (void*)SvPVX (retval), CAIRO_FORMAT_ARGB32, w, h, w * 4);
861 cairo = cairo_create (surface);
862 cairo_set_source_rgba (cairo, self->r, self->g, self->b, self->a);
863
864 pango_cairo_show_layout (cairo, self->pl);
865
866 cairo_destroy (cairo);
867 cairo_surface_destroy (surface);
868
869 // what a mess, and its premultiplied, too :(
870 {
871 uint32_t *p = (uint32_t *)SvPVX (retval);
872 uint32_t *e = p + w * h;
873
874 while (p < e)
875 {
876 uint32_t rgba = *p;
877 rgba = (rgba >> 24) | (rgba << 8);
878 rgba = SDL_SwapBE32 (rgba);
879 *p++ = rgba;
880 }
881 }
882
883 EXTEND (SP, 5);
884 PUSHs (sv_2mortal (newSViv (w)));
885 PUSHs (sv_2mortal (newSViv (h)));
886 PUSHs (sv_2mortal (retval));
887 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
888 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
889 }
890 else
891 {
892 FT_Bitmap bitmap;
893
894 retval = newSV (w * h);
895 SvPOK_only (retval);
896 SvCUR_set (retval, w * h);
897
898 bitmap.rows = h;
899 bitmap.width = w;
900 bitmap.pitch = w;
901 bitmap.buffer = (unsigned char*)SvPVX (retval);
902 bitmap.num_grays = 256;
903 bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
904
905 memset (bitmap.buffer, 0, w * h);
906
907 pango_ft2_render_layout (&bitmap, self->pl, 0 * PANGO_SCALE, 0 * PANGO_SCALE);
908
909 EXTEND (SP, 5);
910 PUSHs (sv_2mortal (newSViv (w)));
911 PUSHs (sv_2mortal (newSViv (h)));
912 PUSHs (sv_2mortal (retval));
913 PUSHs (sv_2mortal (newSViv (GL_ALPHA)));
914 PUSHs (sv_2mortal (newSViv (GL_ALPHA)));
915 }
916 }
917
918 MODULE = CFClient PACKAGE = CFClient::Texture
919
920 void
921 draw_quad (SV *self, float x, float y, float w = 0, float h = 0)
922 PROTOTYPE: $$$;$$
923 ALIAS:
924 draw_quad_alpha = 1
925 draw_quad_alpha_premultiplied = 2
926 CODE:
927 {
928 HV *hv = (HV *)SvRV (self);
929 float s = SvNV (*hv_fetch (hv, "s", 1, 1));
930 float t = SvNV (*hv_fetch (hv, "t", 1, 1));
931 int name = SvIV (*hv_fetch (hv, "name", 4, 1));
932 int wrap_mode = SvIV (*hv_fetch (hv, "wrap_mode", 9, 1));
933
934 if (items < 5)
935 {
936 w = SvNV (*hv_fetch (hv, "w", 1, 1));
937 h = SvNV (*hv_fetch (hv, "h", 1, 1));
938 }
939
940 if (ix)
941 {
942 glEnable (GL_BLEND);
943 glBlendFunc (ix == 1 ? GL_SRC_ALPHA : GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
944 }
945
946 glBindTexture (GL_TEXTURE_2D, name);
947
948 if (wrap_mode)
949 {
950 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
951 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
952 }
953
954 glBegin (GL_QUADS);
955 glTexCoord2f (0, 0); glVertex2f (x , y );
956 glTexCoord2f (0, t); glVertex2f (x , y + h);
957 glTexCoord2f (s, t); glVertex2f (x + w, y + h);
958 glTexCoord2f (s, 0); glVertex2f (x + w, y );
959 glEnd ();
960
961 if (ix)
962 glDisable (GL_BLEND);
963 }
964
965 MODULE = CFClient PACKAGE = CFClient::Map
966
967 CFClient::Map
968 new (SV *class, int map_width, int map_height)
969 CODE:
970 New (0, RETVAL, 1, struct map);
971 RETVAL->x = 0;
972 RETVAL->y = 0;
973 RETVAL->w = map_width;
974 RETVAL->h = map_height;
975 RETVAL->ox = 0;
976 RETVAL->oy = 0;
977 RETVAL->faces = 8192;
978 Newz (0, RETVAL->face, RETVAL->faces, mapface);
979 RETVAL->texs = 8192;
980 Newz (0, RETVAL->tex, RETVAL->texs, maptex);
981 RETVAL->rows = 0;
982 RETVAL->row = 0;
983 OUTPUT:
984 RETVAL
985
986 void
987 DESTROY (CFClient::Map self)
988 CODE:
989 {
990 map_clear (self);
991 Safefree (self->face);
992 Safefree (self);
993 }
994
995 void
996 clear (CFClient::Map self)
997 CODE:
998 map_clear (self);
999
1000 void
1001 set_face (CFClient::Map self, int face, int texid)
1002 CODE:
1003 {
1004 while (self->faces <= face)
1005 {
1006 Append (mapface, self->face, self->faces, self->faces);
1007 self->faces *= 2;
1008 }
1009
1010 self->face [face] = texid;
1011 }
1012
1013 void
1014 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)
1015 CODE:
1016 {
1017 while (self->texs <= texid)
1018 {
1019 Append (maptex, self->tex, self->texs, self->texs);
1020 self->texs *= 2;
1021 }
1022
1023 {
1024 maptex *tex = self->tex + texid;
1025
1026 tex->name = name;
1027 tex->w = w;
1028 tex->h = h;
1029 tex->s = s;
1030 tex->t = t;
1031 tex->r = r;
1032 tex->g = g;
1033 tex->b = b;
1034 tex->a = a;
1035 }
1036 }
1037
1038 int
1039 ox (CFClient::Map self)
1040 ALIAS:
1041 oy = 1
1042 CODE:
1043 switch (ix)
1044 {
1045 case 0: RETVAL = self->ox; break;
1046 case 1: RETVAL = self->oy; break;
1047 }
1048 OUTPUT:
1049 RETVAL
1050
1051 void
1052 scroll (CFClient::Map self, int dx, int dy)
1053 CODE:
1054 {
1055 if (dx > 0)
1056 map_blank (self, self->x, self->y, dx - 1, self->h);
1057 else if (dx < 0)
1058 map_blank (self, self->x + self->w + dx + 1, self->y, 1 - dx, self->h);
1059
1060 if (dy > 0)
1061 map_blank (self, self->x, self->y, self->w, dy - 1);
1062 else if (dy < 0)
1063 map_blank (self, self->x, self->y + self->h + dy + 1, self->w, 1 - dy);
1064
1065 self->ox += dx; self->x += dx;
1066 self->oy += dy; self->y += dy;
1067
1068 while (self->y < 0)
1069 {
1070 Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y);
1071
1072 self->rows += MAP_EXTEND_Y;
1073 self->y += MAP_EXTEND_Y;
1074 }
1075 }
1076
1077 void
1078 map1a_update (CFClient::Map self, SV *data_)
1079 CODE:
1080 {
1081 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
1082 uint8_t *data_end = (uint8_t *)SvEND (data_);
1083 mapcell *cell;
1084 int x, y, flags;
1085
1086 while (data < data_end)
1087 {
1088 flags = (data [0] << 8) + data [1]; data += 2;
1089
1090 x = ((flags >> 10) & 63) + self->x;
1091 y = ((flags >> 4) & 63) + self->y;
1092
1093 cell = map_get_cell (self, x, y);
1094
1095 if (flags & 15)
1096 {
1097 if (cell->darkness < 0)
1098 {
1099 cell->darkness = 0;
1100 cell->face [0] = 0;
1101 cell->face [1] = 0;
1102 cell->face [2] = 0;
1103 }
1104
1105 cell->darkness = flags & 8 ? *data++ : 255;
1106
1107 //TODO: don't trust server data to be in-range(!)
1108
1109 if (flags & 4)
1110 {
1111 cell->face [0] = self->face [(data [0] << 8) + data [1]]; data += 2;
1112 }
1113
1114 if (flags & 2)
1115 {
1116 cell->face [1] = self->face [(data [0] << 8) + data [1]]; data += 2;
1117 }
1118
1119 if (flags & 1)
1120 {
1121 cell->face [2] = self->face [(data [0] << 8) + data [1]]; data += 2;
1122 }
1123 }
1124 else
1125 cell->darkness = -1;
1126 }
1127 }
1128
1129 SV *
1130 mapmap (CFClient::Map self, int x0, int y0, int w, int h)
1131 CODE:
1132 {
1133 int x1, x;
1134 int y1, y;
1135 int z;
1136 SV *map_sv = newSV (w * h * sizeof (uint32_t));
1137 uint32_t *map = (uint32_t *)SvPVX (map_sv);
1138
1139 SvPOK_only (map_sv);
1140 SvCUR_set (map_sv, w * h * sizeof (uint32_t));
1141
1142 x0 += self->x; x1 = x0 + w;
1143 y0 += self->y; y1 = y0 + h;
1144
1145 for (y = y0; y < y1; y++)
1146 {
1147 maprow *row = 0 <= y && y < self->rows
1148 ? self->row + y
1149 : 0;
1150
1151 for (x = x0; x < x1; x++)
1152 {
1153 int r = 32, g = 32, b = 32, a = 192;
1154
1155 if (row && row->c0 <= x && x < row->c1)
1156 {
1157 mapcell *cell = row->col + (x - row->c0);
1158
1159 for (z = 0; z <= 0; z++)
1160 {
1161 mapface face = cell->face [z];
1162
1163 if (face)
1164 {
1165 maptex tex = self->tex [face];
1166 int a0 = 255 - tex.a;
1167 int a1 = tex.a;
1168
1169 r = (r * a0 + tex.r * a1) / 255;
1170 g = (g * a0 + tex.g * a1) / 255;
1171 b = (b * a0 + tex.b * a1) / 255;
1172 a = (a * a0 + tex.a * a1) / 255;
1173 }
1174 }
1175 }
1176
1177 *map++ = (r )
1178 | (g << 8)
1179 | (b << 16)
1180 | (a << 24);
1181 }
1182 }
1183
1184 RETVAL = map_sv;
1185 }
1186 OUTPUT:
1187 RETVAL
1188
1189 void
1190 draw (CFClient::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1191 PPCODE:
1192 {
1193 int vx, vy;
1194 int x, y, z;
1195 int last_name;
1196 mapface face;
1197 int sw4 = (sw + 3) & ~3;
1198 SV *darkness_sv = sv_2mortal (newSV (sw4 * sh));
1199 uint8_t *darkness = (uint8_t *)SvPVX (darkness_sv);
1200
1201 memset (darkness, 255, sw4 * sh);
1202 SvPOK_only (darkness_sv);
1203 SvCUR_set (darkness_sv, sw4 * sh);
1204
1205 vx = self->x + (self->w - sw) / 2 - shift_x;
1206 vy = self->y + (self->h - sh) / 2 - shift_y;
1207
1208 /*
1209 int vx = self->vx = self->w >= sw
1210 ? self->x + (self->w - sw) / 2
1211 : MIN (self->x, MAX (self->x + self->w - sw + 1, self->vx));
1212
1213 int vy = self->vy = self->h >= sh
1214 ? self->y + (self->h - sh) / 2
1215 : MIN (self->y, MAX (self->y + self->h - sh + 1, self->vy));
1216 */
1217
1218 glColor4ub (255, 255, 255, 255);
1219
1220 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1221 glEnable (GL_BLEND);
1222 glEnable (GL_TEXTURE_2D);
1223 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1224
1225 glBegin (GL_QUADS);
1226
1227 last_name = 0;
1228
1229 for (z = 0; z < 3; z++)
1230 for (y = 0; y < sh; y++)
1231 if (0 <= y + vy && y + vy < self->rows)
1232 {
1233 maprow *row = self->row + (y + vy);
1234
1235 for (x = 0; x < sw; x++)
1236 if (row->c0 <= x + vx && x + vx < row->c1)
1237 {
1238 mapcell *cell = row->col + (x + vx - row->c0);
1239
1240 darkness[y * sw4 + x] = cell->darkness < 0
1241 ? 255 - FOW_DARKNESS
1242 : 255 - cell->darkness;
1243
1244 face = cell->face [z];
1245
1246 if (face)
1247 {
1248 maptex tex = self->tex [face];
1249
1250 int px = (x + 1) * 32 - tex.w;
1251 int py = (y + 1) * 32 - tex.h;
1252
1253 if (last_name != tex.name)
1254 {
1255 glEnd ();
1256 last_name = tex.name;
1257 glBindTexture (GL_TEXTURE_2D, last_name);
1258 glBegin (GL_QUADS);
1259 }
1260
1261 glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1262 glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1263 glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1264 glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1265 }
1266 }
1267 }
1268
1269 glEnd ();
1270
1271 glDisable (GL_TEXTURE_2D);
1272 glDisable (GL_BLEND);
1273
1274 EXTEND (SP, 3);
1275 PUSHs (sv_2mortal (newSViv (sw4)));
1276 PUSHs (sv_2mortal (newSViv (sh)));
1277 PUSHs (darkness_sv);
1278 }
1279
1280 SV *
1281 get_rect (CFClient::Map self, int x0, int y0, int w, int h)
1282 CODE:
1283 {
1284 int x, y, x1, y1;
1285 SV *data_sv = newSV (w * h * 7 + 5);
1286 uint8_t *data = (uint8_t *)SvPVX (data_sv);
1287
1288 *data++ = 0; /* version 0 format */
1289 *data++ = w >> 8; *data++ = w;
1290 *data++ = h >> 8; *data++ = h;
1291
1292 // we need to do this 'cause we don't keep an absolute coord system for rows
1293 // TODO: treat rows as we treat columns
1294 map_get_row (self, y0 + self->y - self->oy);//D
1295 map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1296
1297 x0 += self->x - self->ox;
1298 y0 += self->y - self->oy;
1299
1300 x1 = x0 + w;
1301 y1 = y0 + h;
1302
1303 for (y = y0; y < y1; y++)
1304 {
1305 maprow *row = 0 <= y && y < self->rows
1306 ? self->row + y
1307 : 0;
1308
1309 for (x = x0; x < x1; x++)
1310 {
1311 if (row && row->c0 <= x && x < row->c1)
1312 {
1313 mapcell *cell = row->col + (x - row->c0);
1314 uint8_t flags = 0;
1315
1316 if (cell->face [0]) flags |= 1;
1317 if (cell->face [1]) flags |= 2;
1318 if (cell->face [2]) flags |= 4;
1319
1320 *data++ = flags;
1321
1322 if (flags & 1)
1323 {
1324 *data++ = cell->face [0] >> 8;
1325 *data++ = cell->face [0];
1326 }
1327
1328 if (flags & 2)
1329 {
1330 *data++ = cell->face [1] >> 8;
1331 *data++ = cell->face [1];
1332 }
1333
1334 if (flags & 4)
1335 {
1336 *data++ = cell->face [2] >> 8;
1337 *data++ = cell->face [2];
1338 }
1339 }
1340 else
1341 *data++ = 0;
1342 }
1343 }
1344
1345 SvPOK_only (data_sv);
1346 SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
1347 RETVAL = data_sv;
1348 }
1349 OUTPUT:
1350 RETVAL
1351
1352 void
1353 set_rect (CFClient::Map self, int x0, int y0, uint8_t *data)
1354 PPCODE:
1355 {
1356 int x, y, z;
1357 int w, h;
1358 int x1, y1;
1359
1360 if (*data++ != 0)
1361 return; /* version mismatch */
1362
1363 w = *data++ << 8; w |= *data++;
1364 h = *data++ << 8; h |= *data++;
1365
1366 // we need to do this 'cause we don't keep an absolute coord system for rows
1367 // TODO: treat rows as we treat columns
1368 map_get_row (self, y0 + self->y - self->oy);//D
1369 map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1370
1371 x0 += self->x - self->ox;
1372 y0 += self->y - self->oy;
1373
1374 x1 = x0 + w;
1375 y1 = y0 + h;
1376
1377 for (y = y0; y < y1; y++)
1378 {
1379 maprow *row = map_get_row (self, y);
1380
1381 for (x = x0; x < x1; x++)
1382 {
1383 uint8_t flags = *data++;
1384
1385 if (flags)
1386 {
1387 mapface face[3] = { 0, 0, 0 };
1388
1389 mapcell *cell = row_get_cell (row, x);
1390
1391 if (flags & 1) { face[0] = *data++ << 8; face[0] |= *data++; }
1392 if (flags & 2) { face[1] = *data++ << 8; face[1] |= *data++; }
1393 if (flags & 4) { face[2] = *data++ << 8; face[2] |= *data++; }
1394
1395 if (cell->darkness <= 0)
1396 {
1397 cell->darkness = -1;
1398
1399 for (z = 0; z <= 2; z++)
1400 {
1401 cell->face[z] = face[z];
1402
1403 if (face[z] && (face[z] >= self->texs || !self->tex[face [z]].name))
1404 XPUSHs (sv_2mortal (newSViv (face[z])));
1405 }
1406 }
1407 }
1408 }
1409 }
1410 }
1411
1412 MODULE = CFClient PACKAGE = CFClient::MixChunk
1413
1414 CFClient::MixChunk
1415 new_from_file (SV *class, char *path)
1416 CODE:
1417 RETVAL = Mix_LoadWAV (path);
1418 OUTPUT:
1419 RETVAL
1420
1421 void
1422 DESTROY (CFClient::MixChunk self)
1423 CODE:
1424 Mix_FreeChunk (self);
1425
1426 int
1427 volume (CFClient::MixChunk self, int volume = -1)
1428 CODE:
1429 RETVAL = Mix_VolumeChunk (self, volume);
1430 OUTPUT:
1431 RETVAL
1432
1433 int
1434 play (CFClient::MixChunk self, int channel = -1, int loops = 0, int ticks = -1)
1435 CODE:
1436 RETVAL = Mix_PlayChannelTimed (channel, self, loops, ticks);
1437 OUTPUT:
1438 RETVAL
1439
1440 MODULE = CFClient PACKAGE = CFClient::MixMusic
1441
1442 int
1443 volume (int volume = -1)
1444 CODE:
1445 RETVAL = Mix_VolumeMusic (volume);
1446 OUTPUT:
1447 RETVAL
1448
1449 CFClient::MixMusic
1450 new_from_file (SV *class, char *path)
1451 CODE:
1452 RETVAL = Mix_LoadMUS (path);
1453 OUTPUT:
1454 RETVAL
1455
1456 void
1457 DESTROY (CFClient::MixMusic self)
1458 CODE:
1459 Mix_FreeMusic (self);
1460
1461 int
1462 play (CFClient::MixMusic self, int loops = -1)
1463 CODE:
1464 RETVAL = Mix_PlayMusic (self, loops);
1465 OUTPUT:
1466 RETVAL
1467
1468 MODULE = CFClient PACKAGE = CFClient::OpenGL
1469
1470 BOOT:
1471 {
1472 HV *stash = gv_stashpv ("CFClient::OpenGL", 1);
1473 static const struct {
1474 const char *name;
1475 IV iv;
1476 } *civ, const_iv[] = {
1477 # define const_iv(name) { # name, (IV)name }
1478 const_iv (GL_COLOR_MATERIAL),
1479 const_iv (GL_SMOOTH),
1480 const_iv (GL_FLAT),
1481 const_iv (GL_DITHER),
1482 const_iv (GL_BLEND),
1483 const_iv (GL_SCISSOR_TEST),
1484 const_iv (GL_AND),
1485 const_iv (GL_ONE),
1486 const_iv (GL_ZERO),
1487 const_iv (GL_SRC_ALPHA),
1488 const_iv (GL_SRC_ALPHA_SATURATE),
1489 const_iv (GL_ONE_MINUS_SRC_ALPHA),
1490 const_iv (GL_ONE_MINUS_DST_ALPHA),
1491 const_iv (GL_RGB),
1492 const_iv (GL_RGBA),
1493 const_iv (GL_UNSIGNED_BYTE),
1494 const_iv (GL_ALPHA),
1495 const_iv (GL_LUMINANCE),
1496 const_iv (GL_FLOAT),
1497 const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
1498 const_iv (GL_COMPILE),
1499 const_iv (GL_TEXTURE_1D),
1500 const_iv (GL_TEXTURE_2D),
1501 const_iv (GL_TEXTURE_ENV),
1502 const_iv (GL_TEXTURE_MAG_FILTER),
1503 const_iv (GL_TEXTURE_MIN_FILTER),
1504 const_iv (GL_TEXTURE_ENV_MODE),
1505 const_iv (GL_TEXTURE_WRAP_S),
1506 const_iv (GL_TEXTURE_WRAP_T),
1507 const_iv (GL_CLAMP),
1508 const_iv (GL_REPEAT),
1509 const_iv (GL_NEAREST),
1510 const_iv (GL_LINEAR),
1511 const_iv (GL_NEAREST_MIPMAP_NEAREST),
1512 const_iv (GL_LINEAR_MIPMAP_NEAREST),
1513 const_iv (GL_NEAREST_MIPMAP_LINEAR),
1514 const_iv (GL_LINEAR_MIPMAP_LINEAR),
1515 const_iv (GL_GENERATE_MIPMAP),
1516 const_iv (GL_MODULATE),
1517 const_iv (GL_DECAL),
1518 const_iv (GL_REPLACE),
1519 const_iv (GL_COLOR_BUFFER_BIT),
1520 const_iv (GL_PROJECTION),
1521 const_iv (GL_MODELVIEW),
1522 const_iv (GL_COLOR_LOGIC_OP),
1523 const_iv (GL_SEPARABLE_2D),
1524 const_iv (GL_CONVOLUTION_2D),
1525 const_iv (GL_CONVOLUTION_BORDER_MODE),
1526 const_iv (GL_CONSTANT_BORDER),
1527 const_iv (GL_LINES),
1528 const_iv (GL_QUADS),
1529 const_iv (GL_LINE_LOOP),
1530 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
1531 const_iv (GL_FASTEST),
1532 # undef const_iv
1533 };
1534
1535 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1536 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1537 }
1538
1539 int glGetError ()
1540
1541 void glClear (int mask)
1542
1543 void glClearColor (float r, float g, float b, float a = 1.0)
1544 PROTOTYPE: @
1545
1546 void glEnable (int cap)
1547
1548 void glDisable (int cap)
1549
1550 void glShadeModel (int mode)
1551
1552 void glHint (int target, int mode)
1553
1554 void glBlendFunc (int sfactor, int dfactor)
1555
1556 void glLogicOp (int opcode)
1557
1558 void glColorMask (int red, int green, int blue, int alpha)
1559
1560 void glMatrixMode (int mode)
1561
1562 void glPushMatrix ()
1563
1564 void glPopMatrix ()
1565
1566 void glLoadIdentity ()
1567
1568 # near and far are due to microsofts buggy c compiler
1569 void glOrtho (double left, double right, double bottom, double top, double near_, double far_)
1570
1571 void glViewport (int x, int y, int width, int height)
1572
1573 void glScissor (int x, int y, int width, int height)
1574
1575 void glTranslate (float x, float y, float z = 0.)
1576 CODE:
1577 glTranslatef (x, y, z);
1578
1579 void glScale (float x, float y, float z = 1.)
1580 CODE:
1581 glScalef (x, y, z);
1582
1583 void glRotate (float angle, float x, float y, float z)
1584 CODE:
1585 glRotatef (angle, x, y, z);
1586
1587 void glBegin (int mode)
1588
1589 void glEnd ()
1590
1591 void glColor (float r, float g, float b, float a = 1.0)
1592 PROTOTYPE: @
1593 CODE:
1594 // 255.999 is close enough to correctness (256 and clamp)
1595 glColor4ub (r * 255.999, g * 255.999, b * 255.999, a * 255.999);
1596
1597 void glVertex (float x, float y, float z = 0.)
1598 CODE:
1599 glVertex3f (x, y, z);
1600
1601 void glTexCoord (float s, float t)
1602 CODE:
1603 glTexCoord2f (s, t);
1604
1605 void glTexEnv (int target, int pname, float param)
1606 CODE:
1607 glTexEnvf (target, pname, param);
1608
1609 void glTexParameter (int target, int pname, float param)
1610 CODE:
1611 glTexParameterf (target, pname, param);
1612
1613 void glBindTexture (int target, int name)
1614
1615 void glConvolutionParameter (int target, int pname, float params)
1616 CODE:
1617 GL_CALL (PFNGLCONVOLUTIONPARAMETERFEXTPROC, glConvolutionParameterf, (target, pname, params));
1618
1619 void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
1620 CODE:
1621 GL_CALL (PFNGLCONVOLUTIONFILTER2DEXTPROC, glConvolutionFilter2D,
1622 (target, internalformat, width, height, format, type, data));
1623
1624 void glSeparableFilter2D (int target, int internalformat, int width, int height, int format, int type, char *row, char *column)
1625 CODE:
1626 GL_CALL (PFNGLSEPARABLEFILTER2DEXTPROC, glSeparableFilter2D,
1627 (target, internalformat, width, height, format, type, row, column));
1628
1629 void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data)
1630
1631 void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
1632
1633 void glRasterPos (int x, int y)
1634 CODE:
1635 glRasterPos2i (x, y);
1636
1637 void glCopyPixels (int x, int y, int width, int height, int type = GL_COLOR)
1638
1639 int glGenTexture ()
1640 CODE:
1641 {
1642 GLuint name;
1643 glGenTextures (1, &name);
1644 RETVAL = name;
1645 }
1646 OUTPUT:
1647 RETVAL
1648
1649 void glDeleteTexture (int name)
1650 CODE:
1651 {
1652 GLuint name_ = name;
1653 glDeleteTextures (1, &name_);
1654 }
1655
1656 int glGenList ()
1657 CODE:
1658 RETVAL = glGenLists (1);
1659 OUTPUT:
1660 RETVAL
1661
1662 void glDeleteList (int list)
1663 CODE:
1664 glDeleteLists (list, 1);
1665
1666 void glNewList (int list, int mode = GL_COMPILE)
1667
1668 void glEndList ()
1669
1670 void glCallList (int list)
1671