--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+p
+{
+ border:1px solid red;
+ background-color:green;
+ color:white;
+}
+</style>
+</head>
+
+<body>
+<p>A drawing operator that generates the shape from a string of UTF-8 characters, rendered according to the current font_face, font_size (font_matrix), and font_options.This function first computes a set of glyphs for the string of text. The first glyph is placed so that its origin is at the current point. The origin of each subsequent glyph is offset from that of the previous glyph by the advance values of the previous glyph.</p>
+<p>一旦为页面设置了恰当的 DTD,大多数浏览器都会按照上面的图示来呈现内容。然而 IE 5 和 6 的呈现却是不正确的。根据 W3C 的规范,元素内容占据的空间是由 width 属性设置的,而内容周围的 padding 和 border 值是另外计算的。不幸的是,IE5.X 和 6 在怪异模式中使用自己的非标准模型。这些浏览器的 width 属性不是内容的宽度,而是内容、内边距和边框的宽度的总和。</p>
+</body>
+</html>
border:1px solid red;
}
-table
-{
- width:100%;
-/* border-collapse:collapse;*/
-}
+table {width:100%;}
th
{
{border_keys, "", ABC_HTML_ATTR_BORDER, ABC_HTML_FLAG_SHOW},
{padding_keys, "", ABC_HTML_ATTR_PADDING, ABC_HTML_FLAG_SHOW},
+ {width_keys, "", ABC_HTML_ATTR_WIDTH, ABC_HTML_FLAG_SHOW},
+ {height_keys, "", ABC_HTML_ATTR_HEIGHT, ABC_HTML_FLAG_SHOW},
+
{class_keys, "", ABC_HTML_ATTR_CLASS, ABC_HTML_FLAG_SHOW},
{style_keys, "", ABC_HTML_ATTR_STYLE, ABC_HTML_FLAG_SHOW},
{id_keys, "", ABC_HTML_ATTR_ID, ABC_HTML_FLAG_SHOW},
assert(http->rpos > 0);
if (http->rpos < http->rbuf->len)
- c = http->rbuf->data[http->rpos++];
+ c = (uint8_t)http->rbuf->data[http->rpos++];
else
c = EOF;
pthread_mutex_unlock(&http->mutex);
if (io && io->priv) {
s = io->priv;
- if (s->text_i < s->text->len)
- return s->text->data[s->text_i++];
+ if (s->text_i < s->text->len) {
+ uint8_t c = s->text->data[s->text_i++];
+ return c;
+ }
}
return EOF;
#include"abc_io.h"
typedef struct abc_obj_s abc_obj_t;
+typedef struct abc_text_s abc_text_t;
enum abc_objs
{
ABC_BORDER_DASHED,
};
+enum abc_line_style
+{
+ ABC_LINE_NONE,
+ ABC_LINE_UNDER,
+ ABC_LINE_OVER,
+ ABC_LINE_THROUGH,
+};
+
+struct abc_text_s
+{
+ abc_text_t* next;
+
+ int start;
+ int len;
+};
+
struct abc_obj_s
{
scf_list_t list;
char** keys;
scf_string_t* value;
scf_string_t* text;
+ abc_text_t* text_splits; // for layout, split a long text to multi-lines and save every-line here
int text_line;
int text_pos;
#include"abc.h"
+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;
+}
+
int abc_layout_h1(abc_layout_t* layout, abc_obj_t* obj, int width, int height)
{
abc_obj_t* attr;
int size = 16;
attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_SIZE);
- if (attr) {
+ if (attr)
size = atoi(attr->value->data);
- cairo_set_font_size(cr, size);
- }
-
- cairo_font_options_t *options = cairo_font_options_create();
- cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_SUBPIXEL);
- cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_FULL);
- cairo_font_options_set_hint_metrics(options, CAIRO_HINT_METRICS_ON);
- cairo_set_font_options(cr, options);
- cairo_font_options_destroy(options);
+ cairo_set_font_size (cr, size);
cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
- cairo_text_extents(cr, obj->text->data, &extents);
+ int ret = __layout_text(&extents, cr, obj, width);
+ if (ret < 0)
+ scf_loge("ret: %d\n", ret);
int w = 0;
if (ABC_HTML_OL == obj->parent->type)
obj->w = (obj->w + 3) & ~0x3;
obj->h = (obj->h + 3) & ~0x3;
- scf_logd("%s, w: %d, h: %d, x_bearing: %lg, y_bearing: %lg, width: %lg, height: %lg, x_advance: %lg, y_advance: %lg\n",
+ scf_logi("%s, w: %d, h: %d, x_bearing: %lg, y_bearing: %lg, width: %lg, height: %lg, x_advance: %lg, y_advance: %lg\n",
obj->text->data, obj->w, obj->h,
extents.x_bearing, extents.y_bearing, extents.width, extents.height,
extents.x_advance, extents.y_advance);
while (table && ABC_HTML_TABLE != table->type)
table = table->parent;
- // width of event table element is width of the max one
+ // width of every table element is width of the max one
if (obj->w < table->td_width)
obj->w = table->td_width;
else
return 0;
}
+void __draw_text(cairo_text_extents_t* extents, cairo_t* cr, const char* text, double x, double y, int line_type, int line_width)
+{
+ cairo_text_extents(cr, text, extents);
+ double w = extents->width;
+
+ x += extents->x_bearing;
+ y -= extents->y_bearing;
+
+ cairo_set_line_width(cr, 1);
+ cairo_move_to(cr, x, y);
+ cairo_show_text(cr, text);
+ cairo_stroke(cr);
+
+ cairo_set_line_width(cr, line_width);
+ switch (line_type)
+ {
+ case ABC_LINE_UNDER:
+ cairo_move_to(cr, x, y + line_width + 1.0);
+ cairo_line_to(cr, w, y + line_width + 1.0);
+ break;
+
+ case ABC_LINE_OVER:
+ cairo_move_to(cr, x, 1.0);
+ cairo_line_to(cr, w, 1.0);
+ break;
+
+ case ABC_LINE_THROUGH:
+ cairo_move_to(cr, x, y + extents->y_bearing / 2.0 + line_width);
+ cairo_line_to(cr, w, y + extents->y_bearing / 2.0 + line_width);
+ break;
+ default:
+ break;
+ };
+ cairo_stroke(cr);
+}
+
int __init_text(cairo_t* cr, abc_obj_t* obj, int num_flag)
{
abc_obj_t* attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT);
double size = 16.0;
attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_SIZE);
- if (attr) {
+ if (attr)
size = atoi(attr->value->data);
- cairo_set_font_size(cr, size);
- }
-
- cairo_font_options_t *options = cairo_font_options_create();
- cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_SUBPIXEL);
- cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_FULL);
- cairo_font_options_set_hint_metrics(options, CAIRO_HINT_METRICS_ON);
- cairo_set_font_options(cr, options);
- cairo_font_options_destroy(options);
attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_COLOR);
if (attr)
abc_css_color(&r, &g, &b, attr->value->data);
+ cairo_set_font_size (cr, size);
cairo_set_source_rgba(cr, r, g, b, 1.0);
- cairo_text_extents (cr, obj->text->data, &extents);
- switch (obj->parent->type)
+ if (ABC_HTML_OL == obj->parent->type && num_flag)
{
- case ABC_HTML_OL:
- if (num_flag)
- cairo_move_to(cr, obj->parent->padding - (extents.x_bearing + extents.width + size / 2), -obj->y_bearing);
- else
- cairo_move_to(cr, extents.x_bearing + obj->parent->padding, -extents.y_bearing);
- break;
- default:
- cairo_move_to(cr, extents.x_bearing + obj->parent->padding, -extents.y_bearing);
- break;
- };
+ cairo_text_extents(cr, obj->text->data, &extents);
- cairo_show_text(cr, obj->text->data);
- cairo_stroke(cr);
+ cairo_move_to (cr, obj->parent->padding - (extents.x_bearing + extents.width + size / 2), -obj->y_bearing);
+ cairo_show_text(cr, obj->text->data);
+ cairo_stroke(cr);
+ return 0;
+ }
+
+ double line_width = 0.5 + size / 16.0;
+ int line_type = ABC_LINE_NONE;
attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_TEXT_DECORATION);
if (attr) {
- double line = 0.5 + size / 16.0;
- cairo_set_line_width(cr, line);
+ if (!__html_strcmp(attr->value->data, "underline"))
+ line_type = ABC_LINE_UNDER;
- if (!__html_strcmp(attr->value->data, "underline")) {
- cairo_move_to(cr, extents.x_bearing, -extents.y_bearing + line + 1.0);
- cairo_line_to(cr, extents.width, -extents.y_bearing + line + 1.0);
+ else if (!__html_strcmp(attr->value->data, "overline"))
+ line_type = ABC_LINE_OVER;
- } else if (!__html_strcmp(attr->value->data, "overline")) {
- cairo_move_to(cr, extents.x_bearing, 1.0);
- cairo_line_to(cr, extents.width, 1.0);
+ else if (!__html_strcmp(attr->value->data, "line-through"))
+ line_type = ABC_LINE_THROUGH;
+ }
+
+ if (!obj->text_splits) {
+ __draw_text(&extents, cr, obj->text->data, obj->parent->padding, 0.0, line_type, line_width);
+ return 0;
+ }
+
+ scf_string_t* s;
+ abc_text_t* t;
+
+ double x = obj->parent->padding;
+ double y = 0.0;
- } else if (!__html_strcmp(attr->value->data, "line-through")) {
- cairo_move_to(cr, extents.x_bearing, -extents.y_bearing / 2.0 + line);
- cairo_line_to(cr, extents.width, -extents.y_bearing / 2.0 + line);
+ while (obj->text_splits) {
+ t = obj->text_splits;
+
+ s = scf_string_cstr_len(obj->text->data + t->start, t->len);
+ if (!s) {
+ scf_slist_clear(obj->text_splits, abc_text_t, next, free);
+ return -ENOMEM;
}
- cairo_stroke(cr);
+
+ __draw_text(&extents, cr, s->data, x, y, line_type, line_width);
+ y += extents.height;
+
+ obj->text_splits = t->next;
+
+ scf_string_free(s);
+ free(t);
}
return 0;