+static int __layout_text_split(cairo_text_extents_t* extents, cairo_t* cr, const uint8_t* text, int len)
+{
+ int i;
+ for (i = len; i > 0; i--) {
+ int c = text[i];
+
+ if ('\0' == c || ' ' == c || '\t' == c || '\r' == c || '\n' == c || '-' == c)
+ break;
+ else if (c < 0x80)
+ continue;
+
+ if ((c >> 6) != 0x2)
+ break;
+ }
+
+ if (i > 0)
+ len = i;
+
+ scf_string_t* s = scf_string_cstr_len(text, len);
+ if (!s)
+ return -ENOMEM;
+ cairo_text_extents(cr, s->data, extents);
+
+ scf_string_free(s);
+ return len;
+}
+
+int __layout_text(cairo_text_extents_t* extents, cairo_t* cr, abc_obj_t* obj, int width)
+{
+ abc_obj_t* attr;
+ abc_obj_t* style;
+
+ attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT);
+ if (attr) {
+ int bold = CAIRO_FONT_WEIGHT_NORMAL;
+ int italic = CAIRO_FONT_SLANT_NORMAL;
+
+ style = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_STYLE);
+ if (style) {
+ if (!__html_strcmp(style->value->data, "bold"))
+ bold = CAIRO_FONT_WEIGHT_BOLD;
+
+ else if (!__html_strcmp(style->value->data, "italic") || !__html_strcmp(style->value->data, "oblique"))
+ italic = CAIRO_FONT_SLANT_OBLIQUE;
+ }
+
+ cairo_select_font_face(cr, attr->value->data, italic, bold);
+ }
+
+ int size = 16;
+ attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_SIZE);
+ if (attr)
+ size = atoi(attr->value->data);
+
+ cairo_set_font_size(cr, size);
+ cairo_text_extents (cr, obj->text->data, extents);
+
+ int w = extents->x_bearing + extents->width;
+ if (w <= width)
+ return 0;
+
+ extents->width = width;
+ extents->height = 0;
+
+ if (obj->text_splits)
+ scf_slist_clear(obj->text_splits, abc_text_t, next, free);
+
+ assert(NULL == obj->text_splits);
+ abc_text_t** h = &obj->text_splits;
+
+ int n_lines = w / width;
+ int n_chars = obj->text->len * 5 / 4 / n_lines;
+ int n;
+ int i;
+
+ for (i = 0; i < obj->text->len; ) {
+ n = n_chars;
+
+ if (n > obj->text->len - i)
+ n = obj->text->len - i;
+
+ while (1) {
+ cairo_text_extents_t tmp;
+
+ n = __layout_text_split(&tmp, cr, obj->text->data + i, n);
+ if (n < 0)
+ return n;
+
+ if (tmp.x_bearing + tmp.width <= width)
+ {
+ abc_text_t* t = calloc(1, sizeof(abc_text_t));
+ if (!t)
+ return -ENOMEM;
+ t->start = i;
+ t->len = n;
+
+ *h = t;
+ h = &t->next;
+ i += n;
+
+ extents->height += tmp.height;
+ break;
+ }
+
+ n--;
+ }
+ }
+
+ return 0;
+}
+