bool CSSInlineLayoutRenderLayerInline::node(CSSInlineGeneratedBox *cur)
{
	CSSBoxNode *node = cur->box_node;
	CSSBoxText *text = dynamic_cast<CSSBoxText*>(node);
	if (text)
	{
		const CSSComputedValues &properties = text->get_properties();
		if (properties.get_misc_inherit().visibility.type == CSSValueVisibility::type_visible)
		{
			Font font = graphics->get_font(properties);
			FontMetrics metrics = graphics->get_font_metrics(font);
			int pos_x = used_to_actual(cur->relative_x) + formatting_context->get_x();
			int pos_y = used_to_actual(cur->relative_y) + formatting_context->get_y();
			graphics->draw_text(font, pos_x + cur->x, pos_y + cur->y + used_to_actual(metrics.get_ascent()), text->processed_text.substr(cur->text_start, cur->text_end - cur->text_start), properties.get_text_inherit().color.color);
		}
	}
	else if (cur->layout_node)
	{
		CSSLayoutTreeNode *object_node = cur->layout_node;
		bool is_same_stacking_context = (stacking_context == object_node->get_stacking_context());
		bool is_positioned = (object_node->get_element_node()->computed_values.get_box().position.type != CSSValuePosition::type_static);
		if (is_same_stacking_context && !is_positioned)
			object_node->render_layer_inline(graphics, resources);
	}

	return true;
}
Beispiel #2
0
Size Font::get_text_size(Canvas &canvas, const std::string &text)
{
	Size total_size;

	if (impl)
	{
		FontMetrics fm = get_font_metrics();
		int line_spacing = fm.get_external_leading();
		std::vector<std::string> lines = StringHelp::split_text(text, "\n", false);
		for (std::vector<std::string>::size_type i=0; i<lines.size(); i++)
		{
			Size line_size = impl->get_text_size(canvas, lines[i]);

			if ((line_size.width == 0) && (line_size.height == 0) && (lines.size() > 1)) // blank line
				line_size.height = fm.get_descent() + fm.get_ascent(); 

			if ((i+1) != lines.size())	// Do not add the line spacing on the last line
				line_size.height += line_spacing;

			if (total_size.width < line_size.width)	// Find the widest line
				total_size.width = line_size.width;

			total_size.height += line_size.height;
		}
	}
	
	return total_size;
}
Beispiel #3
0
void Font::draw_text_ellipsis(Canvas &canvas, float dest_x, float dest_y, Rectf content_box, const std::string &text, const Colorf &color)
{
	if (impl)
	{
		FontMetrics fm = get_font_metrics();
		int ascent = fm.get_ascent();
		int descent = fm.get_descent();
		int line_spacing = fm.get_height() + fm.get_external_leading();
		std::vector<std::string> lines = StringHelp::split_text(text, "\n", false);
		for (std::vector<std::string>::size_type i=0; i<lines.size(); i++)
		{
			if (i == 0 || (dest_y - ascent >= content_box.top && dest_y + descent < content_box.bottom))
			{
				Size size = get_text_size(canvas, lines[i]);
				if (dest_x + size.width <= content_box.right)
				{
					draw_text(canvas, dest_x, dest_y, lines[i], color);
				}
				else
				{
					Size ellipsis = get_text_size(canvas, "...");

					int seek_start = 0;
					int seek_end = lines[i].size();
					int seek_center = (seek_start + seek_end) / 2;

					UTF8_Reader utf8_reader(lines[i].data(), lines[i].length());
					while (true)
					{
						utf8_reader.set_position(seek_center);
						utf8_reader.move_to_leadbyte();
						if (seek_center != utf8_reader.get_position())
							utf8_reader.next();
						seek_center = utf8_reader.get_position();
						if (seek_center == seek_end)
							break;

						utf8_reader.set_position(seek_start);
						utf8_reader.next();
						if (utf8_reader.get_position() == seek_end)
							break;

						Size text_size = get_text_size(canvas, lines[i].substr(0, seek_center));

						if (dest_x + text_size.width + ellipsis.width >= content_box.right)
							seek_end = seek_center;
						else
							seek_start = seek_center;
						seek_center = (seek_start+seek_end)/2;
					}

					draw_text(canvas, dest_x, dest_y, lines[i].substr(0, seek_center) + "...", color);
				}

				dest_y += line_spacing;
			}
		}
	}
}
static inline float positionOffsetForDecoration(TextDecoration decoration, const FontMetrics& fontMetrics, float thickness)
{
    // FIXME: For SVG Fonts we need to use the attributes defined in the <font-face> if specified.
    // Compatible with Batik/Opera.
    if (decoration == TextDecorationUnderline)
        return fontMetrics.floatAscent() + thickness * 1.5f;
    if (decoration == TextDecorationOverline)
        return thickness;
    if (decoration == TextDecorationLineThrough)
        return fontMetrics.floatAscent() * 5 / 8.0f;

    ASSERT_NOT_REACHED();
    return 0.0f;
}
Beispiel #5
0
static inline float positionOffsetForDecoration(ETextDecoration decoration, const FontMetrics& fontMetrics, float thickness)
{
    // FIXME: For SVG Fonts we need to use the attributes defined in the <font-face> if specified.
    // Compatible with Batik/Opera.
    if (decoration == UNDERLINE)
        return fontMetrics.ascent() + thickness * 1.5f;
    if (decoration == OVERLINE)
        return thickness;
    if (decoration == LINE_THROUGH)
        return fontMetrics.ascent() * 5.0f / 8.0f;

    ASSERT_NOT_REACHED();
    return 0.0f;
}
Beispiel #6
0
int GlyphCache::get_character_index(FontEngine *font_engine, GraphicContext &gc, const std::string &text, const Point &point)
{
	int dest_x = 0;
	int dest_y = 0;

	int character_counter = 0;

	FontMetrics fm = get_font_metrics();
	int font_height = fm.get_height();
	int font_ascent = fm.get_ascent();
	int font_external_leading = fm.get_external_leading();

	std::vector<std::string> lines = StringHelp::split_text(text, "\n", false);
	for (std::vector<std::string>::size_type i=0; i<lines.size(); i++)
	{
		int xpos = dest_x;
		int ypos = dest_y;

		std::string &textline = lines[i];
		std::string::size_type string_length = textline.length();

		// Scan the string

		UTF8_Reader reader(textline.data(), textline.length());
		while(!reader.is_end())
		{
			unsigned int glyph = reader.get_char();
			std::string::size_type glyph_pos = reader.get_position();
			reader.next();

			Font_TextureGlyph *gptr = get_glyph(font_engine, gc, glyph);
			if (gptr == NULL) continue;

			Rect position(xpos, ypos - font_ascent, Size(gptr->increment.x, gptr->increment.y + font_height + font_external_leading));
			if (position.contains(point))
			{
				return glyph_pos + character_counter;
			}
		
			xpos += gptr->increment.x;
			ypos += gptr->increment.y;
		}

		dest_y += font_height + font_external_leading;

		character_counter += string_length + 1;		// (Including the '\n')

	}
	return -1;	// Not found
}
Beispiel #7
0
void Font::draw_text(Canvas &canvas, float dest_x, float dest_y, const std::string &text, const Colorf &color)
{
	if (impl)
	{
		FontMetrics fm = get_font_metrics();
		int line_spacing = fm.get_height() + fm.get_external_leading();
		std::vector<std::string> lines = StringHelp::split_text(text, "\n", false);
		for (std::vector<std::string>::size_type i=0; i<lines.size(); i++)
		{
			impl->draw_text(canvas, dest_x, dest_y, lines[i], color);
			dest_y += line_spacing;
		}
	}
}
int FontProvider_Sprite::get_character_index(GraphicContext &gc, const std::string &text, const Point &point)
{
	int dest_x = 0;
	int dest_y = 0;
	int character_counter = 0;

	FontMetrics fm = get_font_metrics();
	int font_height = fm.get_height();
	int font_external_leading = fm.get_external_leading();

	std::vector<std::string> lines = StringHelp::split_text(text, "\n", false);
	for (std::vector<std::string>::size_type i=0; i<lines.size(); i++)
	{
		int xpos = dest_x;
		int ypos = dest_y;

		std::string &textline = lines[i];
		std::string::size_type string_length = textline.length();

		// Scan the string
		for (std::string::size_type p = 0; p < string_length; p++)
		{
			Font_Sprite_Glyph *gptr = get_glyph(textline[p]);

			int glyph_width;
			if (gptr)
			{
				glyph_width = spr_glyphs.get_frame_size(gptr->sprite_index).width;
			}
			else
			{
				glyph_width = spacelen;
			}


			Rect position(xpos, ypos - font_height, Size(glyph_width, font_height + font_external_leading));
			if (position.contains(point))
				return ((int) p) + character_counter;

			xpos += glyph_width;
		}

		dest_y += font_height + font_external_leading;

		character_counter += string_length + 1;		// (Including the '\n')

	}
	return -1;	// Not found
}
Beispiel #9
0
VerticalTextPosition GUIComponent::get_vertical_text_align(Canvas &canvas, const Rect &content_rect)
{
	Font font = get_font();

	// See diagram in: Documentation\Overview\fonts.html (Font Metrics)

	FontMetrics metrics = font.get_font_metrics();
	float align_height = metrics.get_ascent() - metrics.get_internal_leading();
	float content_height = content_rect.get_height();
	float baseline = (content_height + align_height) / 2.0f;

	VerticalTextPosition result;
	result.baseline = baseline + content_rect.top;
	result.top = result.baseline - metrics.get_ascent();
	result.bottom = result.baseline + metrics.get_descent();
	return result;
}
Beispiel #10
0
	Font::Font(Canvas &canvas, const std::string &typeface_name, Sprite &sprite, const std::string &glyph_list, float spacelen, bool monospace, const FontMetrics &metrics)
	{
		FontDescription desc;
		desc.set_height(metrics.get_height());

		FontFamily font_family(typeface_name);
		font_family.add(canvas, sprite, glyph_list, spacelen, monospace, metrics);
		impl = std::make_shared<Font_Impl>(font_family, desc);
	}
