示例#1
0
	point TextBox::reflowText(LayoutEngine& eng, const Dimensions& containing, const point& current_cursor)
	{
		// clear old data so we can re-calculate it.
		// XXX Future note.
		// unless the text has changed or the width of the containing box changes we shouldn't
		// have to recalculate this.
		lines_.clear();

		point cursor = current_cursor;

		FixedPoint y1 = cursor.y + getOffset().y;
		// XXX if padding left/border left applies should reduce width and move cursor position if isFirstInlineChild() is set.
		// Simlarly the last line width should be reduced by padding right/border right.
		FixedPoint width = eng.getWidthAtPosition(y1, y1 + getLineHeight(), containing.content_.width) - cursor.x + eng.getXAtPosition(y1, y1 + getLineHeight());

		Text::iterator last_it = txt_->begin();
		Text::iterator it = last_it;

		bool done = false;
		while(it != txt_->end()) {
			LinePtr line = txt_->reflowText(it, width, getStyleNode());
			if(line != nullptr && !line->line.empty()) {
				// is the line larger than available space and are there floats present?
				FixedPoint last_x = line->line.back().advance.back().x;
				if(last_x > width && eng.hasFloatsAtPosition(y1, y1 + getLineHeight())) {
					cursor.y += getLineHeight();
					y1 = cursor.y + getOffset().y;
					cursor.x = eng.getXAtPosition(y1, y1 + getLineHeight());
					it = last_it;
					width = eng.getWidthAtPosition(y1, y1 + getLineHeight(), containing.content_.width);
					continue;
				}

				lines_.emplace_back(line, cursor);
				lines_.back().width_ = calculateWidth(lines_.back());
				// XXX This height needs to be modified later if we have inline elements with a different lineheight
				lines_.back().height_ = getLineHeight();
				cursor.x += lines_.back().width_;

				if(line->is_end_line) {
					// update the cursor for the next line
					cursor.y += getLineHeight();
					y1 = cursor.y + getOffset().y;
					cursor.x = eng.getXAtPosition(y1, y1 + getLineHeight());
				}
			}					
		}

		int max_w = 0;
		for(auto& line : lines_) {
			max_w = std::max(max_w, line.width_);
		}
		setContentWidth(max_w);
		
		if(!lines_.empty()) {
			setContentHeight(lines_.back().offset_.y + getLineHeight());
		}

		return cursor;
	}
	void InlineBlockBox::handleLayout(LayoutEngine& eng, const Dimensions& containing)
	{
		eng.setCursor(cursor_);

		layoutChildren(eng);
		layoutHeight(containing);

		if(isReplaceable()) {
			NodePtr node = getNode();
			node->setDimensions(rect(0, 0, getWidth() / LayoutEngine::getFixedPointScale(), getHeight() / LayoutEngine::getFixedPointScale()));
		}

		// try and fit the box at cursor, failing that we move the cursor and try again.
		FixedPoint width_at_cursor = eng.getWidthAtPosition(eng.getCursor().y, eng.getCursor().y + getHeight() + getMBPHeight(), containing.content_.width)
			 - eng.getCursor().x + eng.getXAtPosition(eng.getCursor().y, eng.getCursor().y + getHeight() + getMBPHeight());
		if(getWidth() + getMBPWidth() > width_at_cursor) {
			point p = eng.getCursor();
			p.y += getLineHeight();
			while(eng.hasFloatsAtPosition(p.y, p.y + getHeight() + getMBPHeight()) && getWidth() + getMBPWidth() > width_at_cursor) {
				width_at_cursor = eng.getWidthAtPosition(p.y, p.y + getHeight() + getMBPHeight(), containing.content_.width);
			}
			p.x = eng.getXAtPosition(p.y, p.y + getHeight() + getMBPHeight());
			setContentX(p.x);
			setContentY(p.y);
			p.y += getHeight() + getMBPHeight();
			p.x = eng.getXAtPosition(p.y, p.y + getLineHeight());
			eng.setCursor(p);
		} else {
			setContentX(eng.getCursor().x);
			// XXX if height is greater than other objects on line we need to increase lineheight.
			setContentY(eng.getCursor().y);
			eng.setCursor(point(getLeft() + getWidth() + getMBPRight(), eng.getCursor().y));
		}
	}
