summaryrefslogtreecommitdiffstats
path: root/sub
diff options
context:
space:
mode:
authorwm4 <wm4@mplayer2.org>2011-10-23 05:26:15 +0200
committerwm4 <wm4@mplayer2.org>2012-07-28 20:57:37 +0200
commitac771d288d5a34a10d193bd9352c8f5c744df20f (patch)
tree3c0635ec283c1f8b7726eec7745f72a4cbcc21bc /sub
parent2b5fd80253d357deff6b14ca6777fd08d6fef041 (diff)
downloadmpv-ac771d288d5a34a10d193bd9352c8f5c744df20f.tar.bz2
mpv-ac771d288d5a34a10d193bd9352c8f5c744df20f.tar.xz
osd: enable line breaking for OSD text
OSD text wider than the window will be broken to fit the width. The line breaking algorithm is naive and intended as temporary, until the OSD render code is possibly replaced by "something better". Newline characters are also considered.
Diffstat (limited to 'sub')
-rw-r--r--sub/sub.c98
1 files changed, 67 insertions, 31 deletions
diff --git a/sub/sub.c b/sub/sub.c
index efe648948c..744642dfdd 100644
--- a/sub/sub.c
+++ b/sub/sub.c
@@ -190,43 +190,79 @@ no_utf8:
return c;
}
+//if obj is NULL, don't render, and just return the metrics
+//sw, sh: screen width/height
+//out_w/out_h: return width/height of the text box (write-only)
+static void vo_update_text_osd_render(const char *cp, mp_osd_obj_t *obj,
+ int sw, int sh, int *out_w, int *out_h)
+{
+ int x = 0;
+ int y = 0;
+ int line_height = get_height('t', 0);
+ int w = 0;
+ int h = line_height;
+ int font;
+
+ while (*cp && h < sh && line_height > 0) {
+ const char* prev = cp;
+ uint16_t c = utf8_get_char(&cp);
+ int lf = (c == '\n');
+ int newx;
+ render_one_glyph(vo_font, c);
+ newx = x + vo_font->width[c];
+ if (lf || (newx > sw)) {
+ if (!lf)
+ cp = prev;
+ //can't put at least one char per line?
+ //rare but nasty corner case... simply exit and avoid endless loop
+ if (!lf && x == 0)
+ break;
+ y += h;
+ h = line_height;
+ w = FFMAX(x, w);
+ x = 0;
+ continue;
+ }
+ if (obj && (font = vo_font->font[c]) >= 0)
+ draw_alpha_buf(obj, obj->x + x, obj->y + y,
+ vo_font->width[c],
+ vo_font->pic_a[font]->h,
+ vo_font->pic_b[font]->bmp + vo_font->start[c],
+ vo_font->pic_a[font]->bmp + vo_font->start[c],
+ vo_font->pic_a[font]->w);
+ x = newx + vo_font->charspace;
+ h = get_height(c, h);
+ }
+
+ y += h;
+ w = FFMAX(x, w) - vo_font->charspace;
+
+ *out_w = FFMAX(w, 0);
+ *out_h = y;
+}
+
inline static void vo_update_text_osd(struct osd_state *osd, mp_osd_obj_t* obj,
int dxs, int dys)
{
const char *cp = osd->osd_text;
- int x=20;
- int h=0;
- int font;
-
- obj->bbox.x1=obj->x=x;
- obj->bbox.y1=obj->y=10;
-
- while (*cp){
- uint16_t c=utf8_get_char(&cp);
- render_one_glyph(vo_font, c);
- x+=vo_font->width[c]+vo_font->charspace;
- h=get_height(c,h);
- }
+ int w, h, sw, sh;
- obj->bbox.x2=x-vo_font->charspace;
- obj->bbox.y2=obj->bbox.y1+h;
- obj->flags|=OSDFLAG_BBOX;
+ obj->bbox.x1 = obj->x = 20;
+ obj->bbox.y1 = obj->y = 10;
+ sw = dxs - obj->x;
+ sh = dys - obj->y;
- alloc_buf(obj);
-
- cp = osd->osd_text;
- x = obj->x;
- while (*cp){
- uint16_t c=utf8_get_char(&cp);
- if ((font=vo_font->font[c])>=0)
- draw_alpha_buf(obj,x,obj->y,
- vo_font->width[c],
- vo_font->pic_a[font]->h,
- vo_font->pic_b[font]->bmp+vo_font->start[c],
- vo_font->pic_a[font]->bmp+vo_font->start[c],
- vo_font->pic_a[font]->w);
- x+=vo_font->width[c]+vo_font->charspace;
- }
+ //first pass: calculate obj bounding box
+ vo_update_text_osd_render(cp, NULL, sw, sh, &w, &h);
+
+ obj->bbox.x2 = obj->bbox.x1 + w;
+ obj->bbox.y2 = obj->bbox.y1 + h;
+ obj->flags |= OSDFLAG_BBOX;
+
+ alloc_buf(obj);
+
+ //second pass: actually draw the text
+ vo_update_text_osd_render(cp, obj, sw, sh, &w, &h);
}
#ifdef CONFIG_DVDNAV