Did most of the work for grapheme cluster boundary based text layout characters on GTK+.

This commit is contained in:
Pietro Gagliardi 2016-05-25 01:52:53 -04:00
parent a8aa842172
commit ac652f0690
7 changed files with 58 additions and 22 deletions

View File

@ -19,6 +19,7 @@ CFILES += \
unix/editablecombo.c \ unix/editablecombo.c \
unix/entry.c \ unix/entry.c \
unix/fontbutton.c \ unix/fontbutton.c \
unix/graphemes.c \
unix/group.c \ unix/group.c \
unix/label.c \ unix/label.c \
unix/main.c \ unix/main.c \

View File

@ -173,34 +173,22 @@ void uiDrawTextFontGetMetrics(uiDrawTextFont *font, uiDrawTextFontMetrics *metri
// note: PangoCairoLayouts are tied to a given cairo_t, so we can't store one in this device-independent structure // note: PangoCairoLayouts are tied to a given cairo_t, so we can't store one in this device-independent structure
struct uiDrawTextLayout { struct uiDrawTextLayout {
char *s; char *s;
ptrdiff_t *charsToBytes; PangoGlyphString *glyphString;
PangoFont *defaultFont; PangoFont *defaultFont;
double width; double width;
PangoAttrList *attrs; PangoAttrList *attrs;
}; };
static ptrdiff_t *computeCharsToBytes(const char *s)
{
ptrdiff_t *charsToBytes;
glong i, charlen;
// we INCLUDE the null terminator as a character in the string
// g_utf8_offset_to_pointer() doesn't stop on null terminator so this should work
charlen = g_utf8_strlen(s, -1) + 1;
charsToBytes = (ptrdiff_t *) uiAlloc(charlen * sizeof (ptrdiff_t), "ptrdiff_t[]");
// TODO speed this up by not needing to scan the whole string again
for (i = 0; i < charlen; i++)
charsToBytes[i] = g_utf8_offset_to_pointer(s, i) - s;
return charsToBytes;
}
uiDrawTextLayout *uiDrawNewTextLayout(const char *text, uiDrawTextFont *defaultFont, double width) uiDrawTextLayout *uiDrawNewTextLayout(const char *text, uiDrawTextFont *defaultFont, double width)
{ {
uiDrawTextLayout *layout; uiDrawTextLayout *layout;
PangoContext *context;
layout = uiNew(uiDrawTextLayout); layout = uiNew(uiDrawTextLayout);
layout->s = g_strdup(text); layout->s = g_strdup(text);
layout->charsToBytes = computeCharsToBytes(layout->s); context = mkGenericPangoCairoContext();
layout->glyphString = graphemes(layout->s, context);
g_object_unref(context);
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); uiDrawTextLayoutSetWidth(layout, width);
@ -212,7 +200,7 @@ void uiDrawFreeTextLayout(uiDrawTextLayout *layout)
{ {
pango_attr_list_unref(layout->attrs); pango_attr_list_unref(layout->attrs);
g_object_unref(layout->defaultFont); g_object_unref(layout->defaultFont);
uiFree(layout->charsToBytes); pango_glyph_string_free(layout->glyphString);
g_free(layout->s); g_free(layout->s);
uiFree(layout); uiFree(layout);
} }
@ -279,8 +267,8 @@ void uiDrawText(uiDrawContext *c, double x, double y, uiDrawTextLayout *layout)
static void addAttr(uiDrawTextLayout *layout, PangoAttribute *attr, intmax_t startChar, intmax_t endChar) static void addAttr(uiDrawTextLayout *layout, PangoAttribute *attr, intmax_t startChar, intmax_t endChar)
{ {
attr->start_index = layout->charsToBytes[startChar]; attr->start_index = layout->glyphString->log_clusters[startChar];
attr->end_index = layout->charsToBytes[endChar]; attr->end_index = layout->glyphString->log_clusters[endChar];
pango_attr_list_insert(layout->attrs, attr); pango_attr_list_insert(layout->attrs, attr);
// pango_attr_list_insert() takes attr; we don't free it // pango_attr_list_insert() takes attr; we don't free it
} }

41
unix/graphemes.c Normal file
View File

@ -0,0 +1,41 @@
// 25 may 2016
#include "uipriv_unix.H"
// TODO this breaks for non-BMP characters?
struct gparam {
const char *text;
PangoGlyphString *glyphString;
};
static void runItem(gpointer it, gpointer data)
{
PangoItem *item = (PangoItem *) it;
struct gparam *gparam = (struct gparam *) data;
pango_shape(gparam->text + item->offset,
item->length,
&(item->analysis),
gparam->glyphString);
pango_item_free(item);
}
PangoGlyphString *graphemes(const char *text, PangoContext *context)
{
size_t len;
GList *list;
struct gparam gparam;
len = strlen(text);
list = pango_itemize(context,
text, 0, len,
NULL, NULL);
gparam.text = text;
gparam.glyphString = pango_glyph_string_new();
g_list_foreach(list, runItem, &gparam);
g_list_free(list);
return gparam.glyphString;
}

View File

@ -7,6 +7,7 @@
#include <math.h> #include <math.h>
#include <dlfcn.h> // see drawtext.c #include <dlfcn.h> // see drawtext.c
#include <langinfo.h> #include <langinfo.h>
#include <string.h>
#include "../ui.h" #include "../ui.h"
#include "../ui_unix.h" #include "../ui_unix.h"
#include "../common/uipriv.h" #include "../common/uipriv.h"
@ -42,5 +43,10 @@ extern void childSetMargined(struct child *c, int margined);
// draw.c // draw.c
extern uiDrawContext *newContext(cairo_t *); extern uiDrawContext *newContext(cairo_t *);
extern void freeContext(uiDrawContext *); extern void freeContext(uiDrawContext *);
// drawtext.c
extern uiDrawTextFont *mkTextFont(PangoFont *f, gboolean add); extern uiDrawTextFont *mkTextFont(PangoFont *f, gboolean add);
extern PangoFont *pangoDescToPangoFont(PangoFontDescription *pdesc); extern PangoFont *pangoDescToPangoFont(PangoFontDescription *pdesc);
// graphemes.c
extern PangoGlyphString *graphemes(const char *text, PangoContext *context);

View File

@ -28,7 +28,7 @@ CXXFILES += \
windows/events.cpp \ windows/events.cpp \
windows/fontbutton.cpp \ windows/fontbutton.cpp \
windows/fontdialog.cpp \ windows/fontdialog.cpp \
windows/grapheme.cpp \ windows/graphemes.cpp \
windows/group.cpp \ windows/group.cpp \
windows/init.cpp \ windows/init.cpp \
windows/label.cpp \ windows/label.cpp \

View File

@ -140,7 +140,7 @@ extern BOOL showColorDialog(HWND parent, struct colorDialogRGBA *c);
// sizing.cpp // sizing.cpp
extern void getSizing(HWND hwnd, uiWindowsSizing *sizing, HFONT font); extern void getSizing(HWND hwnd, uiWindowsSizing *sizing, HFONT font);
// grapheme.cpp // graphemes.cpp
extern size_t *graphemes(WCHAR *msg); extern size_t *graphemes(WCHAR *msg);