ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.166
Committed: Fri Dec 8 15:07:08 2006 UTC (17 years, 5 months ago) by root
Branch: MAIN
Changes since 1.165: +1 -2 lines
Log Message:
less hacky equals more correct

File Contents

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