aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeffrey Armstrong <jeff@approximatrix.com>2020-06-08 14:36:34 -0400
committerJeffrey Armstrong <jeff@approximatrix.com>2020-06-08 14:36:34 -0400
commit52915ba4bcb8f82a7d8249df07130e4fc0e5bd32 (patch)
tree25051156bc8fb7a4c45566a6b62f73e0da1a6eb0
parent48512f5d2e180d2086162cdf06c96098e6de96d7 (diff)
downloadLR-87-52915ba4bcb8f82a7d8249df07130e4fc0e5bd32.zip
LR-87-52915ba4bcb8f82a7d8249df07130e4fc0e5bd32.tar.gz
Line wrapping now computed only once for proportional text unless requested by the renderer, providing better performance.
-rw-r--r--ag_render.f903
-rw-r--r--files.f902
-rw-r--r--layout.f9034
-rw-r--r--main.F9010
-rw-r--r--render.f90122
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