ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.28
Committed: Thu Apr 13 00:25:28 2006 UTC (18 years, 1 month ago) by root
Branch: MAIN
Changes since 1.27: +61 -0 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 #include "EXTERN.h"
2     #include "perl.h"
3     #include "XSUB.h"
4    
5 root 1.5 #include <string.h>
6 root 1.25 #include <stdio.h>
7 root 1.5
8 root 1.2 #include <SDL.h>
9 root 1.23 #include <SDL_image.h>
10 root 1.3 #include <SDL_opengl.h>
11 root 1.5
12     #include <pango/pango.h>
13 root 1.10 #include <pango/pangofc-fontmap.h>
14 root 1.5 #include <pango/pangoft2.h>
15    
16 root 1.10 #include <sys/types.h>
17     #include <sys/socket.h>
18     #include <netinet/in.h>
19     #include <netinet/tcp.h>
20    
21 root 1.28 #include <inttypes.h>
22    
23 root 1.5 static PangoContext *context;
24     static PangoFontMap *fontmap;
25 root 1.2
26 root 1.14 typedef struct cf_layout {
27     PangoLayout *pl;
28     int base_height;
29 root 1.15 } *CFClient__Layout;
30 root 1.14
31     static void
32 root 1.19 substitute_func (FcPattern *pattern, gpointer data)
33     {
34 root 1.20 FcPatternAddBool (pattern, FC_HINTING , 1);
35     FcPatternAddBool (pattern, FC_AUTOHINT, 1);
36 root 1.19 }
37    
38     static void
39 root 1.17 layout_update (CFClient__Layout self)
40     {
41 root 1.19 /* use a random scale factor to account for unknown descenders, 0.8 works
42     * reasonably well with bitstream vera
43     */
44 root 1.17 PangoFontDescription *font = pango_context_get_font_description (context);
45 root 1.19 pango_font_description_set_absolute_size (font, self->base_height * (PANGO_SCALE * 8 / 10));
46 root 1.17 }
47    
48     static void
49 root 1.15 layout_get_pixel_size (CFClient__Layout self, int *w, int *h)
50 root 1.14 {
51 root 1.19 layout_update (self);
52 root 1.16
53 root 1.14 pango_layout_get_pixel_size (self->pl, w, h);
54    
55     *w = (*w + 3) & ~3;
56     if (!*w) *w = 1;
57     if (!*h) *h = 1;
58     }
59    
60 root 1.28 typedef struct {
61     uint16_t face[3];
62     uint8_t darkness;
63     uint8_t padding;
64     } mapcell;
65    
66     typedef struct {
67     uint32_t cols;
68     mapcell *col;
69     } maprow;
70    
71     typedef struct map {
72     int x, y, w, h;
73     int faces;
74     GLint *face;
75    
76     uint32_t rows;
77     maprow *row;
78     } *CFClient__Map;
79    
80 root 1.15 MODULE = CFClient PACKAGE = CFClient
81 root 1.1
82 root 1.11 PROTOTYPES: ENABLE
83    
84 root 1.5 BOOT:
85     {
86     fontmap = pango_ft2_font_map_new ();
87 root 1.19 pango_ft2_font_map_set_default_substitute ((PangoFT2FontMap *)fontmap, substitute_func, 0, 0);
88 root 1.8 context = pango_ft2_font_map_create_context ((PangoFT2FontMap *)fontmap);
89 root 1.5 }
90    
91 root 1.10 void
92     lowdelay (int fd, int val = 1)
93     CODE:
94     setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof (val));
95    
96 root 1.3 char *
97 root 1.4 gl_version ()
98     CODE:
99 root 1.5 RETVAL = (char *)glGetString (GL_VERSION);
100 root 1.4 OUTPUT:
101     RETVAL
102    
103     char *
104 root 1.3 gl_extensions ()
105     CODE:
106 root 1.5 RETVAL = (char *)glGetString (GL_EXTENSIONS);
107 root 1.3 OUTPUT:
108     RETVAL
109    
110 root 1.5 void
111 root 1.13 add_font (char *file)
112     CODE:
113     FcConfigAppFontAddFile (0, (const FcChar8 *)file); /* no idea wether this is required */
114    
115     void
116 root 1.9 set_font (char *file)
117 root 1.8 CODE:
118     {
119 root 1.9 int count;
120     FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)file, 0, 0, &count);
121 root 1.10 PangoFontDescription *font = pango_fc_font_description_from_pattern (pattern, 0);
122 root 1.9 FcPatternDestroy (pattern);
123 root 1.8 pango_context_set_font_description (context, font);
124     }
125    
126 root 1.23 void
127     load_image_inline (SV *image_)
128     ALIAS:
129     load_image_file = 1
130     PPCODE:
131     {
132     STRLEN image_len;
133     char *image = (char *)SvPVbyte (image_, image_len);
134     SDL_Surface *surface, *surface2;
135     SDL_PixelFormat fmt;
136     SDL_RWops *rw = ix
137     ? SDL_RWFromFile (image, "r")
138     : SDL_RWFromConstMem (image, image_len);
139    
140     if (!rw)
141     croak ("load_image: unable to open file");
142    
143     surface = IMG_Load_RW (rw, 1);
144     if (!surface)
145     croak ("load_image: unable to read file");
146    
147     fmt.palette = NULL;
148     fmt.BitsPerPixel = 32;
149     fmt.BytesPerPixel = 4;
150     fmt.Rmask = 0x000000ff;
151     fmt.Gmask = 0x0000ff00;
152     fmt.Bmask = 0x00ff0000;
153     fmt.Amask = 0xff000000;
154     fmt.Rloss = 0;
155     fmt.Gloss = 0;
156     fmt.Bloss = 0;
157     fmt.Aloss = 0;
158     fmt.Rshift = 0;
159     fmt.Gshift = 8;
160     fmt.Bshift = 16;
161     fmt.Ashift = 24;
162     fmt.colorkey = 0;
163     fmt.alpha = 0;
164    
165     surface2 = SDL_ConvertSurface (surface, &fmt, SDL_SWSURFACE);
166    
167     EXTEND (SP, 5);
168     PUSHs (sv_2mortal (newSViv (surface2->w)));
169     PUSHs (sv_2mortal (newSViv (surface2->h)));
170     SDL_LockSurface (surface2);
171     PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch)));
172     SDL_UnlockSurface (surface2);
173 root 1.24 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
174 root 1.23 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
175     PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_INT_8_8_8_8_REV)));
176    
177     SDL_FreeSurface (surface);
178     SDL_FreeSurface (surface2);
179     }
180    
181 root 1.25 void
182     fatal (char *message)
183     CODE:
184     #ifdef WIN32
185     MessageBox (0, message, "Crossfire+ Fatal Error", MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
186     #else
187     fprintf (stderr, "%s\n", message);
188     #endif
189     exit (1);
190    
191 root 1.15 MODULE = CFClient PACKAGE = CFClient::Layout
192 root 1.14
193 root 1.15 CFClient::Layout
194 root 1.14 new (SV *class, int base_height = 10)
195     CODE:
196     New (0, RETVAL, 1, struct cf_layout);
197     RETVAL->base_height = base_height;
198     RETVAL->pl = pango_layout_new (context);
199     pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
200     OUTPUT:
201     RETVAL
202    
203     void
204 root 1.15 DESTROY (CFClient::Layout self)
205 root 1.14 CODE:
206     g_object_unref (self->pl);
207     Safefree (self);
208 root 1.13
209 root 1.8 void
210 root 1.15 set_markup (CFClient::Layout self, SV *text_)
211 root 1.14 CODE:
212 root 1.5 {
213     STRLEN textlen;
214     char *text = SvPVutf8 (text_, textlen);
215 root 1.14
216     pango_layout_set_markup (self->pl, text, textlen);
217     }
218    
219     void
220 root 1.16 set_height (CFClient::Layout self, int base_height)
221     CODE:
222     self->base_height = base_height;
223    
224     void
225 root 1.15 set_width (CFClient::Layout self, int max_width = -1)
226 root 1.14 CODE:
227     pango_layout_set_width (self->pl, max_width < 0 ? max_width : max_width * PANGO_SCALE);
228    
229     void
230 root 1.15 size (CFClient::Layout self)
231 root 1.14 PPCODE:
232     {
233     int w, h;
234    
235 root 1.17 layout_update (self);
236 root 1.14 layout_get_pixel_size (self, &w, &h);
237    
238     EXTEND (SP, 2);
239     PUSHs (sv_2mortal (newSViv (w)));
240     PUSHs (sv_2mortal (newSViv (h)));
241     }
242    
243 root 1.17 int
244     xy_to_index (CFClient::Layout self, int x, int y)
245     CODE:
246     {
247     int index, trailing;
248    
249     layout_update (self);
250     pango_layout_xy_to_index (self->pl, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing);
251    
252     RETVAL = index;
253     }
254     OUTPUT:
255     RETVAL
256    
257     void
258     cursor_pos (CFClient::Layout self, int index)
259     PPCODE:
260     {
261     PangoRectangle strong_pos;
262     layout_update (self);
263     pango_layout_get_cursor_pos (self->pl, index, &strong_pos, 0);
264     EXTEND (SP, 3);
265     PUSHs (sv_2mortal (newSViv (strong_pos.x / PANGO_SCALE)));
266     PUSHs (sv_2mortal (newSViv (strong_pos.y / PANGO_SCALE)));
267     PUSHs (sv_2mortal (newSViv (strong_pos.height / PANGO_SCALE)));
268     }
269    
270 root 1.14 void
271 root 1.15 render (CFClient::Layout self)
272 root 1.14 PPCODE:
273     {
274 root 1.5 SV *retval;
275     int w, h;
276     FT_Bitmap bitmap;
277    
278 root 1.17 layout_update (self);
279 root 1.14 layout_get_pixel_size (self, &w, &h);
280 root 1.5
281     retval = newSV (w * h);
282     SvPOK_only (retval);
283     SvCUR_set (retval, w * h);
284    
285     bitmap.rows = h;
286     bitmap.width = w;
287     bitmap.pitch = w;
288     bitmap.buffer = (unsigned char*)SvPVX (retval);
289     bitmap.num_grays = 256;
290     bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
291    
292     memset (bitmap.buffer, 0, w * h);
293    
294 root 1.14 pango_ft2_render_layout (&bitmap, self->pl, 0 * PANGO_SCALE, 0 * PANGO_SCALE);
295 root 1.1
296 root 1.5 EXTEND (SP, 3);
297     PUSHs (sv_2mortal (newSViv (w)));
298     PUSHs (sv_2mortal (newSViv (h)));
299     PUSHs (sv_2mortal (retval));
300     }
301 root 1.11
302 root 1.15 MODULE = CFClient PACKAGE = CFClient::Texture
303 root 1.11
304     void
305 root 1.12 draw_quad (SV *self, double x, double y, double w = 0, double h = 0)
306     PROTOTYPE: $$$;$$
307 root 1.11 CODE:
308     {
309 root 1.12 HV *hv = (HV *)SvRV (self);
310     double s = SvNV (*hv_fetch (hv, "s", 1, 1));
311     double t = SvNV (*hv_fetch (hv, "t", 1, 1));
312     int name = SvIV (*hv_fetch (hv, "name", 4, 1));
313    
314     if (items < 5)
315     {
316 root 1.18 w = SvNV (*hv_fetch (hv, "w", 1, 1));
317     h = SvNV (*hv_fetch (hv, "h", 1, 1));
318 root 1.12 }
319    
320     glBindTexture (GL_TEXTURE_2D, name);
321     glBegin (GL_QUADS);
322     glTexCoord2d (0, 0); glVertex2d (x , y );
323     glTexCoord2d (0, t); glVertex2d (x , y + h);
324     glTexCoord2d (s, t); glVertex2d (x + w, y + h);
325     glTexCoord2d (s, 0); glVertex2d (x + w, y );
326     glEnd ();
327 root 1.11 }
328 root 1.28
329     MODULE = CFClient PACKAGE = CFClient::Map
330    
331     CFClient::Map
332     new (SV *class, int map_width, int map_height)
333     CODE:
334     New (0, RETVAL, 1, struct map);
335     RETVAL->x = 0;
336     RETVAL->y = 0;
337     RETVAL->w = map_width;
338     RETVAL->h = map_height;
339     RETVAL->faces = 0;
340     RETVAL->face = 0;
341    
342     RETVAL->rows = 0;
343     RETVAL->row = 0;
344     OUTPUT:
345     RETVAL
346    
347     void
348     DESTROY (CFClient::Map self)
349     CODE:
350     {
351     int r, c;
352    
353     Safefree (self->face);
354     for (r = 0; r < self->rows; r++)
355     {
356     maprow *row = self->row + r;
357     if (!row)
358     continue;
359    
360     Safefree (row->col);
361     }
362    
363     Safefree (self->row);
364     Safefree (self);
365     }
366