#include #include #include #include #include "xwchar.h" #include "text.h" #include "image.h" #include "frame.h" #include "href.h" #ifndef MAX #define MAX(a,b) (((a)>(b))?(a):(b)) #endif void frame_add_link(Frame *f, HTMLHrefInfo *p) { p->next = f->links; f->links = p; } void frame_add_obj(Frame *f, HTMLObj *obj) { BlockFormatInfo *bfi = frame_get_blockformatinfo(f); obj->x = bfi->off_x + CUR_X; obj->y = bfi->off_y + bfi->cur_y; bfi->max_ascent = MAX(bfi->max_ascent, obj->ascent); bfi->max_descent = MAX(bfi->max_descent, obj->descent); bfi->formatted_width = MAX(bfi->formatted_width, bfi->cur_x + obj->rbearing); bfi->cur_x += obj->width; obj->next = bfi->obj; obj->prev = bfi->obj->prev; bfi->obj->prev->next = obj; bfi->obj->prev = obj; } void frame_add_obj_before_line(Frame *f, HTMLObj *obj) { BlockFormatInfo *bfi = frame_get_blockformatinfo(f); if (bfi->line == bfi->obj) { /* special case */ obj->next = bfi->obj; obj->prev = bfi->obj; bfi->obj->next = obj; bfi->obj->prev = obj; bfi->line = obj; } else { obj->next = bfi->line; obj->prev = bfi->line->prev; bfi->line->prev->next = obj; bfi->line->prev = obj; } } void frame_add_left(Frame *f, HTMLObj *obj) { BlockFormatInfo *bfi = frame_get_blockformatinfo(f); obj->next = bfi->left; obj->prev = bfi->left->prev; bfi->left->prev->next = obj; bfi->left->prev = obj; } void frame_add_right(Frame *f, HTMLObj *obj) { BlockFormatInfo *bfi = frame_get_blockformatinfo(f); obj->next = bfi->right; obj->prev = bfi->right->prev; bfi->right->prev->next = obj; bfi->right->prev = obj; } /* 縦方向の空白の追加 */ void frame_add_vspace(Frame *f, int linesep) { BlockFormatInfo *bfi = frame_get_blockformatinfo(f); bfi->cur_y += linesep; if (bfi->left_image_height > 0) { bfi->left_image_height -= linesep; if (bfi->left_image_height <= 0) bfi->left_image_margin = 0; } /* 左 */ while (bfi->left_image_height < 0 || (bfi->left_image_height == 0 && bfi->left->next != bfi->left)) { int line = bfi->left_image_height; if (bfi->left->next != bfi->left) { HTMLObj *p; p = bfi->left->next; bfi->left_image_margin = p->width; bfi->left_image_height = p->height; p->next->prev = bfi->left; bfi->left->next = p->next; p->x = bfi->off_x; p->y = bfi->off_y + bfi->cur_y + line; frame_add_obj_before_line(f,p); bfi->left_image_height += line; } else { bfi->left_image_margin = 0; bfi->left_image_height = 0; break; } } /* 右 */ if (bfi->right_image_height > 0) { bfi->right_image_height -= linesep; if (bfi->right_image_height <= 0) bfi->right_image_margin = 0; } while (bfi->right_image_height < 0 || (bfi->right_image_height == 0 && bfi->right->next!=bfi->right)){ int line = bfi->right_image_height; if (bfi->right->next != bfi->right) { HTMLObj *p; p = bfi->right->next; bfi->right_image_margin = p->width; bfi->right_image_height = p->height; p->next->prev = bfi->right; bfi->right->next = p->next; p->x = bfi->off_x + bfi->width - bfi->right_image_margin; p->y = bfi->off_y + bfi->cur_y + line; frame_add_obj_before_line(f,p); bfi->right_image_height += line; } else { bfi->right_image_margin = 0; bfi->right_image_height = 0; break; } } } /* 改行 & 各種再計算 */ void frame_add_lf(Frame *f, int mode) { HTMLObj *o; BlockFormatInfo *bfi = frame_get_blockformatinfo(f); BlockStyleInfo *bsi = frame_get_blockstyleinfo(f); int linesep; int dx = 0; if (bfi->cur_x < WIDTH) { if (bsi->text_align == ALIGN_JUSTIFY) { int n = 0; if ((o = bfi->line->next) != bfi->obj) { o = o->next; while (o != bfi->obj) { /* count */ n++; o = o->next; } dx = (WIDTH - bfi->cur_x)/n; o = bfi->line->next->next; while (o != bfi->obj) { o->y += bfi->max_ascent; o->x += dx; o = o->next; } } } else { switch (bsi->text_align) { case ALIGN_RIGHT: dx = WIDTH - bfi->cur_x; break; case ALIGN_CENTER: dx = (WIDTH - bfi->cur_x) / 2; break; default: case ALIGN_LEFT: dx = 0; break; } o = bfi->line->next; while (o != bfi->obj) { o->y += bfi->max_ascent; o->x += dx; o = o->next; } } } else { o = bfi->line->next; while (o != bfi->obj) { o->y += bfi->max_ascent; o = o->next; } } bfi->line = bfi->obj->prev; bfi->line_p = bfi->line->prev; linesep = bfi->max_descent + bfi->max_ascent; /* XXX line_width */ switch(bsi->line_height.type) { case SSTERM_NUMBER: bfi->next_linesep = linesep * (bsi->line_height.num - 1); break; case SSTERM_LENGTH_PX: bfi->next_linesep = bsi->line_height.num - linesep; break; default: break; } bfi->cur_x = 0; bfi->max_ascent = 0; bfi->max_descent = 0; retry: frame_add_vspace(f, linesep); /* ひたすら改行させる */ if (mode == BR_ALL) { if ((bfi->right_image_height > 0 || bfi->left_image_height > 0) ) { linesep = MAX(bfi->right_image_height, bfi->left_image_height); goto retry; } } else if (mode == BR_RIGHT) { if (bfi->right_image_height > 0) { linesep = bfi->right_image_height; goto retry; } } else if (mode == BR_LEFT) { if (bfi->left_image_height > 0) { linesep = bfi->left_image_height; goto retry; } } #if 0 fprintf(stderr, "margin info: %d %d %d %d\n", bfi->width, bfi->left_image_margin, bfi->right_image_margin, f->formatted_width); #endif bfi->after_lf = 1; } void frame_add_body(Frame *f) { if (f->bg_image && f->bg_image->pixmap != None) { XSetWindowBackgroundPixmap(f->dpy, f->win, f->bg_image->pixmap); XSetTile(f->dpy, f->gc, f->bg_image->pixmap); XSetTSOrigin(f->dpy, f->gc, f->off_x - f->scr_x, f->off_y -f->scr_y); XSetFillStyle(f->dpy, f->gc, FillTiled); XFillRectangle(f->dpy, f->backup, f->gc, 0, 0, f->r_w, f->r_h); XSetFillStyle(f->dpy, f->gc, FillSolid); } else { XSetWindowBackground(f->dpy, f->win, f->background); XSetForeground(f->dpy, f->gc, f->background); XFillRectangle(f->dpy, f->backup, f->gc, 0, 0, f->r_w, f->r_h); } f->body = frame_get_blockformatinfo(f)->obj; frame_expose(f, 0, 0, f->r_w, f->r_h); } #define BULLET_SIZE 8 void frame_add_bullet(Frame *f, int type) { HTMLObj *obj; obj = htmlobj_new(); obj->type = HTMLOBJ_BULLET; obj->data = (void*)type; obj->lbearing = -BULLET_SIZE/2; obj->rbearing = BULLET_SIZE/2; obj->width = BULLET_SIZE; obj->height = BULLET_SIZE; obj->ascent = BULLET_SIZE; obj->descent = 0; frame_add_obj(f,obj); } /* 文字列追加 */ void frame_add_string(Frame *f, wchar_t *str, size_t len, int mode) { XCharStruct all; HTMLObj *obj; HTMLTextObj *t; BlockFormatInfo *bfi = frame_get_blockformatinfo(f); ParseInfo *pi = f->pinfo; if (len == 0) return; obj = htmlobj_new(); t = htmltextobj_new(); obj->type = HTMLOBJ_TEXT; obj->data = t; t->oc = pi->istyle->oc; if (bfi->linkmode) { obj->link = f->links; obj->pixel = f->link_style->pixel; } else { obj->pixel = pi->istyle->pixel; } t->str = str; t->len = len; WcExtents(pi->istyle->oc, str, len, &all); obj->lbearing = all.lbearing; obj->rbearing = all.rbearing; obj->width = all.width; obj->height = all.ascent + all.descent; obj->ascent = all.ascent; obj->descent = all.descent; bfi->prev_ascent = all.ascent; bfi->prev_descent = all.descent; if (mode) bfi->cur_x -= obj->width; frame_add_obj(f,obj); #if 0 { int i; fprintf(stderr,"add string:[%d,%d]", obj->x, obj->y); for (i=0;ipinfo; obj = htmlobj_new(); i = htmlimageobj_new(); i->anim = a; obj->type = HTMLOBJ_IMAGE; obj->data = i; if (bfi->linkmode) { obj->link = f->links; obj->pixel = f->link_style->pixel; } else obj->pixel = pi->istyle->pixel; if (i->anim != NULL) { obj->width = i->anim->w; obj->rbearing = i->anim->w; obj->height = height = i->anim->h; /* entry animation pattern */ if (i->anim->list->next->next != i->anim->list) mytimer_entry(f->images, obj); } switch (align) { case ALIGN_LEFT: case ALIGN_RIGHT: ascent = 0; break; case ALIGN_TOP: ascent = bfi->prev_ascent; break; case ALIGN_BOTTOM: ascent = height; break; case ALIGN_ABSMIDDLE: ascent = (height + bfi->prev_ascent - bfi->prev_descent)/2; break; case ALIGN_NONE: case ALIGN_MIDDLE: default: ascent = height / 2; break; } obj->ascent = ascent; obj->descent = obj->height - ascent; if (align == ALIGN_LEFT) { if (bfi->after_lf && bfi->left_image_height == 0) { bfi->left_image_margin = obj->width; bfi->left_image_height = obj->height; obj->x = bfi->off_x; obj->y = bfi->off_y + bfi->cur_y; frame_add_obj_before_line(f,obj); } else /* 左画像リストにエントリ */ frame_add_left(f,obj); } else if (align == ALIGN_RIGHT) { if (bfi->cur_x < (bfi->width - bfi->left_image_margin - obj->width) && bfi->right_image_margin == 0) { bfi->right_image_margin = obj->width; bfi->right_image_height = obj->height; obj->x = bfi->off_x + bfi->width - bfi->right_image_margin; obj->y = bfi->off_y + bfi->cur_y; frame_add_obj_before_line(f,obj); } else /* 左画像リストにエントリ */ frame_add_right(f,obj); } else { /* 行間空白 */ if (bfi->after_lf && bfi->next_linesep > 0) { frame_add_vspace(f, bfi->next_linesep); } bfi->after_lf = 0; if (bfi->pre != TAG_OPEN && bfi->cur_x + obj->width >= WIDTH) frame_add_lf(f,BR_NORMAL); frame_add_obj(f,obj); } } void frame_add_hr(Frame *f, int align, int width, int size) { BlockFormatInfo *bfi = frame_get_blockformatinfo(f); HTMLObj *obj = htmlobj_new(); obj->type = HTMLOBJ_HR; obj->ascent = size/2; obj->descent = size - obj->ascent; obj->width = obj->rbearing = WIDTH; obj->height = size; obj->pixel = f->pinfo->istyle->pixel; frame_add_obj(f,obj); frame_add_lf(f, BR_NORMAL); } void frame_add_blockobj(Frame *f, ParseInfo *p) { BlockFormatInfo *bf = p->bfinfo; BlockStyleInfo *bs = p->bstyle; HTMLObj *obj = htmlobj_new(); HTMLBlockObj *bo = blockobj_new(); obj->type = HTMLOBJ_BLOCK; obj->data = bo; bo->border_pixel = f->foreground; bo->border_top_width = bs->border_top_width; bo->border_right_width = bs->border_right_width; bo->border_left_width = bs->border_left_width; bo->border_bottom_width = bs->border_bottom_width; bo->height = bf->cur_y + bs->padding_top + bs->padding_bottom + bs->border_top_width + bs->border_bottom_width; bo->width = bf->formatted_width + bs->padding_right + bs->padding_left + bs->border_right_width + bs->border_left_width; bo->off_x = bs->margin_left; bo->off_y = bs->margin_top; obj->width = bo->width + bs->margin_left + bs->margin_right; obj->height = bo->height + bs->margin_top + bs->margin_bottom; obj->lbearing = 0; obj->rbearing = obj->width; obj->ascent = obj->height / 2; obj->descent = obj->height - obj->ascent; bo->obj = bf->obj; /* move obj list */ bf->obj = NULL; frame_add_obj(f, obj); }