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;
}
예제 #2
0
파일: font.cpp 프로젝트: rombust/UICore
	std::string Font::clipped_text(const CanvasPtr &canvas, const Sizef &box_size, const std::string &text, const std::string &ellipsis_text)
	{
		std::string out_string;
		out_string.reserve(text.length());

		Pointf pos;

		FontMetrics fm = font_metrics(canvas);
		float descent = fm.descent();
		float line_spacing = fm.line_height();
		std::vector<std::string> lines = Text::split(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.position())
							utf8_reader.next();
						seek_center = utf8_reader.position();
						if (seek_center == seek_end)
							break;

						utf8_reader.set_position(seek_start);
						utf8_reader.next();
						if (utf8_reader.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;
	}