Author Topic: Looking for falcon.h documentation  (Read 2737 times)

0 Members and 1 Guest are viewing this topic.

Offline RhoSigma

  • QB64 Developer
  • Forum Resident
  • Posts: 565
    • View Profile
Looking for falcon.h documentation
« on: August 06, 2019, 03:58:57 am »
As the title line says, has anybody have a documentation of the functions provided via "falcon.h"? As it is used in InForm, Fellippe maybe? I know there was once a whole thread about it on the old [abandoned, outdated and now likely malicious qb64 dot net website - don’t go there] forum, but as this is only available in very rudimentary form now, I cannot find it there anymore.
Thanx
My Projects:   https://qb64forum.alephc.xyz/index.php?topic=809
GuiTools - A graphic UI framework (can do multiple UI forms/windows in one program)
Libraries - ImageProcess, StringBuffers (virt. files), MD5/SHA2-Hash, LZW etc.
Bonus - Blankers, QB64/Notepad++ setup pack

Offline luke

  • Administrator
  • Seasoned Forum Regular
  • Posts: 324
    • View Profile
Re: Looking for falcon.h documentation
« Reply #1 on: August 06, 2019, 10:03:40 am »
The original thread for it contained a demo program and some rather detailed notes on all the parameters - which of course I have no record of and is probably lost forever.

falcon was never really intended for public consumption (originally it was part of a long-abandoned menuing system, then it got picked up for InForm) so I think there's a few versions of it floating around; for reference I have attached my copy of it, and it's what I'll base my notes below on.

Code: [Select]
DECLARE LIBRARY "falcon"
    SUB uprint_extra (BYVAL x&, BYVAL y&, BYVAL chars%&, BYVAL length%&, BYVAL kern&, BYVAL do_render&, txt_width&, BYVAL charpos%&, charcount&, BYVAL colour~&, BYVAL max_width&)
    FUNCTION uprint (BYVAL x&, BYVAL y&, chars$, BYVAL txt_len&, BYVAL colour~&, BYVAL max_width&)
    FUNCTION uprintwidth (chars$, BYVAL txt_len&, BYVAL max_width&)
    FUNCTION uheight& ()
    FUNCTION falcon_uspacing& ALIAS uspacing ()
    FUNCTION uascension& ()
END DECLARE

Strings are expected to be UTF-8 encoded.

uprint_extra is the main function:
  • x&, y& : coordinates to render at
  • chars%& : offset to text (i.e. _OFFSET(text$))
  • length%& : string length in bytes
  • kern& : boolean value to enable/disable kerninig
  • do_render& : boolean value to enable/disable actually printing text. Disabling this is useful for doing size calculations with variable-width fonts
  • txt_width& (output) : returns the horizontal size of the rendered text, in pixels
  • charpos%& (output) : Declare an array     REDIM charpos(LEN(text$)) AS LONG and pass _OFFSET(charpos()). Then charpos(1) is the location of the end of the first character, charpos(2) the end of the second character, and so on. Locations are horizontal pixel distances from the left boundary.
  • charcount& (output) : The number of characters actually printed
  • colour~& : Font colour. Use _RGB32().
  • max_width& : The maximum width in pixels the text should have. If there is not enough room, the text is truncated to however many characters will fit.

The uprint function differs only in that it takes a string argument for the text, and has the defaults:
  • kern = true
  • do_render = true
It returns the txt_width parameter described above. Other output values are not available.

The uprintwidth function takes only the text data and the maximum print width, and returns the actual width the text would have if printed.

The other functions are font metrics, and my memory's a little shaky. You might need to experiment a little:
uheight& is the vertical distance between baselines, in pixels.
uascension& is the distance from the baseline to the top. Lets you find the position of the baseline.
uspacing& ¯\_(ツ)_/¯

