← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/fh1-sharedptr into lp:widelands

 

GunChleoc has proposed merging lp:~widelands-dev/widelands/fh1-sharedptr into lp:widelands.

Commit message:
Replaced raw pointers in the font renderer with shared_ptr.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/fh1-sharedptr/+merge/334791

Converting to the new font renderer has now become critical, because our Korean translator can only see square boxes instead of text in campaign messages.

I can't reproduce the problem, so the easiest fix is not to fix it but to get rid of the old renderer altogther.
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/fh1-sharedptr into lp:widelands.
=== modified file 'src/graphic/text/rt_render.cc'
--- src/graphic/text/rt_render.cc	2017-11-27 21:21:06 +0000
+++ src/graphic/text/rt_render.cc	2017-12-06 08:32:17 +0000
@@ -312,7 +312,7 @@
 
 class Layout {
 public:
-	explicit Layout(std::vector<RenderNode*>& all) : h_(0), idx_(0), all_nodes_(all) {
+	explicit Layout(std::vector<std::shared_ptr<RenderNode>>& all) : h_(0), idx_(0), all_nodes_(all) {
 	}
 	virtual ~Layout() {
 	}
@@ -320,7 +320,7 @@
 	uint16_t height() {
 		return h_;
 	}
-	uint16_t fit_nodes(std::vector<RenderNode*>& rv, uint16_t w, Borders p, bool shrink_to_fit);
+	uint16_t fit_nodes(std::vector<std::shared_ptr<RenderNode>>& rv, uint16_t w, Borders p, bool shrink_to_fit);
 
 private:
 	// Represents a change in the rendering constraints. For example when an
@@ -336,21 +336,21 @@
 		}
 	};
 
-	uint16_t fit_line(uint16_t w, const Borders&, std::vector<RenderNode*>* rv, bool shrink_to_fit);
+	uint16_t fit_line(uint16_t w, const Borders&, std::vector<std::shared_ptr<RenderNode>>* rv, bool shrink_to_fit);
 
 	uint16_t h_;
 	size_t idx_;
-	std::vector<RenderNode*>& all_nodes_;
+	std::vector<std::shared_ptr<RenderNode>>& all_nodes_;
 	std::priority_queue<ConstraintChange> constraint_changes_;
 };
 
 uint16_t
