Implemented the new multiline text stuff on GTK+.

This commit is contained in:
Pietro Gagliardi 2016-01-16 15:59:34 -05:00
parent 9c6c16be53
commit b0621a6b1f
2 changed files with 54 additions and 11 deletions

View File

@ -547,7 +547,7 @@ static void mkFramesetter(uiDrawTextLayout *layout, struct framesetter *fs)
fs->frameAttrib = NULL; fs->frameAttrib = NULL;
width = layout->width; width = layout->width;
if (width < 0) if (layout->width < 0)
width = CGFLOAT_MAX; width = CGFLOAT_MAX;
// TODO these seem to be floor()'d or truncated? // TODO these seem to be floor()'d or truncated?
fs->extents = CTFramesetterSuggestFrameSizeWithConstraints(fs->fs, fs->extents = CTFramesetterSuggestFrameSizeWithConstraints(fs->fs,
@ -566,6 +566,7 @@ static void freeFramesetter(struct framesetter *fs)
// TODO document that the extent width can be greater than the requested width if the requested width is small enough that only one character can fit // TODO document that the extent width can be greater than the requested width if the requested width is small enough that only one character can fit
// TODO figure out how line separation and leading plays into this // TODO figure out how line separation and leading plays into this
// TODO reconcile differences in character wrapping on platforms
void uiDrawTextLayoutExtents(uiDrawTextLayout *layout, double *width, double *height) void uiDrawTextLayoutExtents(uiDrawTextLayout *layout, double *width, double *height)
{ {
struct framesetter fs; struct framesetter fs;

View File

@ -527,6 +527,12 @@ static const PangoGravity pangoGravities[] = {
[uiDrawTextGravityAuto] = PANGO_GRAVITY_AUTO, [uiDrawTextGravityAuto] = PANGO_GRAVITY_AUTO,
}; };
// we need a context for a few things
// the documentation suggests creating cairo_t-specific, GdkScreen-specific, or even GtkWidget-specific contexts, but we can't really do that because we want our uiDrawTextFonts and uiDrawTextLayouts to be context-independent
// so this will have to do
// TODO really see if there's a better way instead; what do GDK and GTK+ do internally? gdk_pango_context_get()?
#define mkGenericPangoCairoContext() (pango_font_map_create_context(pango_cairo_font_map_get_default()))
uiDrawTextFont *uiDrawLoadClosestFont(const uiDrawTextFontDescriptor *desc) uiDrawTextFont *uiDrawLoadClosestFont(const uiDrawTextFontDescriptor *desc)
{ {
uiDrawTextFont *font; uiDrawTextFont *font;
@ -554,11 +560,8 @@ uiDrawTextFont *uiDrawLoadClosestFont(const uiDrawTextFontDescriptor *desc)
pango_font_description_set_gravity(pdesc, pango_font_description_set_gravity(pdesc,
pangoGravities[desc->Gravity]); pangoGravities[desc->Gravity]);
// we need a context for metrics to be correct // in this case, the context is necessary for the metrics to be correct
// the documentation suggests creating cairo_t-specific, GdkScreen-specific, or even GtkWidget-specific contexts, but we can't really do that because we want our uiDrawTextFonts to be context-independent context = mkGenericPangoCairoContext();
// so this will have to do
// TODO really see if there's a better way instead; what do GDK and GTK+ do internally? gdk_pango_context_get()?
context = pango_font_map_create_context(pango_cairo_font_map_get_default());
font->f = pango_font_map_load_font(pango_cairo_font_map_get_default(), context, pdesc); font->f = pango_font_map_load_font(pango_cairo_font_map_get_default(), context, pdesc);
if (font->f == NULL) { if (font->f == NULL) {
// TODO // TODO
@ -595,6 +598,7 @@ void uiDrawTextFontDescribe(uiDrawTextFont *font, uiDrawTextFontDescriptor *desc
// See https://developer.gnome.org/pango/1.30/pango-Cairo-Rendering.html#pango-Cairo-Rendering.description // See https://developer.gnome.org/pango/1.30/pango-Cairo-Rendering.html#pango-Cairo-Rendering.description
// Note that we convert to double before dividing to make sure the floating-point stuff is right // Note that we convert to double before dividing to make sure the floating-point stuff is right
#define pangoToCairo(pango) (((double) (pango)) / PANGO_SCALE) #define pangoToCairo(pango) (((double) (pango)) / PANGO_SCALE)
#define cairoToPango(cairo) ((gint) ((cairo) * PANGO_SCALE))
// TODO this isn't enough; pango adds extra space to each layout // TODO this isn't enough; pango adds extra space to each layout
void uiDrawTextFontGetMetrics(uiDrawTextFont *font, uiDrawTextFontMetrics *metrics) void uiDrawTextFontGetMetrics(uiDrawTextFont *font, uiDrawTextFontMetrics *metrics)
@ -615,9 +619,10 @@ void uiDrawTextFontGetMetrics(uiDrawTextFont *font, uiDrawTextFontMetrics *metri
struct uiDrawTextLayout { struct uiDrawTextLayout {
char *s; char *s;
PangoFont *defaultFont; PangoFont *defaultFont;
double width;
}; };
uiDrawTextLayout *uiDrawNewTextLayout(const char *text, uiDrawTextFont *defaultFont) uiDrawTextLayout *uiDrawNewTextLayout(const char *text, uiDrawTextFont *defaultFont, double width)
{ {
uiDrawTextLayout *layout; uiDrawTextLayout *layout;
@ -625,6 +630,7 @@ uiDrawTextLayout *uiDrawNewTextLayout(const char *text, uiDrawTextFont *defaultF
layout->s = g_strdup(text); layout->s = g_strdup(text);
layout->defaultFont = defaultFont->f; layout->defaultFont = defaultFont->f;
g_object_ref(layout->defaultFont); // retain a copy g_object_ref(layout->defaultFont); // retain a copy
uiDrawTextLayoutSetWidth(layout, width);
return layout; return layout;
} }
@ -635,12 +641,15 @@ void uiDrawFreeTextLayout(uiDrawTextLayout *layout)
uiFree(layout); uiFree(layout);
} }
void uiDrawText(uiDrawContext *c, double x, double y, uiDrawTextLayout *layout) void uiDrawTextLayoutSetWidth(uiDrawTextLayout *layout, double width)
{ {
PangoLayout *pl; layout->width = width;
PangoFontDescription *desc; }
pl = pango_cairo_create_layout(c->cr); static void prepareLayout(uiDrawTextLayout *layout, PangoLayout *pl)
{
PangoFontDescription *desc;
int width;
pango_layout_set_text(pl, layout->s, -1); pango_layout_set_text(pl, layout->s, -1);
@ -650,6 +659,39 @@ void uiDrawText(uiDrawContext *c, double x, double y, uiDrawTextLayout *layout)
pango_layout_set_font_description(pl, desc); pango_layout_set_font_description(pl, desc);
pango_font_description_free(desc); pango_font_description_free(desc);
width = cairoToPango(layout->width);
if (layout->width < 0)
width = -1;
pango_layout_set_width(pl, width);
}
void uiDrawTextLayoutExtents(uiDrawTextLayout *layout, double *width, double *height)
{
PangoContext *context;
PangoLayout *pl;
PangoRectangle logical;
// in this case, the context is necessary to create the layout
context = mkGenericPangoCairoContext();
pl = pango_layout_new(context);
// TODO g_object_unref() context?
prepareLayout(layout, pl);
pango_layout_get_extents(pl, NULL, &logical);
g_object_unref(pl);
*width = pangoToCairo(logical.width);
*height = pangoToCairo(logical.height);
}
void uiDrawText(uiDrawContext *c, double x, double y, uiDrawTextLayout *layout)
{
PangoLayout *pl;
pl = pango_cairo_create_layout(c->cr);
prepareLayout(layout, pl);
cairo_move_to(c->cr, x, y); cairo_move_to(c->cr, x, y);
pango_cairo_show_layout(c->cr, pl); pango_cairo_show_layout(c->cr, pl);