aboutsummaryrefslogtreecommitdiff
path: root/render.f90
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 /render.f90
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.
Diffstat (limited to 'render.f90')
-rw-r--r--render.f90122
1 files changed, 118 insertions, 4 deletions
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