From fe3032d66691a01d0a970dda3fa33f39b2c4cf5b Mon Sep 17 00:00:00 2001 From: Jeffrey Armstrong Date: Tue, 9 Jun 2020 09:29:27 -0400 Subject: Added support for quotes that are new in the spec. Looks pretty on Win32, untested in dumb renderer. --- ag_render.f90 | 103 ++++++++++++++++++++++--------------- dumb_render.f90 | 43 ++++++++-------- render.f90 | 155 ++++++++++++++++++++++++++------------------------------ 3 files changed, 158 insertions(+), 143 deletions(-) diff --git a/ag_render.f90 b/ag_render.f90 index e98d7b6..fc80295 100644 --- a/ag_render.f90 +++ b/ag_render.f90 @@ -94,7 +94,7 @@ implicit none procedure :: text_height => ag_text_height procedure :: is_text_visible => ag_text_visible - procedure :: draw_porportional => ag_text_draw + procedure :: draw_proportional => ag_text_draw procedure :: preformatted_width => ag_preformatted_width procedure :: preformatted_height => ag_preformatted_height @@ -440,36 +440,46 @@ contains end subroutine ag_new_page - pure function get_font_size(self, heading) + pure function get_font_size(self, text_type) implicit none class(appgraphics_renderer), intent(in)::self - integer, intent(in)::heading + integer, intent(in)::text_type integer::get_font_size get_font_size = self%font_size - if(heading == 1) then + if(text_type == proportional_type_heading_1) then get_font_size = 2*get_font_size - else if(heading > 1) then + else if(text_type > proportional_type_heading_1) then get_font_size = (3*get_font_size)/2 end if end function get_font_size - function ag_text_width(self, text, heading, list_item) + pure function get_indent_margin(self) + implicit none + + type(appgraphics_renderer), intent(in)::self + integer::get_indent_margin + + get_indent_margin = self%font_size + 2*self%bullet_margin + + end function get_indent_margin + + function ag_text_width(self, text, text_type) use appgraphics + use render implicit none class(appgraphics_renderer)::self character(*), intent(in)::text - integer, intent(in), optional::heading - logical, intent(in), optional::list_item + integer, intent(in), optional::text_type integer::ag_text_width integer::font_size font_size = self%font_size - if(present(heading)) then - font_size = get_font_size(self, heading) + if(present(text_type)) then + font_size = get_font_size(self, text_type) end if call settextstyle(self%default_font, HORIZ_DIR, font_size) @@ -481,28 +491,29 @@ contains ag_text_width = ag_text_width + self%left_border + self%right_border - if(present(list_item)) then - if(list_item) then - ag_text_width = ag_text_width + self%font_size/2 + 2*self%bullet_margin + if(present(text_type)) then + if(text_type == proportional_type_list_item) then + ag_text_width = ag_text_width + get_indent_margin(self) + else if(text_type == proportional_type_quotation) then + ag_text_width = ag_text_width + 2 * get_indent_margin(self) end if end if end function ag_text_width - function ag_text_height(self, text, heading, list_item) + function ag_text_height(self, text, text_type) use appgraphics implicit none class(appgraphics_renderer)::self character(*), intent(in)::text - integer, intent(in), optional::heading - logical, intent(in), optional::list_item + integer, intent(in), optional::text_type integer::ag_text_height integer::font_size font_size = self%font_size - if(present(heading)) then - font_size = get_font_size(self, heading) + if(present(text_type)) then + font_size = get_font_size(self, text_type) end if call settextstyle(self%default_font, HORIZ_DIR, font_size) @@ -526,43 +537,55 @@ contains end function ag_text_visible - subroutine ag_text_draw(self, text, heading, list_item) + subroutine ag_text_draw(self, text, text_type) use appgraphics implicit none class(appgraphics_renderer)::self character(*), intent(in)::text - integer, intent(in), optional::heading - logical, intent(in), optional::list_item + integer, intent(in), optional::text_type integer::font_size integer::x, bx, by + integer::font_color font_size = self%font_size - if(present(heading)) then - font_size = get_font_size(self, heading) - - ! The first level 1 heading can be guessed as the page title - if(heading == 1 .and. .not. self%title_guessed) then - call set_window_title(self, text) - self%title_guessed = .true. - end if - end if - + font_color = self%text_color x = self%left_border - if(present(list_item)) then - if(list_item) then - bx = x + self%bullet_margin - by = self%y + self%font_size/4 + + if(present(text_type)) then + font_size = get_font_size(self, text_type) + + select case(text_type) - call setfillstyle(SOLID_FILL, self%text_color) - call bar(bx, by, bx+self%font_size/2, by+self%font_size/2) + case (proportional_type_heading_1) + ! The first level 1 heading can be guessed as the page title + if(.not. self%title_guessed) then + + call set_window_title(self, text) + self%title_guessed = .true. - x = bx + self%bullet_margin + self%font_size/2 - end if + end if + + case (proportional_type_list_item) + ! If a list item, need to draw a box + bx = x + self%bullet_margin + by = self%y + self%font_size/4 + + call setfillstyle(SOLID_FILL, self%text_color) + call bar(bx, by, bx+self%font_size/2, by+self%font_size/2) + + x = get_indent_margin(self) + + case (proportional_type_quotation) + ! Scoot in and draw grey + x = x + get_indent_margin(self) + font_color = DARKGRAY + + end select end if call settextstyle(self%default_font, HORIZ_DIR, font_size) - call setcolor(self%text_color) + call setcolor(font_color) call outtextxy(x, self%y, trim(text)) end subroutine ag_text_draw diff --git a/dumb_render.f90 b/dumb_render.f90 index 23b991b..be911b7 100644 --- a/dumb_render.f90 +++ b/dumb_render.f90 @@ -29,6 +29,8 @@ implicit none character, parameter::bullet_character = '-' + integer, parameter::indent_margin = 3 + type, extends(renderer) :: dumb_renderer integer::link_index @@ -46,7 +48,7 @@ implicit none procedure :: text_height => dumb_text_height procedure :: is_text_visible => dumb_text_visible - procedure :: draw_porportional => dumb_text_draw + procedure :: draw_proportional => dumb_text_draw procedure :: preformatted_width => dumb_simple_width procedure :: preformatted_height => dumb_simple_height @@ -127,38 +129,38 @@ contains end function store_link - function dumb_text_width(self, text, heading, list_item) + function dumb_text_width(self, text, text_type) implicit none class(dumb_renderer)::self character(*), intent(in)::text - integer, intent(in), optional::heading - logical, intent(in), optional::list_item + integer, intent(in), optional::text_type integer::dumb_text_width dumb_text_width = len_trim(text) - if(present(list_item)) then - if(list_item) then - dumb_text_width = dumb_text_width + 3 + if(present(text_type)) then + if(text_type == proportional_type_list_item) then + dumb_text_width = dumb_text_width + indent_margin + else if(text_type == proportional_type_quotation) then + dumb_text_width = dumb_text_width + 2*indent_margin end if end if end function dumb_text_width - function dumb_text_height(self, text, heading, list_item) + function dumb_text_height(self, text, text_type) implicit none class(dumb_renderer)::self character(*), intent(in)::text - integer, intent(in), optional::heading - logical, intent(in), optional::list_item + integer, intent(in), optional::text_type integer::dumb_text_height dumb_text_height = 1 - if(present(heading)) then - if(heading > 0) then + if(present(text_type)) then + if(text_type > 0) then dumb_text_height = 2 end if end if @@ -222,21 +224,22 @@ contains end if end subroutine dumb_simple_draw - subroutine dumb_text_draw(self, text, heading, list_item) + subroutine dumb_text_draw(self, text, text_type) implicit none class(dumb_renderer)::self character(*), intent(in)::text - integer, intent(in), optional::heading - logical, intent(in), optional::list_item + integer, intent(in), optional::text_type integer::limit_x character(5)::formatting character(self%max_width)::heading_line ! Put a bullet for list items - if(present(list_item)) then - if(list_item) then + if(present(text_type)) then + if(text_type == proportional_type_list_item) then write(*, '(1X, A1, 1X)', advance='no') bullet_character + else if(text_type == proportional_type_quotation) then + write(*, '(3X)', advance='no') end if end if @@ -254,10 +257,10 @@ contains end if ! For headings, plop a second line as an underline - if(present(heading)) then - if(heading > 0) then + if(present(text_type)) then + if(text_type > 0) then if(limit_x > 0) then - if(heading == 1) then + if(text_type == proportional_type_heading_1) then heading_line = repeat("=", limit_x) else heading_line = repeat("-", limit_x) diff --git a/render.f90 b/render.f90 index 335cbcb..b37eb50 100644 --- a/render.f90 +++ b/render.f90 @@ -32,6 +32,11 @@ implicit none integer, parameter::last_break = -1 + integer, parameter::proportional_type_normal = 0 + integer, parameter::proportional_type_list_item = -1 + integer, parameter::proportional_type_quotation = -2 + integer, parameter::proportional_type_heading_1 = 1 ! For heading level, it's just positive + character(11), dimension(2)::base_supported_types = & ["text/plain ", & "text/gemini" ] @@ -57,7 +62,7 @@ implicit none procedure(calculate_width), deferred::text_width procedure(calculate_height), deferred::text_height procedure(calculate_visibility), deferred::is_text_visible - procedure(draw_text), deferred::draw_porportional + procedure(draw_text), deferred::draw_proportional procedure(calculate_simple_width), deferred::preformatted_width procedure(calculate_simple_height), deferred::preformatted_height @@ -103,34 +108,31 @@ implicit none end interface abstract interface - function calculate_width(self, text, heading, list_item) + function calculate_width(self, text, text_type) import::renderer class(renderer)::self character(*), intent(in)::text - integer, intent(in), optional::heading - logical, intent(in), optional::list_item + integer, intent(in), optional::text_type integer::calculate_width end function calculate_width end interface abstract interface - function calculate_height(self, text, heading, list_item) + function calculate_height(self, text, text_type) import::renderer class(renderer)::self character(*), intent(in)::text - integer, intent(in), optional::heading - logical, intent(in), optional::list_item + integer, intent(in), optional::text_type integer::calculate_height end function calculate_height end interface abstract interface - subroutine draw_text(self, text, heading, list_item) + subroutine draw_text(self, text, text_type) import::renderer class(renderer)::self character(*), intent(in)::text - integer, intent(in), optional::heading - logical, intent(in), optional::list_item + integer, intent(in), optional::text_type end subroutine draw_text end interface @@ -256,14 +258,13 @@ contains end function report_unsupported_protocol - function width_of_line(r, text, startpos, endpos, heading_level, list_item) + function width_of_line(r, text, startpos, endpos, proportional_type) implicit none class(renderer)::r character(*), intent(in)::text integer, intent(in)::startpos, endpos - integer, intent(in)::heading_level - logical, intent(in)::list_item + integer, intent(in)::proportional_type integer::width_of_line integer::my_start, my_end @@ -282,20 +283,18 @@ contains width_of_line = 0 else width_of_line = r%text_width(text(my_start:my_end), & - heading=heading_level, & - list_item=list_item) + text_type=proportional_type) end if end function width_of_line - function wrap_line(r, text, startpos, heading_level, list_item) result(endpos) + function wrap_line(r, text, startpos, proportional_type) result(endpos) implicit none class(renderer)::r character(*), intent(in)::text integer, intent(in)::startpos - integer, intent(in)::heading_level - logical, intent(in)::list_item + integer, intent(in)::proportional_type integer::endpos integer::my_start integer::w @@ -306,7 +305,7 @@ contains end if endpos = len_trim(text) - w = width_of_line(r, text, my_start, endpos, heading_level, list_item) + w = width_of_line(r, text, my_start, endpos, proportional_type) do while(w > r%max_width) endpos = endpos - 1 @@ -314,11 +313,46 @@ contains endpos = endpos - 1 end do - w = width_of_line(r, text, my_start, endpos, heading_level, list_item) + w = width_of_line(r, text, my_start, endpos, proportional_type) end do end function wrap_line + function get_start_position_and_type(text, proportional_type) result(startpos) + implicit none + + character(*), intent(in)::text + integer, intent(out)::proportional_type + integer::startpos + + startpos = 1 + proportional_type = proportional_type_normal + + ! Check for headings first + do while(text(startpos:startpos) == '#') + proportional_type = proportional_type + 1 + startpos = startpos + 1 + end do + + if(proportional_type == proportional_type_normal) then + if(text(1:1) == '*') then + proportional_type = proportional_type_list_item + startpos = startpos + 1 + else if(text(1:1) == '>') then + proportional_type = proportional_type_quotation + startpos = startpos + 1 + end if + end if + + ! If either occurred, advance past whitespace + if(proportional_type /= proportional_type_normal) then + do while(text(startpos:startpos) == ' ' .or. text(startpos:startpos) == char(9)) + startpos = startpos + 1 + end do + end if + + end function get_start_position_and_type + function calculate_wrapping(r, text) result(breaks) implicit none @@ -327,8 +361,8 @@ contains integer, dimension(:), pointer::breaks integer::startpos, endpos - integer::heading_level - logical::list_item + integer::proportional_type + logical::list_item, quotation integer::current_allocation integer::break_count @@ -340,32 +374,9 @@ contains 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 + startpos = get_start_position_and_type(text, proportional_type) - ! 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) + endpos = wrap_line(r, text, startpos, proportional_type) do while(endpos > startpos) ! Save this break @@ -392,8 +403,11 @@ contains 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) + if(proportional_type == proportional_type_list_item) then + proportional_type = proportional_type_normal + end if + + endpos = wrap_line(r, text, startpos, proportional_type) end do end if @@ -423,44 +437,19 @@ contains integer, dimension(:)::breaks integer::startpos, endpos - integer::heading_level - logical::list_item - + integer::proportional_type integer::break_index if(len_trim(text) == 0) then if(r%is_text_visible(" ")) then - call r%draw_porportional("") + call r%draw_proportional("") end if r%y = r%y + r%text_height(" ") else - 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 + startpos = get_start_position_and_type(text, proportional_type) break_index = 1 endpos = breaks(break_index) @@ -470,13 +459,11 @@ contains do while(endpos > startpos) if(r%is_text_visible(text(startpos:endpos))) then - call r%draw_porportional(text(startpos:endpos), & - heading=heading_level, & - list_item=list_item) + call r%draw_proportional(text(startpos:endpos), & + text_type=proportional_type) end if r%y = r%y + r%text_height(text(startpos:endpos), & - heading=heading_level, & - list_item=list_item) + text_type=proportional_type) ! Advance string positions startpos = endpos+1 @@ -485,7 +472,9 @@ contains end do ! Do not mark as a list item for subsequent lines - list_item = .FALSE. + if(proportional_type == proportional_type_list_item) then + proportional_type = proportional_type_normal + end if if(breaks(break_index) /= last_break) then break_index = break_index + 1 -- cgit v1.2.3