/* doBlock: * Set positions of block sn and its child blocks. */ static void doBlock(Agraph_t * g, block_t * sn, double min_dist) { block_t *child; nodelist_t *longest_path; int childCount, length; double centerAngle = M_PI; /* layout child subtrees */ childCount = 0; for (child = sn->children.first; child; child = child->next) { doBlock(g, child, min_dist); childCount++; } /* layout this block */ longest_path = layout_block(g, sn, min_dist); sn->circle_list = longest_path; length = sizeNodelist(longest_path); /* path contains everything in block */ /* attach children */ if (childCount > 0) centerAngle = position(g, childCount, length, longest_path, sn, min_dist); if ((length == 1) && (BLK_PARENT(sn))) { sn->parent_pos = centerAngle; if (sn->parent_pos < 0) sn->parent_pos += 2 * M_PI; } }
void fz_layout_html(fz_context *ctx, fz_html *box, float w, float h, float em) { fz_html page_box; init_box(ctx, &page_box); page_box.w = w; page_box.h = 0; layout_block(ctx, box, &page_box, em, 0, h); }
void CL_SpanLayout_Impl::layout_lines(CL_GraphicContext & gc, int max_width) { lines.clear(); if (objects.empty()) return; layout_cache.metrics = -1; layout_cache.object_index = -1; CurrentLine current_line; std::vector<TextBlock> blocks = find_text_blocks(); for (std::vector<TextBlock>::size_type block_index = 0; block_index < blocks.size(); block_index++) { if (objects[current_line.object_index].type == object_text) layout_text(gc, blocks, block_index, current_line, max_width); else layout_block(current_line, max_width, blocks, block_index); } next_line(current_line); }
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; } } }