diff --git a/cmuratori/hero/code/code530.hmml b/cmuratori/hero/code/code530.hmml new file mode 100644 index 0000000..3933a33 --- /dev/null +++ b/cmuratori/hero/code/code530.hmml @@ -0,0 +1,99 @@ +[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]