Handmade Hero»Episode Guide
Writing Large PNGs and Supersampling Fonts
?
?

Keyboard Navigation

Global Keys

[, < / ], > Jump to previous / next episode
W, K, P / S, J, N Jump to previous / next marker
t / T Toggle theatre / SUPERtheatre mode
V Revert filter to original state Y Select link (requires manual Ctrl-c)

Menu toggling

q Quotes r References f Filter y Link c Credits

In-Menu Movement

a
w
s
d
h j k l


Quotes and References Menus

Enter Jump to timecode

Quotes, References and Credits Menus

o Open URL (in new tab)

Filter Menu

x, Space Toggle category and focus next
X, ShiftSpace Toggle category and focus previous
v Invert topics / media as per focus

Filter and Link Menus

z Toggle filter / linking mode

Credits Menu

Enter Open URL (in new tab)
0:00Recap and set the stage for the day with a few words on asset metadata
🗩
0:00Recap and set the stage for the day with a few words on asset metadata
🗩
0:00Recap and set the stage for the day with a few words on asset metadata
🗩
4:19Determine to address the "Support writing "large" PNGs" issue1
📖
4:19Determine to address the "Support writing "large" PNGs" issue1
📖
4:19Determine to address the "Support writing "large" PNGs" issue1
📖
7:01Run our font exporter–extractor for 20px high glyphs
🗹
7:01Run our font exporter–extractor for 20px high glyphs
🗹
7:01Run our font exporter–extractor for 20px high glyphs
🗹
8:44Run our font exporter–extractor for 512px high glyphs to exhibit our bug
🗹
8:44Run our font exporter–extractor for 512px high glyphs to exhibit our bug
🗹
8:44Run our font exporter–extractor for 512px high glyphs to exhibit our bug
🗹
10:34Set up to enable WritePNG() write out large images in multiple chunks
📖
10:34Set up to enable WritePNG() write out large images in multiple chunks
📖
10:34Set up to enable WritePNG() write out large images in multiple chunks
📖
12:51Enable WritePNG() to write out multiple chunks2
12:51Enable WritePNG() to write out multiple chunks2
12:51Enable WritePNG() to write out multiple chunks2
25:26Consult the ZLIB spec to see where the ADLER32 checksum is supposed to go3
📖
25:26Consult the ZLIB spec to see where the ADLER32 checksum is supposed to go3
📖
25:26Consult the ZLIB spec to see where the ADLER32 checksum is supposed to go3
📖
28:22Continue to enable WritePNG() to handle multiple chunks, prepending rows with the filter value
28:22Continue to enable WritePNG() to handle multiple chunks, prepending rows with the filter value
28:22Continue to enable WritePNG() to handle multiple chunks, prepending rows with the filter value
36:59Thoughts on a more succinct and maintainable specification of the ability to modify rarely modified values, e.g. PNG filter per row
🗩
36:59Thoughts on a more succinct and maintainable specification of the ability to modify rarely modified values, e.g. PNG filter per row
🗩
36:59Thoughts on a more succinct and maintainable specification of the ability to modify rarely modified values, e.g. PNG filter per row
🗩
38:31Continue to enable WritePNG() to process rows for multiple chunks
38:31Continue to enable WritePNG() to process rows for multiple chunks
38:31Continue to enable WritePNG() to process rows for multiple chunks
41:23Enable WritePNG() to handle the ADLER32 checksum for multiple chunks, introducing BeginAdler32() and Adler32Append()
41:23Enable WritePNG() to handle the ADLER32 checksum for multiple chunks, introducing BeginAdler32() and Adler32Append()
41:23Enable WritePNG() to handle the ADLER32 checksum for multiple chunks, introducing BeginAdler32() and Adler32Append()
48:01Step through WritePNG() to find that our B and Width fail to line up
🏃
48:01Step through WritePNG() to find that our B and Width fail to line up
🏃
48:01Step through WritePNG() to find that our B and Width fail to line up
🏃
50:11Fix WritePNG() to correctly detect the end of row
50:11Fix WritePNG() to correctly detect the end of row
50:11Fix WritePNG() to correctly detect the end of row
50:41Run hhfont to completion, and check out a glyph in GIMP to see no antialiasing
🗹
50:41Run hhfont to completion, and check out a glyph in GIMP to see no antialiasing
🗹
50:41Run hhfont to completion, and check out a glyph in GIMP to see no antialiasing
🗹
52:15Consult the documentation on CreateFontA() for its ANTIALIASED_QUALITY parameter4
📖
52:15Consult the documentation on CreateFontA() for its ANTIALIASED_QUALITY parameter4
📖
52:15Consult the documentation on CreateFontA() for its ANTIALIASED_QUALITY parameter4
📖
55:26Enable ExtractFont() and LoadGlyphBitmap() to oversample our output glyphs5
55:26Enable ExtractFont() and LoadGlyphBitmap() to oversample our output glyphs5
55:26Enable ExtractFont() and LoadGlyphBitmap() to oversample our output glyphs5
1:11:27Run our exporter–extractor to find that we produced corrupted .png files
🗹
1:11:27Run our exporter–extractor to find that we produced corrupted .png files
🗹
1:11:27Run our exporter–extractor to find that we produced corrupted .png files
🗹
1:12:32Prevent LoadGlyphBitmap() and ExtractFont() from scaling
1:12:32Prevent LoadGlyphBitmap() and ExtractFont() from scaling
1:12:32Prevent LoadGlyphBitmap() and ExtractFont() from scaling
1:13:11Run our exporter–extractor successfully on both 512px and 800px high glyphs
🗹
1:13:11Run our exporter–extractor successfully on both 512px and 800px high glyphs
🗹
1:13:11Run our exporter–extractor successfully on both 512px and 800px high glyphs
🗹
1:14:00Make ExtractFont() oversample by 2
1:14:00Make ExtractFont() oversample by 2
1:14:00Make ExtractFont() oversample by 2
1:14:08Run our exporter–extractor to find that we produced corrupted .png files
🗹
1:14:08Run our exporter–extractor to find that we produced corrupted .png files
🗹
1:14:08Run our exporter–extractor to find that we produced corrupted .png files
🗹
1:14:20Step in to WritePNG() to see that the Width and Height are 0, and then on through LoadGlyphBitmap() to see what it does
🏃
1:14:20Step in to WritePNG() to see that the Width and Height are 0, and then on through LoadGlyphBitmap() to see what it does
🏃
1:14:20Step in to WritePNG() to see that the Width and Height are 0, and then on through LoadGlyphBitmap() to see what it does
🏃
1:16:22Change LoadGlyphBitmap() to increment the SampleInner
1:16:22Change LoadGlyphBitmap() to increment the SampleInner
1:16:22Change LoadGlyphBitmap() to increment the SampleInner
1:16:54Step back in to WritePNG() to still see a Width and Height of 0
🏃
1:16:54Step back in to WritePNG() to still see a Width and Height of 0
🏃
1:16:54Step back in to WritePNG() to still see a Width and Height of 0
🏃
1:17:16Fix LoadGlyphBitmap() to increment the Sample
1:17:16Fix LoadGlyphBitmap() to increment the Sample
1:17:16Fix LoadGlyphBitmap() to increment the Sample
1:17:33Step back in to WritePNG() to find more plausible Width and Height values
🏃
1:17:33Step back in to WritePNG() to find more plausible Width and Height values
🏃
1:17:33Step back in to WritePNG() to find more plausible Width and Height values
🏃
1:17:37View our glyphs to find that they appear squished horizontally, but antialiased
🗹
1:17:37View our glyphs to find that they appear squished horizontally, but antialiased
🗹
1:17:37View our glyphs to find that they appear squished horizontally, but antialiased
🗹
1:18:11Fix LoadGlyphBitmap() to increment the Sample by the Scale
1:18:11Fix LoadGlyphBitmap() to increment the Sample by the Scale
1:18:11Fix LoadGlyphBitmap() to increment the Sample by the Scale
1:18:23Rerun our exporter–extractor and check the antialiasing of our correctly scaled glyphs
🗹
1:18:23Rerun our exporter–extractor and check the antialiasing of our correctly scaled glyphs
🗹
1:18:23Rerun our exporter–extractor and check the antialiasing of our correctly scaled glyphs
🗹
1:20:21Increase the scaling to 4 in ExtractFont()
1:20:21Increase the scaling to 4 in ExtractFont()
1:20:21Increase the scaling to 4 in ExtractFont()
1:20:39Rerun our exporter–extractor and check the antialiasing of these ×4 oversampled glyphs
🗹
1:20:39Rerun our exporter–extractor and check the antialiasing of these ×4 oversampled glyphs
🗹
1:20:39Rerun our exporter–extractor and check the antialiasing of these ×4 oversampled glyphs
🗹
1:21:46Prevent ExtractFont() from scaling
1:21:46Prevent ExtractFont() from scaling
1:21:46Prevent ExtractFont() from scaling
1:22:00Rerun our exporter–extractor and compare the antialiasing of our unscaled and oversampled glyphs
🗹
1:22:00Rerun our exporter–extractor and compare the antialiasing of our unscaled and oversampled glyphs
🗹
1:22:00Rerun our exporter–extractor and compare the antialiasing of our unscaled and oversampled glyphs
🗹
1:22:32Increase the scaling to 8 in ExtractFont()
1:22:32Increase the scaling to 8 in ExtractFont()
1:22:32Increase the scaling to 8 in ExtractFont()
1:22:45Rerun our exporter–extractor and compare the antialiasing of our variously oversampled glyphs
🗹
1:22:45Rerun our exporter–extractor and compare the antialiasing of our variously oversampled glyphs
🗹
1:22:45Rerun our exporter–extractor and compare the antialiasing of our variously oversampled glyphs
🗹
1:23:59Set our Scale amount to 4 in ExtractFont(), and briefly check the CreateFontA() documentation for the switch-over point of antialising6
1:23:59Set our Scale amount to 4 in ExtractFont(), and briefly check the CreateFontA() documentation for the switch-over point of antialising6
1:23:59Set our Scale amount to 4 in ExtractFont(), and briefly check the CreateFontA() documentation for the switch-over point of antialising6
1:26:08Prevent ExtractFont() from scaling, to allow Windows to perform antialiasing
1:26:08Prevent ExtractFont() from scaling, to allow Windows to perform antialiasing
1:26:08Prevent ExtractFont() from scaling, to allow Windows to perform antialiasing
1:26:29Start to binary search the switch-over point of Windows' font antialiasing
🗹
1:26:29Start to binary search the switch-over point of Windows' font antialiasing
🗹
1:26:29Start to binary search the switch-over point of Windows' font antialiasing
🗹
1:27:37Make ExtractFont() pass the negative SamplePixelHeight to CreateFontA()
1:27:37Make ExtractFont() pass the negative SamplePixelHeight to CreateFontA()
1:27:37Make ExtractFont() pass the negative SamplePixelHeight to CreateFontA()
1:27:50Find that our glyphs are now larger, and explain the reason for this negative cHeight value7
🗹
1:27:50Find that our glyphs are now larger, and explain the reason for this negative cHeight value7
🗹
1:27:50Find that our glyphs are now larger, and explain the reason for this negative cHeight value7
🗹
1:28:54Continue to binary search the switch-over point of Windows' font antialiasing
🗹
1:28:54Continue to binary search the switch-over point of Windows' font antialiasing
🗹
1:28:54Continue to binary search the switch-over point of Windows' font antialiasing
🗹
1:32:13Note that 354 is the magic value at which Windows stops antialiasing font glyphs
🗹
1:32:13Note that 354 is the magic value at which Windows stops antialiasing font glyphs
🗹
1:32:13Note that 354 is the magic value at which Windows stops antialiasing font glyphs
🗹
1:35:48Make ExtractFont() oversample if the pixel height is greater than 4
1:35:48Make ExtractFont() oversample if the pixel height is greater than 4
1:35:48Make ExtractFont() oversample if the pixel height is greater than 4
1:36:42Run our exporter–extractor on various glyph heights and check their antialiasing
🗹
1:36:42Run our exporter–extractor on various glyph heights and check their antialiasing
🗹
1:36:42Run our exporter–extractor on various glyph heights and check their antialiasing
🗹
1:37:39Q&A
🗩
1:37:39Q&A
🗩
1:37:39Q&A
🗩
1:38:15vtlmks Q: Perhaps your certificate for large font antialiasing died
🗪
1:38:15vtlmks Q: Perhaps your certificate for large font antialiasing died
🗪
1:38:15vtlmks Q: Perhaps your certificate for large font antialiasing died
🗪
1:38:35x13pixels Q: In ExtractFont(), MaxGlyphDim's x value is set using TextMetric.tmOverhang. It seems like tmOverhang should only apply to MaxGlyphDim's y-value?
🗪
1:38:35x13pixels Q: In ExtractFont(), MaxGlyphDim's x value is set using TextMetric.tmOverhang. It seems like tmOverhang should only apply to MaxGlyphDim's y-value?
🗪
1:38:35x13pixels Q: In ExtractFont(), MaxGlyphDim's x value is set using TextMetric.tmOverhang. It seems like tmOverhang should only apply to MaxGlyphDim's y-value?
🗪
1:39:27theomarest Q: Would this only work for monospace fonts?
🗪
1:39:27theomarest Q: Would this only work for monospace fonts?
🗪
1:39:27theomarest Q: Would this only work for monospace fonts?
🗪
1:39:34centhusiast Q: What is the difference between the FreeType and TrueType fonts? Do both do the sub-pixel rasterization?
🗪
1:39:34centhusiast Q: What is the difference between the FreeType and TrueType fonts? Do both do the sub-pixel rasterization?
🗪
1:39:34centhusiast Q: What is the difference between the FreeType and TrueType fonts? Do both do the sub-pixel rasterization?
🗪
1:40:08ivereadthesequel handmade_hero You wrote in the note 543->544 instead of 353->354. Glasses!
🗪
1:40:08ivereadthesequel handmade_hero You wrote in the note 543->544 instead of 353->354. Glasses!
🗪
1:40:08ivereadthesequel handmade_hero You wrote in the note 543->544 instead of 353->354. Glasses!
🗪
1:40:19Fix the antialiasing magic value note in ExtractFont()
1:40:19Fix the antialiasing magic value note in ExtractFont()
1:40:19Fix the antialiasing magic value note in ExtractFont()
1:40:36boonetbe Q: Did you try the Kakoune editor? Could its behavior be achieved in 4coder?
🗪
1:40:36boonetbe Q: Did you try the Kakoune editor? Could its behavior be achieved in 4coder?
🗪
1:40:36boonetbe Q: Did you try the Kakoune editor? Could its behavior be achieved in 4coder?
🗪
1:41:48glog78 Q: Didn't MSN say something about small fonts too?
🗪
1:41:48glog78 Q: Didn't MSN say something about small fonts too?
🗪
1:41:48glog78 Q: Didn't MSN say something about small fonts too?
🗪
1:42:51teamrandb Q: But did you not check 500 and it worked?
🗪
1:42:51teamrandb Q: But did you not check 500 and it worked?
🗪
1:42:51teamrandb Q: But did you not check 500 and it worked?
🗪
1:43:55floorislava Q: GitHub bug report?
🗪
1:43:55floorislava Q: GitHub bug report?
🗪
1:43:55floorislava Q: GitHub bug report?
🗪
1:44:17Close the "Support writing "large" PNGs" issue8
🗹
1:44:17Close the "Support writing "large" PNGs" issue8
🗹
1:44:17Close the "Support writing "large" PNGs" issue8
🗹
1:44:42Address the "Should we advance a character here?" issue9
📖
1:44:42Address the "Should we advance a character here?" issue9
📖
1:44:42Address the "Should we advance a character here?" issue9
📖
1:46:22Fix GetTokenRaw() to skip past the '.' of decimal numbers
1:46:22Fix GetTokenRaw() to skip past the '.' of decimal numbers
1:46:22Fix GetTokenRaw() to skip past the '.' of decimal numbers
1:46:40Close the "Should we advance a character here?" issue10
🗹
1:46:40Close the "Should we advance a character here?" issue10
🗹
1:46:40Close the "Should we advance a character here?" issue10
🗹
1:47:36mycon_ Q: Are there any plans for a new HandmadeCon?11
🗪
1:47:36mycon_ Q: Are there any plans for a new HandmadeCon?11
🗪
1:47:36mycon_ Q: Are there any plans for a new HandmadeCon?11
🗪
1:49:00centhusiast 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?12
🗪
1:49:00centhusiast 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?12
🗪
1:49:00centhusiast 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?12
🗪
1:50:43Close it down
🗩
1:50:43Close it down
🗩
1:50:43Close it down
🗩