static float layout_block(fz_context *ctx, fz_html *box, fz_html *top, float em, float page_h, float vertical) { fz_html *child; int first; fz_css_style *style = &box->style; float *margin = box->margin; float *border = box->border; float *padding = box->padding; em = box->em = fz_from_css_number(style->font_size, em, em); margin[0] = fz_from_css_number(style->margin[0], em, top->w); margin[1] = fz_from_css_number(style->margin[1], em, top->w); margin[2] = fz_from_css_number(style->margin[2], em, top->w); margin[3] = fz_from_css_number(style->margin[3], em, top->w); padding[0] = fz_from_css_number(style->padding[0], em, top->w); padding[1] = fz_from_css_number(style->padding[1], em, top->w); padding[2] = fz_from_css_number(style->padding[2], em, top->w); padding[3] = fz_from_css_number(style->padding[3], em, top->w); border[0] = style->border_style[0] ? fz_from_css_number(style->border_width[0], em, top->w) : 0; border[1] = style->border_style[1] ? fz_from_css_number(style->border_width[1], em, top->w) : 0; border[2] = style->border_style[2] ? fz_from_css_number(style->border_width[2], em, top->w) : 0; border[3] = style->border_style[3] ? fz_from_css_number(style->border_width[3], em, top->w) : 0; box->x = top->x + margin[L] + border[L] + padding[L]; box->w = top->w - (margin[L] + margin[R] + border[L] + border[R] + padding[L] + padding[R]); if (margin[T] > vertical) margin[T] -= vertical; else margin[T] = 0; if (padding[T] == 0 && border[T] == 0) vertical += margin[T]; else vertical = 0; box->y = top->y + top->h + margin[T] + border[T] + padding[T]; box->h = 0; first = 1; for (child = box->down; child; child = child->next) { if (child->type == BOX_BLOCK) { vertical = layout_block(ctx, child, box, em, page_h, vertical); if (first) { /* move collapsed parent/child top margins to parent */ margin[T] += child->margin[T]; box->y += child->margin[T]; child->margin[T] = 0; first = 0; } box->h += child->h + child->padding[T] + child->padding[B] + child->border[T] + child->border[B] + child->margin[T] + child->margin[B]; } else if (child->type == BOX_BREAK) { box->h += fz_from_css_number_scale(style->line_height, em, em, em); vertical = 0; first = 0; } else if (child->type == BOX_FLOW) { layout_flow(ctx, child, box, em, page_h); if (child->h > 0) { box->h += child->h; vertical = 0; first = 0; } } } /* reserve space for the list mark */ if (box->list_item && box->h == 0) { box->h += fz_from_css_number_scale(style->line_height, em, em, em); vertical = 0; } if (box->h == 0) { if (margin[B] > vertical) margin[B] -= vertical; else margin[B] = 0; } else { box->h -= vertical; vertical = fz_max(margin[B], vertical); margin[B] = vertical; } return vertical; }
static void layout_block(fz_context *ctx, fz_html *box, fz_html *top, float em, float top_collapse_margin, float page_h) { fz_html *child; float box_collapse_margin; int prev_br; float *margin = box->margin; float *border = box->border; float *padding = box->padding; em = fz_from_css_number(box->style.font_size, em, em); margin[0] = fz_from_css_number(box->style.margin[0], em, top->w); margin[1] = fz_from_css_number(box->style.margin[1], em, top->w); margin[2] = fz_from_css_number(box->style.margin[2], em, top->w); margin[3] = fz_from_css_number(box->style.margin[3], em, top->w); padding[0] = fz_from_css_number(box->style.padding[0], em, top->w); padding[1] = fz_from_css_number(box->style.padding[1], em, top->w); padding[2] = fz_from_css_number(box->style.padding[2], em, top->w); padding[3] = fz_from_css_number(box->style.padding[3], em, top->w); if (box->style.border_style) { border[0] = fz_from_css_number(box->style.border_width[0], em, top->w); border[1] = fz_from_css_number(box->style.border_width[1], em, top->w); border[2] = fz_from_css_number(box->style.border_width[2], em, top->w); border[3] = fz_from_css_number(box->style.border_width[3], em, top->w); } else border[0] = border[1] = border[2] = border[3] = 0; if (padding[T] == 0 && border[T] == 0) box_collapse_margin = margin[T]; else box_collapse_margin = 0; if (margin[T] > top_collapse_margin) margin[T] -= top_collapse_margin; else margin[T] = 0; box->x = top->x + margin[L] + border[L] + padding[L]; box->y = top->y + top->h + margin[T] + border[T] + padding[T]; box->w = top->w - (margin[L] + margin[R] + border[L] + border[R] + padding[L] + padding[R]); box->h = 0; prev_br = 0; for (child = box->down; child; child = child->next) { if (child->type == BOX_BLOCK) { layout_block(ctx, child, box, em, box_collapse_margin, page_h); box->h += child->h + child->padding[T] + child->padding[B] + child->border[T] + child->border[B] + child->margin[T] + child->margin[B]; box_collapse_margin = child->margin[B]; prev_br = 0; } else if (child->type == BOX_BREAK) { /* TODO: interaction with page breaks */ if (prev_br) box->h += fz_from_css_number_scale(box->style.line_height, em, em, em); prev_br = 1; } else if (child->type == BOX_FLOW) { layout_flow(ctx, child, box, em, page_h); if (child->h > 0) { box->h += child->h; box_collapse_margin = 0; prev_br = 0; } } } if (padding[B] == 0 && border[B] == 0) { if (margin[B] > 0) { box->h -= box_collapse_margin; if (margin[B] < box_collapse_margin) margin[B] = box_collapse_margin; } } }