--- deliantra/Deliantra-Client/Client.xs 2006/05/08 18:28:40 1.75 +++ deliantra/Deliantra-Client/Client.xs 2006/05/11 23:41:45 1.76 @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -20,6 +21,7 @@ #include #include #include +#include #ifndef _WIN32 # include @@ -66,14 +68,16 @@ typedef PangoFontDescription *CFClient__Font; typedef struct cf_layout { - PangoLayout *pl; + PangoLayout *pl; // either derived from a cairo or ft2 context + int rgba; // wether we use rgba (cairo) or grayscale (ft2) + float r, g, b, a; // default color for rgba mode int base_height; CFClient__Font font; } *CFClient__Layout; static CFClient__Font default_font; -static PangoContext *context; -static PangoFontMap *fontmap; +static PangoContext *ft2_context, *cairo_context; +static PangoFontMap *ft2_fontmap, *cairo_fontmap; static void substitute_func (FcPattern *pattern, gpointer data) @@ -101,9 +105,10 @@ { pango_layout_get_pixel_size (self->pl, w, h); - *w = (*w + 3) & ~3; if (!*w) *w = 1; if (!*h) *h = 1; + + *w = (*w + 3) & ~3; } typedef uint16_t mapface; @@ -402,9 +407,12 @@ for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); - 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); + ft2_fontmap = pango_ft2_font_map_new (); + pango_ft2_font_map_set_default_substitute ((PangoFT2FontMap *)ft2_fontmap, substitute_func, 0, 0); + ft2_context = pango_ft2_font_map_create_context ((PangoFT2FontMap *)ft2_fontmap); + + cairo_fontmap = pango_cairo_font_map_get_default (); + cairo_context = pango_cairo_font_map_create_context ((PangoCairoFontMap *)cairo_fontmap); } int @@ -689,14 +697,21 @@ MODULE = CFClient PACKAGE = CFClient::Layout CFClient::Layout -new (SV *class, int base_height = MIN_FONT_HEIGHT) +new (SV *class, int rgba = 0) CODE: New (0, RETVAL, 1, struct cf_layout); - RETVAL->pl = pango_layout_new (context); - RETVAL->base_height = base_height; - RETVAL->font = 0; + + RETVAL->pl = pango_layout_new (rgba ? cairo_context : ft2_context); + RETVAL->rgba = rgba; + RETVAL->r = 1.; + RETVAL->g = 1.; + RETVAL->b = 1.; + RETVAL->a = 1.; + RETVAL->base_height = MIN_FONT_HEIGHT; + RETVAL->font = 0; + pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR); - pango_layout_set_font_description (RETVAL->pl, default_font); + layout_update_font (RETVAL); OUTPUT: RETVAL @@ -706,6 +721,13 @@ g_object_unref (self->pl); Safefree (self); +int +is_rgba (CFClient::Layout self) + CODE: + RETVAL = self->rgba; + OUTPUT: + RETVAL + void set_text (CFClient::Layout self, SV *text_) CODE: @@ -735,6 +757,14 @@ RETVAL void +set_foreground (CFClient::Layout self, float r, float g, float b, float a = 1.) + CODE: + self->r = r; + self->g = g; + self->b = b; + self->a = a; + +void set_font (CFClient::Layout self, CFClient::Font font = 0) CODE: if (self->font != font) @@ -800,29 +830,77 @@ { SV *retval; int w, h; - FT_Bitmap bitmap; layout_get_pixel_size (self, &w, &h); - retval = newSV (w * h); - SvPOK_only (retval); - SvCUR_set (retval, w * h); - - bitmap.rows = h; - bitmap.width = w; - bitmap.pitch = w; - bitmap.buffer = (unsigned char*)SvPVX (retval); - bitmap.num_grays = 256; - bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; + if (self->rgba) + { + cairo_surface_t *surface; + cairo_t *cairo; - memset (bitmap.buffer, 0, w * h); - - pango_ft2_render_layout (&bitmap, self->pl, 0 * PANGO_SCALE, 0 * PANGO_SCALE); + retval = newSV (w * h * 4); + SvPOK_only (retval); + SvCUR_set (retval, w * h * 4); - EXTEND (SP, 3); - PUSHs (sv_2mortal (newSViv (w))); - PUSHs (sv_2mortal (newSViv (h))); - PUSHs (sv_2mortal (retval)); + memset (SvPVX (retval), 0, w * h * 4); + + surface = cairo_image_surface_create_for_data ( + (void*)SvPVX (retval), CAIRO_FORMAT_ARGB32, w, h, w * 4); + cairo = cairo_create (surface); + cairo_set_source_rgba (cairo, self->r, self->g, self->b, self->a); + + pango_cairo_show_layout (cairo, self->pl); + + cairo_destroy (cairo); + cairo_surface_destroy (surface); + + // what a mess, and its premultiplied, too :( + { + uint32_t *p = (uint32_t *)SvPVX (retval); + uint32_t *e = p + w * h; + + while (p < e) + { + uint32_t rgba = *p; + rgba = (rgba >> 24) | (rgba << 8); + rgba = SDL_SwapBE32 (rgba); + *p++ = rgba; + } + } + + EXTEND (SP, 5); + PUSHs (sv_2mortal (newSViv (w))); + PUSHs (sv_2mortal (newSViv (h))); + PUSHs (sv_2mortal (retval)); + PUSHs (sv_2mortal (newSViv (GL_RGBA))); + PUSHs (sv_2mortal (newSViv (GL_RGBA))); + } + else + { + FT_Bitmap bitmap; + + retval = newSV (w * h); + SvPOK_only (retval); + SvCUR_set (retval, w * h); + + bitmap.rows = h; + bitmap.width = w; + bitmap.pitch = w; + bitmap.buffer = (unsigned char*)SvPVX (retval); + bitmap.num_grays = 256; + bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; + + memset (bitmap.buffer, 0, w * h); + + pango_ft2_render_layout (&bitmap, self->pl, 0 * PANGO_SCALE, 0 * PANGO_SCALE); + + EXTEND (SP, 5); + PUSHs (sv_2mortal (newSViv (w))); + PUSHs (sv_2mortal (newSViv (h))); + PUSHs (sv_2mortal (retval)); + PUSHs (sv_2mortal (newSViv (GL_ALPHA))); + PUSHs (sv_2mortal (newSViv (GL_ALPHA))); + } } MODULE = CFClient PACKAGE = CFClient::Texture @@ -830,6 +908,9 @@ void draw_quad (SV *self, float x, float y, float w = 0, float h = 0) PROTOTYPE: $$$;$$ + ALIAS: + draw_quad_alpha = 1 + draw_quad_alpha_premultiplied = 2 CODE: { HV *hv = (HV *)SvRV (self); @@ -844,17 +925,29 @@ h = SvNV (*hv_fetch (hv, "h", 1, 1)); } + if (ix) + { + glEnable (GL_BLEND); + glBlendFunc (ix == 1 ? GL_SRC_ALPHA : GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + glBindTexture (GL_TEXTURE_2D, name); - if (wrap_mode) { - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - } + + if (wrap_mode) + { + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + } + glBegin (GL_QUADS); glTexCoord2f (0, 0); glVertex2f (x , y ); glTexCoord2f (0, t); glVertex2f (x , y + h); glTexCoord2f (s, t); glVertex2f (x + w, y + h); glTexCoord2f (s, 0); glVertex2f (x + w, y ); glEnd (); + + if (ix) + glDisable (GL_BLEND); } MODULE = CFClient PACKAGE = CFClient::Map @@ -1387,6 +1480,7 @@ const_iv (GL_RGBA), const_iv (GL_UNSIGNED_BYTE), const_iv (GL_ALPHA), + const_iv (GL_LUMINANCE), const_iv (GL_FLOAT), const_iv (GL_UNSIGNED_INT_8_8_8_8_REV), const_iv (GL_COMPILE),