unicode/Gargoyle

I think Bocfel, the Z-machine interpreter in Gargoyle, uses unicode to simulate font 3, so if the glyphs are missing in the default font, they will be missing in Bocfel as well.

1 Like

it’s not always possible to drill down to the display code and find out how character display works. (It’s basically impossible in Javascript, for example.)

I know nothing of Javascript, but is there no way to draw two characters (where one is the known “character not found” character) as images and then compare the image data?

CanvasRenderingContext2D.getImageData() seems like it should do the trick.

That sounds like a nightmare solution, honestly.

1 Like

It seems to be the preferred way to do it on iOS, and it seems to work fine in Spatterlight. But I guess Canvas works differently.

1 Like

Yes, this is correct.

It’d be nice getting this in Gargoyle, too, certainly. But since there are, generally, multiple fonts in use (monospace and proportional at least, and at the extreme, Gargoyle can use 8 completely separate fonts); so how would this work when different fonts have different coverages?

On the direct topic, and related to the linked topic in the first post, I’ve been working on font substitution in Gargoyle. At least for a first cut, the best option I found is to use GNU Unifont as a fallback font, and include it with Gargoyle. This has wide coverage of Unicode (not all, as that’s impossible in a single font), and at the moment I don’t want to deal with the possibility of shipping a bunch of different fonts, such as the Noto family, to get better coverage. A single font that does fallback is better than nothing, at least! Plus I’ve added the ability for users to specify their own fallback fonts, so if they want to slot some Noto fonts in, they can. The result looks like this (sample from Zarf’s Glulx Unicode test):

Gargoyle before substitution:
Original

Using Unifont as the fallback:
Unifont

Using a user-specified Noto Serif Hebrew as a fallback:
Noto

(I conveniently cut off the part noting that the aleph is in the wrong place: that’s a future issue to deal with…)

Unifont is very utilitarian, but it does work. The more glyphs that are missing, though, the worse things get, but it shouldn’t be worse than the question marks Gargoyle currently uses.

2 Likes

Gargoyle can use 8 completely separate fonts); so how would this work when different fonts have different coverages?

The way I implemented it, it checks if the font used by the current window style can print it. Or if there is no current window style, the normal buffer style.

EDIT: Although that is a bit overkill in Spatterlight, as the OS will look through every installed font for missing glyphs, so the answer will be the same for every font.

Not a Mac developer and I apologize in advance for naivete, but would this other approach to test if a unicode character is available using CTFontGetGlyphsForCharacters work?

That will check if a glyph is available in the font, but if you try to print a glyph that is missing in the current font, the OS might substitute it from another installed font that has it, so it won’t actually tell wether the glyph can be printed or not.

It might be possible to get a list of all installed fonts and iterate through that, but I don’t know how.

1 Like

Seems to be working in Spatterlight now. Unfortunately, unlike the built-in Inform IDE interpreter (pictured below), it won’t print emojis, and I’m not sure why.

Inform 7 source below. Note that [Unicode N] won’t work, so I had to roll my own.

"UnicodeTest" by Administrator

Example Location is a room. 

To decide if unicode character (N - a number) is printable:
	(- (glk_gestalt(gestalt_CharOutput, {N}) ~= gestalt_CharOutput_CannotPrint) -).
	
To say (N - a number) as uni:
	(- glk_put_char_uni({N}); -).
	
When play begins:
	repeat with N running from 2612 to 2713:
		say "Emoji [N as uni] for code [N] is valid: ";
		if unicode character N is printable:
			say "true";
		otherwise:
			say "false";
		say line break.

2 Likes

Given a say N as uni phrase like the above, you can even assign a character corresponding to something above 65535 to a text and it’ll work, up to a point.

let t1 be "[128521 as uni]";
say t1; [works]

The point beyond which it’ll fail is if it gets copied to a different text: the top 16 bits get stripped.

let t2 be "[t1]";
say t2; [ fails: tries to output 0xF609, which is in a private use area ]

But if you add the following, it works (code is for 10.1; the equivalent for 9.3 works there, too):

