[video output=day532 member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Finishing HHT-Based Font Importing" vod_platform=youtube id=nTirm1eqz8M annotator=Miblo]
[0:02][Recap and set the stage for the day][:speech]
[1:32][Check out our NotImplemented routines][:research]
[2:34][Implement the overloaded GetOrCreateAssetSourceFile() that takes a string, making the char * version call it]
[4:27][Set up to implement ImportGlyph(), reacquainting ourselves with ParseTopLevelBlock() with a view to compressing it][:"asset system" :font :research]
[8:30][Enable ImportGlyph() to open source PNG file based on code copied from ParseTopLevelBlock()][:"asset system" :"file io" :font]
[12:03][Compress out the asset data updating code from ParseTopLevelBlock() into UpdateAssetDataFromFile()][:"asset system" :font :parsing]
[23:04][Remove ImportGlyph() in favour of making ParseFontBlock() perform that work itself][:"asset system" :font :parsing]
[25:05][Merge ProcesPlateImport() into ProcessSingleTileImport(), making the latter take a MaximumDim value][:"asset system"]
[27:34][Continue to implement ParseFontBlock(), calling UpdateAssetDataFromFile() and setting the BitmapID for each glyph][:"asset system" :font :parsing]
[34:12][Compress out the file matching code from ParseFontBlock() into FindMatchingFileFor(), for ParseTopLevelBlock() also to call][:"asset system" :"file io" :font]
[49:41][Reflect on the state of our :"asset system" with a view to testing the :font importing][:speech]
[51:08][Move the base_game.* and intro_cutscene.* files out of the way, and trigger a non-font asset rebuild][:"asset system" :run]
[55:37][@clownoffire][@handmade_hero Are you having any issues with the debugger or is it okay even if it's an early version?]
[58:04][Find that everything imported correctly][:"asset system" :run]
[58:38][:Run in release mode to find that the sound is fine, with the determination to finish up dynamic loading of fonts][:"asset system"]
[59:59][Make ExtractFont() write out all our glyph information and set their alignment points][:"asset system" :font]
[1:08:50][Consider getting updated alignment points to flow to ParseFontBlock()][:"asset system" :font :speech]
[1:12:18][Enable UpdateAssetDataFromFile() to update alignment points][:"asset system"]
[1:14:22][Understanding C's rightward-then-leftward :parsing behaviour, and our ability to control it using parentheses][:language :speech]
[1:17:41][Make ParseFontBlock() pass an hha_align_point array to UpdateAssetDataFromFile()][:"asset system" :font]
[1:22:00][Trigger a full .hha rebuild][:"asset system" :run]
[1:23:13][Find that the full rebuild succeeded][:"asset system" :run]
[1:23:24][Move testfonts_v2.* out of the way, trigger a :font asset rebuild, and hit a ~remedybg crash][:"asset system" :run]
[1:24:02][Set up WinDBG as our just-in-time debugger[ref
    site="Visual Studio Docs"
    page="Just-In-Time Debugging in Visual Studio"
    url=https://docs.microsoft.com/en-us/visualstudio/debugger/just-in-time-debugging-in-visual-studio?view=vs-2015][ref
        site="Hardware Dev Center"
        page="Enabling Postmortem Debugging"
        url=https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/enabling-postmortem-debugging][ref
            site="Windows Dev Center"
            page="Virtual-Key Codes"
            url=https://docs.microsoft.com/en-us/windows/desktop/inputdev/virtual-key-codes]][:admin]
[1:33:02][Click "Debug" and hit a "Visual Studio Just-In-Time Debugger" error][:admin]
[1:33:45][Fix the path of WinDBG so that the root user can find it][:admin]
[1:34:43][Trigger a :font asset rebuild, reliably crash ~remedybg and save our mini-dump to send to [@x13pixels George][ref
    site="Hardware Dev Center"
    page=".dump (Create Dump File)"
    url=https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/-dump--create-dump-file-]][:admin]
[1:39:14][:Run win32_handmade in ~remedybg okay]
[1:39:56][Step through SynchronizeAssetFileChanges() to see files being erroneously marked as modified][:"asset system" :run]
[1:40:58][Regenerate our glyph PNGs using hhafont and organise them into our directory structure][:admin :"asset system" :font]
[1:45:04][#include LiberationMono.hht in base_game.hht][:admin :"asset system" :font]
[1:46:54][Step through ParseHHT() on the included LiberationMono.hht][:"asset system" :font :parsing :run]
[1:48:24][Add a ParseFontBlock() call to ParseHHT()][:"asset system" :font :parsing]
[1:48:53][Step through ParseFontBlock(), to find that we encounter a :parsing error][:"asset system" :font :run]
[1:50:02][Fix ParseFontBlock() to treat the FontName syntactically as a string][:"asset system" :font :parsing]
[1:52:28][Continue to step through ParseFontBlock() to find that the Glyph syntax is parsed incorrectly][:"asset system" :font :parsing :run]
[1:55:30][Enable ParseFontBlock() to handle more correctly our desired Glyph syntax][:"asset system" :font :parsing]
[1:56:20][Continue to step through ParseFontBlock() to find that the Glyph syntax :parsing is a little incorrect][:"asset system" :font :run]
[1:57:01][Fix ParseFontBlock() to fully handle our desired Glyph syntax][:"asset system" :font :parsing]
[1:58:06][Continue to step through ParseFontBlock() to ParsePNG(), to find that the latter fails due to the PNG being zero-sized][:"asset system" :font :parsing :run]
[2:01:10][Force WritePNG() to enter the chunk writing loop][:"asset system" :"file format"]
[2:02:25][Regenerate our glyph PNGs using hhafont][:admin :"asset system" :font]
[2:03:24][Step through ParseFontBlock() and past a zero-sized ParsePNG() call, until finally failing in GetFontInfo()][:"asset system" :font :parsing :run]
[2:06:00][Reacquaint ourselves with the Asset->HHA.Type setting code][:"asset system" :research]
[2:09:30][Make ParseFontBlock() set the Asset->HHA.Type][:"asset system" :font]
[2:10:04][Again hit our assertion in GetFontInfo()][:"asset system" :font :parsing :run]
[2:10:30][Tag the liberation_mono :font with Tag_FontType(10)][:admin :"asset system"]
[2:11:32][Crash in StringLength(), and investigate why][:run]
[2:14:12][Try to watch the Format variable of OutfArgList() and crash ~remedybg][:run]
[2:15:10][Continue to investigate our crash in StringLength()][:run]
[2:18:33][Rename to ErrorArgList() the overloaded version of Error() that takes a va_list, to work around the treatment of va_list as a char *][:language]
[2:19:25][Find that the StringLength() crash is fixed, and that we are back to addressing the assertion in GetFontInfo()][:"asset system" :font :parsing :run]
[2:19:40][Set the GlyphCount before the Tags in LiberationMono.hht][:admin :"asset system" :font]
[2:19:46][Find that we still hit that assertion in GetFontInfo()][:"asset system" :font :parsing :run]
[2:20:34][Make ParseFontBlock() set the font's basic category][:"asset system" :font :parsing]
[2:24:36][Find that GetBestMatchAssetFrom() still fails to find our :font][:"asset system" :parsing :run]
[2:24:47][Change ParseFontBlock() to set the font's basic category in the ExtraTags][:"asset system" :font :parsing]
[2:25:34][Find that GetBestMatchAssetFrom() still fails to find our :font][:"asset system" :parsing :run]
[2:25:54][Step through ParseFontBlock(), to find that we have a :parsing error][:"asset system" :parsing :run]
[2:27:15][Fix the FontType tag in LiberationMono.hht][:admin :"asset system" :font]
[2:27:21][Step through ParseFontBlock() to completion, but sadly not success][:"asset system" :parsing :run]
[2:28:34][Fix ParseFontBlock() to set the glyph's BitmapID whether or not the :font was updated][:"asset system" :parsing]
[2:30:29][Step through ParseFontBlock() to find that our glyphs' BitmapID values do not align as expected][:"asset system" :font :parsing :run]
[2:37:01][Using one integer to refer to an asset, by offsetting indices by those of other assets, as opposed to pre-allocating all the indices (as in The Witness)][:"asset system" :speech]
[2:38:27][Fix ParseFontBlock() to offset the glyph BitmapID values by the AssetBase of their containing .hha file][:"asset system" :parsing]
[2:41:28][Find that our :font importing works, but that the spacing may be a little off][:"asset system" :parsing :run]
[2:42:23][:Run in release mode to see no obvious :font bugs][:"asset system"]
[2:43:18][Q&A][:speech]
[2:44:05][@macielda][Q: If you had to support ligatures (for instance "ffi" can optionally become a single glyph when using some fonts), how would you store that information in an asset file? (I think Arabic works in a similar way...?) What about substitutions, like in some fonts the uppercase 'Q' can have a longer tail when in front of 'u' like in 'Quest'?[ref
    site="Unicode codepoint lookup/search tool"
    page="ﬃ"
    url=http://unicode.scarfboy.com/?s=U%2Bfb03]][:"asset system" :font]
[2:45:51][Make CameraEditor() append "\\\\5c0f" to the "SAVE STARTUP LOCATION" button][:font :ui]
[2:46:32][Find that the "\\\\5c0f" codepoint did not get parsed as expected][:font :ui :run]
[2:47:29][Change IsHex() to be case-insensitive][:parsing]
[2:47:58][Find that the "\\\\5c0f" codepoint did not display as expected][:font :ui :run]
[2:48:10][Change GetHex() to be case-insensitive][:parsing]
[2:48:28][Find our glyph displaying in the button][:font :ui :run]
[2:48:32][Add the U+FB00 to U+FB05 ligatures to the Test charset in hhafont[ref
    site=Wikipedia
    page="Typographic ligature"
    url=https://en.wikipedia.org/wiki/Typographic_ligature]][:font]
[2:52:06][Make CameraEditor() use the "\\\\FB03" codepoint in our button][:font :ui]
[2:52:47][Find that our :font must lack the U+FB03 (ﬃ) ligature][:run :ui]
[2:53:28][Try to determine the existence of "ﬃ" in Liberation Mono using LibreOffice Writer][:admin :font]
[2:56:46][Temporarily change our :font to Segoe UI Regular][:admin :"asset system"]
[2:59:47][Regenerate our assets, triggering a ~remedybg crash][:"asset system" :font :run]
[3:02:52][Check out the exported ligatures of Segoe UI Regular and Liberation Mono][:admin :"asset system" :font]
[3:05:03][@tshugako][This wasn't the kanji for owl...][:language]
[3:07:27][@letambourinroyal][@handmade_hero 小 is not owl, it means small][:language]
[3:08:43][@xxthebigfoxx][Q: I was going through the platform code and noticed that you declare the platform struct with all the function pointers as extern in handmade_platform.h. How does the linker resolve that? Isn't the platform in a different executable?]
[3:09:35][@letambourinroyal][Q: How do we render text and do you have any thoughts on dealing with a large number of glyphs such as in Chinese][:font :language]
[3:10:35][@diffserv][Q: [@cmuratori Casey], do you think most of the optimizations you use are domain specific, i.e. game development related? And if so, do you think it's possible to decouple optimizations and algorithms in the context of games? And if so, to what extent?][:optimisation]
[3:11:47][@centhusiast][Q: How was your experience of CygnusEd text editor on Amiga? How do you compare it to emacs?]
[3:12:57][@miblo][Okay, the selection happened right here[ref
    site="Handmade Hero"
    page="Adding Sparse Unicode Support"
    url=https://guide.handmadehero.org/code/day174/#617]]
[3:14:08][Kanji owl :research[ref
    site="Sibagu"
    page="Using Chinese characters (kanji) to write Japanese bird names"
    url=http://sibagu.com/notes/kanji.html]][:language]
[3:16:40][@miblo][Q: Sadly the site you found it on seems be deceased (or at least changed). But yeah, "short eared owl" is indeed what the site said!]
[3:16:58][Wrap it up][:speech]
[/video]
