forked from mtcontrib/display_modpack
		
	New Font:render method
This commit is contained in:
		
							
								
								
									
										44
									
								
								API.md
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								API.md
									
									
									
									
									
								
							| @@ -37,7 +37,7 @@ minetest.register_node("mymod:test_text_node", { | ||||
| }) | ||||
| ``` | ||||
|  | ||||
| At this step, your node already displays text form "display_text" (hardcoded) node meta. | ||||
| At this step, your node already displays text form "display_text" (by default) node meta. If you want to store your text into another meta data field, add a `meta_text` field to display entity definition. | ||||
|  | ||||
| But it uses defaults (default font, default size, default color). Likely you need something more. | ||||
|  | ||||
| @@ -59,6 +59,28 @@ Then specify the char width. Two methods available: | ||||
|   * `halign`: Horizontal alignment: "left", "center" or "right" (default "center"). | ||||
|   * `valign`: Vertical alignement: "top", "middle" or "bottom" (default "middle"). | ||||
|  | ||||
| ### Example | ||||
| Using blue //botic// font, three lines height, aligned top left. Text stored in "text" node meta. | ||||
| ``` | ||||
| minetest.register_node("mymod:test_text_node", { | ||||
| 	... | ||||
| 	... | ||||
| 	display_entities = { | ||||
| 		["mymod:text"] = { | ||||
| 			depth = -0.5 - display_api.entity_spacing, | ||||
| 			on_display_update = font_api.on_display_update | ||||
| 			meta_text = "text", | ||||
| 			font_name = "botic", | ||||
| 			color = "#0000FF", | ||||
| 			maxlines = 3, | ||||
| 			aspect_ratio = 0.5, | ||||
| 			halign = "left", | ||||
| 			valign = "top", | ||||
| 			}, | ||||
| 	} | ||||
| 	... | ||||
| }) | ||||
| ``` | ||||
| ## Provided methods | ||||
| ### font_api.get_default_font_name() | ||||
| Returns de default font name. | ||||
| @@ -159,19 +181,13 @@ Returns line(s) height. Takes care of top and bottom margins and line spacing. | ||||
| Returns the width of a text line. Beware, if line contains any new line char, they are ignored. | ||||
|   * `line`: Line of text which the width will be computed. | ||||
|  | ||||
| ### font:make_line_texture(line, texturew, x, y) | ||||
| Create a texture for a text line. | ||||
|   * `line`: Line of text to be rendered in texture. | ||||
|   * `texturew`: Width of the texture (extra text is not rendered). | ||||
|   * `x`: Starting x position in texture. | ||||
| 	* `y`: Vertical position of the line in texture. | ||||
|  | ||||
| ### font:make_text_texture(text, texturew, textureh, maxlines, halign, valign, color) | ||||
| ### font:renter(text, texturew, textureh, style) | ||||
| Builds texture for a multiline colored text. | ||||
|   * `text`: Text to be rendered. | ||||
|   * `texturew`: Width of the texture (extra text will be truncated). | ||||
|   * `textureh`: Height of the texture. | ||||
|   * `maxlines`: Maximum number of lines. | ||||
|   * `halign`: Horizontal text align ("left"/"center"/"right") (optional). | ||||
|   * `valign`: Vertical text align ("top"/"center"/"bottom") (optional). | ||||
|   * `color`: Color of the text (optional). | ||||
|   * `textureh`: Height of the texture (extra text will be truncated). | ||||
|   * `style`: A table with style indications: | ||||
|     - `lines` or `maxlines`: Maximum number of lines (default none). | ||||
|     - `halign`: Horizontal text align: "left"/"center"/"right" (default "center") | ||||
|     - `valign`: Vertical text align: "top"/"middle"/"bottom" (default "middle") | ||||
|     - `color`: Color of the text (default black) | ||||
|   | ||||
							
								
								
									
										142
									
								
								font.lua
									
									
									
									
									
								
							
							
						
						
									
										142
									
								
								font.lua
									
									
									
									
									
								
							| @@ -54,20 +54,6 @@ local function char_to_codepoint(str) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| -- Split multiline text into array of lines, with <maxlines> maximum lines. | ||||
| -- Can not use minetest string.split as it has bug if first line(s) empty | ||||
| local function split_lines(text, maxlines) | ||||
| 	local lines = {} | ||||
| 	local pos = 1 | ||||
| 	repeat | ||||
| 		local found = string.find(text, "\n", pos) | ||||
| 		found = found or #text + 1 | ||||
| 		lines[#lines + 1] = string.sub(text, pos, found - 1) | ||||
| 		pos = found + 1 | ||||
| 	until (maxlines and (#lines >= maxlines)) or (pos > (#text + 1)) | ||||
| 	return lines | ||||
| end | ||||
|  | ||||
| -------------------------------------------------------------------------------- | ||||
| --- Font class | ||||
|  | ||||
| @@ -195,88 +181,86 @@ function Font:get_width(line) | ||||
| 	return width | ||||
| end | ||||
|  | ||||
| --- Builds texture part for a text line | ||||
| -- @param line Text line to be rendered | ||||
| -- @param texturew Width of the texture (extra text is not rendered) | ||||
| -- @param x Starting x position in texture | ||||
| -- @param y Vertical position of the line in texture | ||||
| -- @return Texture string | ||||
|  | ||||
| function Font:make_line_texture(line, texturew, x, y) | ||||
| 	local codepoint | ||||
| 	local texture = "" | ||||
| 	line = line or '' | ||||
|  | ||||
| 	while line ~= '' do | ||||
| 		codepoint, line = self:get_next_char(line) | ||||
|  | ||||
| 		-- Add image only if it is visible (at least partly) | ||||
| 		if x + self:get_char_width(codepoint) >= 0 and x <= texturew then | ||||
| 			texture = texture.. | ||||
| 				string.format(":%d,%d=font_%s_%04x.png", | ||||
| 				              x, y, self.name, codepoint) | ||||
| 		end | ||||
| 		x = x + self:get_char_width(codepoint) | ||||
| 	end | ||||
|  | ||||
| 	return texture | ||||
| end | ||||
|  | ||||
| --- Builds texture for a multiline colored text | ||||
| -- @param text Text to be rendered | ||||
| -- @param texturew Width of the texture (extra text will be truncated) | ||||
| -- @param textureh Height of the texture | ||||
| -- @param maxlines Maximum number of lines | ||||
| -- @param halign Horizontal text align ("left"/"center"/"right") (optional) | ||||
| -- @param valign Vertical text align ("top"/"center"/"bottom") (optional) | ||||
| -- @param color Color of the text (optional) | ||||
| -- @return Texture string | ||||
| --- Legacy make_text_texture method (replaced by "render" - Dec 2018) | ||||
|  | ||||
| function Font:make_text_texture(text, texturew, textureh, maxlines, | ||||
| 		halign, valign, color) | ||||
| 	local texture = "" | ||||
| 	local lines = {} | ||||
| 	local textheight = 0 | ||||
| 	local y | ||||
| 		return self:render(text, texturew, textureh, { | ||||
| 			lines = maxlines, | ||||
| 			valign = valign, | ||||
| 			halign = halign, | ||||
| 			color = color | ||||
| 		}) | ||||
| end | ||||
|  | ||||
| 	-- Split text into lines (limited to maxlines fist lines) | ||||
| 	for num, line in pairs(split_lines(text, maxlines)) do | ||||
| 		lines[num] = { text = line, width = self:get_width(line) } | ||||
| --- Render text with the font in a view | ||||
| -- @param text Text to be rendered | ||||
| -- @param texturew Width (in pixels) of the texture (extra text will be truncated) | ||||
| -- @param textureh Height (in pixels) of the texture (extra text will be truncated) | ||||
| -- @param style Style of the rendering: | ||||
| --		- lines: maximum number of text lines (if text is limited) | ||||
| --		- halign: horizontal align ("left"/"center"/"right") | ||||
| --		- valign: vertical align ("top"/"center"/"bottom") | ||||
| --		- color: color of the text ("#rrggbb") | ||||
| -- @return Texture string | ||||
|  | ||||
| function Font:render(text, texturew, textureh, style) | ||||
| 	local style = style or {} | ||||
|  | ||||
| 	-- Split text into lines (and limit to style.lines # of lines) | ||||
| 	local lines = {} | ||||
| 	local pos = 1 | ||||
| 	local found, line | ||||
| 	repeat | ||||
| 		found = string.find(text, "\n", pos) or (#text + 1) | ||||
| 		line = string.sub(text, pos, found - 1) | ||||
| 		lines[#lines + 1] = { text = line, width = self:get_width(line) } | ||||
| 		pos = found + 1 | ||||
| 	until (style.lines and (#lines >= style.lines)) or (pos > (#text + 1)) | ||||
|  | ||||
| 	if not #lines then | ||||
| 		return "" | ||||
| 	end | ||||
|  | ||||
| 	textheight = self:get_height(#lines) | ||||
| 	local x, y, codepoint | ||||
| 	local texture = "" | ||||
| 	local textheight = self:get_height(#lines) | ||||
|  | ||||
| 	if #lines then | ||||
| 		if valign == "top" then | ||||
| 			y = 0 | ||||
| 		elseif valign == "bottom" then | ||||
| 			y = textureh - textheight | ||||
| 		else | ||||
| 			y = (textureh - textheight) / 2 | ||||
| 		end | ||||
| 	if style.valign == "top" then | ||||
| 		y = 0 | ||||
| 	elseif style.valign == "bottom" then | ||||
| 		y = textureh - textheight | ||||
| 	else | ||||
| 		y = (textureh - textheight) / 2 | ||||
| 	end | ||||
|  | ||||
| 	y = y + (self.margintop or 0) | ||||
|  | ||||
| 	for _, line in pairs(lines) do | ||||
| 		if halign == "left" then | ||||
| 			texture = texture.. | ||||
| 				self:make_line_texture(line.text, texturew, | ||||
| 				0, y) | ||||
| 		elseif halign == "right" then | ||||
| 			texture = texture.. | ||||
| 				self:make_line_texture(line.text, texturew, | ||||
| 				texturew - line.width, y) | ||||
| 		if style.halign == "left" then | ||||
| 			x = 0 | ||||
| 		elseif style.halign == "right" then | ||||
| 			x = texturew - line.width | ||||
| 		else | ||||
| 			texture = texture.. | ||||
| 				self:make_line_texture(line.text, texturew, | ||||
| 				(texturew - line.width) / 2, y) | ||||
| 			x = (texturew - line.width) / 2 | ||||
| 		end | ||||
|  | ||||
| 		while line.text ~= '' do | ||||
| 			codepoint, line.text = self:get_next_char(line.text) | ||||
|  | ||||
| 			-- Add image only if it is visible (at least partly) | ||||
| 			if x + self.widths[codepoint] >= 0 and x <= texturew then | ||||
| 				texture = texture.. | ||||
| 					string.format(":%d,%d=font_%s_%04x.png", x, y, self.name, codepoint) | ||||
| 			end | ||||
| 			x = x + self.widths[codepoint] | ||||
| 		end | ||||
|  | ||||
| 		y = y + self:get_height() + (self.linespacing or 0) | ||||
| 	end | ||||
|  | ||||
| 	texture = string.format("[combine:%dx%d", texturew, textureh)..texture | ||||
| 	if color then texture = texture.."^[colorize:"..color end | ||||
| 	if style.color then | ||||
| 		texture = texture.."^[colorize:"..style.color | ||||
| 	end | ||||
| 	return texture | ||||
| end | ||||
|   | ||||
							
								
								
									
										72
									
								
								init.lua
									
									
									
									
									
								
							
							
						
						
									
										72
									
								
								init.lua
									
									
									
									
									
								
							| @@ -39,43 +39,49 @@ dofile(font_api.path.."/fontform.lua") | ||||
|  | ||||
| function font_api.on_display_update(pos, objref) | ||||
| 	local meta = minetest.get_meta(pos) | ||||
| 	local text = meta:get_string("display_text") | ||||
| 	local ndef = minetest.registered_nodes[minetest.get_node(pos).name] | ||||
| 	local entity = objref:get_luaentity() | ||||
|  | ||||
| 	if entity and ndef.display_entities[entity.name] then | ||||
| 		local def = ndef.display_entities[entity.name] | ||||
| 		local font = font_api.get_font(meta:get_string("font") ~= "" | ||||
| 			and meta:get_string("font") or def.font_name) | ||||
|  | ||||
| 		-- Compute entity resolution accroding to given attributes | ||||
| 		local texturew, textureh | ||||
| 		textureh = font:get_height(def.lines or def.maxlines or 1) | ||||
|  | ||||
| 		if def.columns then | ||||
| 			if font.fixedwidth then | ||||
| 				texturew = def.columns * font.fixedwidth | ||||
| 				if def.aspect_ratio then | ||||
| 					minetest.log('warning', "[font_api] 'aspect_ratio' ignored because 'columns' is specified") | ||||
| 				end | ||||
| 			else | ||||
| 				minetest.log('warning', "[font_api] 'columns' ignored because '"..font.name.."' is not a fixed width font.") | ||||
| 			end | ||||
| 		end | ||||
|  | ||||
| 		if not texturew then | ||||
| 			if not def.aspect_ratio then | ||||
| 				minetest.log('warning', "[font_api] No 'aspect_ratio' specified, using default 1.") | ||||
| 			end | ||||
| 			texturew = textureh * def.size.x / def.size.y	/ (def.aspect_ratio or 1) | ||||
| 		end | ||||
|  | ||||
| 		objref:set_properties({ | ||||
| 			textures={font:make_text_texture(text, texturew, textureh, | ||||
| 				def.maxlines, def.halign, def.valign, def.color)}, | ||||
| 			visual_size = def.size | ||||
| 		}) | ||||
| 	if not entity or not ndef.display_entities[entity.name] then | ||||
| 		return | ||||
| 	end | ||||
|  | ||||
| 	local def = ndef.display_entities[entity.name] | ||||
| 	local font = font_api.get_font(meta:get_string("font") ~= "" | ||||
| 		and meta:get_string("font") or def.font_name) | ||||
|  | ||||
| 	local text = meta:get_string(def.meta_text or "display_text") | ||||
|  | ||||
| 	-- Compute entity resolution accroding to given attributes | ||||
| 	local texturew, textureh | ||||
| 	textureh = font:get_height(def.lines or def.maxlines or 1) | ||||
|  | ||||
| 	if def.columns then | ||||
| 		if font.fixedwidth then | ||||
| 			texturew = def.columns * font.fixedwidth | ||||
| 			if def.aspect_ratio then | ||||
| 				minetest.log('warning', "[font_api] 'aspect_ratio' ignored because 'columns' is specified") | ||||
| 			end | ||||
| 		else | ||||
| 			minetest.log('warning', "[font_api] 'columns' ignored because '"..font.name.."' is not a fixed width font.") | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	if not texturew then | ||||
| 		if not def.aspect_ratio then | ||||
| 			minetest.log('warning', "[font_api] No 'aspect_ratio' specified, using default 1.") | ||||
| 		end | ||||
| 		texturew = textureh * def.size.x / def.size.y	/ (def.aspect_ratio or 1) | ||||
| 	end | ||||
|  | ||||
| 	objref:set_properties({ | ||||
| 		textures={ font:render(text, texturew, textureh, { | ||||
| 			lines = def.maxlines or def.lines, | ||||
| 			halign = def.halign, | ||||
| 			valign = def.valign, | ||||
| 			color = def.color} ) }, | ||||
| 		visual_size = def.size, | ||||
| 	}) | ||||
| end | ||||
|  | ||||
| -- Compatibility | ||||
|   | ||||
		Reference in New Issue
	
	Block a user