Repository navigation
text-freetype2: Read the matched font's face index from fontconfig - #1411
Merged
Merged
Conversation
github-merge-queue
Bot
removed this pull request from the merge queue due to a conflict with the base branch
Oct 18, 2026
rdoupe
force-pushed
the
fix/ft2-face-index
branch
from
October 18, 2026 16:09
c659161 to
b304cd7
Compare
zackees
enabled auto-merge
October 18, 2026 16:13
zackees
approved these changes
Oct 18, 2026
zackees
left a comment
Member
There was a problem hiding this comment.
Coordinator review: LGTM.
FcPatternGetInteger(match, FC_INDEX, 0, ...)is the right fix: the third argument is the value position, and FC_INDEX has one value, so position 1 always failed and leftfc_indexat 0.- Variable-font named instances (index in the high 16 bits, e.g. 458752) pass through
FT_New_Faceunchanged, so they work too. - RED then GREEN commits; the test is hermetic (its own fontconfig file and cache dir, only the synthetic fixture visible) and the fixture is reproducible from
text-collection.py; features ledger line present.
The Tier 2 (tests ON) failure is test_group_hide_transition_audio, the known load flake in #838 and unrelated to this change. I've re-run it; auto-merge is on.
The Text (FreeType 2) source on Linux loads the first face of a font file whatever face fontconfig matched (obsproject/obs-studio#11819). A face of a .ttc/.otc collection, such as Noto Sans CJK SC, TC or KR, or a named instance of a variable font, such as Adwaita Sans Bold, renders as face 0. test_text_freetype2_face_index points fontconfig at a directory that holds only text-collection.ttc, a two-face collection generated by test/cmocka/data/text-collection.py from synthetic outlines ("OBS Collection Fixture" Regular as face 0, Bold as face 1), and asks get_font_path() for each style. Fails 1 of 2: bold_resolves_to_face_1 ("Bold resolved to face 0 of .../text-collection.ttc (expected 1)"). Regular passes. Needs no display. Refs obs-rust#1409.
get_font_path() read FC_INDEX with FcPatternGetInteger(match, FC_INDEX, 1, ...). The third argument is the position among the property's values, and a matched pattern has one index, at position 0. The call always failed, fc_index kept its default 0, and FT_New_Face() loaded the first face of the file (obsproject/obs-studio#11819). So any font that is not face 0 of its file rendered as face 0: Bold and the other named instances of a variable font (Adwaita Sans Bold is index 458752 in AdwaitaSans-Regular.ttf), and the faces of a .ttc collection (Noto Sans CJK SC is face 2 of NotoSansCJK-Regular.ttc; it rendered as the JP face 0). Port of the first commit of obsproject/obs-studio#13290 by reyohoho. The other two commits there (a larger glyph atlas, pre-cached Cyrillic) are covered here by obs-rust#196's atlas fix and are not part of this change. test_text_freetype2_face_index: 2 of 2. In the app, Adwaita Sans Bold now renders bold (513 -> 525 px wide, ink 0.185 -> 0.273 at 96 px), and Noto Sans CJK SC renders the SC glyphs instead of JP's. Fixes obs-rust#1409. Co-Authored-By: reyohoho <reyohoho@proton.me>
rdoupe
force-pushed
the
fix/ft2-face-index
branch
from
October 18, 2026 16:57
b304cd7 to
fdf012d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1409
What and why
The Text (FreeType 2) source on Linux now renders the font face that was picked when it is not the first face of its file. Upstream: obsproject/obs-studio#11819 (confirmed, open); fix by reyohoho in obsproject/obs-studio#13290 (open, unreviewed since April 2026).
get_font_path()(plugins/text-freetype2/find-font-unix.c.h) read the face index withFcPatternGetInteger(match, FC_INDEX, 1, &fc_index). The third argument is the position among the property's values, and a matched pattern has one index, at position 0. The call always failed, sofc_indexstayed 0 andFT_New_Face()loaded face 0.AdwaitaSans-Regular.ttf), rendered as Regular..ttc/.otc, such as Noto Sans CJK SC (face 2 ofNotoSansCJK-Regular.ttc), rendered as face 0, which is JP there. A collection face with less glyph coverage drops letters, as in the #11819 report.Headless (private Xvfb, private D-Bus, fresh HOME), driven over obs-websocket. Text (FreeType 2) at 96 px, source screenshots; fonts from the host's fontconfig:
RED → GREEN
test/cmocka: Add failing test for a font that is not face 0 of its file.test_text_freetype2_face_indexpoints fontconfig at a directory holding onlytest/cmocka/data/text-collection.ttc, a 2 KB two-face collection ("OBS Collection Fixture" Regular as face 0, Bold as face 1). It is generated bytext-collection.pyfrom synthetic outlines, liketext-aa.ttf. The test asksget_font_path()for each style. On master it fails 1 of 2:bold_resolves_to_face_1("Bold resolved to face 0 of .../text-collection.ttc (expected 1)"). It needs no display or installed fonts.text-freetype2: Read the matched font's face index from fontconfig. 2 of 2; the other text-freetype2 tests (bundled font, host font, platform) still pass. Full build (C libobs lane) and full ctest -j4 (private Xvfb, private D-Bus, fresh HOME, systemlibobs-openglmasked): 304/304; the only skipped case isopen_crashes_without_obs_core, as on master. The plugin has no Rust port.Checklist
master-W..., ratchets): noneAI note: Claude Code (Claude Opus 5.5) wrote the test, the font fixture, the commit messages and this text under the submitter's direction, and ran the tests above on the submitter's machines. The fix itself is reyohoho's.