B4A Class Draw HTML text (also some HTML parsing)

Discussion in 'Additional libraries, classes and official updates' started by NeoTechni, Nov 4, 2018.

  1. NeoTechni

    NeoTechni Well-Known Member Licensed User

    I am working on a game and I wanted dialog to be more than just plain text. Some games starting with the N64 and GBA era have had switches of text color and size. I figured the easiest way to control all that would be to use HTML. It also has the standard typewriter effect, and a scrolling effect when done. But more effects can be added later (ie: slow down/speed up the typewriter effect down for some parts)

    Tags it supports:

    <B>: Sets the current block to bold
    <U>: Sets the current block to underline
    <I>: Sets the current block to italic
    <FONT>
    Supported parameters:
    COLOR="#FF00FF": Color format in #RRGGBB, or #AARRGGBB
    COLOR="red": supports all the predefined HTML colors
    FACE="fontname"
    use .AddFont or .AddFontFile to add a font beforehand. But if fontname is a font file in the asset directory it'll be added automatically.
    Android's built in fonts have the fontnames as: default, default bold, monospace, sans serif, serif
    SIZE:
    "number": Set the fontsize of this block to number
    "+number", "-number": Set the fontsize of this block to number+/- the current fontsize
    "xx-small": default fontsize - 3
    "x-small": default fontsize - 2
    "small": default fontsize - 1
    "large": default fontsize + 1
    "x-large": default fontsize + 2
    "xx-large": default fontsize + 3
    "xx-smaller": current fontsize - 3
    "x-smaller": current fontsize - 2
    "smaller": current fontsize - 1
    "larger": current fontsize + 1
    "x-larger": current fontsize + 2
    "xx-larger": current fontsize + 3
    <IMG SRC="name">: Draws an image scaled to the size of the line (useful for button icons)
    <BR>/<P>: Forces a carriage return

    All HTML entities are supported except for "shy", "zwnj", "zwj", "lrm", "rlm".
    This includes specifying the number in decimal (&#nnnn; where nnnn = decimal number) and hexadecimal (&#xhhhh; where hhhh = hexadecimal number)
    They're all converted to their proper character in the parsing stage, except for &NBSP; which is handled a special way for the word wrapping.

    It now supports basic CSS (see post below)

    HTML parsing:
    SplitHTML: Splits HTML up into parts of plain text, and HTML tags
    IsValidHTML: Checks split HTML if the HTML tags are in a valid order. ie: each tag that requires and ending tag has one in the proper spot
    ParseTag: Parses an HTML tag into into a map containing it's parameters=values pairs (all lower-cased), tag_name, tag_closing ("open" = <TAG>, "start" = </TAG>, "end" = <TAG />, "singleton" = tags that don't require an ending tag ("area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param", "source", "track", "wbr"))

    Unlike a web browser, carriage returns and repeated spaces are treated as they are, instead of collapsing them into a single space. I may eliminate repeated spaces later on.

    The code is optimized to run fast, so when you pass it HTML, it is split apart and parsed into segments that can be handled by the draw system much faster than parsing HTML each frame. You can set up the default font, size, color, bold/italic/underline, alpha as they're just public variables.

    If you leave the drawing up to this class, you can set the background color (so it's not just drawing text over text from a previous frame) or tell it to sample the canvas in case you have an image you want to preserve as the background using .SampleBackground and .ClearBackground

    This code is actually more advanced than what many games use. It's more advanced than code I used to use (which was just simple word-wrapping using a single font and size), and that alone was even more advanced than many games use. I can't tell you how many games I've played that used a single, hard-coded font size, or have caught improper/manual word-wrapping. I know gamers have complained about those sort of things (ie: The start of the HD era of console gaming had complaints of small font sizes, which even with my older code could have been easily solved by letting users choose their font size).

    If there is demand for more functionality added, I'll endeavor to do so. I can even add keyboard handling (ie: pass it a keycode, and it'll move the caret/cursor around, handle selection highlighting, editing the text)

    Example:
    Code:
    Sub Globals
       
    'These global variables will be redeclared each time the activity is created.
       'These variables can only be accessed from this module.
       Dim BG As Canvas
       
    Dim HTMLtextObject As HTMLtext
    End Sub

    Sub Activity_Create(FirstTime As Boolean)
       BG.Initialize(
    Activity)
    End Sub

    Sub Activity_Resume
       BG.Initialize(
    Activity)
    End Sub

    Sub Activity_Touch (Action As Int, X As Float, Y As Float)
       
    If Action = 0 Then
           
    Dim HTML As String = "this is a test <FONT COLOR='red'>of&NBSP;the</FONT> &ograve; &ogrAve; html splitter&exclamation;"
           HTMLtextObject.Initialize(BG)
        
           HTMLtextObject.setDestination(
    100,100,200,200)
           HTMLtextObject.InitializeEvent(Me, 
    "HTML")
           HTMLtextObject.InitializeTimer(
    50)
         
           HTMLtextObject.LoadCSS(
    File.DirAssets, "test.css")
           HTMLtextObject.HTML = HTML
           HTMLtextObject.StartTypewiter
       
    End If
    End Sub

    Sub HTML_Tick
       
    Activity.Invalidate
    End Sub
    Sub HTML_TypewriterDone
       HTMLtextObject.ScrollSpeed = 
    5
    End Sub
    Sub HTML_ScrollDone
       
    Log("Scroll done")
    End Sub
     

    Attached Files:

    Last edited: Nov 11, 2018 at 11:48 PM
  2. Informatix

    Informatix Expert Licensed User

    Could you explain how to change the size ? Because I'm unable to change it. DefaultFontSize or the SIZE tag does not seem to have any effect.
     
  3. NeoTechni

    NeoTechni Well-Known Member Licensed User

    There is no size tag. It's <FONT SIZE="10">text</FONT>

    My example code screwed up the order since it's setting the font size after loading the HTML, which already has the text size set... I updated the code.

    I'm also considering some basic CSS support. Like just classnames and tagnames in particular
     
  4. NeoTechni

    NeoTechni Well-Known Member Licensed User

    I added basic CSS support.

    Upon loading a CSS file using .LoadCSS, it'll check for any CSS block (or whatever you call it) that matches the "body, html" selector, and use those blocks to set the defaults.

    Upon loading HTML, it'll check for CSS blocks that matches the Class or ID paramters, or the tagname
    meaning <DEMO ID="test", CLASS="classtest classing"> will match against either "demo", "#test", ".classtest", or ".classing"
    I am trying to stick to the standards as much as I can
    It won't check any of the advanced CSS selectors, like checking if it's the child of a selector, or ":not(something)"

    I figure the use case of this is if you want say, certain settings to always be used for a specific character in a game, so you can use
    <DIV CLASS="msg-jimbob">Hi y'all</DIV>
    And have jimbob use a specific font all the time (ie: comic sans)

    Now currently the CSS supports only specific key:value; key names
    "background-color": sets the background color of the entire window for now
    "font-size"
    "font-style": can be "italic", "bold", "underline", "regular" or "normal" (italic, bold and underline are all set to false), "default" (set to the defaults)
    "content": sets the text of the node
    "font-family": sets the font of the node
    "line-height" sets the line height of the entirety of the HTML

    I can add support for more of course.
    I intend to add text alignment, and the ability to set the width of nodes (so you can have columns, ie: for end credits), but those are more complex than you'd think
     
  5. Informatix

    Informatix Expert Licensed User

    Maybe you should add a version number to your file. If we come back later, we can see if we are up to date.
     
  6. Informatix

    Informatix Expert Licensed User

    There's a typo error in this function name: StartTypew(r)iter
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice