brndnmtthws / conky

Light-weight system monitor for X, Wayland (sort of), and other things, too
https://conky.cc
GNU General Public License v3.0
7.27k stars 620 forks source link

Can I use the Imlib2 Lua bindings for font rendering? #900

Closed philer closed 7 months ago

philer commented 5 years ago

TL;DR Trying to use font related imlib_… functions in Lua apparently does nothing.

I've been creating a fairly elaborate system of cairo based lua widgets for conky here. However, cairo's text rendering is extremely limited as explained in the official documentation. Hence, I was hoping to get some better font rendering via Imlib2, which conky provides Lua bindings for. Unfortunately, they apparently don't work – or I am doing it wrong.

Details

I've tried this on both version 1.11.5_pre (Lua 5.3), compiled today, and on version 1.10.8 (Lua 5.1) installed via package manager on Linux Mint 19. Imlib2 is listed in the Lua bindings section of conky -v.

require "imlib2" works. All the expected globals are present. I can call any number of imlib_… functions from within my code, except none of the ones I'm interested do or return anything. For instance the following code:

local number_return
local font_paths = imlib_list_font_path(number_return)
print(font_paths, number_return)

outputs nil nil. The function's documentation is quite clear that it should return a list of strings, which I understand would need to be converted to a Lua table before they can be used.

As a further example, if I run

local font = imlib_load_font("ubuntu/10")
imlib_context_set_font(font)
imlib_text_draw(0, 0, "hello world")

I get an error message:

***** Imlib2 Developer Warning ***** :
This program is calling the Imlib call:
imlib_text_draw_with_return_metrics();
With the parameter:
font
being NULL. Please fix your program.

which is expected, since font is also nil. Meanwhile the "ubuntu" font is most definitely available in TrueType format on my system.

So now I'm facing two issues:

  1. I have no idea if it's possible to use imlib from within my Lua code.
  2. Assuming it's possible I still can't find any documentation telling me how. There is apparently a cairo_draw_image function defined in a cairo/imlib2 helper but I'd still have to rely on a lot of trial-and-error to figure out if/how I can use that to solve my problem.

I'd be quite grateful for some hints here. Let me know if I should provide any further details.

philer commented 5 years ago

So with a lot of trial-and-error and the help of this horrible piece of code I've figured out a couple of things:

  1. imlib apparently starts with no font paths, so something like imlib_add_path_to_font_path("/usr/share/fonts/truetype/ubuntu") is necessary before any font loading can happen.
  2. Even then imlib_list_font_path will only return garbled text, e.g. "P��n�U". I assume there's some issue with converting **char to a table of strings in lua.
  3. Trying to imitate the behaviour from libcairo_imlib2_helper.h in lua did nothing [1].
  4. However, using imlib_render_image_on_drawble works. The following will draw "Hello World":
    imlib_add_path_to_font_path("/usr/share/fonts/truetype/ubuntu")
    local img = imlib_create_image(200, 200)
    imlib_context_set_image(img)
    imlib_image_set_has_alpha(1)
    imlib_image_clear()
    local font = imlib_load_font("Ubuntu-R/8")
    imlib_context_set_font(font)
    imlib_context_set_color(255, 255, 255, 255)
    imlib_text_draw(10, 10, "Hello World")
    imlib_render_image_on_drawable(0, 0)

    So this may be considered a small success. Unfortunately for my purpose it turns out that imlib2's font rendering is even worse than cairo's. It does no kerning either and at small font sizes the output becomes completely unreadable. The sizing is also different and can only be scaled in integer steps, making it impossible to match the font size as drawn by conky/cairo.

I will consider this a failed experiment and leave my findings here in case anyone else has a use for it or can add something to it.

A suggestion that could improve the situation: It would be nice if conky exposed its own font rendering facilities (I believe it uses XftDrawString or something like that) in lua. That way Lua themes could also use crisp font rendering.


[1] Here's the code I tried to use instead of imlib_render_on_drawable in the example above. It doesn't raise any errors but has no visible effect either (cr is the normal cairo_t).

    local data = imlib_image_get_data_for_reading_only()
    local stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, 100)
    local surf = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32,
                                                     100, 100, stride)
    cairo_set_source_surface(cr, surf, 0, 0)
    cairo_paint(cr)
    cairo_surface_destroy(surf)
    imlib_free_image()
simotek commented 1 year ago

It seems we are trying to head in a similar direction, your Polycore stuff is awesome and has saved huge amounts of time so firstly thankyou.

I had a play with Pango as a solution today but it is pretty tied into the gobject bindings and seems unlikely to work with conky's cairo bindings.

On the other hand using freetype and harfbuzz looks like it could be promising [1], unfortunately for my system this looks like starting off by packaging up several more lua bindings so I didn't get to it this weekend, but given I don't really want to go back to fighting to get configs to show in the right place between both lua and conky configs i'll probably get to trying something reasonably soon.

Also thankyou again because I believe the code above should give me a way to create a widget that renders a jpeg image which is something I was jet to figure out on the lua side

  1. https://github.com/luapower/harfbuzz/blob/master/harfbuzz_demo.lua
github-actions[bot] commented 8 months ago

This issue is stale because it has been open 365 days with no activity. Remove stale label or comment, or this issue will be closed in 30 days.

github-actions[bot] commented 7 months ago

This issue was closed because it has been stalled for 30 days with no activity.