Ejemplo n.º 1
0
	margins units_converter::from_device_units(const margins& aValue) const
	{
		return margins{
			from_device_units(iContext.device_metrics().extents(), size{ aValue.left, 0 }).cx,
			from_device_units(iContext.device_metrics().extents(), size{ 0, aValue.top }).cy,
			from_device_units(iContext.device_metrics().extents(), size{ aValue.right, 0 }).cx,
			from_device_units(iContext.device_metrics().extents(), size{ 0, aValue.bottom }).cy };
	}
Ejemplo n.º 2
0
	path graphics_context::from_device_units(const path& aValue) const
	{
		path result = aValue;
		result.set_position(from_device_units(result.position()));
		for (std::size_t i = 0; i < result.paths().size(); ++i)
			for (std::size_t j = 0; j < result.paths()[i].size(); ++j)
				result.paths()[i][j] = from_device_units(result.paths()[i][j]);
		return result;
	}
Ejemplo n.º 3
0
	size graphics_context::text_extent(string::const_iterator aTextBegin, string::const_iterator aTextEnd, const font& aFont, bool aUseCache) const
	{
		const auto& glyphText = aUseCache && !iGlyphTextCache->empty() ? *iGlyphTextCache : to_glyph_text(aTextBegin, aTextEnd, aFont);
		if (aUseCache && iGlyphTextCache->empty())
			*iGlyphTextCache = glyphText;
		return from_device_units(size(glyphText.extents().cx, glyphText.extents().cy));
	}
Ejemplo n.º 4
0
	void graphics_context::draw_multiline_text(const point& aPoint, const string& aText, const font& aFont, dimension aMaxWidth, const colour& aColour, alignment aAlignment, bool aUseCache) const
	{
		const auto& glyphText = aUseCache && !iGlyphTextCache->empty() ? *iGlyphTextCache : to_glyph_text(aText.begin(), aText.end(), aFont);
		if (aUseCache && iGlyphTextCache->empty())
			*iGlyphTextCache = glyphText;
		typedef std::pair<glyph_text::const_iterator, glyph_text::const_iterator> line_t;
		typedef std::vector<line_t> lines_t;
		lines_t lines;
		std::array<glyph, 2> delimeters = { glyph(text_direction::Whitespace, '\r'), glyph(text_direction::Whitespace, '\n') };
		neolib::tokens(glyphText.cbegin(), glyphText.cend(), delimeters.begin(), delimeters.end(), lines, 0, false);
		size textExtent = multiline_text_extent(aText, aFont, aMaxWidth, aUseCache);
		point pos = aPoint;
		for (lines_t::const_iterator i = lines.begin(); i != lines.end(); ++i)
		{
			const auto& line = (logical_coordinates()[1] > logical_coordinates()[3] ? *i : *(lines.rbegin() + (i - lines.begin())));
			if (aMaxWidth == 0)
			{
				point linePos = pos;
				size lineExtent = from_device_units(glyph_text::extents(aFont, line.first, line.second));
				if (glyph_text_direction(line.first, line.second) == text_direction::RTL)
					linePos.x += textExtent.cx - lineExtent.cx;
				draw_glyph_text(linePos, line.first, line.second, aFont, aColour);
				pos.y += lineExtent.cy;
			}
			else
			{
				glyph_text::const_iterator next = line.first;
				glyph_text::const_iterator lineStart = next;
				glyph_text::const_iterator lineEnd = line.second;
				dimension maxWidth = to_device_units(size(aMaxWidth, 0)).cx;
				dimension lineWidth = 0;
				while(next != line.second)
				{
					bool gotLine = false;
					if (lineWidth + next->advance().cx > maxWidth)
					{
						std::pair<glyph_text::const_iterator, glyph_text::const_iterator> wordBreak = glyphText.word_break(lineStart, next);
						lineWidth -= glyph_text::extents(aFont, wordBreak.first, next).cx;
						lineEnd = wordBreak.first;
						next = wordBreak.second;
						if (lineEnd == next)
						{
							while(lineEnd != line.second && (lineEnd + 1)->source() == wordBreak.first->source())
								++lineEnd;
							next = lineEnd;
						}
						gotLine = true;
					}
					else
					{
						lineWidth += next->advance().cx;
						++next;
					}
					if (gotLine || next == line.second)
					{
						point linePos = pos;
						if (aAlignment == alignment::Left && glyph_text_direction(lineStart, next) == text_direction::RTL ||
							aAlignment == alignment::Right && glyph_text_direction(lineStart, next) == text_direction::LTR)
							linePos.x += textExtent.cx - from_device_units(size(lineWidth, 0)).cx;
						else if (aAlignment == alignment::Centre)
							linePos.x += std::ceil((textExtent.cx - from_device_units(size(lineWidth, 0)).cx) / 2);
						draw_glyph_text(linePos, lineStart, lineEnd, aFont, aColour);
						pos.y += glyph_text::extents(aFont, lineStart, lineEnd).cy;
						lineStart = next;
						lineEnd = line.second;
						lineWidth = 0;
					}
				}
				if (line.first == line.second)
					pos.y += font().height();
			}
		}
	}