Beispiel #11
0
int computeUnderlineOffset(TextUnderlinePosition underlinePosition, const FontMetrics& fontMetrics, const InlineTextBox* inlineTextBox, int textDecorationThickness)
{
    // This represents the gap between the baseline and the closest edge of the underline.
    int gap = std::max<int>(1, ceilf(textDecorationThickness / 2.0));
    
    // FIXME: The code for visual overflow detection passes in a null inline text box. This means it is now
    // broken for the case where auto needs to behave like "under".
    
    // According to the specification TextUnderlinePositionAuto should avoid drawing through glyphs in
    // scripts where it would not be appropriate (e.g., ideographs).
    // Strictly speaking this can occur whenever the line contains ideographs
    // even if it is horizontal, but detecting this has performance implications. For now we only work with
    // vertical text, since we already determined the baseline type to be ideographic in that
    // case.
    TextUnderlinePosition resolvedUnderlinePosition = underlinePosition == TextUnderlinePositionAuto && inlineTextBox && inlineTextBox->root().baselineType() == IdeographicBaseline ? TextUnderlinePositionUnder : TextUnderlinePositionAlphabetic;
    
    switch (resolvedUnderlinePosition) {
    case TextUnderlinePositionAlphabetic:
        return fontMetrics.ascent() + gap;
    case TextUnderlinePositionUnder: {
        ASSERT(inlineTextBox);
        // Position underline relative to the bottom edge of the lowest element's content box.
        const RootInlineBox& rootBox = inlineTextBox->root();
        const RenderElement* decorationRenderer = inlineTextBox->parent()->renderer().enclosingRendererWithTextDecoration(TextDecorationUnderline, inlineTextBox->isFirstLine());
        
        float offset;
        if (inlineTextBox->renderer().style().isFlippedLinesWritingMode()) {
            offset = inlineTextBox->logicalTop();
            rootBox.minLogicalTopForTextDecorationLine(offset, decorationRenderer, TextDecorationUnderline);
            offset = inlineTextBox->logicalTop() - offset;
        } else {
            offset = inlineTextBox->logicalBottom();
            rootBox.maxLogicalBottomForTextDecorationLine(offset, decorationRenderer, TextDecorationUnderline);
            offset -= inlineTextBox->logicalBottom();
        }
        return inlineTextBox->logicalHeight() + gap + std::max<float>(offset, 0);
    }
    case TextUnderlinePositionAuto:
        ASSERT_NOT_REACHED();
    }

    ASSERT_NOT_REACHED();
    return fontMetrics.ascent() + gap;
}
Beispiel #12
0
	void TPopupMenu::show(Component* origin, int x, int y) {
		if (items.size() <= 0) {
			return;
		}
		base = origin;
		int fw = 100;
		FontMetrics* fm = getFontMetrics();
		int fh = fm->getHeight("0") + 6;
		int h = 0;
		for (int ii = 0; ii < items.size(); ii++) {
			TMenuItem* item = (TMenuItem*)items.get(ii);
			switch (item->getType()) {
				case TMenuItem::TYPE_ITEM:
					if (fm->getWidth(item->getTitle()) + 20 > fw) {
						fw = fm->getWidth(item->getTitle()) + 20;
					}
					break;
				default:
					break;
			}

		}
		for (int ii = 0; ii < items.size(); ii++) {
			TMenuItem* item = (TMenuItem*)items.get(ii);
			switch (item->getType()) {
				case TMenuItem::TYPE_ITEM:
					item->setBounds(base->getX() + x + 2, base->getY() + y + h + 2, fw, fh);
					h += fh;
					break;
				case TMenuItem::TYPE_SEPARATOR:
					item->setBounds(base->getX() + x + 2, base->getY() + y + h + 2, fw, 8);
					h += 8;
					break;
			}

		}
		setBounds(base->getX() + x, base->getY() + y, fw + 4, h + 4);
		//boo
		RootWindow* root = (RootWindow*)base->getMainWindow();
		if (root) {
			root->ShowPopupMenu(this);
		}
	}