示例#3
0
	void BlockBox::handleLayout(LayoutEngine& eng, const Dimensions& containing)
	{
		if(isReplaceable()) {
			layoutChildren(eng);
		} else {
			layoutChildren(eng);
			layoutHeight(containing);
		}

		if(isFloat()) {
			FixedPoint top = 0;
			const FixedPoint lh = getStyleNode()->getHeight()->isAuto() ? getLineHeight() : getStyleNode()->getHeight()->getLength().compute(containing.content_.height);
			const FixedPoint box_w = getDimensions().content_.width;

			FixedPoint y = 0;
			FixedPoint x = 0;

			FixedPoint y1 = y + getOffset().y;
			FixedPoint left = getStyleNode()->getFloat() == Float::LEFT ? eng.getXAtPosition(y1, y1 + lh) + x : eng.getX2AtPosition(y1, y1 + lh);
			FixedPoint w = eng.getWidthAtPosition(y1, y1 + lh, containing.content_.width);
			bool placed = false;
			while(!placed) {
				if(w >= box_w) {
					left = left - (getStyleNode()->getFloat() == Float::LEFT ? x : box_w) + getMBPLeft();
					top = y + getMBPTop() + containing.content_.height;
					placed = true;
				} else {
					y += lh;
					y1 = y + getOffset().y;
					left = getStyleNode()->getFloat() == Float::LEFT ? eng.getXAtPosition(y1, y1 + lh) + x : eng.getX2AtPosition(y1, y1 + lh);
					w = eng.getWidthAtPosition(y1, y1 + lh, containing.content_.width);
				}
			}
			setContentX(left);
			setContentY(top);

		} else {
			for(auto& child : getChildren()) {
				setContentHeight(child->getTop() + child->getHeight() + child->getMBPBottom());
			}
		}
	}
示例#4
0
	void ListItemBox::handleLayout(LayoutEngine& eng, const Dimensions& containing) 
	{
		auto lst = getStyleNode()->getListStyleType();
		switch(lst) {
			case ListStyleType::DISC: /* is the default */ break;
			case ListStyleType::CIRCLE:
				marker_ = utils::codepoint_to_utf8(marker_circle);
				break;
			case ListStyleType::SQUARE:
				marker_ = utils::codepoint_to_utf8(marker_square);
				break;
			case ListStyleType::DECIMAL: {
				std::ostringstream ss;
				ss << std::dec << count_ << ".";
				marker_ = ss.str();
				break;
			}
			case ListStyleType::DECIMAL_LEADING_ZERO: {
				std::ostringstream ss;
				ss << std::dec << std::setfill('0') << std::setw(2) << count_ << ".";
				marker_ = ss.str();
				break;
			}
			case ListStyleType::LOWER_ROMAN:
				if(count_ < 4000) {
					marker_ = to_roman(count_, true) + ".";
				}
				break;
			case ListStyleType::UPPER_ROMAN:
				if(count_ < 4000) {
					marker_ = to_roman(count_, false) + ".";
				}
				break;
			case ListStyleType::LOWER_GREEK:
				if(count_ <= (marker_lower_greek_end - marker_lower_greek + 1)) {
					marker_ = utils::codepoint_to_utf8(marker_lower_greek + count_) + ".";
				}
				break;
			case ListStyleType::LOWER_ALPHA:
			case ListStyleType::LOWER_LATIN:
				if(count_ <= (marker_lower_latin_end - marker_lower_latin + 1)) {
					marker_ = utils::codepoint_to_utf8(marker_lower_latin + count_) + ".";
				}
				break;
			case ListStyleType::UPPER_ALPHA:
			case ListStyleType::UPPER_LATIN:
				if(count_ <= (marker_upper_latin_end - marker_upper_latin + 1)) {
					marker_ = utils::codepoint_to_utf8(marker_upper_latin + count_) + ".";
				}
				break;
			case ListStyleType::ARMENIAN:
				if(count_ <= (marker_armenian_end - marker_armenian + 1)) {
					marker_ = utils::codepoint_to_utf8(marker_armenian + count_) + ".";
				}
				break;
			case ListStyleType::GEORGIAN:
				if(count_ <= (marker_georgian_end - marker_georgian + 1)) {
					marker_ = utils::codepoint_to_utf8(marker_georgian + count_) + ".";
				}
				break;
			case ListStyleType::NONE:
			default: 
				marker_.clear();
				break;
		}

		FixedPoint top = getMBPTop() + containing.content_.height;
		FixedPoint left = getMBPLeft();

		if(isFloat()) {
			// XXX fixme to use a more intelligent approach than iterating every pixel!
			const FixedPoint lh = 65536;//getDimensions().content_.height;
			const FixedPoint box_w = getDimensions().content_.width;

			FixedPoint y = getMBPTop();
			FixedPoint x = getMBPLeft();

			FixedPoint y1 = y + getOffset().y;
			left = getStyleNode()->getFloat() == Float::LEFT ? eng.getXAtPosition(y1, y1 + lh) + x : eng.getX2AtPosition(y1, y1 + lh);
			FixedPoint w = eng.getWidthAtPosition(y1, y1 + lh, containing.content_.width);
			bool placed = false;
			while(!placed) {
				if(w >= box_w) {
					left = left - (getStyleNode()->getFloat() == Float::LEFT ? x : box_w);
					top = y;
					placed = true;
				} else {
					y += lh;
					y1 = y + getOffset().y;
					left = getStyleNode()->getFloat() == Float::LEFT ? eng.getXAtPosition(y1, y1 + lh) + x : eng.getX2AtPosition(y1, y1 + lh);
					w = eng.getWidthAtPosition(y1, y1 + lh, containing.content_.width);
				}
			}
		}

		setContentX(left);
		setContentY(top);

		auto& css_height = getStyleNode()->getHeight();
		if(!css_height->isAuto()) {
			FixedPoint h = css_height->getLength().compute(containing.content_.height);
			//if(h > child_height_) {
			//	/* apply overflow properties */
			//}
			setContentHeight(h);
		}

	}