Ejemplo n.º 5
0
	size graphics_context::multiline_text_extent(const string& aText, const font& aFont, dimension aMaxWidth, bool aUseCache) const
	{
		const auto& glyphText = aUseCache && !iGlyphTextCache->empty() ? *iGlyphTextCache : to_glyph_text(aText.begin(), aText.end(), aFont);
		if (aUseCache && iGlyphTextCache->empty())
			*iGlyphTextCache = glyphText;
		typedef std::pair<glyph_text::const_iterator, glyph_text::const_iterator> line_t;
		typedef std::vector<line_t> lines_t;
		lines_t lines;
		std::array<glyph, 2> delimeters = { glyph(text_direction::Whitespace, '\r'), glyph(text_direction::Whitespace, '\n') };
		neolib::tokens(glyphText.cbegin(), glyphText.cend(), delimeters.begin(), delimeters.end(), lines, 0, false);
		size result;
		for (lines_t::const_iterator i = lines.begin(); i != lines.end(); ++i)
		{
			if (aMaxWidth == 0)
			{
				size lineExtent = from_device_units(glyph_text::extents(aFont, i->first, i->second));
				result.cx = std::max(result.cx, lineExtent.cx);
				result.cy += lineExtent.cy;
			}
			else
			{
				glyph_text::const_iterator next = i->first;
				glyph_text::const_iterator lineStart = next;
				glyph_text::const_iterator lineEnd = i->second;
				dimension maxWidth = to_device_units(size(aMaxWidth, 0)).cx;
				dimension lineWidth = 0;
				bool gotLine = false;
				while(next != i->second)
				{
					if (lineWidth + next->advance().cx > maxWidth)
					{
						std::pair<glyph_text::const_iterator, glyph_text::const_iterator> wordBreak = glyphText.word_break(lineStart, next);
						lineWidth -= glyph_text::extents(aFont, wordBreak.first, next).cx;
						lineEnd = wordBreak.first;
						next = wordBreak.second;
						if (lineEnd == next)
						{
							while(lineEnd != i->second && (lineEnd + 1)->source() == wordBreak.first->source())
								++lineEnd;
							next = lineEnd;
						}
						gotLine = true;
					}
					else
					{	
						lineWidth += next->advance().cx;
						++next;
					}
					if (gotLine || next == i->second)
					{
						result.cx = std::max(result.cx, from_device_units(size(lineWidth, 0)).cx);
						result.cy += from_device_units(glyph_text::extents(aFont, i->first, i->second)).cy;
						lineStart = next;
						lineEnd = i->second;
						lineWidth = 0;
						gotLine = false;
					}
				}
			}
		}
		if (result.cy == 0)
			result.cy = from_device_units(size(0, aFont.height())).cy;
		return result;
	}
Ejemplo n.º 6
0
	point graphics_context::origin() const
	{
		return from_device_units(iOrigin);
	}
Ejemplo n.º 7
0
	rect units_converter::from_device_units(const size& aExtents, const rect& aValue) const
	{
		return rect(from_device_units(aExtents, aValue.position()), from_device_units(aExtents, aValue.extents()));
	}
Ejemplo n.º 8
0
	dimension units_converter::from_device_units(const size& aExtents, dimension aValue) const
	{
		return from_device_units(aExtents, size{aValue, 0.0}).cx;
	}
Ejemplo n.º 9
0
	rect units_converter::from_device_units(const rect& aValue) const
	{
		return from_device_units(iContext.device_metrics().extents(), aValue);
	}
Ejemplo n.º 10
0
	dimension units_converter::from_device_units(dimension aValue) const
	{
		return from_device_units(iContext.device_metrics().extents(), size{ aValue, 0 }).cx;
	}