From: Dana Jansens Date: Thu, 7 Feb 2008 03:12:54 +0000 (-0500) Subject: allow font rendering to use multiple lines X-Git-Tag: backport~298 X-Git-Url: http://git.openbox.org/?p=dana%2Fopenbox.git;a=commitdiff_plain;h=7867ced6222e1edb9624bd25122a11b808164041 allow font rendering to use multiple lines --- diff --git a/render/font.c b/render/font.c index 29d4821..2f06c73 100644 --- a/render/font.c +++ b/render/font.c @@ -108,7 +108,6 @@ RrFont *RrFontOpen(const RrInstance *inst, const gchar *name, gint size, /* setup the layout */ pango_layout_set_font_description(out->layout, out->font_desc); - pango_layout_set_single_paragraph_mode(out->layout, TRUE); pango_layout_set_wrap(out->layout, PANGO_WRAP_WORD_CHAR); /* get the ascent and descent */ @@ -141,13 +140,20 @@ void RrFontClose(RrFont *f) static void font_measure_full(const RrFont *f, const gchar *str, gint *x, gint *y, gint shadow_x, gint shadow_y, - gint maxwidth) + gboolean flow, gint maxwidth) { PangoRectangle rect; pango_layout_set_text(f->layout, str, -1); - pango_layout_set_width(f->layout, - (maxwidth <= 0 ? -1 : maxwidth * PANGO_SCALE)); + if (flow) { + pango_layout_set_single_paragraph_mode(f->layout, FALSE); + pango_layout_set_width(f->layout, maxwidth * PANGO_SCALE); + } + else { + /* single line mode */ + pango_layout_set_single_paragraph_mode(f->layout, TRUE); + pango_layout_set_width(f->layout, -1); + } /* pango_layout_get_pixel_extents lies! this is the right way to get the size of the text's area */ @@ -166,12 +172,16 @@ static void font_measure_full(const RrFont *f, const gchar *str, } RrSize *RrFontMeasureString(const RrFont *f, const gchar *str, - gint shadow_x, gint shadow_y, gint maxwidth) + gint shadow_x, gint shadow_y, + gboolean flow, gint maxwidth) { RrSize *size; + + g_assert(!flow || maxwidth > 0); + size = g_new(RrSize, 1); font_measure_full(f, str, &size->width, &size->height, shadow_x, shadow_y, - maxwidth); + flow, maxwidth); return size; } @@ -212,16 +222,22 @@ void RrFontDraw(XftDraw *d, RrTextureText *t, RrRect *area) PangoAttrList *attrlist; PangoEllipsizeMode ell; - /* center the text vertically - We do this centering based on the 'baseline' since different fonts have - different top edges. It looks bad when the whole string is moved when 1 - character from a non-default language is included in the string */ - y = area->y + - font_calculate_baseline(t->font, area->height); + g_assert(!t->flow || t->maxwidth > 0); + + y = area->y; + if (!t->flow) + /* center the text vertically + We do this centering based on the 'baseline' since different fonts + have different top edges. It looks bad when the whole string is + moved when 1 character from a non-default language is included in + the string */ + y += font_calculate_baseline(t->font, area->height); /* the +2 and -4 leave a small blank edge on the sides */ x = area->x + 2; - w = area->width - 4; + w = area->width; + if (t->flow) w = MAX(w, t->maxwidth); + w -= 4; h = area->height; switch (t->ellipsize) { @@ -242,6 +258,7 @@ void RrFontDraw(XftDraw *d, RrTextureText *t, RrRect *area) pango_layout_set_text(t->font->layout, t->string, -1); pango_layout_set_width(t->font->layout, w * PANGO_SCALE); pango_layout_set_ellipsize(t->font->layout, ell); + pango_layout_set_single_paragraph_mode(t->font->layout, !t->flow); /* * * end of setting up the layout * * */ @@ -280,10 +297,23 @@ void RrFontDraw(XftDraw *d, RrTextureText *t, RrRect *area) c.pixel = t->shadow_color->pixel; /* see below... */ - pango_xft_render_layout_line - (d, &c, pango_layout_get_line(t->font->layout, 0), - (x + t->shadow_offset_x) * PANGO_SCALE, - (y + t->shadow_offset_y) * PANGO_SCALE); + if (!t->flow) { + pango_xft_render_layout_line + (d, &c, +#if PANGO_VERSION_MAJOR > 1 || \ + (PANGO_VERSION_MAJOR == 1 && PANGO_VERSION_MINOR >= 16) + pango_layout_get_line_readonly(t->font->layout, 0), +#else + pango_layout_get_line(t->font->layout, 0), +#endif + (x + t->shadow_offset_x) * PANGO_SCALE, + (y + t->shadow_offset_y) * PANGO_SCALE); + } + else { + pango_xft_render_layout(d, &c, t->font->layout, + (x + t->shadow_offset_x) * PANGO_SCALE, + (y + t->shadow_offset_y) * PANGO_SCALE); + } } c.color.red = t->color->r | t->color->r << 8; @@ -310,9 +340,23 @@ void RrFontDraw(XftDraw *d, RrTextureText *t, RrRect *area) /* layout_line() uses y to specify the baseline The line doesn't need to be freed, it's a part of the layout */ - pango_xft_render_layout_line - (d, &c, pango_layout_get_line(t->font->layout, 0), - x * PANGO_SCALE, y * PANGO_SCALE); + if (!t->flow) { + pango_xft_render_layout_line + (d, &c, +#if PANGO_VERSION_MAJOR > 1 || \ + (PANGO_VERSION_MAJOR == 1 && PANGO_VERSION_MINOR >= 16) + pango_layout_get_line_readonly(t->font->layout, 0), +#else + pango_layout_get_line(t->font->layout, 0), +#endif + x * PANGO_SCALE, + y * PANGO_SCALE); + } + else { + pango_xft_render_layout(d, &c, t->font->layout, + x * PANGO_SCALE, + y * PANGO_SCALE); + } if (t->shortcut) { t->font->shortcut_underline->start_index = 0; diff --git a/render/render.c b/render/render.c index 2147df0..75dead1 100644 --- a/render/render.c +++ b/render/render.c @@ -180,8 +180,6 @@ RrAppearance *RrAppearanceNew(const RrInstance *inst, gint numtex) void RrAppearanceRemoveTextures(RrAppearance *a) { - gint i; - g_free(a->texture); a->textures = 0; } @@ -387,6 +385,7 @@ gint RrMinWidth(RrAppearance *a) a->texture[i].data.text.string, a->texture[i].data.text.shadow_offset_x, a->texture[i].data.text.shadow_offset_y, + a->texture[i].data.text.flow, a->texture[i].data.text.maxwidth); w = MAX(w, m->width); g_free(m); @@ -413,6 +412,7 @@ gint RrMinHeight(RrAppearance *a) { gint i; gint l, t, r, b; + RrSize *m; gint h = 0; for (i = 0; i < a->textures; ++i) { @@ -423,8 +423,24 @@ gint RrMinHeight(RrAppearance *a) h = MAX(h, a->texture[i].data.mask.mask->height); break; case RR_TEXTURE_TEXT: - h += MAX(h, RrFontHeight(a->texture[i].data.text.font, - a->texture[i].data.text.shadow_offset_y)); + if (a->texture[i].data.text.flow) { + g_assert(a->texture[i].data.text.string != NULL); + + m = RrFontMeasureString + (a->texture[i].data.text.font, + a->texture[i].data.text.string, + a->texture[i].data.text.shadow_offset_x, + a->texture[i].data.text.shadow_offset_y, + a->texture[i].data.text.flow, + a->texture[i].data.text.maxwidth); + h += MAX(h, m->height); + g_free(m); + } + else + h += MAX(h, + RrFontHeight + (a->texture[i].data.text.font, + a->texture[i].data.text.shadow_offset_y)); break; case RR_TEXTURE_RGBA: h += MAX(h, a->texture[i].data.rgba.height); diff --git a/render/render.h b/render/render.h index c812c31..0034ad4 100644 --- a/render/render.h +++ b/render/render.h @@ -141,6 +141,7 @@ struct _RrTextureText { gboolean shortcut; /*!< Underline a character */ guint shortcut_pos; /*!< Position in bytes of the character to underline */ RrEllipsizeMode ellipsize; + gboolean flow; /* allow multiple lines. must set maxwidth below */ gint maxwidth; }; @@ -254,7 +255,7 @@ RrFont *RrFontOpenDefault (const RrInstance *inst); void RrFontClose (RrFont *f); RrSize *RrFontMeasureString (const RrFont *f, const gchar *str, gint shadow_offset_x, gint shadow_offset_y, - gint maxwidth); + gboolean flow, gint maxwidth); gint RrFontHeight (const RrFont *f, gint shadow_offset_y); gint RrFontMaxCharWidth (const RrFont *f); @@ -265,6 +266,8 @@ Pixmap RrPaintPixmap (RrAppearance *a, gint w, gint h); void RrPaint (RrAppearance *a, Window win, gint w, gint h); void RrMinSize (RrAppearance *a, gint *w, gint *h); gint RrMinWidth (RrAppearance *a); +/* For text textures, if flow is TRUE, then the string must be set before + calling this, otherwise it doesn't need to be */ gint RrMinHeight (RrAppearance *a); void RrMargins (RrAppearance *a, gint *l, gint *t, gint *r, gint *b);