panda3d
panda3d copied to clipboard
text: add 'small_caps' functionality to harfbuzz
Issue description
This commit attempts to resolve issue #1666 (which was introduced when building with harfbuzz after commit 0dad38d), by adding code in TextAssembler.shape_buffer(), to handle the case where:
- harfbuzz is built with the engine
- is wanted via the config variable
text-use-harfbuzzbeing set to true, and - the TextProperties associated with the to-be-drawn text also has the small_caps field set.
Solution description
If the above cases are all true, then the buffer is first remade with all harfbuzz 'codepoints' switched to the uppercase variant (if needed and possible), while keeping the harfbuzz 'cluster' value the same for tracking what characters need their scaling changed.
Later when the glyphs are actually in the process of being generated, I check to see if those earlier 'cluster' values are lowercase values, and go ahead and use individual scale values for each character, using get_small_caps_scale() for these characters instead of the usual get_glyph_scale() in every other case.
Checklist
I have done my best to ensure that…
- [x] …I have familiarized myself with the CONTRIBUTING.md file
- [x] …this change follows the coding style and design patterns of the codebase
- [x] …I own the intellectual property rights to this code
- [x] …the intent of this change is clearly explained
- [x] …existing uses of the Panda3D API are not broken
- [x] …the changed code is adequately covered by the test suite, where possible.
Should we not try and pass the
smcpfeature tohb_shapeto use the native small caps support if provided by the font?
Oh? I was not aware of that feature (sorry, this is perhaps the first time I'm actually tinkering with harfbuzz and Unicode character handling in general).
I'll go and make those changes (including changing has_small_caps() to get_small_caps()!
Well, I've commented out my original code while experimenting, and while I do believe the code I wrote to use the smcp feature seems to work,
std::vector<hb_feature_t> hb_shape_feats;
if (properties.get_small_caps()) {
hb_feature_t tmp_feat;
tmp_feat.tag = HB_TAG('s', 'm', 'c', 'p');
tmp_feat.value = 1;
tmp_feat.start = HB_FEATURE_GLOBAL_START;
tmp_feat.end = HB_FEATURE_GLOBAL_END;
hb_shape_feats.push_back(tmp_feat);
}
if (hb_shape_feats.size() > 0) {
hb_shape(hb_font, buf, hb_shape_feats.data(), hb_shape_feats.size());
} else {
hb_shape(hb_font, buf, nullptr, 0);
}
it does not seem to do anything in the demo code provided in issue #1666. I'm trying to look into this further, and if it's possible for me to query the font to see if it has small caps support.
What's the current status of this?
I've been dealing with personal issues for a while, and I'm not sure at this time when I can continue looking into this.
No worries. I'll finish the work and push it shortly. Will be part of 1.10.15. Thanks for looking into all this!
I looked into smcp and only some fonts supported it. The first font I tried (Inter) actually only supported it for some glyphs, creating a strange result. So, I think we're just going to do our own scaling, and maybe revisit smcp in the future.