Hey, I bet you thought I’d forgotten about this thread… Here’s my current idea.
We will have a glk_image_draw_scaled_ext() function:
glui32 glk_image_draw_scaled(winid_t win, glui32 image, glsi32 val1, glsi32 val2, glui32 width, glui32 height, glui32 ext);
The new ext
argument contains three flags. (I may rename the argument and the flags, but I want to get this written down before I go to bed, so I’m just naming stuff on the fly.)
- WidthRule (2 bits): can be ORIG, FIXED, or WIDTHRATIO.
- HeightRule (2 bits): can be ORIG, FIXED, or ASPECTRATIO.
- MaxWidth (1 bit): boolean.
What do these mean for buffer windows?
- WidthRule_ORIG:
width
argument is ignored; displayed width is the image original width.
- WidthRule_FIXED: displayed width is given by
width
argument in pixels.
- WidthRule_WIDTHRATIO: displayed width is the buffer window width multiplied by the
width
argument, which is interpreted as a 16.16 fixed-point value. (So 0x10000 means 100% of the buffer window width.)
- HeightRule_ORIG:
height
argument is ignored; displayed height is the image original height.
- HeightRule_FIXED: displayed height is given by
height
argument in pixels.
- HeightRule_ASPECTRATIO: displayed height is based on the displayed width, maintaining the aspect ratio multiplied by
height
(as 16.16). That is, if height
is 0x10000, the original aspect ratio is maintained. If height
is 0x20000, the image is stretched vertically by a factor of 2.
If the MaxWidth flag is true, the image gets a maximum display width of the buffer window window. If it’s too wide, it’s scaled down (strictly proportionally) to fit.
If MaxWidth is false, there is no such limit. (But, to be clear, images must be clipped if they’re too large for a window.)
The current defined behavior of both glk_image_draw() and glk_image_draw_scaled() are MaxWidth=false. But, as discussed above, we would like to change this default to be MaxWidth=true. That’s change in spec behavior but it’s almost certain to be an improvement.
Thus, in the new world, the old glk_image_draw() call becomes a shortcut for:
glk_image_draw_scaled_ext(win, image, val1, val2, _, _, WidthRule_ORIG|HeightRule_ORIG|MaxWidth);
Note that the fifth and sixth arguments are ignored because of ORIG|ORIG.
Similarly, the old glk_image_draw_scaled() call becomes a shortcut for:
glk_image_draw_scaled_ext(win, image, val1, val2, width, height, WidthRule_FIXED|HeightRule_FIXED|MaxWidth);
We keep the rule that if the final width or height is zero, the image is not drawn. (This will happen if the width
or height
argument is zero, unless we’re in the ORIG rule case.)
As you see, this proposal completely bags the idea of fitting an image into the vertical span of the buffer window. I think there are just too many headaches down that road.
In particular, I would really like the image handling to be implementable in HTML by using pure CSS, with no calculated reference to the window size. I think all the cases in my proposal can be. (I haven’t tested this yet!) But a “max-height” constraint could not be, because the DOM container height is the scroll height, not the visible height.
(Maybe there’s a way to do it with the CSS calc()
feature, but it seems like a big added headache even if it is possible.)
Also: remember that the text buffer window can be resized freely by the player. This will automatically resize images if they are defined relative to the window width (or if they hit the MaxWidth constraint). Again, this should work “by magic” (and in an intuitive way) if it’s all handled at the CSS level.