Finally, here's a cute textbox I found that uses the charpos() array to draw a cursor:
Code: [Select]
DECLARE LIBRARY "falcon"
    SUB uprint_extra (BYVAL x&, BYVAL y&, BYVAL chars%&, BYVAL length%&, BYVAL kern&, BYVAL do_render&, txt_width&, BYVAL charpos%&, charcount&, BYVAL colour~&, BYVAL max_width&)
    FUNCTION uprint (BYVAL x&, BYVAL y&, chars$, BYVAL txt_len&, BYVAL colour~&, BYVAL max_width&)
    FUNCTION uprintwidth (chars$, BYVAL txt_len&, BYVAL max_width&)
    FUNCTION uheight& ()
    FUNCTION falcon_uspacing& ALIAS uspacing ()
    FUNCTION uascension& ()
END DECLARE

TYPE textbox_t
    shadow_screen AS LONG
    hardware_screen AS LONG
    box_x AS LONG
    box_y AS LONG
    box_width AS LONG
    box_height AS LONG
    cursor_offset AS LONG
    cursorx AS LONG
    cursory AS LONG
    cursor_image AS LONG
END TYPE

DEFLNG A-Z

CONST FONTFILE = "cyberbit.ttf"
CONST BOX_X = 60
CONST BOX_Y = 90
CONST BOX_WIDTH = 520
CONST BOX_HEIGHT = 300

SCREEN _NEWIMAGE(640, 480, 32)

DIM textbox AS textbox_t
create_textbox _LOADFONT(FONTFILE, 16), BOX_X, BOX_Y, BOX_WIDTH, BOX_HEIGHT, textbox
cursor_image = create_cursor

text$ = "Quis sunt vel ut dolor sed natus. Autem odit eius sapiente nostrum velit blanditiis eius. Aut earum sed est."
textcopy$ = text$
textbox.cursor_offset = 10
_DISPLAYORDER _HARDWARE

typeset_textbox textbox, textcopy$
DO
    _LIMIT 50
    k$ = INKEY$
    IF k$ <> "" THEN
        SELECT CASE k$
            CASE CHR$(8)
                IF textbox.cursor_offset > 0 THEN
                    IF textbox.cursor_offset = LEN(text$) THEN
                        text$ = LEFT$(text$, LEN(text$) - 1)
                    ELSE
                        text$ = LEFT$(text$, textbox.cursor_offset - 1) + MID$(text$, textbox.cursor_offset + 1)
                    END IF
                    textbox.cursor_offset = textbox.cursor_offset - 1
                END IF
            CASE CHR$(0) + "M"
                IF textbox.cursor_offset < LEN(text$) THEN textbox.cursor_offset = textbox.cursor_offset + 1
            CASE CHR$(0) + "K"
                IF textbox.cursor_offset > 0 THEN textbox.cursor_offset = textbox.cursor_offset - 1
            CASE CHR$(0) + "G"
                textbox.cursor_offset = 0
            CASE CHR$(0) + "O"
                textbox.cursor_offset = LEN(text$)
            CASE ELSE
                IF textbox.cursor_offset = LEN(text$) THEN
                    text$ = text$ + k$
                ELSE
                    text$ = LEFT$(text$, textbox.cursor_offset) + k$ + MID$(text$, textbox.cursor_offset + 1)
                END IF
                textbox.cursor_offset = textbox.cursor_offset + 1
        END SELECT
        textcopy$ = text$
        typeset_textbox textbox, textcopy$
    END IF
    render_textbox textbox
    _DISPLAY
LOOP

SUB render_textbox (textbox AS textbox_t)
    _PUTIMAGE (textbox.box_x, textbox.box_y), textbox.hardware_screen
    _PUTIMAGE (textbox.box_x + textbox.cursorx, textbox.box_y + textbox.cursory), textbox.cursor_image
END SUB

SUB bench (t0!, t1!, t2!)
    STATIC n, a1!, a2!
    a1! = (a1! * n + (t1! - t0!)) / (n + 1)
    a2! = (a2! * n + (t2! - t1!)) / (n + 1)
    n = n + 1
    _TITLE STR$(a1!) + " " + STR$(a2!)
END SUB

FUNCTION create_cursor
    image = _NEWIMAGE(1, uheight&, 32)
    olddest = _DEST
    _DEST image
    LINE (0, 0)-(0, uheight&), _RGB32(255, 0, 0)
    _DEST olddest
    create_cursor = _COPYIMAGE(image, 33)
    _FREEIMAGE image
