--- deliantra/Deliantra-Client/Client.xs 2006/04/11 13:05:11 1.14 +++ deliantra/Deliantra-Client/Client.xs 2006/04/12 21:01:45 1.24 @@ -5,12 +5,17 @@ #include #include +#include #include #include #include #include +#include +#include +#include + #include #include #include @@ -22,11 +27,30 @@ typedef struct cf_layout { PangoLayout *pl; int base_height; -} *Crossfire__Client__Layout; +} *CFClient__Layout; + +static void +substitute_func (FcPattern *pattern, gpointer data) +{ + FcPatternAddBool (pattern, FC_HINTING , 1); + FcPatternAddBool (pattern, FC_AUTOHINT, 1); +} + +static void +layout_update (CFClient__Layout self) +{ + /* use a random scale factor to account for unknown descenders, 0.8 works + * reasonably well with bitstream vera + */ + PangoFontDescription *font = pango_context_get_font_description (context); + pango_font_description_set_absolute_size (font, self->base_height * (PANGO_SCALE * 8 / 10)); +} static void -layout_get_pixel_size (Crossfire__Client__Layout self, int *w, int *h) +layout_get_pixel_size (CFClient__Layout self, int *w, int *h) { + layout_update (self); + pango_layout_get_pixel_size (self->pl, w, h); *w = (*w + 3) & ~3; @@ -34,13 +58,14 @@ if (!*h) *h = 1; } -MODULE = Crossfire::Client PACKAGE = Crossfire::Client +MODULE = CFClient PACKAGE = CFClient PROTOTYPES: ENABLE BOOT: { fontmap = pango_ft2_font_map_new (); + pango_ft2_font_map_set_default_substitute ((PangoFT2FontMap *)fontmap, substitute_func, 0, 0); context = pango_ft2_font_map_create_context ((PangoFT2FontMap *)fontmap); } @@ -79,9 +104,64 @@ pango_context_set_font_description (context, font); } -MODULE = Crossfire::Client PACKAGE = Crossfire::Client::Layout +void +load_image_inline (SV *image_) + ALIAS: + load_image_file = 1 + PPCODE: +{ + STRLEN image_len; + char *image = (char *)SvPVbyte (image_, image_len); + SDL_Surface *surface, *surface2; + SDL_PixelFormat fmt; + SDL_RWops *rw = ix + ? SDL_RWFromFile (image, "r") + : SDL_RWFromConstMem (image, image_len); + + if (!rw) + croak ("load_image: unable to open file"); + + surface = IMG_Load_RW (rw, 1); + if (!surface) + croak ("load_image: unable to read file"); + + fmt.palette = NULL; + fmt.BitsPerPixel = 32; + fmt.BytesPerPixel = 4; + fmt.Rmask = 0x000000ff; + fmt.Gmask = 0x0000ff00; + fmt.Bmask = 0x00ff0000; + fmt.Amask = 0xff000000; + fmt.Rloss = 0; + fmt.Gloss = 0; + fmt.Bloss = 0; + fmt.Aloss = 0; + fmt.Rshift = 0; + fmt.Gshift = 8; + fmt.Bshift = 16; + fmt.Ashift = 24; + fmt.colorkey = 0; + fmt.alpha = 0; + + surface2 = SDL_ConvertSurface (surface, &fmt, SDL_SWSURFACE); + + EXTEND (SP, 5); + PUSHs (sv_2mortal (newSViv (surface2->w))); + PUSHs (sv_2mortal (newSViv (surface2->h))); + SDL_LockSurface (surface2); + PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch))); + SDL_UnlockSurface (surface2); + PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB))); + PUSHs (sv_2mortal (newSViv (GL_RGBA))); + PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_INT_8_8_8_8_REV))); -Crossfire::Client::Layout + SDL_FreeSurface (surface); + SDL_FreeSurface (surface2); +} + +MODULE = CFClient PACKAGE = CFClient::Layout + +CFClient::Layout new (SV *class, int base_height = 10) CODE: New (0, RETVAL, 1, struct cf_layout); @@ -92,13 +172,13 @@ RETVAL void -DESTROY (Crossfire::Client::Layout self) +DESTROY (CFClient::Layout self) CODE: g_object_unref (self->pl); Safefree (self); void -set_markup (Crossfire::Client::Layout self, SV *text_) +set_markup (CFClient::Layout self, SV *text_) CODE: { STRLEN textlen; @@ -108,19 +188,22 @@ } void -set_width (Crossfire::Client::Layout self, int max_width = -1) +set_height (CFClient::Layout self, int base_height) + CODE: + self->base_height = base_height; + +void +set_width (CFClient::Layout self, int max_width = -1) CODE: pango_layout_set_width (self->pl, max_width < 0 ? max_width : max_width * PANGO_SCALE); void -size (Crossfire::Client::Layout self) +size (CFClient::Layout self) PPCODE: { int w, h; - PangoFontDescription *font = pango_context_get_font_description (context); - pango_font_description_set_absolute_size (font, self->base_height * PANGO_SCALE); - + layout_update (self); layout_get_pixel_size (self, &w, &h); EXTEND (SP, 2); @@ -128,14 +211,42 @@ PUSHs (sv_2mortal (newSViv (h))); } +int +xy_to_index (CFClient::Layout self, int x, int y) + CODE: +{ + int index, trailing; + + layout_update (self); + pango_layout_xy_to_index (self->pl, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing); + + RETVAL = index; +} + OUTPUT: + RETVAL + +void +cursor_pos (CFClient::Layout self, int index) + PPCODE: +{ + PangoRectangle strong_pos; + layout_update (self); + pango_layout_get_cursor_pos (self->pl, index, &strong_pos, 0); + EXTEND (SP, 3); + PUSHs (sv_2mortal (newSViv (strong_pos.x / PANGO_SCALE))); + PUSHs (sv_2mortal (newSViv (strong_pos.y / PANGO_SCALE))); + PUSHs (sv_2mortal (newSViv (strong_pos.height / PANGO_SCALE))); +} + void -render (Crossfire::Client::Layout self) +render (CFClient::Layout self) PPCODE: { SV *retval; int w, h; FT_Bitmap bitmap; + layout_update (self); layout_get_pixel_size (self, &w, &h); retval = newSV (w * h); @@ -159,7 +270,7 @@ PUSHs (sv_2mortal (retval)); } -MODULE = Crossfire::Client PACKAGE = Crossfire::Client::Texture +MODULE = CFClient PACKAGE = CFClient::Texture void draw_quad (SV *self, double x, double y, double w = 0, double h = 0) @@ -173,8 +284,8 @@ if (items < 5) { - w = SvNV (*hv_fetch (hv, "width", 5, 1)); - h = SvNV (*hv_fetch (hv, "height", 6, 1)); + w = SvNV (*hv_fetch (hv, "w", 1, 1)); + h = SvNV (*hv_fetch (hv, "h", 1, 1)); } glBindTexture (GL_TEXTURE_2D, name);