From 52915ba4bcb8f82a7d8249df07130e4fc0e5bd32 Mon Sep 17 00:00:00 2001 From: Jeffrey Armstrong Date: Mon, 8 Jun 2020 14:36:34 -0400 Subject: Line wrapping now computed only once for proportional text unless requested by the renderer, providing better performance. --- ag_render.f90 | 3 +- files.f90 | 2 + layout.f90 | 34 +++++++++++++++- main.F90 | 10 ++++- render.f90 | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 163 insertions(+), 8 deletions(-) diff --git a/ag_render.f90 b/ag_render.f90 index 8dfbb78..e98d7b6 100644 --- a/ag_render.f90 +++ b/ag_render.f90 @@ -249,6 +249,7 @@ contains address_width = getmaxx()/2 - textwidth("Address:") - 5 if(self%address_id < 0) then self%address_id = createtextbox(x, 2, address_width, 20) + call settextboxentercallback(self%address_id, go_button_callback) else call settextboxposition(self%address_id, x, 2, address_width, 20) end if @@ -780,7 +781,7 @@ contains self%max_width = compute_max_width(self) self%y = 0 - ag_action = render_action_layout + ag_action = render_action_rewrap end select diff --git a/files.f90 b/files.f90 index 9da1ae8..c09e535 100644 --- a/files.f90 +++ b/files.f90 @@ -187,6 +187,7 @@ contains call read_line_text(unit_number, first_line%text, iostatus) first_line%next => null() + first_line%breaks => null() walker=>first_line @@ -196,6 +197,7 @@ contains allocate(next_line) next_line%next => null() + next_line%breaks => null() walker%next => next_line next_line => null() diff --git a/layout.f90 b/layout.f90 index 685d646..714d62b 100644 --- a/layout.f90 +++ b/layout.f90 @@ -32,7 +32,7 @@ implicit none character(len=:), allocatable::text integer::line_type - integer, dimension(128)::breaks + integer, dimension(:), pointer::breaks type(line), pointer::next end type line @@ -56,10 +56,18 @@ contains do while(laying_out) + if(walker%line_type == line_type_text .and. .not. associated(walker%breaks)) then + walker%breaks => calculate_wrapping(rendering_engine, walker%text) + end if + + if(associated(walker%breaks)) then + Print *, "Associated" + end if + select case (walker%line_type) case (line_type_text) - call render_proportional(rendering_engine, walker%text) + call render_proportional(rendering_engine, walker%text, walker%breaks) case (line_type_preformatted) call render_preformatted(rendering_engine, walker%text) @@ -78,6 +86,26 @@ contains end subroutine layout_lines + subroutine clear_line_breaks(first_line) + implicit none + + type(line), intent(inout), pointer::first_line + type(line), pointer::walker + + walker => first_line + + do while(associated(walker)) + if(associated(walker%breaks)) then + deallocate(walker%breaks) + walker%breaks => null() + end if + + walker => walker%next + + end do + + end subroutine clear_line_breaks + subroutine free_lines(first_line) implicit none @@ -85,6 +113,8 @@ contains type(line), pointer::walker, past + call clear_line_breaks(first_line) + walker => first_line do while(associated(walker)) diff --git a/main.F90 b/main.F90 index 9d8e7a4..126796b 100644 --- a/main.F90 +++ b/main.F90 @@ -92,7 +92,7 @@ implicit none else - initial_site = "gemini://lilarm/" + initial_site = "gemini://gemini.circumlunar.space/" end if @@ -210,6 +210,14 @@ implicit none call r%status_ready() end if + case (render_action_rewrap) + if(associated(first_line)) then + call r%report_status("Performing Layout") + call clear_line_breaks(first_line) + call layout_lines(first_line, r) + call r%status_ready() + end if + case (render_action_goto) if(index(input, "://") > 0) then desired_url = input diff --git a/render.f90 b/render.f90 index ff9ed7f..335cbcb 100644 --- a/render.f90 +++ b/render.f90 @@ -27,7 +27,10 @@ implicit none integer, parameter::render_action_goto = 2 integer, parameter::render_action_layout = 3 integer, parameter::render_action_back = 4 - integer, parameter::render_action_quit = 5 + integer, parameter::render_action_rewrap = 5 + integer, parameter::render_action_quit = 6 + + integer, parameter::last_break = -1 character(11), dimension(2)::base_supported_types = & ["text/plain ", & @@ -316,16 +319,115 @@ contains end function wrap_line - subroutine render_proportional(r, text) + function calculate_wrapping(r, text) result(breaks) + implicit none + + class(renderer)::r + character(*), intent(in)::text + integer, dimension(:), pointer::breaks + + integer::startpos, endpos + integer::heading_level + logical::list_item + + integer::current_allocation + integer::break_count + integer, dimension(:), pointer::realloc + + current_allocation = 16 + break_count = 0 + allocate(breaks(current_allocation)) + + if(len_trim(text) > 0) then + + startpos = 1 + + ! Check for headings first + heading_level = 0 + do while(text(startpos:startpos) == '#') + heading_level = heading_level + 1 + startpos = startpos + 1 + end do + + ! Or a list item + list_item = .FALSE. + if(heading_level == 0) then + list_item = (text(1:1) == '*') + if(list_item) then + startpos = startpos + 1 + end if + end if + + ! If either occurred, advance past whitespace + if(heading_level > 0 .or. list_item) then + do while(text(startpos:startpos) == ' ' .or. text(startpos:startpos) == char(9)) + startpos = startpos + 1 + end do + end if + + endpos = wrap_line(r, text, startpos, heading_level, list_item) + do while(endpos > startpos) + + ! Save this break + break_count = break_count + 1 + + ! Messy memory handling... + if(break_count > current_allocation) then + realloc => breaks + breaks => null() + + allocate(breaks(current_allocation + 16)) + breaks(1:current_allocation) = realloc + current_allocation = current_allocation + 16 + deallocate(realloc) + end if + + ! Now actually save it + breaks(break_count) = endpos + + ! Advance string positions + startpos = endpos+1 + do while(text(startpos:startpos) == ' ') + startpos = startpos + 1 + end do + + ! Do not mark as a list item for subsequent lines + list_item = .FALSE. + endpos = wrap_line(r, text, startpos, heading_level, list_item) + end do + end if + + break_count = break_count + 1 + + ! Messy memory handling... + if(break_count > current_allocation) then + realloc => breaks + breaks => null() + + allocate(breaks(current_allocation + 16)) + breaks(1:current_allocation) = realloc + current_allocation = current_allocation + 16 + deallocate(realloc) + end if + + ! Save an ending indicator + breaks(break_count) = last_break + + end function calculate_wrapping + + subroutine render_proportional(r, text, breaks) implicit none class(renderer)::r character(*)::text + integer, dimension(:)::breaks integer::startpos, endpos integer::heading_level logical::list_item + integer::break_index + if(len_trim(text) == 0) then if(r%is_text_visible(" ")) then @@ -360,7 +462,12 @@ contains end do end if - endpos = wrap_line(r, text, startpos, heading_level, list_item) + break_index = 1 + endpos = breaks(break_index) + if(endpos == last_break) then + endpos = len_trim(text) + end if + do while(endpos > startpos) if(r%is_text_visible(text(startpos:endpos))) then call r%draw_porportional(text(startpos:endpos), & @@ -380,7 +487,14 @@ contains ! Do not mark as a list item for subsequent lines list_item = .FALSE. - endpos = wrap_line(r, text, startpos, heading_level, list_item) + if(breaks(break_index) /= last_break) then + break_index = break_index + 1 + endpos = breaks(break_index) + if(endpos == last_break) then + endpos = len_trim(text) + end if + end if + end do end if -- cgit v1.2.3