Include (-
Constant TEXT_TY_Storage_Flags = BLK_FLAG_MULTIPLE + BLK_FLAG_WORD;
-) replacing "TEXT_TY_Storage_Flags";

…or at least I haven’t seen it cause problems. But I haven’t tried it beyond the proof of concept and it’s probably a terrible idea.

2 Likes

From the perspective of GlkOte and RemGlk, actually testing if a character was supported would need to take place over the JSON protocol. That would then mean that glk_gestalt would need to be changed to be async, turning what had been a very quick function (that Zarf once told me wasn’t worth caching the results of :stuck_out_tongue:) into one that could affect the performance of everything that calls it.

There’s also the complication that the proportional and mono fonts will support different glyphs.

I just don’t see a good way of handling it in GlkOte.

In the code you just pushed to github, you use unichar uniglyph[1] in handleCanPrintGlyph which seems to be just a 16 bit type, so only works for characters in the BMP.

you use unichar uniglyph[1] in handleCanPrintGlyph which seems to be just a 16 bit type, so only works for characters in the BMP

Thanks! unichar is used for all text output in Spatterlight, so that is obviously the problem. I’ll need to take a look at the Zoom code to see how it is done there.

You just need to convert them to a surrogate pair, see https://en.wikipedia.org/wiki/UTF-16#U+D800_to_U+DFFF.

Edit: Some time ago I tricked some z-machine interpreters to print characters outside the BMP, this may be of some use as a test case: Z-Machine 1.2 Proposal (again) - #30 by borg323

1 Like

On the plus side, web browsers are generally pretty good about having fallback fonts, so there’s more likely to be something instead of just a question mark or an empty space.

That would then mean that glk_gestalt would need to be changed to be async

You could always special-case gestalt_CharOutput, so that only that check needs to be async and the rest of glk_gestalt stays as it is.

There’s also the complication that the proportional and mono fonts will support different glyphs.

Most browsers running GlkOte will probably implement some kind of glyph substitution, so the answer will likely be the same for every font. As long as one of the installed fonts supports a glyph, it will be printed.

I was going to say that wouldn’t be possible, but I guess it could if glk_gestalt was changed to a macro. But that’s only for C. I don’t think we could do anything for JS.

I would love to be able to use smallcaps font variant instead of bold, so I am excited about this font path lookup thing.

But I would like to suggest a change to the propz font descriptor. I want to use smallcaps for headers and subheaders, but keep bold for user input. The way I can do this is to repurpose propz like this:

propz         Fontin-SmallCaps.otf
.
.
tfont  3      propz           # Header
tfont  4      propz           # Subheader

Gargoyle uses the correct font but unfortunately propz machine-slants the smallcaps fonts in this case. Maybe I can convince you to change this propz behaviour or provide a neutral user defined propx descriptor that uses the font file as it finds it and not try to slant or bolden it.

Anyway, it would be nice to be able to use the custom fonts like that system wide(not game specific) but not requiring to copy the font files to the root directory (that is the working directory in Mojave for programs run from the launcher), but I realize that requires a substantial overhaul of the font management system for a cross-platform application for just one person, so I am not asking for it :slight_smile: .

The way propz works can’t be changed, as there are a lot of config files out there relying on it (implicitly or otherwise). “z” here is just a single-character identifier that means “bold italic”, and if the selected font doesn’t support bold or italic, Gargoyle fakes it, as you’ve noticed.

Your use case is valid, though. You can create a feature request issue at Issues · garglk/garglk · GitHub, and I can look into a way to provide more control over fonts without breaking existing configurations.

1 Like

I have slept on the problem and found that I have overlooked an obvious fix: opened Fontin-SmallCaps.otf in FontForge, changed OS/2 style map to Bold Italic, regenerated the font, copied the new Fontin-SmallCaps.otf into to root directory. Now Gargoyle thinks it is already bold and slanted and displays it as it is when I use it with propz. No need to waste your time for my specific pet peeve.

Also thank you for showing me that those custom font ini-file entries are possible. I didn’t know that until I saw it here.