From 876d6298b40fc8b00bf559d4ec2d909ab1e6bc80 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Sat, 1 Apr 2023 16:29:17 -0700 Subject: [PATCH] App.width can no longer take a Text In the process I discovered the horrible fact that Text.x allocates a new Text. And it gets called (just once, thank goodness) on every single frame. --- app.lua | 11 +---------- drawing.lua | 9 ++++----- edit.lua | 7 ------- run.lua | 4 +--- search.lua | 5 +---- select.lua | 7 ++----- source.lua | 4 +--- source_edit.lua | 7 ------- source_select.lua | 7 ++----- source_text.lua | 19 ++++++++----------- text.lua | 19 ++++++++----------- 11 files changed, 28 insertions(+), 71 deletions(-) diff --git a/app.lua b/app.lua index 816c9af..48ab363 100644 --- a/app.lua +++ b/app.lua @@ -219,10 +219,7 @@ function App.newText(font, s) end function App.width(text) - if type(text) == 'string' then - return love.graphics.getFont():getWidth(text) - end - return text.text:getWidth() + return love.graphics.getFont():getWidth(text) end function App.screen.draw(obj, x,y) @@ -428,12 +425,6 @@ function App.disable_tests() App.screen.print = love.graphics.print App.newText = love.graphics.newText App.screen.draw = love.graphics.draw - App.width = function(text) - if type(text) == 'string' then - return love.graphics.getFont():getWidth(text) - end - return text:getWidth() - end if Current_app == nil or Current_app == 'run' then App.open_for_reading = function(filename) return io.open(filename, 'r') end App.open_for_writing = function(filename) return io.open(filename, 'w') end diff --git a/drawing.lua b/drawing.lua index 99193c6..5af25fb 100644 --- a/drawing.lua +++ b/drawing.lua @@ -60,14 +60,13 @@ function Drawing.draw(State, line_index, y) if State.current_drawing_mode == 'name' and i == line.pending.target_point then -- create a faint red box for the name App.color(Current_name_background_color) - local name_text - -- TODO: avoid computing name width on every repaint + local name_width if p.name == '' then - name_text = State.em + name_width = App.width('m') else - name_text = App.newText(love.graphics.getFont(), p.name) + name_width = App.width(p.name) end - love.graphics.rectangle('fill', x,y, App.width(name_text), State.line_height) + love.graphics.rectangle('fill', x,y, name_width, State.line_height) end end end diff --git a/edit.lua b/edit.lua index 3cea87f..407d8fb 100644 --- a/edit.lua +++ b/edit.lua @@ -103,7 +103,6 @@ function edit.initialize_state(top, left, right, font_height, line_height) -- c -- search search_term = nil, - search_text = nil, search_backup = nil, -- stuff to restore when cancelling search } return result @@ -324,7 +323,6 @@ function edit.text_input(State, t) --? print('text input', t) if State.search_term then State.search_term = State.search_term..t - State.search_text = nil Text.search_next(State) elseif State.lines.current_drawing and State.current_drawing_mode == 'name' then local before = snapshot(State, State.lines.current_drawing_index) @@ -355,20 +353,17 @@ function edit.keychord_press(State, chord, key) for _,line_cache in ipairs(State.line_cache) do line_cache.starty = nil end -- just in case we scroll if chord == 'escape' then State.search_term = nil - State.search_text = nil State.cursor1 = State.search_backup.cursor State.screen_top1 = State.search_backup.screen_top State.search_backup = nil Text.redraw_all(State) -- if we're scrolling, reclaim all fragments to avoid memory leaks elseif chord == 'return' then State.search_term = nil - State.search_text = nil State.search_backup = nil elseif chord == 'backspace' then local len = utf8.len(State.search_term) local byte_offset = Text.offset(State.search_term, len) State.search_term = string.sub(State.search_term, 1, byte_offset-1) - State.search_text = nil elseif chord == 'down' then State.cursor1.pos = State.cursor1.pos+1 Text.search_next(State) @@ -382,7 +377,6 @@ function edit.keychord_press(State, chord, key) cursor={line=State.cursor1.line, pos=State.cursor1.pos}, screen_top={line=State.screen_top1.line, pos=State.screen_top1.pos}, } - assert(State.search_text == nil) -- zoom elseif chord == 'C-=' then edit.update_font_settings(State, State.font_height+2) @@ -514,7 +508,6 @@ function edit.update_font_settings(State, font_height) State.font_height = font_height love.graphics.setFont(love.graphics.newFont(State.font_height)) State.line_height = math.floor(font_height*1.3) - State.em = App.newText(love.graphics.getFont(), 'm') Text_cache = {} end diff --git a/run.lua b/run.lua index 6da1c59..f3364c2 100644 --- a/run.lua +++ b/run.lua @@ -71,12 +71,10 @@ end function run.initialize_default_settings() local font_height = 20 love.graphics.setFont(love.graphics.newFont(font_height)) - local em = App.newText(love.graphics.getFont(), 'm') - run.initialize_window_geometry(App.width(em)) + run.initialize_window_geometry(App.width('m')) Editor_state = edit.initialize_state(Margin_top, Margin_left, App.screen.width-Margin_right) Editor_state.font_height = font_height Editor_state.line_height = math.floor(font_height*1.3) - Editor_state.em = em Settings = run.settings() end diff --git a/search.lua b/search.lua index f7d4732..7d3d335 100644 --- a/search.lua +++ b/search.lua @@ -13,10 +13,7 @@ function Text.draw_search_bar(State) love.graphics.rectangle('line', 20, y-6, App.screen.width-40, h+2, 2,2) App.color(Text_color) App.screen.print(State.search_term, 25,y-5) - if State.search_text == nil then - State.search_text = App.newText(love.graphics.getFont(), State.search_term) - end - Text.draw_cursor(State, 25+App.width(State.search_text),y-5) + Text.draw_cursor(State, 25+App.width(State.search_term),y-5) end function Text.search_next(State) diff --git a/select.lua b/select.lua index bae9504..efb6909 100644 --- a/select.lua +++ b/select.lua @@ -58,15 +58,12 @@ function Text.draw_highlight(State, line, x,y, pos, lo,hi) lo_px = 0 else local before = line.data:sub(pos_offset, lo_offset-1) - local before_text = App.newText(love.graphics.getFont(), before) - lo_px = App.width(before_text) + lo_px = App.width(before) end --? print(lo,pos,hi, '--', lo_offset,pos_offset,hi_offset, '--', lo_px) local s = line.data:sub(lo_offset, hi_offset-1) - local text = App.newText(love.graphics.getFont(), s) - local text_width = App.width(text) App.color(Highlight_color) - love.graphics.rectangle('fill', x+lo_px,y, text_width,State.line_height) + love.graphics.rectangle('fill', x+lo_px,y, App.width(s),State.line_height) App.color(Text_color) return lo_px end diff --git a/source.lua b/source.lua index bc2b1c5..3531bbf 100644 --- a/source.lua +++ b/source.lua @@ -162,13 +162,11 @@ end function source.initialize_default_settings() local font_height = 20 love.graphics.setFont(love.graphics.newFont(font_height)) - local em = App.newText(love.graphics.getFont(), 'm') - source.initialize_window_geometry(App.width(em)) + source.initialize_window_geometry(App.width('m')) Editor_state = edit.initialize_state(Margin_top, Margin_left, App.screen.width-Margin_right) Editor_state.filename = 'run.lua' Editor_state.font_height = font_height Editor_state.line_height = math.floor(font_height*1.3) - Editor_state.em = em end function source.initialize_window_geometry(em_width) diff --git a/source_edit.lua b/source_edit.lua index 2fc7e1b..de3ddd2 100644 --- a/source_edit.lua +++ b/source_edit.lua @@ -104,7 +104,6 @@ function edit.initialize_state(top, left, right, font_height, line_height) -- c -- search search_term = nil, - search_text = nil, search_backup = nil, -- stuff to restore when cancelling search } return result @@ -325,7 +324,6 @@ function edit.text_input(State, t) --? print('text input', t) if State.search_term then State.search_term = State.search_term..t - State.search_text = nil Text.search_next(State) elseif State.lines.current_drawing and State.current_drawing_mode == 'name' then local before = snapshot(State, State.lines.current_drawing_index) @@ -356,20 +354,17 @@ function edit.keychord_press(State, chord, key) for _,line_cache in ipairs(State.line_cache) do line_cache.starty = nil end -- just in case we scroll if chord == 'escape' then State.search_term = nil - State.search_text = nil State.cursor1 = State.search_backup.cursor State.screen_top1 = State.search_backup.screen_top State.search_backup = nil Text.redraw_all(State) -- if we're scrolling, reclaim all fragments to avoid memory leaks elseif chord == 'return' then State.search_term = nil - State.search_text = nil State.search_backup = nil elseif chord == 'backspace' then local len = utf8.len(State.search_term) local byte_offset = Text.offset(State.search_term, len) State.search_term = string.sub(State.search_term, 1, byte_offset-1) - State.search_text = nil elseif chord == 'down' then State.cursor1.pos = State.cursor1.pos+1 Text.search_next(State) @@ -383,7 +378,6 @@ function edit.keychord_press(State, chord, key) cursor={line=State.cursor1.line, pos=State.cursor1.pos}, screen_top={line=State.screen_top1.line, pos=State.screen_top1.pos}, } - assert(State.search_text == nil) -- zoom elseif chord == 'C-=' then edit.update_font_settings(State, State.font_height+2) @@ -515,7 +509,6 @@ function edit.update_font_settings(State, font_height) State.font_height = font_height love.graphics.setFont(love.graphics.newFont(State.font_height)) State.line_height = math.floor(font_height*1.3) - State.em = App.newText(love.graphics.getFont(), 'm') Text_cache = {} end diff --git a/source_select.lua b/source_select.lua index 297a7bc..2298513 100644 --- a/source_select.lua +++ b/source_select.lua @@ -60,15 +60,12 @@ function Text.draw_highlight(State, line, x,y, pos, lo,hi) lo_px = 0 else local before = line.data:sub(pos_offset, lo_offset-1) - local before_text = App.newText(love.graphics.getFont(), before) - lo_px = App.width(before_text) + lo_px = App.width(before) end --? print(lo,pos,hi, '--', lo_offset,pos_offset,hi_offset, '--', lo_px) local s = line.data:sub(lo_offset, hi_offset-1) - local text = App.newText(love.graphics.getFont(), s) - local text_width = App.width(text) App.color(Highlight_color) - love.graphics.rectangle('fill', x+lo_px,y, text_width,State.line_height) + love.graphics.rectangle('fill', x+lo_px,y, App.width(s),State.line_height) App.color(Text_color) return lo_px end diff --git a/source_text.lua b/source_text.lua index 2aa27bc..cf47f2a 100644 --- a/source_text.lua +++ b/source_text.lua @@ -26,7 +26,7 @@ function Text.draw(State, line_index, y, startpos, hide_cursor) --? print('skipping', frag) else -- render fragment - local frag_width = App.width(frag_text) + local frag_width = App.width(f.data) if x + frag_width > State.right then assert(x > State.left) -- no overfull lines y = y + State.line_height @@ -106,7 +106,7 @@ function Text.populate_screen_line_starting_pos(State, line_index) for _, f in ipairs(line_cache.fragments) do local frag, frag_text = f.data, f.text -- render fragment - local frag_width = App.width(frag_text) + local frag_width = App.width(f.data) if x + frag_width > State.right then x = State.left table.insert(line_cache.screen_line_starting_pos, pos) @@ -130,7 +130,7 @@ function Text.compute_fragments(State, line_index) -- try to wrap at word boundaries for frag in line.data:gmatch('%S*%s*') do local frag_text = App.newText(love.graphics.getFont(), frag) - local frag_width = App.width(frag_text) + local frag_width = App.width(frag) --? print('x: '..tostring(x)..'; frag_width: '..tostring(frag_width)..'; '..tostring(State.right-x)..'px to go') while x + frag_width > State.right do --? print(('checking whether to split fragment ^%s$ of width %d when rendering from %d'):format(frag, frag_width, x)) @@ -145,13 +145,13 @@ function Text.compute_fragments(State, line_index) --? print('space for '..tostring(bpos)..' graphemes, '..tostring(boffset-1)..' bytes') local frag1 = string.sub(frag, 1, boffset-1) local frag1_text = App.newText(love.graphics.getFont(), frag1) - local frag1_width = App.width(frag1_text) + local frag1_width = App.width(frag1) --? print('extracting ^'..frag1..'$ of width '..tostring(frag1_width)..'px') assert(x + frag1_width <= State.right) table.insert(line_cache.fragments, {data=frag1, text=frag1_text}) frag = string.sub(frag, boffset) frag_text = App.newText(love.graphics.getFont(), frag) - frag_width = App.width(frag_text) + frag_width = App.width(frag) end x = State.left -- new line end @@ -775,8 +775,7 @@ function Text.screen_line_width(State, line_index, i) else screen_line = string.sub(line.data, start_pos) end - local screen_line_text = App.newText(love.graphics.getFont(), screen_line) - return App.width(screen_line_text) + return App.width(screen_line) end function Text.screen_line_index(screen_line_starting_pos, pos) @@ -864,15 +863,13 @@ function Text.x_after(s, pos) local offset = Text.offset(s, math.min(pos+1, #s+1)) local s_before = s:sub(1, offset-1) --? print('^'..s_before..'$') - local text_before = App.newText(love.graphics.getFont(), s_before) - return App.width(text_before) + return App.width(s_before) end function Text.x(s, pos) local offset = Text.offset(s, pos) local s_before = s:sub(1, offset-1) - local text_before = App.newText(love.graphics.getFont(), s_before) - return App.width(text_before) + return App.width(s_before) end function Text.to2(State, loc1) diff --git a/text.lua b/text.lua index 589e4fd..5045570 100644 --- a/text.lua +++ b/text.lua @@ -23,7 +23,7 @@ function Text.draw(State, line_index, y, startpos) --? print('skipping', frag) else -- render fragment - local frag_width = App.width(frag_text) + local frag_width = App.width(f.data) if x + frag_width > State.right then assert(x > State.left) -- no overfull lines y = y + State.line_height @@ -90,7 +90,7 @@ function Text.populate_screen_line_starting_pos(State, line_index) for _, f in ipairs(line_cache.fragments) do local frag, frag_text = f.data, f.text -- render fragment - local frag_width = App.width(frag_text) + local frag_width = App.width(f.data) if x + frag_width > State.right then x = State.left table.insert(line_cache.screen_line_starting_pos, pos) @@ -114,7 +114,7 @@ function Text.compute_fragments(State, line_index) -- try to wrap at word boundaries for frag in line.data:gmatch('%S*%s*') do local frag_text = App.newText(love.graphics.getFont(), frag) - local frag_width = App.width(frag_text) + local frag_width = App.width(frag) --? print('x: '..tostring(x)..'; frag_width: '..tostring(frag_width)..'; '..tostring(State.right-x)..'px to go') while x + frag_width > State.right do --? print(('checking whether to split fragment ^%s$ of width %d when rendering from %d'):format(frag, frag_width, x)) @@ -129,13 +129,13 @@ function Text.compute_fragments(State, line_index) --? print('space for '..tostring(bpos)..' graphemes, '..tostring(boffset-1)..' bytes') local frag1 = string.sub(frag, 1, boffset-1) local frag1_text = App.newText(love.graphics.getFont(), frag1) - local frag1_width = App.width(frag1_text) + local frag1_width = App.width(frag1) --? print('extracting ^'..frag1..'$ of width '..tostring(frag1_width)..'px') assert(x + frag1_width <= State.right) table.insert(line_cache.fragments, {data=frag1, text=frag1_text}) frag = string.sub(frag, boffset) frag_text = App.newText(love.graphics.getFont(), frag) - frag_width = App.width(frag_text) + frag_width = App.width(frag) end x = State.left -- new line end @@ -759,8 +759,7 @@ function Text.screen_line_width(State, line_index, i) else screen_line = string.sub(line.data, start_pos) end - local screen_line_text = App.newText(love.graphics.getFont(), screen_line) - return App.width(screen_line_text) + return App.width(screen_line) end function Text.screen_line_index(screen_line_starting_pos, pos) @@ -848,15 +847,13 @@ function Text.x_after(s, pos) local offset = Text.offset(s, math.min(pos+1, #s+1)) local s_before = s:sub(1, offset-1) --? print('^'..s_before..'$') - local text_before = App.newText(love.graphics.getFont(), s_before) - return App.width(text_before) + return App.width(s_before) end function Text.x(s, pos) local offset = Text.offset(s, pos) local s_before = s:sub(1, offset-1) - local text_before = App.newText(love.graphics.getFont(), s_before) - return App.width(text_before) + return App.width(s_before) end function Text.to2(State, loc1)