-Layout::fit_line(uint16_t w, const Borders& p, std::vector<RenderNode*>* rv, bool shrink_to_fit) {
+Layout::fit_line(uint16_t w, const Borders& p, std::vector<std::shared_ptr<RenderNode>>* rv, bool shrink_to_fit) {
 	assert(rv->empty());
 
 	// Remove leading spaces
 	while (idx_ < all_nodes_.size() && all_nodes_[idx_]->is_non_mandatory_space() && shrink_to_fit) {
-		delete all_nodes_[idx_++];
+		all_nodes_[idx_++].reset();
 	}
 
 	uint16_t x = p.left;
@@ -358,7 +358,7 @@
 
 	// Calc fitting nodes
 	while (idx_ < all_nodes_.size()) {
-		RenderNode* n = all_nodes_[idx_];
+		std::shared_ptr<RenderNode> n = all_nodes_[idx_];
 		uint16_t nw = n->width();
 		if (x + nw + p.right > w || n->get_floating() != RenderNode::NO_FLOAT) {
 			if (idx_ == first_idx) {
@@ -375,7 +375,7 @@
 	// Remove trailing spaces
 	while (!rv->empty() && rv->back()->is_non_mandatory_space() && shrink_to_fit) {
 		x -= rv->back()->width();
-		delete rv->back();
+		rv->back().reset();
 		rv->pop_back();
 	}
 
@@ -387,16 +387,19 @@
 
 	// Find expanding nodes
 	std::vector<size_t> expanding_nodes;
-	for (size_t idx = 0; idx < rv->size(); ++idx)
-		if (rv->at(idx)->is_expanding())
+	for (size_t idx = 0; idx < rv->size(); ++idx) {
+		if (rv->at(idx)->is_expanding()) {
 			expanding_nodes.push_back(idx);
+		}
+	}
 
 	if (!expanding_nodes.empty()) {  // If there are expanding nodes, we fill the space
 		const uint16_t individual_w = remaining_space / expanding_nodes.size();
 		for (const size_t idx : expanding_nodes) {
 			rv->at(idx)->set_w(individual_w);
-			for (size_t nidx = idx + 1; nidx < rv->size(); ++nidx)
+			for (size_t nidx = idx + 1; nidx < rv->size(); ++nidx) {
 				rv->at(nidx)->set_x(rv->at(nidx)->x() + individual_w);
+			}
 		}
 	} else {
 		// Take last elements style in this line and check horizontal alignment
@@ -404,7 +407,7 @@
 			if ((*rv->rbegin())->halign() == UI::Align::kCenter) {
 				remaining_space /= 2;  // Otherwise, we align right
 			}
-			for (RenderNode* node : *rv) {
+			for (std::shared_ptr<RenderNode> node : *rv) {
 				node->set_x(node->x() + remaining_space);
 			}
 		}
@@ -412,7 +415,7 @@
 
 	// Find the biggest hotspot of the truly remaining items.
 	uint16_t cur_line_hotspot = 0;
-	for (RenderNode* node : *rv) {
+	for (std::shared_ptr<RenderNode> node : *rv) {
 		cur_line_hotspot = std::max(cur_line_hotspot, node->hotspot_y());
 	}
 	return cur_line_hotspot;
@@ -422,21 +425,20 @@
  * Take ownership of all nodes, delete those that we do not render anyways (for
  * example unneeded spaces), append the rest to the vector we got.
  */
-uint16_t
-Layout::fit_nodes(std::vector<RenderNode*>& rv, uint16_t w, Borders p, bool shrink_to_fit) {
+uint16_t Layout::fit_nodes(std::vector<std::shared_ptr<RenderNode>>& rv, uint16_t w, Borders p, bool shrink_to_fit) {
 	assert(rv.empty());
 	h_ = p.top;
 
 	uint16_t max_line_width = 0;
 	while (idx_ < all_nodes_.size()) {
-		std::vector<RenderNode*> nodes_in_line;
+		std::vector<std::shared_ptr<RenderNode>> nodes_in_line;
 		size_t idx_before_iteration_ = idx_;
 		uint16_t biggest_hotspot = fit_line(w, p, &nodes_in_line, shrink_to_fit);
 
 		int line_height = 0;
 		int line_start = INFINITE_WIDTH;
 		// Compute real line height and width, taking into account alignement
-		for (RenderNode* n : nodes_in_line) {
+		for (std::shared_ptr<RenderNode> n : nodes_in_line) {
 			line_height = std::max(line_height, biggest_hotspot - n->hotspot_y() + n->height());
 			n->set_y(h_ + biggest_hotspot - n->hotspot_y());
 			if (line_start >= INFINITE_WIDTH || n->x() < line_start) {
@@ -446,7 +448,7 @@
 		}
 
 		// Go over again and adjust position for VALIGN
-		for (RenderNode* n : nodes_in_line) {
+		for (std::shared_ptr<RenderNode> n : nodes_in_line) {
 			uint16_t space = line_height - n->height();
 			if (!space || n->valign() == UI::Align::kBottom) {
 				continue;
@@ -470,7 +472,7 @@
 		}
 
 		if ((idx_ < all_nodes_.size()) && all_nodes_[idx_]->get_floating()) {
-			RenderNode* n = all_nodes_[idx_];
+			std::shared_ptr<RenderNode> n = all_nodes_[idx_];
 			n->set_y(h_);
 			ConstraintChange cc = {h_ + n->height(), 0, 0};
 			if (n->get_floating() == RenderNode::FLOAT_LEFT) {
@@ -778,9 +780,6 @@
 	     background_image_(nullptr) {
 	}
 	~DivTagRenderNode() override {
-		for (RenderNode* n : nodes_to_render_) {
-			delete n;
-		}
 		nodes_to_render_.clear();
 	}
 
@@ -825,7 +824,7 @@
 			rendered_text->rects.push_back(std::unique_ptr<UI::RenderedRect>(std::move(bg_rect)));
 		}
 
-		for (RenderNode* n : nodes_to_render_) {
+		for (std::shared_ptr<RenderNode> n : nodes_to_render_) {
 			const auto& renderme = n->render(texture_cache);
 			for (auto& rendered_rect : renderme->rects) {
 				if (rendered_rect->was_visited()) {
@@ -839,7 +838,6 @@
 				}
 				rendered_text->rects.push_back(std::move(rendered_rect));
 			}
-			delete n;
 		}
 		nodes_to_render_.clear();
 
@@ -863,7 +861,7 @@
 	void set_background(const Image* img) {
 		background_image_ = img;
 	}
-	void set_nodes_to_render(std::vector<RenderNode*>& n) {
+	void set_nodes_to_render(std::vector<std::shared_ptr<RenderNode>>& n) {
 		nodes_to_render_ = n;
 	}
 	void add_reference(int16_t gx, int16_t gy, uint16_t w, uint16_t h, const std::string& s) {
@@ -874,7 +872,7 @@
 private:
 	DesiredWidth desired_width_;
 	uint16_t w_, h_;
-	std::vector<RenderNode*> nodes_to_render_;
+	std::vector<std::shared_ptr<RenderNode>> nodes_to_render_;
 	Borders margin_;
 	RGBColor background_color_;
 	bool is_background_color_set_;
@@ -979,10 +977,10 @@
 
 	virtual void enter() {
 	}
-	virtual void emit_nodes(std::vector<RenderNode*>&);
+	virtual void emit_nodes(std::vector<std::shared_ptr<RenderNode>>&);
 
 private:
-	void make_text_nodes(const std::string& txt, std::vector<RenderNode*>& nodes, NodeStyle& ns);
+	void make_text_nodes(const std::string& txt, std::vector<std::shared_ptr<RenderNode>>& nodes, NodeStyle& ns);
 
 protected:
 	Tag& tag_;
@@ -993,18 +991,16 @@
 	const UI::FontSets& fontsets_;
 };
 
-void TagHandler::make_text_nodes(const std::string& txt,
-                                 std::vector<RenderNode*>& nodes,
-                                 NodeStyle& ns) {
+void TagHandler::make_text_nodes(const std::string& txt, std::vector<std::shared_ptr<RenderNode>>& nodes, NodeStyle& ns) {
 	TextStream ts(txt);
 	std::string word;
-	std::vector<RenderNode*> text_nodes;
+	std::vector<std::shared_ptr<RenderNode>> text_nodes;
 
 	// Bidirectional text (Arabic etc.)
 	if (i18n::has_rtl_character(txt.c_str())) {
 		std::string previous_word;
-		std::vector<RenderNode*>::iterator it = text_nodes.begin();
-		std::vector<WordSpacerNode*> spacer_nodes;
+		std::vector<std::shared_ptr<RenderNode>>::iterator it = text_nodes.begin();
+		std::vector<std::shared_ptr<RenderNode>> spacer_nodes;
 
 		// Collect the word nodes
 		while (ts.pos() < txt.size()) {
@@ -1015,7 +1011,7 @@
 			// We only know if the spacer goes to the left or right after having a look at the current
 			// word.
 			for (uint16_t ws_indx = 0; ws_indx < ts.pos() - cpos; ws_indx++) {
-				spacer_nodes.push_back(new WordSpacerNode(font_cache_, ns));
+				spacer_nodes.push_back(std::shared_ptr<RenderNode>(new WordSpacerNode(font_cache_, ns)));
 			}
 
 			word = ts.till_any_or_end(" \t\n\r");
@@ -1025,31 +1021,31 @@
 				bool word_is_bidi = i18n::has_rtl_character(word.c_str());
 				word = i18n::make_ligatures(word.c_str());
 				if (word_is_bidi || i18n::has_rtl_character(previous_word.c_str())) {
-					for (WordSpacerNode* spacer : spacer_nodes) {
+					for (std::shared_ptr<RenderNode> spacer : spacer_nodes) {
 						it = text_nodes.insert(text_nodes.begin(), spacer);
 					}
 					if (word_is_bidi) {
 						word = i18n::line2bidi(word.c_str());
 					}
 					it = text_nodes.insert(
-					   text_nodes.begin(), new TextNode(font_cache_, ns, word.c_str()));
+					   text_nodes.begin(), std::shared_ptr<RenderNode>(new TextNode(font_cache_, ns, word.c_str())));
 				} else {  // Sequences of Latin words go to the right from current position
 					if (it < text_nodes.end()) {
 						++it;
 					}
-					for (WordSpacerNode* spacer : spacer_nodes) {
+					for (std::shared_ptr<RenderNode> spacer : spacer_nodes) {
 						it = text_nodes.insert(it, spacer);
 						if (it < text_nodes.end()) {
 							++it;
 						}
 					}
-					it = text_nodes.insert(it, new TextNode(font_cache_, ns, word));
+					it = text_nodes.insert(it, std::shared_ptr<RenderNode>(new TextNode(font_cache_, ns, word)));
 				}
 			}
 			previous_word = word;
 		}
 		// Add the nodes to the end of the previously existing nodes.
-		for (RenderNode* node : text_nodes) {
+		for (std::shared_ptr<RenderNode> node : text_nodes) {
 			nodes.push_back(node);
 		}
 
@@ -1058,7 +1054,7 @@
 			std::size_t cpos = ts.pos();
 			ts.skip_ws();
 			for (uint16_t ws_indx = 0; ws_indx < ts.pos() - cpos; ws_indx++) {
-				nodes.push_back(new WordSpacerNode(font_cache_, ns));
+				nodes.push_back(std::shared_ptr<RenderNode>(new WordSpacerNode(font_cache_, ns)));
 			}
 			word = ts.till_any_or_end(" \t\n\r");
 			ns.fontset = i18n::find_fontset(word.c_str(), fontsets_);
@@ -1068,17 +1064,17 @@
 				if (i18n::has_script_character(word.c_str(), UI::FontSets::Selector::kCJK)) {
 					std::vector<std::string> units = i18n::split_cjk_word(word.c_str());
 					for (const std::string& unit : units) {
-						nodes.push_back(new TextNode(font_cache_, ns, unit));
+						nodes.push_back(std::shared_ptr<RenderNode>(new TextNode(font_cache_, ns, unit)));
 					}
 				} else {
-					nodes.push_back(new TextNode(font_cache_, ns, word));
+					nodes.push_back(std::shared_ptr<RenderNode>(new TextNode(font_cache_, ns, word)));
 				}
 			}
 		}
 	}
 }
 
-void TagHandler::emit_nodes(std::vector<RenderNode*>& nodes) {
+void TagHandler::emit_nodes(std::vector<std::shared_ptr<RenderNode>>& nodes) {
 	for (Child* c : tag_.children()) {
 		if (c->tag) {
 			std::unique_ptr<TagHandler> th(create_taghandler(
@@ -1161,13 +1157,13 @@
 		if (a.has("spacing"))
 			nodestyle_.spacing = a["spacing"].get_int();
 	}
-	void emit_nodes(std::vector<RenderNode*>& nodes) override {
+	void emit_nodes(std::vector<std::shared_ptr<RenderNode>>& nodes) override {
 		// Put a newline if this is not the first paragraph
 		if (!nodes.empty()) {
-			nodes.push_back(new NewlineNode(nodestyle_));
+			nodes.push_back(std::shared_ptr<RenderNode>(new NewlineNode(nodestyle_)));
 		}
 		if (indent_) {
-			nodes.push_back(new SpaceNode(nodestyle_, indent_));
+			nodes.push_back(std::shared_ptr<RenderNode>(new SpaceNode(nodestyle_, indent_)));
 		}
 		TagHandler::emit_nodes(nodes);
 	}
@@ -1211,14 +1207,14 @@
 				scale = static_cast<double>(width) / image_width;
 			}
 		}
-		render_node_ = new ImgRenderNode(nodestyle_, image_filename, scale, color, use_playercolor);
+		render_node_ = std::shared_ptr<ImgRenderNode>(new ImgRenderNode(nodestyle_, image_filename, scale, color, use_playercolor));
 	}
-	void emit_nodes(std::vector<RenderNode*>& nodes) override {
+	void emit_nodes(std::vector<std::shared_ptr<RenderNode>>& nodes) override {
 		nodes.push_back(render_node_);
 	}
 
 private:
-	ImgRenderNode* render_node_;
+	std::shared_ptr<ImgRenderNode> render_node_;
 };
 
 class VspaceTagHandler : public TagHandler {
@@ -1237,9 +1233,9 @@
 
 		space_ = a["gap"].get_int();
 	}
-	void emit_nodes(std::vector<RenderNode*>& nodes) override {
-		nodes.push_back(new SpaceNode(nodestyle_, 0, space_));
-		nodes.push_back(new NewlineNode(nodestyle_));
+	void emit_nodes(std::vector<std::shared_ptr<RenderNode>>& nodes) override {
+		nodes.push_back(std::shared_ptr<RenderNode>(new SpaceNode(nodestyle_, 0, space_)));
+		nodes.push_back(std::shared_ptr<RenderNode>(new NewlineNode(nodestyle_)));
 	}
 
 private:
@@ -1278,25 +1274,27 @@
 		}
 	}
 
-	void emit_nodes(std::vector<RenderNode*>& nodes) override {
-		RenderNode* rn = nullptr;
+	void emit_nodes(std::vector<std::shared_ptr<RenderNode>>& nodes) override {
 		if (!fill_text_.empty()) {
-			if (space_ < INFINITE_WIDTH)
-				rn = new FillingTextNode(font_cache_, nodestyle_, space_, fill_text_);
-			else
-				rn = new FillingTextNode(font_cache_, nodestyle_, 0, fill_text_, true);
+			std::shared_ptr<FillingTextNode> node;
+			if (space_ < INFINITE_WIDTH) {
+				node = std::shared_ptr<FillingTextNode>(new FillingTextNode(font_cache_, nodestyle_, space_, fill_text_));
+			} else {
+				node = std::shared_ptr<FillingTextNode>(new FillingTextNode(font_cache_, nodestyle_, 0, fill_text_, true));
+			}
+			nodes.push_back(node);
 		} else {
-			SpaceNode* sn;
-			if (space_ < INFINITE_WIDTH)
-				sn = new SpaceNode(nodestyle_, space_, 0);
-			else
-				sn = new SpaceNode(nodestyle_, 0, 0, true);
-
-			if (background_image_)
-				sn->set_background(background_image_, image_filename_);
-			rn = sn;
+			std::shared_ptr<SpaceNode> node;
+			if (space_ < INFINITE_WIDTH) {
+				node = std::shared_ptr<SpaceNode>(new SpaceNode(nodestyle_, space_, 0));
+			} else {
+				node = std::shared_ptr<SpaceNode>(new SpaceNode(nodestyle_, 0, 0, true));
+			}
+			if (background_image_) {
+				node->set_background(background_image_, image_filename_);
+			}
+			nodes.push_back(node);
 		}
-		nodes.push_back(rn);
 	}
 
 private:
@@ -1317,8 +1315,8 @@
 	   : TagHandler(tag, fc, ns, image_cache, init_renderer_style, fontsets) {
 	}
 
-	void emit_nodes(std::vector<RenderNode*>& nodes) override {
-		nodes.push_back(new NewlineNode(nodestyle_));
+	void emit_nodes(std::vector<std::shared_ptr<RenderNode>>& nodes) override {
+		nodes.push_back(std::shared_ptr<RenderNode>(new NewlineNode(nodestyle_)));
 	}
 };
 
@@ -1335,7 +1333,7 @@
 	   : TagHandler(tag, fc, ns, image_cache, init_renderer_style, fontsets),
 	     shrink_to_fit_(shrink_to_fit),
 	     w_(max_w),
-	     render_node_(new DivTagRenderNode(ns)) {
+	     render_node_(std::shared_ptr<DivTagRenderNode>(new DivTagRenderNode(ns))) {
 	}
 
 	void enter() override {
@@ -1369,11 +1367,11 @@
 			margin.left = margin.top = margin.right = margin.bottom = p;
 		}
 
-		std::vector<RenderNode*> subnodes;
+		std::vector<std::shared_ptr<RenderNode>> subnodes;
 		TagHandler::emit_nodes(subnodes);
 
 		if (!w_) {  // Determine the width by the width of the widest subnode
-			for (RenderNode* n : subnodes) {
+			for (std::shared_ptr<RenderNode> n : subnodes) {
 				if (n->width() >= INFINITE_WIDTH)
 					continue;
 				w_ = std::max<int>(w_, n->width() + padding.left + padding.right);
@@ -1394,7 +1392,8 @@
 
 		// Layout takes ownership of subnodes
 		Layout layout(subnodes);
-		std::vector<RenderNode*> nodes_to_render;
+		std::vector<std::shared_ptr<RenderNode>> nodes_to_render;
+
 		uint16_t max_line_width = layout.fit_nodes(nodes_to_render, w_, padding, shrink_to_fit_);
 		uint16_t extra_width = 0;
 		if (w_ < INFINITE_WIDTH && w_ > max_line_width) {
@@ -1405,7 +1404,7 @@
 		}
 
 		// Collect all tags from children
-		for (RenderNode* rn : nodes_to_render) {
+		for (std::shared_ptr<RenderNode> rn : nodes_to_render) {
 			for (const Reference& r : rn->get_references()) {
 				render_node_->add_reference(
 				   rn->x() + r.dim.x, rn->y() + r.dim.y, r.dim.w, r.dim.h, r.ref);
@@ -1434,7 +1433,7 @@
 		render_node_->set_dimensions(w_, layout.height(), margin);
 		render_node_->set_nodes_to_render(nodes_to_render);
 	}
-	void emit_nodes(std::vector<RenderNode*>& nodes) override {
+	void emit_nodes(std::vector<std::shared_ptr<RenderNode>>& nodes) override {
 		nodes.push_back(render_node_);
 	}
 
@@ -1489,7 +1488,7 @@
 
 private:
 	uint16_t w_;
-	DivTagRenderNode* render_node_;
+	std::shared_ptr<DivTagRenderNode> render_node_;
 };
 
 class RTTagHandler : public DivTagHandler {
@@ -1523,12 +1522,12 @@
 	return new T(tag, fc, ns, image_cache, renderer_style, fontsets);
 }
 using TagHandlerMap = std::map<const std::string,
-                               TagHandler* (*)(Tag& tag,
-                                               FontCache& fc,
-                                               NodeStyle& ns,
-                                               ImageCache* image_cache,
-                                               RendererStyle& renderer_style,
-                                               const UI::FontSets& fontsets)>;
+                          TagHandler* (*)(Tag& tag,
+                                          FontCache& fc,
+                                          NodeStyle& ns,
+                                          ImageCache* image_cache,
+                                          RendererStyle& renderer_style,
+                                          const UI::FontSets& fontsets)>;
 
 TagHandler* create_taghandler(Tag& tag,
                               FontCache& fc,
@@ -1570,7 +1569,7 @@
 Renderer::~Renderer() {
 }
 
-RenderNode* Renderer::layout_(const std::string& text, uint16_t width, const TagSet& allowed_tags) {
+std::shared_ptr<RenderNode> Renderer::layout(const std::string& text, uint16_t width, const TagSet& allowed_tags) {
 	std::unique_ptr<Tag> rt(parser_->parse(text, allowed_tags));
 
 	if (!width) {
@@ -1594,7 +1593,7 @@
 
 	RTTagHandler rtrn(
 	   *rt, *font_cache_, default_style, image_cache_, renderer_style_, fontsets_, width);
-	std::vector<RenderNode*> nodes;
+	std::vector<std::shared_ptr<RenderNode>> nodes;
 	rtrn.enter();
 	rtrn.emit_nodes(nodes);
 
@@ -1605,13 +1604,13 @@
 
 std::shared_ptr<const UI::RenderedText>
 Renderer::render(const std::string& text, uint16_t width, const TagSet& allowed_tags) {
-	std::unique_ptr<RenderNode> node(layout_(text, width, allowed_tags));
+	std::shared_ptr<RenderNode> node(layout(text, width, allowed_tags));
 	return std::shared_ptr<const UI::RenderedText>(node->render(texture_cache_));
 }
 
 IRefMap*
 Renderer::make_reference_map(const std::string& text, uint16_t width, const TagSet& allowed_tags) {
-	std::unique_ptr<RenderNode> node(layout_(text, width, allowed_tags));
+	std::shared_ptr<RenderNode> node(layout(text, width, allowed_tags));
 	return new RefMap(node->get_references());
 }
 }

=== modified file 'src/graphic/text/rt_render.h'
--- src/graphic/text/rt_render.h	2017-05-21 18:15:17 +0000
+++ src/graphic/text/rt_render.h	2017-12-06 08:32:17 +0000
@@ -89,7 +89,7 @@
 	IRefMap* make_reference_map(const std::string&, uint16_t, const TagSet& = TagSet());
 
 private:
-	RenderNode* layout_(const std::string& text, uint16_t width, const TagSet& allowed_tags);
+	std::shared_ptr<RenderNode> layout(const std::string& text, uint16_t width, const TagSet& allowed_tags);
 
 	std::unique_ptr<FontCache> font_cache_;
 	std::unique_ptr<Parser> parser_;


Follow ups