[video member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Writing Large PNGs and Supersampling Fonts" vod_platform=youtube id=6-nOuoehfd4 annotator=Miblo] [0:00][Recap and set the stage for the day with a few words on asset metadata][:"asset system" :font :speech] [4:19][Determine to address the "Support writing "large" PNGs" issue[ref site=GitHub page="HandmadeHero / cpp / Support writing \"large\" PNGs" url=https://github.com/HandmadeHero/cpp/issues/92]][:"asset system" :research] [7:01][Run our :font exporter–extractor for 20px high glyphs][:admin :"asset system"] [8:44][Run our :font exporter–extractor for 512px high glyphs to exhibit our bug][:admin :"asset system"] [10:34][Set up to enable WritePNG() write out large images in multiple chunks][:"asset system" :font :research] [12:51][Enable WritePNG() to write out multiple chunks[ref site=W3C page="Portable Network Graphics (PNG) Specification (Second Edition)" url=https://w3.org/TR/2003/REC-PNG-20031110/]][:"asset system" :"file format"] [25:26][Consult the ZLIB spec to see where the ADLER32 checksum is supposed to go[ref site=IETF page="ZLIB Compressed Data Format Specification version 3.3" url=http://www.ietf.org/rfc/rfc1950.txt]][:"file format" :research] [28:22][Continue to enable WritePNG() to handle multiple chunks, prepending rows with the filter value][:"asset system" :"file format"] [36:59][Thoughts on a more succinct and maintainable specification of the ability to modify rarely modified values, e.g. PNG filter per row][:"file format" :speech] [38:31][Continue to enable WritePNG() to process rows for multiple chunks][:"asset system" :"file format"] [41:23][Enable WritePNG() to handle the ADLER32 checksum for multiple chunks, introducing BeginAdler32() and Adler32Append()][:"file format" :hashing] [48:01][Step through WritePNG() to find that our B and Width fail to line up][:"asset system" :"file format" :run] [50:11][Fix WritePNG() to correctly detect the end of row][:"asset system" :"file format"] [50:41][Run hhfont to completion, and check out a glyph in GIMP to see no antialiasing][:admin :"asset system" :"file format" :font] [52:15][Consult the documentation on CreateFontA() for its ANTIALIASED_QUALITY parameter[ref site="Windows Dev Center" page="CreateFontA function" url=https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/nf-wingdi-createfonta]][:font :"platform layer" :research] [55:26][Enable ExtractFont() and LoadGlyphBitmap() to oversample our output glyphs[ref site="Windows Dev Center" page="CreateFontA function" url=https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/nf-wingdi-createfonta]][:font :rendering] [1:11:27][Run our exporter–extractor to find that we produced corrupted .png files][:admin :"asset system" :font] [1:12:32][Prevent LoadGlyphBitmap() and ExtractFont() from scaling][:font :rendering] [1:13:11][Run our exporter–extractor successfully on both 512px and 800px high glyphs][:admin :"asset system" :font] [1:14:00][Make ExtractFont() oversample by 2][:font :rendering] [1:14:08][Run our exporter–extractor to find that we produced corrupted .png files][:admin :"asset system" :font] [1:14:20][Step in to WritePNG() to see that the Width and Height are 0, and then on through LoadGlyphBitmap() to see what it does][:"asset system" :font :rendering :run] [1:16:22][Change LoadGlyphBitmap() to increment the SampleInner][:"asset system" :font :rendering] [1:16:54][Step back in to WritePNG() to still see a Width and Height of 0][:"asset system" :font :rendering :run] [1:17:16][Fix LoadGlyphBitmap() to increment the Sample][:"asset system" :font :rendering] [1:17:33][Step back in to WritePNG() to find more plausible Width and Height values][:"asset system" :font :rendering :run] [1:17:37][View our glyphs to find that they appear squished horizontally, but antialiased][:admin :"asset system" :font :rendering] [1:18:11][Fix LoadGlyphBitmap() to increment the Sample by the Scale][:"asset system" :font :rendering] [1:18:23][Rerun our exporter–extractor and check the antialiasing of our correctly scaled glyphs][:admin :"asset system" :font :rendering] [1:20:21][Increase the scaling to 4 in ExtractFont()][:font :rendering] [1:20:39][Rerun our exporter–extractor and check the antialiasing of these ×4 oversampled glyphs][:admin :"asset system" :font :rendering] [1:21:46][Prevent ExtractFont() from scaling][:font :rendering] [1:22:00][Rerun our exporter–extractor and compare the antialiasing of our unscaled and oversampled glyphs][:admin :"asset system" :font :rendering] [1:22:32][Increase the scaling to 8 in ExtractFont()][:font :rendering] [1:22:45][Rerun our exporter–extractor and compare the antialiasing of our variously oversampled glyphs][:admin :"asset system" :font :rendering] [1:23:59][Set our Scale amount to 4 in ExtractFont(), and briefly check the CreateFontA() documentation for the switch-over point of antialising[ref site="Windows Dev Center" page="CreateFontA function" url=https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/nf-wingdi-createfonta]][:font :rendering] [1:26:08][Prevent ExtractFont() from scaling, to allow Windows to perform antialiasing][:font :rendering] [1:26:29][Start to binary search the switch-over point of Windows' :font antialiasing][:admin :rendering] [1:27:37][Make ExtractFont() pass the negative SamplePixelHeight to CreateFontA()][:font] [1:27:50][Find that our glyphs are now larger, and explain the reason for this negative cHeight value[ref site="Windows Dev Center" page="CreateFontA function" url=https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/nf-wingdi-createfonta]][:admin :font] [1:28:54][Continue to binary search the switch-over point of Windows' :font antialiasing][:admin :rendering] [1:32:13][Note that 354 is the magic value at which Windows stops antialiasing :font glyphs][:admin :rendering] [1:35:48][Make ExtractFont() oversample if the pixel height is greater than 4][:font :rendering] [1:36:42][Run our exporter–extractor on various glyph heights and check their antialiasing][:admin :"asset system" :font :rendering] [1:37:39][Q&A][:speech] [1:38:15][@vtlmks][Q: Perhaps your certificate for large font antialiasing died] [1:38:35][@x13pixels][Q: In ExtractFont(), MaxGlyphDim's x value is set using TextMetric.tmOverhang. It seems like tmOverhang should only apply to MaxGlyphDim's y-value?][:font] [1:39:27][@theomarest][Q: Would this only work for monospace fonts?][:font] [1:39:34][@centhusiast][Q: What is the difference between the FreeType and TrueType fonts? Do both do the sub-pixel rasterization?][:font] [1:40:08][@ivereadthesequel][@handmade_hero You wrote in the note 543->544 instead of 353->354. Glasses!][:font :rendering] [1:40:19][Fix the antialiasing magic value note in ExtractFont()][:font] [1:40:36][@boonetbe][Q: Did you try the Kakoune editor? Could its behavior be achieved in ~4coder?] [1:41:48][@glog78][Q: Didn't MSN say something about small fonts too?][:font] [1:42:51][@teamrandb][Q: But did you not check 500 and it worked?][:font] [1:43:55][@floorislava][Q: GitHub bug report?] [1:44:17][Close the "Support writing "large" PNGs" issue[ref site=GitHub page="HandmadeHero / cpp / Support writing \"large\" PNGs" url=https://github.com/HandmadeHero/cpp/issues/92]][:admin] [1:44:42][Address the "Should we advance a character here?" issue[ref site=GitHub page="HandmadeHero / cpp / Should we advance a character here?" url=https://github.com/HandmadeHero/cpp/issues/93]][:parsing :research] [1:46:22][Fix GetTokenRaw() to skip past the '.' of decimal numbers][:parsing] [1:46:40][Close the "Should we advance a character here?" issue[ref site=GitHub page="HandmadeHero / cpp / Should we advance a character here?" url=https://github.com/HandmadeHero/cpp/issues/93]][:admin :parsing] [1:47:36][@mycon_][Q: Are there any plans for a new HandmadeCon?[ref site="Handmade Hero" page="Handmade Hero-related Conferences" url=https://handmadehero.org/conference]] [1:49:00][@centhusiast][Q: I followed your suggestions and used Roboto and Droid Sans fonts for my desktop app. They look good! Thanks for that. Do you have any other suggestions for a good looking :font?[ref site="Google Fonts" url=https://fonts.google.com/]] [1:50:43][Close it down][:speech] [/video]