END FUNCTION


SUB typeset_textbox (textbox AS textbox_t, s$)
    LINE (textbox.box_x, textbox.box_y)-STEP(textbox.box_width, textbox.box_height), _RGB32(255, 255, 255), BF
    olddest = _DEST
    _DEST textbox.shadow_screen
    LINE (0, 0)-(BOX_WIDTH, BOX_HEIGHT), _RGB32(255, 255, 255), BF
    REDIM charpos(LEN(s$)) AS LONG
    cursor_offset = textbox.cursor_offset

    DO
        uprint_extra 0, vertical_offset, _OFFSET(s$), LEN(s$), -1, -1, txt_width&, _OFFSET(charpos()), charcount&, _RGB32(0, 0, 0), BOX_WIDTH

        'Line ended partway through a word?
        IF LEN(s$) > charcount& THEN
            IF MID$(s$, charcount&, 1) <> " " AND MID$(s$, charcount& + 1, 1) <> " " THEN
                'Find end of previous word
                charcount& = reverse_find_word_end(s$, charcount&)
            END IF
        END IF

        newwidth& = charpos&(charcount&)
        LINE (newwidth& + 1, vertical_offset)-(BOX_WIDTH, vertical_offset + uheight& - 1), _RGB32(255, 255, 255), BF

        IF NOT cursor_found AND cursor_offset <= charcount& THEN
            textbox.cursorx = charpos(cursor_offset)
            textbox.cursory = vertical_offset
            cursor_found = -1
        END IF

        vertical_offset = vertical_offset + uheight&

        IF LEN(s$) = charcount& THEN
            EXIT DO
        ELSE
            'remove leading spaces
            'WARNING: This part will mean the cursor offsets are no longer contiguous; it will break on line ends and get positions wrong
            'Need to decide on a behaviour to make them both work
            'FOR i = charcount& + 1 TO LEN(s$)
            '    IF MID$(s$, i, 1) <> " " THEN EXIT FOR
            'NEXT i
            'IF i > LEN(s$) THEN EXIT DO 'turns out the entire remaining text was spaces
            's$ = MID$(s$, i)
            s$ = MID$(s$, charcount& + 1)

            'Keep cursor offset relative to our ever-shrinking string
            cursor_offset = cursor_offset - charcount&
        END IF
    LOOP
    IF textbox.hardware_screen <> 0 THEN _FREEIMAGE textbox.hardware_screen
    textbox.hardware_screen = _COPYIMAGE(textbox.shadow_screen, 33)
    _DEST olddest
END SUB


SUB create_textbox (fonthandle, box_x, box_y, box_width, box_height, textbox AS textbox_t)
    textbox.shadow_screen = _NEWIMAGE(box_width, box_height, 32)
    textbox.box_x = box_x
    textbox.box_y = box_y
    textbox.box_width = box_width
    textbox.box_height = box_height
    textbox.cursor_image = create_cursor

    olddest = _DEST
    _DEST textbox.shadow_screen
    _FONT fonthandle
    _DEST olddest
END SUB


'Finds the end of the last complete word in the substring of s$ from start to length&
FUNCTION reverse_find_word_end (s$, length&)
    FOR i = length& TO 2 STEP -1
        'Looking for a space proceeded by a non-space
        IF MID$(s$, i, 1) = " " AND MID$(s$, i - 1, 1) <> " " THEN
            reverse_find_word_end = i - 1
            EXIT FUNCTION
        END IF
    NEXT i
    'What to do if there's no location meeting this condition?
END FUNCTION

Offline RhoSigma

  • QB64 Developer
  • Forum Resident
  • Posts: 565
    • View Profile
Re: Looking for falcon.h documentation
« Reply #2 on: August 06, 2019, 01:52:50 pm »
Thank you Luke, this will help alot.
My Projects:   https://qb64forum.alephc.xyz/index.php?topic=809
GuiTools - A graphic UI framework (can do multiple UI forms/windows in one program)
Libraries - ImageProcess, StringBuffers (virt. files), MD5/SHA2-Hash, LZW etc.
Bonus - Blankers, QB64/Notepad++ setup pack