Beispiel #13
0
static int computeUnderlineOffset(const TextUnderlinePosition underlinePosition, const FontMetrics& fontMetrics, const InlineTextBox* inlineTextBox, const float textDecorationThickness)
{
    // Compute the gap between the font and the underline. Use at least one
    // pixel gap, if underline is thick then use a bigger gap.
    int gap = 0;

    // Underline position of zero means draw underline on Baseline Position,
    // in Blink we need at least 1-pixel gap to adding following check.
    // Positive underline Position means underline should be drawn above baselin e
    // and negative value means drawing below baseline, negating the value as in Blink
    // downward Y-increases.

    if (fontMetrics.underlinePosition())
        gap = -fontMetrics.underlinePositio
template<class FontMetrics> void elidedMultiLength_helper()
{
    QString text1 = QLatin1String("Long Text 1\x9cShorter\x9csmall");
    QString text1_long = "Long Text 1";
    QString text1_short = "Shorter";
    QString text1_small = "small";
    FontMetrics fm = FontMetrics(QFont());
    int width_long = fm.size(0, text1_long).width();
    QCOMPARE(fm.elidedText(text1,Qt::ElideRight, 8000), text1_long);
    QCOMPARE(fm.elidedText(text1,Qt::ElideRight, width_long + 1), text1_long);
    QCOMPARE(fm.elidedText(text1,Qt::ElideRight, width_long - 1), text1_short);
    int width_short = fm.size(0, text1_short).width();
    QCOMPARE(fm.elidedText(text1,Qt::ElideRight, width_short + 1), text1_short);
    QCOMPARE(fm.elidedText(text1,Qt::ElideRight, width_short - 1), text1_small);

    // Not even wide enough for "small" - should use ellipsis
    QChar ellipsisChar(0x2026);
    QString text1_el = QString::fromLatin1("s") + ellipsisChar;
    int width_small = fm.width(text1_el);
    QCOMPARE(fm.elidedText(text1,Qt::ElideRight, width_small + 1), text1_el);
}
Beispiel #15
0
	std::string Font::get_clipped_text(Canvas &canvas, const Sizef &box_size, const std::string &text, const std::string &ellipsis_text)
	{
		std::string out_string;
		out_string.reserve(text.length());

		if (impl)
		{
			Pointf pos;

			FontMetrics fm = get_font_metrics(canvas);
			float descent = fm.get_descent();
			float line_spacing = fm.get_line_height();
			std::vector<std::string> lines = StringHelp::split_text(text, "\n", false);
			for (std::vector<std::string>::size_type i = 0; i < lines.size(); i++)
			{
				if (i == 0 || pos.y + descent < box_size.height)
				{
					Sizef size = measure_text(canvas, lines[i]).bbox_size;
					if (pos.x + size.width <= box_size.width)
					{
						if (!out_string.empty())
							out_string += "\n";
						out_string += lines[i];
					}
					else
					{
						Sizef ellipsis = measure_text(canvas, ellipsis_text).bbox_size;

						int seek_start = 0;
						int seek_end = lines[i].size();
						int seek_center = (seek_start + seek_end) / 2;

						UTF8_Reader utf8_reader(lines[i].data(), lines[i].length());
						while (true)
						{
							utf8_reader.set_position(seek_center);
							utf8_reader.move_to_leadbyte();
							if (seek_center != utf8_reader.get_position())
								utf8_reader.next();
							seek_center = utf8_reader.get_position();
							if (seek_center == seek_end)
								break;

							utf8_reader.set_position(seek_start);
							utf8_reader.next();
							if (utf8_reader.get_position() == seek_end)
								break;

							Sizef text_size = measure_text(canvas, lines[i].substr(0, seek_center)).bbox_size;

							if (pos.x + text_size.width + ellipsis.width >= box_size.width)
								seek_end = seek_center;
							else
								seek_start = seek_center;
							seek_center = (seek_start + seek_end) / 2;
						}

						if (!out_string.empty())
							out_string += "\n";
						out_string += lines[i].substr(0, seek_center) + ellipsis_text;
					}
					pos.y += line_spacing;
				}
			}
		}
		return out_string;
	}
float CanvasRenderingContext2D::getFontBaseline(
    const FontMetrics& fontMetrics) const {
  // If the font is so tiny that the lroundf operations result in two
  // different types of text baselines to return the same baseline, use
  // floating point metrics (crbug.com/338908).
  // If you changed the heuristic here, for consistency please also change it
  // in SimpleFontData::platformInit().
  bool useFloatAscentDescent =
      fontMetrics.ascent() < 3 || fontMetrics.height() < 2;
  switch (state().getTextBaseline()) {
    case TopTextBaseline:
      return useFloatAscentDescent ? fontMetrics.floatAscent()
                                   : fontMetrics.ascent();
    case HangingTextBaseline:
      // According to
      // http://wiki.apache.org/xmlgraphics-fop/LineLayout/AlignmentHandling
      // "FOP (Formatting Objects Processor) puts the hanging baseline at 80% of
      // the ascender height"
      return useFloatAscentDescent ? (fontMetrics.floatAscent() * 4.0) / 5.0
                                   : (fontMetrics.ascent() * 4) / 5;
    case BottomTextBaseline:
    case IdeographicTextBaseline:
      return useFloatAscentDescent ? -fontMetrics.floatDescent()
                                   : -fontMetrics.descent();
    case MiddleTextBaseline:
      return useFloatAscentDescent
                 ? -fontMetrics.floatDescent() + fontMetrics.floatHeight() / 2.0
                 : -fontMetrics.descent() + fontMetrics.height() / 2;
    case AlphabeticTextBaseline:
    default:
      // Do nothing.
      break;
  }
  return 0;
}