Changeset - r23598:7da4fa077a86
[Not reviewed]
master
0 5 0
Michael Lutz - 5 years ago 2019-04-02 19:30:53
michi@icosahedron.de
Codechange: Store text layout runs directly as values in a std::vector instead of heap allocated.

This reduces memory allocations and heap fragmentation.
5 files changed with 65 insertions and 42 deletions:
0 comments (0 inline, 0 general)
src/gfx.cpp
Show inline comments
 
@@ -376,7 +376,7 @@ static int DrawLayoutLine(const Paragrap
 
		 * another size would be chosen it won't have truncated too little for
 
		 * the truncation dots.
 
		 */
 
		FontCache *fc = ((const Font*)line->GetVisualRun(0)->GetFont())->fc;
 
		FontCache *fc = ((const Font*)line->GetVisualRun(0).GetFont())->fc;
 
		GlyphID dot_glyph = fc->MapCharToGlyph('.');
 
		dot_width = fc->GetGlyphWidth(dot_glyph);
 
		dot_sprite = fc->GetGlyph(dot_glyph);
 
@@ -422,8 +422,8 @@ static int DrawLayoutLine(const Paragrap
 
	TextColour colour = TC_BLACK;
 
	bool draw_shadow = false;
 
	for (int run_index = 0; run_index < line->CountRuns(); run_index++) {
 
		const ParagraphLayouter::VisualRun *run = line->GetVisualRun(run_index);
 
		const Font *f = (const Font*)run->GetFont();
 
		const ParagraphLayouter::VisualRun &run = line->GetVisualRun(run_index);
 
		const Font *f = (const Font*)run.GetFont();
 

	
 
		FontCache *fc = f->fc;
 
		colour = f->colour;
 
@@ -435,15 +435,15 @@ static int DrawLayoutLine(const Paragrap
 

	
 
		draw_shadow = fc->GetDrawGlyphShadow() && (colour & TC_NO_SHADE) == 0 && colour != TC_BLACK;
 

	
 
		for (int i = 0; i < run->GetGlyphCount(); i++) {
 
			GlyphID glyph = run->GetGlyphs()[i];
 
		for (int i = 0; i < run.GetGlyphCount(); i++) {
 
			GlyphID glyph = run.GetGlyphs()[i];
 

	
 
			/* Not a valid glyph (empty) */
 
			if (glyph == 0xFFFF) continue;
 

	
 
			int begin_x = (int)run->GetPositions()[i * 2]     + left - offset_x;
 
			int end_x   = (int)run->GetPositions()[i * 2 + 2] + left - offset_x  - 1;
 
			int top     = (int)run->GetPositions()[i * 2 + 1] + y;
 
			int begin_x = (int)run.GetPositions()[i * 2]     + left - offset_x;
 
			int end_x   = (int)run.GetPositions()[i * 2 + 2] + left - offset_x  - 1;
 
			int top     = (int)run.GetPositions()[i * 2 + 1] + y;
 

	
 
			/* Truncated away. */
 
			if (truncation && (begin_x < min_x || end_x > max_x)) continue;
src/gfx_layout.cpp
Show inline comments
 
@@ -143,14 +143,14 @@ public:
 
	};
 

	
 
	/** A single line worth of VisualRuns. */
 
	class ICULine : public AutoDeleteSmallVector<ICUVisualRun *>, public ParagraphLayouter::Line {
 
	class ICULine : public std::vector<ICUVisualRun>, public ParagraphLayouter::Line {
 
		icu::ParagraphLayout::Line *l; ///< The actual ICU line.
 

	
 
	public:
 
		ICULine(icu::ParagraphLayout::Line *l) : l(l)
 
		{
 
			for (int i = 0; i < l->countRuns(); i++) {
 
				this->push_back(new ICUVisualRun(l->getVisualRun(i)));
 
				this->emplace_back(l->getVisualRun(i));
 
			}
 
		}
 
		~ICULine() override { delete l; }
 
@@ -158,7 +158,7 @@ public:
 
		int GetLeading() const override { return l->getLeading(); }
 
		int GetWidth() const override   { return l->getWidth(); }
 
		int CountRuns() const override  { return l->countRuns(); }
 
		const ParagraphLayouter::VisualRun *GetVisualRun(int run) const override { return this->at(run); }
 
		const ParagraphLayouter::VisualRun &GetVisualRun(int run) const override { return this->at(run); }
 

	
 
		int GetInternalCharLength(WChar c) const override
 
		{
 
@@ -259,6 +259,7 @@ public:
 

	
 
	public:
 
		FallbackVisualRun(Font *font, const WChar *chars, int glyph_count, int x);
 
		FallbackVisualRun(FallbackVisualRun &&other) noexcept;
 
		~FallbackVisualRun() override;
 
		const Font *GetFont() const override;
 
		int GetGlyphCount() const override;
 
@@ -269,12 +270,12 @@ public:
 
	};
 

	
 
	/** A single line worth of VisualRuns. */
 
	class FallbackLine : public AutoDeleteSmallVector<FallbackVisualRun *>, public ParagraphLayouter::Line {
 
	class FallbackLine : public std::vector<FallbackVisualRun>, public ParagraphLayouter::Line {
 
	public:
 
		int GetLeading() const override;
 
		int GetWidth() const override;
 
		int CountRuns() const override;
 
		const ParagraphLayouter::VisualRun *GetVisualRun(int run) const override;
 
		const ParagraphLayouter::VisualRun &GetVisualRun(int run) const override;
 

	
 
		int GetInternalCharLength(WChar c) const override { return 1; }
 
	};
 
@@ -350,6 +351,18 @@ FallbackParagraphLayout::FallbackVisualR
 
	}
 
}
 

	
 
/** Move constructor for visual runs.*/
 
FallbackParagraphLayout::FallbackVisualRun::FallbackVisualRun(FallbackVisualRun &&other) noexcept : font(other.font), glyph_count(other.glyph_count)
 
{
 
	this->positions = other.positions;
 
	this->glyph_to_char = other.glyph_to_char;
 
	this->glyphs = other.glyphs;
 

	
 
	other.positions = NULL;
 
	other.glyph_to_char = NULL;
 
	other.glyphs = NULL;
 
}
 

	
 
/** Free all data. */
 
FallbackParagraphLayout::FallbackVisualRun::~FallbackVisualRun()
 
{
 
@@ -419,8 +432,8 @@ int FallbackParagraphLayout::FallbackVis
 
int FallbackParagraphLayout::FallbackLine::GetLeading() const
 
{
 
	int leading = 0;
 
	for (const FallbackVisualRun * const &run : *this) {
 
		leading = max(leading, run->GetLeading());
 
	for (const auto &run : *this) {
 
		leading = max(leading, run.GetLeading());
 
	}
 

	
 
	return leading;
 
@@ -439,8 +452,8 @@ int FallbackParagraphLayout::FallbackLin
 
	 * Since there is no left-to-right support, taking this value of
 
	 * the last run gives us the end of the line and thus the width.
 
	 */
 
	const ParagraphLayouter::VisualRun *run = this->GetVisualRun(this->CountRuns() - 1);
 
	return (int)run->GetPositions()[run->GetGlyphCount() * 2];
 
	const auto &run = this->GetVisualRun(this->CountRuns() - 1);
 
	return (int)run.GetPositions()[run.GetGlyphCount() * 2];
 
}
 

	
 
/**
 
@@ -456,7 +469,7 @@ int FallbackParagraphLayout::FallbackLin
 
 * Get a specific visual run.
 
 * @return The visual run.
 
 */
 
const ParagraphLayouter::VisualRun *FallbackParagraphLayout::FallbackLine::GetVisualRun(int run) const
 
const ParagraphLayouter::VisualRun &FallbackParagraphLayout::FallbackLine::GetVisualRun(int run) const
 
{
 
	return this->at(run);
 
}
 
@@ -498,7 +511,7 @@ const ParagraphLayouter::Line *FallbackP
 
	if (*this->buffer == '\0') {
 
		/* Only a newline. */
 
		this->buffer = NULL;
 
		l->push_back(new FallbackVisualRun(this->runs.front().second, this->buffer, 0, 0));
 
		l->emplace_back(this->runs.front().second, this->buffer, 0, 0);
 
		return l;
 
	}
 

	
 
@@ -527,7 +540,7 @@ const ParagraphLayouter::Line *FallbackP
 

	
 
		if (this->buffer == next_run) {
 
			int w = l->GetWidth();
 
			l->push_back(new FallbackVisualRun(iter->second, begin, this->buffer - begin, w));
 
			l->emplace_back(iter->second, begin, this->buffer - begin, w);
 
			iter++;
 
			assert(iter != this->runs.End());
 

	
 
@@ -574,7 +587,7 @@ const ParagraphLayouter::Line *FallbackP
 

	
 
	if (l->size() == 0 || last_char - begin != 0) {
 
		int w = l->GetWidth();
 
		l->push_back(new FallbackVisualRun(iter->second, begin, last_char - begin, w));
 
		l->emplace_back(iter->second, begin, last_char - begin, w);
 
	}
 
	return l;
 
}
 
@@ -772,12 +785,12 @@ Point Layouter::GetCharPosition(const ch
 

	
 
		/* Scan all runs until we've found our code point index. */
 
		for (int run_index = 0; run_index < line->CountRuns(); run_index++) {
 
			const ParagraphLayouter::VisualRun *run = line->GetVisualRun(run_index);
 
			const ParagraphLayouter::VisualRun &run = line->GetVisualRun(run_index);
 

	
 
			for (int i = 0; i < run->GetGlyphCount(); i++) {
 
			for (int i = 0; i < run.GetGlyphCount(); i++) {
 
				/* Matching glyph? Return position. */
 
				if ((size_t)run->GetGlyphToCharMap()[i] == index) {
 
					Point p = { (int)run->GetPositions()[i * 2], (int)run->GetPositions()[i * 2 + 1] };
 
				if ((size_t)run.GetGlyphToCharMap()[i] == index) {
 
					Point p = { (int)run.GetPositions()[i * 2], (int)run.GetPositions()[i * 2 + 1] };
 
					return p;
 
				}
 
			}
 
@@ -798,18 +811,18 @@ const char *Layouter::GetCharAtPosition(
 
	const ParagraphLayouter::Line *line = this->front();
 

	
 
	for (int run_index = 0; run_index < line->CountRuns(); run_index++) {
 
		const ParagraphLayouter::VisualRun *run = line->GetVisualRun(run_index);
 
		const ParagraphLayouter::VisualRun &run = line->GetVisualRun(run_index);
 

	
 
		for (int i = 0; i < run->GetGlyphCount(); i++) {
 
		for (int i = 0; i < run.GetGlyphCount(); i++) {
 
			/* Not a valid glyph (empty). */
 
			if (run->GetGlyphs()[i] == 0xFFFF) continue;
 
			if (run.GetGlyphs()[i] == 0xFFFF) continue;
 

	
 
			int begin_x = (int)run->GetPositions()[i * 2];
 
			int end_x   = (int)run->GetPositions()[i * 2 + 2];
 
			int begin_x = (int)run.GetPositions()[i * 2];
 
			int end_x   = (int)run.GetPositions()[i * 2 + 2];
 

	
 
			if (IsInsideMM(x, begin_x, end_x)) {
 
				/* Found our glyph, now convert to UTF-8 string index. */
 
				size_t index = run->GetGlyphToCharMap()[i];
 
				size_t index = run.GetGlyphToCharMap()[i];
 

	
 
				size_t cur_idx = 0;
 
				for (const char *str = this->string; *str != '\0'; ) {
src/gfx_layout.h
Show inline comments
 
@@ -137,7 +137,7 @@ public:
 
		virtual int GetLeading() const = 0;
 
		virtual int GetWidth() const = 0;
 
		virtual int CountRuns() const = 0;
 
		virtual const VisualRun *GetVisualRun(int run) const = 0;
 
		virtual const VisualRun &GetVisualRun(int run) const = 0;
 
		virtual int GetInternalCharLength(WChar c) const = 0;
 
	};
 

	
src/os/macosx/string_osx.cpp
Show inline comments
 
@@ -53,6 +53,7 @@ public:
 

	
 
	public:
 
		CoreTextVisualRun(CTRunRef run, Font *font, const CoreTextParagraphLayoutFactory::CharType *buff);
 
		CoreTextVisualRun(CoreTextVisualRun &&other) = default;
 

	
 
		const GlyphID *GetGlyphs() const override { return &this->glyphs[0]; }
 
		const float *GetPositions() const override { return &this->positions[0]; }
 
@@ -65,7 +66,7 @@ public:
 
	};
 

	
 
	/** A single line worth of VisualRuns. */
 
	class CoreTextLine : public AutoDeleteSmallVector<CoreTextVisualRun *>, public ParagraphLayouter::Line {
 
	class CoreTextLine : public std::vector<CoreTextVisualRun>, public ParagraphLayouter::Line {
 
	public:
 
		CoreTextLine(CTLineRef line, const FontMap &fontMapping, const CoreTextParagraphLayoutFactory::CharType *buff)
 
		{
 
@@ -78,7 +79,7 @@ public:
 
				auto map = fontMapping.begin();
 
				while (map < fontMapping.end() - 1 && map->first <= chars.location) map++;
 

	
 
				this->push_back(new CoreTextVisualRun(run, map->second, buff));
 
				this->emplace_back(run, map->second, buff);
 
			}
 
			CFRelease(line);
 
		}
 
@@ -86,7 +87,7 @@ public:
 
		int GetLeading() const override;
 
		int GetWidth() const override;
 
		int CountRuns() const override { return this->size(); }
 
		const VisualRun *GetVisualRun(int run) const override { return this->at(run);  }
 
		const VisualRun &GetVisualRun(int run) const override { return this->at(run);  }
 

	
 
		int GetInternalCharLength(WChar c) const override
 
		{
src/os/windows/string_uniscribe.cpp
Show inline comments
 
@@ -90,6 +90,7 @@ public:
 

	
 
	public:
 
		UniscribeVisualRun(const UniscribeRun &range, int x);
 
		UniscribeVisualRun(UniscribeVisualRun &&other) noexcept;
 
		~UniscribeVisualRun() override
 
		{
 
			free(this->glyph_to_char);
 
@@ -106,12 +107,12 @@ public:
 
	};
 

	
 
	/** A single line worth of VisualRuns. */
 
	class UniscribeLine : public AutoDeleteSmallVector<UniscribeVisualRun *>, public ParagraphLayouter::Line {
 
	class UniscribeLine : public std::vector<UniscribeVisualRun>, public ParagraphLayouter::Line {
 
	public:
 
		int GetLeading() const override;
 
		int GetWidth() const override;
 
		int CountRuns() const override { return (uint)this->size();  }
 
		const VisualRun *GetVisualRun(int run) const override { return this->at(run);  }
 
		const VisualRun &GetVisualRun(int run) const override { return this->at(run);  }
 

	
 
		int GetInternalCharLength(WChar c) const override
 
		{
 
@@ -424,7 +425,7 @@ static std::vector<SCRIPT_ITEM> Uniscrib
 
			if (!UniscribeShapeRun(this->text_buffer, run)) return NULL;
 
		}
 

	
 
		line->push_back(new UniscribeVisualRun(run, cur_pos));
 
		line->emplace_back(run, cur_pos);
 
		cur_pos += run.total_advance;
 
	}
 

	
 
@@ -448,8 +449,8 @@ static std::vector<SCRIPT_ITEM> Uniscrib
 
int UniscribeParagraphLayout::UniscribeLine::GetLeading() const
 
{
 
	int leading = 0;
 
	for (const UniscribeVisualRun *run : *this) {
 
		leading = max(leading, run->GetLeading());
 
	for (const auto &run : *this) {
 
		leading = max(leading, run.GetLeading());
 
	}
 

	
 
	return leading;
 
@@ -462,8 +463,8 @@ int UniscribeParagraphLayout::UniscribeL
 
int UniscribeParagraphLayout::UniscribeLine::GetWidth() const
 
{
 
	int length = 0;
 
	for (const UniscribeVisualRun *run : *this) {
 
		length += run->GetAdvance();
 
	for (const auto &run : *this) {
 
		length += run.GetAdvance();
 
	}
 

	
 
	return length;
 
@@ -484,6 +485,14 @@ UniscribeParagraphLayout::UniscribeVisua
 
	this->positions[this->num_glyphs * 2] = advance + x;
 
}
 

	
 
UniscribeParagraphLayout::UniscribeVisualRun::UniscribeVisualRun(UniscribeVisualRun&& other) noexcept
 
								: glyphs(std::move(other.glyphs)), positions(std::move(other.positions)), char_to_glyph(std::move(other.char_to_glyph)),
 
								  start_pos(other.start_pos), total_advance(other.total_advance), num_glyphs(other.num_glyphs), font(other.font)
 
{
 
	this->glyph_to_char = other.glyph_to_char;
 
	other.glyph_to_char = NULL;
 
}
 

	
 
const int *UniscribeParagraphLayout::UniscribeVisualRun::GetGlyphToCharMap() const
 
{
 
	if (this->glyph_to_char == NULL) {
0 comments (0 inline, 0 general)