summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/xine.h.in14
-rw-r--r--src/xine-engine/osd.c173
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;