diff options
-rw-r--r-- | include/xine.h.in | 14 | ||||
-rw-r--r-- | src/xine-engine/osd.c | 173 |
2 files changed, 122 insertions, 65 deletions
diff --git a/include/xine.h.in b/include/xine.h.in index 5965b4d96..415e8c2d7 100644 --- a/include/xine.h.in +++ b/include/xine.h.in @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: xine.h.in,v 1.136 2004/12/14 20:45:22 miguelfreitas Exp $ + * $Id: xine.h.in,v 1.137 2005/01/22 23:29:06 holstsn Exp $ * * public xine-lib (libxine) interface and documentation * @@ -1822,15 +1822,14 @@ void xine_osd_draw_line (xine_osd_t *self, int x1, int y1, void xine_osd_draw_rect (xine_osd_t *self, int x1, int y1, int x2, int y2, int color, int filled ); -/* for freetype2 fonts x1 and y1 specifies the beginning of the baseline, - for xine fonts x1 and y1 specifies the upper left corner of the text - to be rendered */ +/* x1 and y1 specifies the upper left corner of the text to be rendered */ void xine_osd_draw_text (xine_osd_t *self, int x1, int y1, const char *text, int color_base); void xine_osd_draw_bitmap (xine_osd_t *self, uint8_t *bitmap, int x1, int y1, int width, int height, uint8_t *palette_map); -/* for freetype2 fonts the height is taken from _baseline_ to top */ +/* for freetype2 fonts the height is the maximum height for the whole font and not + * only for the specified text */ void xine_osd_get_text_size (xine_osd_t *self, const char *text, int *width, int *height); /* with freetype2 support compiled in, you can also specify a font file @@ -1859,6 +1858,11 @@ void xine_osd_clear (xine_osd_t *self); * color index, up to the size of the text palette. * * Use OSD_TEXT1, OSD_TEXT2, ... for some preassigned color indices. + * + * these palettes are not really well working the true type fonts. + * First thing is that these fonts can not have a border. So the best + * result you can get by loading a linearly blending palette from the + * background (at index 0) to the forground color (at index 10) */ void xine_osd_set_text_palette (xine_osd_t *self, int palette_number, diff --git a/src/xine-engine/osd.c b/src/xine-engine/osd.c index 17f09c2c5..de5c97073 100644 --- a/src/xine-engine/osd.c +++ b/src/xine-engine/osd.c @@ -990,6 +990,10 @@ static int osd_render_text (osd_object_t *osd, int x1, int y1, uint16_t unicode; size_t inbytesleft; +#ifdef HAVE_FT2 + FT_UInt previous = 0; +#endif + lprintf("osd=%p (%d,%d) \"%s\"\n", osd, x1, y1, text); /* some sanity checks for the color indices */ @@ -1015,6 +1019,11 @@ static int osd_render_text (osd_object_t *osd, int x1, int y1, } } +#ifdef HAVE_FT2 + FT_Bool use_kerning = osd->ft2 && osd->ft2->useme && FT_HAS_KERNING(osd->ft2->face); + int first = 1; +#endif + if( x1 < osd->x1 ) osd->x1 = x1; if( y1 < osd->y1 ) osd->y1 = y1; @@ -1031,90 +1040,100 @@ static int osd_render_text (osd_object_t *osd, int x1, int y1, inbytesleft--; #endif + #ifdef HAVE_FT2 if (osd->ft2 && osd->ft2->useme) { - i = FT_Get_Char_Index( osd->ft2->face, unicode ); - } else { -#endif - - i = osd_search(font->fontchar, font->num_fontchars, unicode); + int gheight, gwidth; - lprintf("font '%s' [%d, U+%04X == U+%04X] %dx%d -> %d,%d\n", font->name, i, - unicode, font->fontchar[i].code, font->fontchar[i].width, - font->fontchar[i].height, x1, y1); + FT_GlyphSlot slot = osd->ft2->face->glyph; -#ifdef HAVE_FT2 - } /* !(osd->ft2 && osd->ft2->useme) */ -#endif + i = FT_Get_Char_Index( osd->ft2->face, unicode ); + + /* add kerning relative to the previous letter */ + if (use_kerning && previous && i) { + FT_Vector delta; + FT_Get_Kerning(osd->ft2->face, previous, i, FT_KERNING_DEFAULT, &delta); + x1 += delta.x / 64; + } + previous = i; -#ifdef HAVE_FT2 - if (osd->ft2 && osd->ft2->useme) { - int gheight, gwidth; - FT_GlyphSlot slot = osd->ft2->face->glyph; - if (FT_Load_Glyph(osd->ft2->face, i, FT_LOAD_DEFAULT)) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("osd: error loading glyph\n")); - continue; + continue; } if (slot->format != ft_glyph_format_bitmap) { - if (FT_Render_Glyph(osd->ft2->face->glyph, ft_render_mode_normal)) - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("osd: error in rendering glyph\n")); + if (FT_Render_Glyph(slot, ft_render_mode_normal)) + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("osd: error in rendering glyph\n")); } - dst = osd->area + y1 * osd->width + x1; + /* we shift the whole glyph down by it's ascender so that the specified coordinate + * is the top left corner which is much more practical than the baseline as the user + * normally has no idea where the baseline is + */ + dst = osd->area + (y1+(osd->ft2->face->ascender/64)-slot->bitmap_top) * osd->width; src = (uint8_t*) slot->bitmap.buffer; gheight = slot->bitmap.rows; gwidth = slot->bitmap.width; + if (first) x1 -= slot->bitmap_left; + first = 0; + for( y = 0; y < gheight; y++ ) { uint8_t *s = src; - uint8_t *d = dst - - slot->bitmap_top * osd->width - + slot->bitmap_left; - - while (s < src + gwidth) { - if(d <= (osd->area + (osd->width * osd->height))) - *d = (uint8_t)(*s/26+1) + (uint8_t) color_base; - - d++; - s++; - } + uint8_t *d = dst + x1 + slot->bitmap_left; + + while (s < src + gwidth) { + if ((d > osd->area) && (d < osd->area + osd->width * osd->height) && + (d < dst + osd->width) && (*s > 0)) + *d = (uint8_t)(*s/25) + (uint8_t) color_base; + + d++; + s++; + } src += slot->bitmap.pitch; dst += osd->width; } + x1 += slot->advance.x >> 6; if( x1 > osd->x2 ) osd->x2 = x1; if( y1 > osd->y2 ) osd->y2 = y1; } else { + #endif - if ( i != font->num_fontchars ) { - dst = osd->area + y1 * osd->width + x1; - src = font->fontchar[i].bmp; + i = osd_search(font->fontchar, font->num_fontchars, unicode); + + lprintf("font '%s' [%d, U+%04X == U+%04X] %dx%d -> %d,%d\n", font->name, i, + unicode, font->fontchar[i].code, font->fontchar[i].width, + font->fontchar[i].height, x1, y1); + + if ( i != font->num_fontchars ) { + dst = osd->area + y1 * osd->width + x1; + src = font->fontchar[i].bmp; + + for( y = 0; y < font->fontchar[i].height; y++ ) { + int width = font->fontchar[i].width; + uint8_t *s = src, *d = dst; + + while (s < src + width) { + if(d <= (osd->area + (osd->width * osd->height)) + && *s > 1) /* skip drawing transparency */ + *d = *s + (uint8_t) color_base; + + d++; + s++; + } + src += font->fontchar[i].width; + dst += osd->width; + } + x1 += font->fontchar[i].width - (font->fontchar[i].width * FONT_OVERLAP); - for( y = 0; y < font->fontchar[i].height; y++ ) { - int width = font->fontchar[i].width; - uint8_t *s = src, *d = dst; - - while (s < src + width) { - if(d <= (osd->area + (osd->width * osd->height)) - && *s > 1) /* skip drawing transparency */ - *d = *s + (uint8_t) color_base; - - d++; - s++; - } - src += font->fontchar[i].width; - dst += osd->width; + if( x1 > osd->x2 ) osd->x2 = x1; + if( y1 + font->fontchar[i].height > osd->y2 ) + osd->y2 = y1 + font->fontchar[i].height; } - x1 += font->fontchar[i].width - (font->fontchar[i].width * FONT_OVERLAP); - - if( x1 > osd->x2 ) osd->x2 = x1; - if( y1 + font->fontchar[i].height > osd->y2 ) - osd->y2 = y1 + font->fontchar[i].height; - } #ifdef HAVE_FT2 } /* !(osd->ft2 && osd->ft2->useme) */ @@ -1158,6 +1177,13 @@ static int osd_get_text_size(osd_object_t *osd, const char *text, int *width, in } } +#ifdef HAVE_FT2 + /* not all free type fonts provide kerning */ + FT_Bool use_kerning = osd->ft2 && osd->ft2->useme && FT_HAS_KERNING(osd->ft2->face); + FT_UInt previous = 0; + int first_glyph = 1; +#endif + *width = 0; *height = 0; @@ -1176,11 +1202,18 @@ static int osd_get_text_size(osd_object_t *osd, const char *text, int *width, in #ifdef HAVE_FT2 if (osd->ft2 && osd->ft2->useme) { - int first = 1; FT_GlyphSlot slot = osd->ft2->face->glyph; i = FT_Get_Char_Index( osd->ft2->face, unicode); + /* kerning add the relative to the previous letter */ + if (use_kerning && previous && i) { + FT_Vector delta; + FT_Get_Kerning(osd->ft2->face, previous, i, FT_KERNING_DEFAULT, &delta); + *width += delta.x / 64; + } + previous = i; + if (FT_Load_Glyph(osd->ft2->face, i, FT_LOAD_DEFAULT)) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("osd: error loading glyph %i\n"), i); text++; @@ -1189,13 +1222,17 @@ static int osd_get_text_size(osd_object_t *osd, const char *text, int *width, in if (slot->format != ft_glyph_format_bitmap) { if (FT_Render_Glyph(osd->ft2->face->glyph, ft_render_mode_normal)) - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("osd: error in rendering\n")); + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("osd: error in rendering\n")); } - if (first) *width += slot->bitmap_left; - first = 0; + /* left shows the left edge relative to the base point. A positive value means the + * letter is shifted right, so we need to subtract the value from the width + */ + if (first_glyph) *width -= slot->bitmap_left; + first_glyph = 0; *width += slot->advance.x >> 6; - /* font height from baseline to top */ - *height = MAX(*height, slot->bitmap_top); + /* we return the height of the font for the height, so we are on the save side + */ + *height = osd->ft2->face->height >> 6; text++; } else { #endif @@ -1211,6 +1248,22 @@ static int osd_get_text_size(osd_object_t *osd, const char *text, int *width, in #endif } +#ifdef HAVE_FT2 + if (osd->ft2 && osd->ft2->useme) { + /* if we have a true type font we need to do some corrections for the last + * letter. As this one is still in the gylph slot we can still work with + * it. For the last letter be must not use advance and width but the real + * width of the bitmap. We're right from the base point so we subtract the + * advance value that was added in the for-loop and add the width. We have + * to also add the left bearing because the letter might be shifted left or + * right and then the right edge is also shifted + */ + *width -= osd->ft2->face->glyph->advance.x >> 6; + *width += osd->ft2->face->glyph->bitmap.width; + *width += osd->ft2->face->glyph->bitmap_left; + } +#endif + pthread_mutex_unlock (&this->osd_mutex); return 1; |