Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set LCD geometry for subpixel rendering #296

Open
Qrox opened this issue Jul 19, 2023 · 14 comments
Open

Set LCD geometry for subpixel rendering #296

Qrox opened this issue Jul 19, 2023 · 14 comments
Milestone

Comments

@Qrox
Copy link

Qrox commented Jul 19, 2023

Currently, SDL_ttf uses the Harmony algorithm with default LCD geometry (uniform RGB subpixels in the horizontal direction) when doing subpixel rendering. According to freetype docs,

Harmony with default LCD geometry is equivalent to ClearType with light filter.

which apparently does not work for screens with a different subpixel layout, as evidenced by this post.

Freetype has a function FT_Library_SetLcdGeometry for setting the geometry but it requires passing in the library instance which is a static variable in SDL_ttf, so it is currently impossible to set the LCD geometry when using SDL_ttf.

It would be nice if SDL_ttf can expose this function to achieve the best rendering quality on non-conventional screens.

@1bsyl
Copy link
Contributor

1bsyl commented Jul 30, 2023

Yes, I think this make sense to expose a wrapper to be able to use this function !
feel free to make a PR for it

@1bsyl
Copy link
Contributor

1bsyl commented Aug 6, 2023

So according to https://freetype.org/freetype2/docs/reference/ft2-lcd_rendering.html

Subpixel rendering mode, depends on FT compilation option.

FT_CONFIG_OPTION_SUBPIXEL_RENDERING enables ClearType-style rendering. Otherwise, Harmony LCD rendering is enabled.

ClearType-style rendering: (since FT 2.3.0)

ClearType-style LCD rendering exploits the color-striped structure of LCD pixels, increasing the available resolution in the direction of the stripe (usually horizontal RGB) by a factor of 3

Use the functions:
FT_Library_SetLcdFilter( FT_Library library, FT_LcdFilter filter );
FT_Library_SetLcdFilterWeights( FT_Library library,unsigned char *weights );

Harmony LCD rendering: (since FT 2.10.0)

Harmony LCD rendering is suitable to panels with any regular subpixel structure, not just monitors with 3 color striped subpixels, as long as the color subpixels have fixed positions relative to the pixel center

Use the functions:
FT_Library_SetLcdGeometry( FT_Library library, FT_Vector sub[3] );

So we would need 3 stubs to FreeType functions to cover the two modes + one function to tell if we're doing ClearType-style or Harmony.

or just export the "FT_Library" internal handle and let people deal with it ?
@slouken ?

1bsyl added a commit to 1bsyl/SDL_ttf that referenced this issue Aug 7, 2023
 TTF_GetSubpixelMode()
 TTF_SetLcdFilter()
 TTF_SetLcdFilterWeights()
 TTF_SetLcdGeometry()

see libsdl-org#296
@1bsyl
Copy link
Contributor

1bsyl commented Aug 7, 2023

I think adding / exposing the freetype function is the way to go:
TTF_GetSubpixelMode()
TTF_SetLcdFilter()
TTF_SetLcdFilterWeights()
TTF_SetLcdGeometry()

@Qrox
hey, can you try this patch, to customize the subpixel rendering ?

@1bsyl 1bsyl changed the title Set LCD geoemtry for subpixel rendering Set LCD geometry for subpixel rendering Aug 7, 2023
@Qrox
Copy link
Author

Qrox commented Aug 7, 2023

@1bsyl Thanks for the update. The patch looks good to me but unfortunately I do not have time to test it right now. I can provide some observation that might make sense to note in the documentation though.

  1. FT_Library_SetLcdGeometry's y coordinates are in reverse from the usual SDL notation (larger = upper as opposed to larger = lower).
  2. The current code does not clear the glyph cache of created SDL_ttf fonts when changing the filter/geometry, but clearing the glyph cache would require keeping a list of created fonts since the filter/geometry are global settings.
  3. The current implementation of TTF_GetSubpixelMode may reset the geometry and/or filter.

1bsyl added a commit to 1bsyl/SDL_ttf that referenced this issue Aug 7, 2023
 TTF_GetSubpixelMode()
 TTF_SetLcdFilter()
 TTF_SetLcdFilterWeights()
 TTF_SetLcdGeometry()

see libsdl-org#296
@1bsyl
Copy link
Contributor

1bsyl commented Aug 7, 2023

Thanks for the feedback !

update:

  • SDLCALL

  • const int param

  • rename param to pixel_coordinates

  • add comment for FT_Library_SetLcdGeometry:
    since, this is just a stub to FT library ... just add a remark in the header...

  • I think TTF_GetSubpixelMode() is ok. because "done" and "mode" are static var. so the detection is done once. then the cached value is returned ?

@1bsyl
Copy link
Contributor

1bsyl commented Aug 7, 2023

indeed:
The current code does not clear the glyph cache of created SDL_ttf fonts when changing the filter/geometry, but clearing the glyph cache would require keeping a list of created fonts since the filter/geometry are global settings.

1bsyl added a commit to 1bsyl/SDL_ttf that referenced this issue Aug 7, 2023
 TTF_GetSubpixelMode()
 TTF_SetLcdFilter()
 TTF_SetLcdFilterWeights()
 TTF_SetLcdGeometry()

see libsdl-org#296
@1bsyl
Copy link
Contributor

1bsyl commented Aug 7, 2023

updated with "extern declspec"

@1bsyl
Copy link
Contributor

1bsyl commented Aug 7, 2023

should we maintain an internal list of open fonts or just document the behavior :/

@Qrox
Copy link
Author

Qrox commented Aug 8, 2023

There's also the scenario of multiple monitors with different subpixel layouts, and not clearing the glyph cache can enable the user to create different versions of a font to apply to different monitors. But it sounds a bit hacky and I suppose the proper way is to ask freetype to add a per-font layout setting.

@1bsyl
Copy link
Contributor

1bsyl commented Aug 8, 2023

maybe, we should tweak those new TTF_SetLcd function to take a TTF_Font in parameter,
We only apply the filter setting the current font (and set back to default for other fonts), and we handle the lcd filter switching internally so that each font is rendered with its own filter.

@1bsyl
Copy link
Contributor

1bsyl commented Aug 8, 2023

I've update the PR so that the setting are per-font,
#302

re-apply the setting if they have changed, flush the cache.
ok, compiles, but not tested at all :)

@1bsyl
Copy link
Contributor

1bsyl commented Aug 10, 2023

@Qrox
it would be nice if you could give a try when you have some time
thanks

@Qrox
Copy link
Author

Qrox commented Aug 10, 2023

Sure, I have some in progress changes to showfont.c to test LCD rendering mode, when I have more time I'll test your PR with those changes and create a PR.

@1bsyl
Copy link
Contributor

1bsyl commented Aug 11, 2023

I have added tests in example/testapp.c to test filter and filterweight and harmony
so this is now somehow tested.
there is real difference of fonts when using the lcd filter. I believe this is only meant to be used with specific display hardware

maybe this ok, for merging ? @slouken

@slouken slouken added this to the 3.0 milestone Jan 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants