summaryrefslogtreecommitdiff
path: root/src/xine-engine/osd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xine-engine/osd.c')
-rw-r--r--src/xine-engine/osd.c119
1 files changed, 104 insertions, 15 deletions
diff --git a/src/xine-engine/osd.c b/src/xine-engine/osd.c
index 85837ef84..8e896b9e8 100644
--- a/src/xine-engine/osd.c
+++ b/src/xine-engine/osd.c
@@ -32,6 +32,9 @@
#include <zlib.h>
#include <sys/types.h>
#include <dirent.h>
+#include <errno.h>
+#include <iconv.h>
+#include <langinfo.h>
#include "xine_internal.h"
#include "video_out/alphablend.h"
@@ -44,6 +47,11 @@
#define LOG_DEBUG 1
*/
+#define BINARY_SEARCH 1
+
+/* unicode value of alias character (it used if conversion fails) */
+#define ALIAS_CHARACTER ' '
+
#ifdef MAX
#undef MAX
#endif
@@ -478,7 +486,7 @@ static uint16_t gzread_i16(gzFile *fp) {
load bitmap font into osd engine
*/
-static void osd_renderer_load_font(osd_renderer_t *this, char *filename) {
+static int osd_renderer_load_font(osd_renderer_t *this, char *filename) {
gzFile *fp;
osd_font_t *font = NULL;
@@ -504,14 +512,14 @@ static void osd_renderer_load_font(osd_renderer_t *this, char *filename) {
font->fontchar = malloc( sizeof(osd_fontchar_t) * font->num_fontchars );
#ifdef LOG_DEBUG
- printf("osd: font %s %d\n",font->name, font->num_fontchars);
+ printf("osd: font %s %d\n", font->name, font->num_fontchars);
#endif
for( i = 0; i < font->num_fontchars; i++ ) {
font->fontchar[i].code = gzread_i16(fp);
font->fontchar[i].width = gzread_i16(fp);
font->fontchar[i].height = gzread_i16(fp);
font->fontchar[i].bmp = malloc(font->fontchar[i].width*font->fontchar[i].height);
- if( gzread(fp,font->fontchar[i].bmp,
+ if( gzread(fp, font->fontchar[i].bmp,
font->fontchar[i].width*font->fontchar[i].height) <= 0 )
break;
}
@@ -543,6 +551,7 @@ static void osd_renderer_load_font(osd_renderer_t *this, char *filename) {
}
pthread_mutex_unlock (&this->osd_mutex);
+ return ret;
}
/*
@@ -582,6 +591,7 @@ static int osd_renderer_unload_font(osd_renderer_t *this, char *fontname ) {
else
this->fonts = font->next;
free( font );
+ ret = 1;
break;
}
last = font;
@@ -633,18 +643,46 @@ static int osd_set_font( osd_object_t *osd, const char *fontname, int size) {
}
+#ifdef BINARY_SEARCH
+/*
+ * search the character in the sorted array
+ */
+static int binsearch(osd_fontchar_t *array, size_t n, uint16_t code) {
+ size_t i, left, right;
+
+ if (!n) return 0;
+
+ left = 0;
+ right = n - 1;
+ while (right > left) {
+ i = (left + right) >> 1;
+ if (code <= array[i].code) right = i;
+ else left = i + 1;
+ }
+
+ return array[right].code == code ? right : n;
+}
+#endif
+
+
/*
- * render text on x,y position (8 bits version)
+ * render text on x,y position
* no \n yet
+ * if encoding == NULL current locale encoding is used
*/
static int osd_render_text (osd_object_t *osd, int x1, int y1,
- const char *text, int color_base) {
+ const char *text, const char *encoding,
+ int color_base) {
osd_renderer_t *this = osd->renderer;
osd_font_t *font;
int i, y;
uint8_t *dst, *src;
- int c;
+ iconv_t cd;
+ char *inbuf;
+ uint16_t unicode;
+ size_t inbytesleft;
+ int def_charset_flag = 0;
#ifdef LOG_DEBUG
printf("osd_render_text %p (%d,%d) \"%s\"\n", osd, x1, y1, text);
@@ -658,23 +696,74 @@ static int osd_render_text (osd_object_t *osd, int x1, int y1,
pthread_mutex_lock (&this->osd_mutex);
- font = osd->font;
+ if ((font = osd->font) == NULL) {
+ printf(_("osd: font isn't defined\n"));
+ pthread_mutex_unlock(&this->osd_mutex);
+ return 0;
+ }
if( x1 < osd->x1 ) osd->x1 = x1;
if( y1 < osd->y1 ) osd->y1 = y1;
- while( font && *text ) {
- c = *text & 0xff;
-
+ inbuf = (char *)text;
+ inbytesleft = strlen(text);
+
+ if (!encoding) {
+#ifdef ENABLE_NLS
+ if ((encoding = nl_langinfo(CODESET)) == NULL) {
+ printf(_("osd: can't find out current locale character set\n"));
+ encoding = "iso-8859-1";
+ def_charset_flag = 1;
+ }
+#else
+ encoding = "iso-8859-1";
+ def_charset_flag = 1;
+#endif
+ }
+
+ /* prepare conversion to UCS-2 */
+ if ((cd = iconv_open("UCS-2", encoding)) == (iconv_t)-1) {
+ printf(_("osd: unsupported conversion %s -> UCS-2\n"), encoding);
+ if (!def_charset_flag) {
+ printf("osd: trying iso-8859-1 -> UCS-2\n");
+ if ((cd = iconv_open("UCS-2", "iso-8859-1")) == (iconv_t)-1) {
+ printf(_("osd: iconv_open() failed\n"));
+ pthread_mutex_unlock(&this->osd_mutex);
+ return 0;
+ }
+ }
+ }
+
+ while( inbytesleft ) {
+ char *outbuf = (char*)&unicode;
+ size_t outbytesleft = 2;
+ size_t count;
+
+ /* get unicode value */
+ count = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
+ if (count == (size_t)-1 && errno != E2BIG) {
+ /* unknown character or character wider than 16 bits, try skip one byte */
+ printf(_("osd: unknown sequence starting with byte 0x%02X in encoding \"%s\", skipping\n"),
+ inbuf[0] & 0xFF, encoding);
+ if (!inbytesleft) break;
+ inbytesleft--;
+ inbuf++;
+ unicode = ALIAS_CHARACTER;
+ }
+
+#ifdef BINARY_SEARCH
+ i = binsearch(font->fontchar, font->num_fontchars, unicode);
+#else
for( i = 0; i < font->num_fontchars; i++ ) {
- if( font->fontchar[i].code == c )
+ if( font->fontchar[i].code == unicode )
break;
}
+#endif
#ifdef LOG_DEBUG
- printf("font %s [%c:%d] %dx%d -> %d,%d\n",font->name, c, font->fontchar[i].code,
- font->fontchar[i].width, font->fontchar[i].height,
- x1,y1);
+ printf("font %s [%d, 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);
#endif
if ( i != font->num_fontchars ) {
@@ -701,8 +790,8 @@ static int osd_render_text (osd_object_t *osd, int x1, int y1,
if( y1 + font->fontchar[i].height > osd->y2 )
osd->y2 = y1 + font->fontchar[i].height;
}
- text++;
}
+ iconv_close(cd);
pthread_mutex_unlock (&this->osd_mutex);