JuliaGraphics / Cairo.jl

Bindings to the Cairo graphics library.
Other
87 stars 56 forks source link

Windows 7 font issues #138

Closed ma-laforge closed 2 months ago

ma-laforge commented 8 years ago

Hi,

I could not find an issue on this, but I am having font issues Cairo (I presume). I notice it on Gtk displays.

  1. The standard typefaces (I believe they are supposed to be standard) do not appear to be available in Windows. It looks like Cairo always reverts to a default font in Windows.
  2. I also get issues displaying unicode exponent characters (all except 1, 2, 3). Consequently, I cannot use the output from showoff.jl to display with scientific notation in a Gtk window.
  3. Although I can select Windows fonts from a Windows session (ex "Times"), These fonts still do not appear to support the exponent characters.

Sample Code

using Gtk
using Cairo

bold = false
DISPLAYSTRING = "min:−3, supnum: ⁰¹²³⁴⁵⁶⁷⁸⁹, supmin: ⁻², Greek: αΑβΒφϕΦγΓ"
FONTNAMES = ["Sans", "Serif", "Fantasy", "Monospace"]
weight = bold? Cairo.FONT_WEIGHT_BOLD: Cairo.FONT_WEIGHT_NORMAL
slant = Cairo.FONT_SLANT_NORMAL
_size = 12

canvas = @GtkCanvas
win = @GtkWindow(canvas, "Test Window")

@guarded draw(canvas) do widget
    ctx = getgc(canvas)
    h = height(ctx)
    pitch = h/(length(FONTNAMES)+1)

    set_font_size(ctx, _size)
    y = 0

    for fontname in FONTNAMES
        y += pitch
        text = "$fontname: $DISPLAYSTRING"
        Cairo.move_to(ctx, 0, y)
        select_font_face(ctx, fontname, slant,  weight)
        show_text(ctx, text)
    end
end

showall(win)
ma-laforge commented 8 years ago

My mistake: Apparently this API is for "toy" examples only. Font availability is not guaranteed.

ma-laforge commented 8 years ago

I looked a the provided examples in Samples.md, but do not see a good example of how one can successfully draw text across different platforms using a Unicode-capapable typeface. As far as I can tell, the Cairo documentation seems to discourage the use of select_font_face, as demonstrated in sample_text.jl.

To be honest, the select_font_face API does appear to be sufficient for my own needs... or at least it would be if it allowed met to auto-select a reasonable-looking serif font with good unicode support.

lobingera commented 8 years ago

To make a longer story short: the libcairo font interface is rather low level, that's why you find some pango interfacing there also (and that's also the reason why in Compose.jl there is more pango adaptation incl. font selection).

The examples in Samples.md are drawing examples only.

lobingera commented 8 years ago

you can use the exported text interface. This here works (...tested on linux... fontselecting and finding fonts is a major headache in Windows).

s = Cairo.CairoImageSurface(800,200,Cairo.FORMAT_RGB24);
c = Cairo.CairoContext(s);
t = Cairo.set_font_face(c,"Arial Bold 16")
DISPLAYSTRING = "min:−3, supnum: ⁰¹²³⁴⁵⁶⁷⁸⁹, supmin: ⁻², Greek: αΑβΒφϕΦγΓ"
set_source_rgb(c,1,1,1)
paint(c)
set_source_rgb(c,0,0,0)
text(c,10,100,DISPLAYSTRING)
write_to_png(s,"a1.png")

a1

ma-laforge commented 8 years ago

Interesting...

The Pango set_font_face interface seems to "honour" the 4 fonts that are supposedly supported by Cairo: Sans, Serif, Fantasy, & Monospace... Even in my Windows 7 installation.

Even stranger: unlike select_font_face, it does not supports the Times font...

Sadly, the set_font_face()/text() solution is inadequate for my application. Cairo's transform operations don't get applied when I use it. That means I cannot rotate my text.

Thanks for the help anyways.

lobingera commented 8 years ago
s = Cairo.CairoImageSurface(800,200,Cairo.FORMAT_RGB24);
c = Cairo.CairoContext(s);
t = Cairo.set_font_face(c,"Arial Bold 16")
DISPLAYSTRING = "min:−3, supnum: ⁰¹²³⁴⁵⁶⁷⁸⁹, supmin: ⁻², Greek: αΑβΒφϕΦγΓ"
set_source_rgb(c,1,1,1)
paint(c)
set_source_rgb(c,0,0,0)
text(c,10,200,DISPLAYSTRING,angle=15.0)

a1

ma-laforge commented 8 years ago

That's good.

... But text() appears to change the meaning of font size... which now make Cairo.text_extents() completely inaccurate.

Question Are we supposed to use a different tool to get text extents & figure out display coordinates?

Moreover The behaviour of this text() function seems unconventional to me: This function reset transforms before applying the rotation, which limits its usefulness:

  1. Save context
  2. reset context
  3. Draw rotated text in native coordinate system.
  4. Restore context

I would have expected:

  1. Save context
  2. Draw rotated text on top of current coordinate system.
  3. Restore context.
lobingera commented 8 years ago

To your

I would have expected:

well, just implement it. You can see from the implementation of text how to use update_layout which is the main interface between cairo's CTM and pango's internal CTM. As i wrote above, Cairo.jl is using both variants to show text.

The major problem (and more of a problem in Windows OS) is to correctly find and select an installed font (for proper definition of installed). Just look into https://www.cairographics.org/manual/cairo-text.html, esp. https://www.cairographics.org/manual/cairo-text.html#cairo-select-font-face and https://developer.gnome.org/pango/unstable/pango-Cairo-Rendering.html.

lobingera commented 8 years ago

btw, i ran your code (changing font size) on my linux box and get: screenshot from 2016-06-05 09 51 28

I have no font called Fantasy, but the other defaults seem to work. Can you please post a screenshot of your problem?

ma-laforge commented 8 years ago

well, just implement it.

Fair enough. I will take a closer look at the code then.

The major problem (and more of a problem in Windows OS) is to correctly find and select an installed font (for proper definition of installed). Just look into [...]

Thanks for the references.

Windows snapshot cairofonts_win

Linux snapshot cairofonts_linux

Fantasy does map to a font on my Linux... but it has limited unicode support. It would not work well with showoff.jl (for example).

lobingera commented 8 years ago

I know it's not helpful, but i could reproduce your problem on a Win7. I really see this as font selection problem, because only some glyphs are not available, but the general text setting is working.

ma-laforge commented 8 years ago

I know it's not helpful, but i could reproduce your problem on a Win7.

Well, it is good to know. That means it is probably not a setup issue on my system.

I really see this as font selection problem, because only some glyphs are not available, but the general text setting is working.

Agreed.

I guess my question is:

Is this a bug? It is clear to me that Cairo can find reasonable fonts for Sans, Serif, Monospace (though not Fantasy), as shown below:

Windows 7 + set_font_face/text

cairofonts_win7highlevel

(Generated using slightly altered code):

using Gtk
using Cairo

test_lowlevel = false

bold = false
DISPLAYSTRING = "min:−3, supnum: ⁰¹²³⁴⁵⁶⁷⁸⁹, supmin: ⁻², Greek: αΑβΒφϕΦγΓ"
FONTNAMES = ["Sans", "Serif", "Fantasy", "Monospace"]
weight = bold? Cairo.FONT_WEIGHT_BOLD: Cairo.FONT_WEIGHT_NORMAL
slant = Cairo.FONT_SLANT_NORMAL
_size = 12 #12, 20

canvas = @GtkCanvas
win = @GtkWindow(canvas, "Test Window")

@guarded draw(canvas) do widget
    ctx = getgc(widget)
    h = height(ctx)
    pitch = h/(length(FONTNAMES)+1)
    y = 0

    for fontname in FONTNAMES
        y += pitch
        disptext = "$fontname: $DISPLAYSTRING"

        if test_lowlevel
            set_font_size(ctx, _size)
            select_font_face(ctx, fontname, slant,  weight)
            Cairo.move_to(ctx, 0, y)
            show_text(ctx, disptext)
        else
            fmtstr = (bold?" Bold":"") * " $_size"
            Cairo.set_font_face(ctx,"$fontname $fmtstr")
            Cairo.text(ctx,0,y,disptext)
        end
    end
end

showall(win)

I admit there might be more going on in the backend, but I would have expected even the low-level interface to be able to find proper mappings for the "default fonts".

lobingera commented 8 years ago

What would you consider the bug?

I read today i little bit into libcairo sources and i'm reasonably confused how even the default fonts are selected (per OS). cairo (the library, not Cairo.jl) makes no guarantees for the fonts except the cairo:$family which seems to be built-in in all cairo variants (there is a long list of option for building the library).

To your https://github.com/JuliaGraphics/Cairo.jl/issues/138#issuecomment-223174666: I can think about doing a 'simple' text setting example (incl. coordination transformation) that should work on Sans-Serif and Serif basis, but solving general font selection (OS agnostic) is out of my reach. Maybe like this: If the example doesn't show all glyphs (like in your subscript/greek/math example) it's an indication you need to solve this first, locally.

ma-laforge commented 8 years ago

[...cairo...] makes no guarantees for the fonts except the cairo:$family which seems to be built-in in all cairo variants

I saw that too... but I was not able to make it work. I tried running the above code with FONTNAMES = ["Cairo:Sans", "Cairo:Serif", "Cairo:Fantasy", "Cairo:Monospace"]... but this did not work for me.

(there is a long list of option for building the library).

Maybe that's the problem... I need to figure out how to compile the fonts in, or something.


Well, I think it sounds like there is no issue with Cairo.jl. Feel free to close this issue.

lobingera commented 8 years ago

@ma-laforge Maybe a last check: Which version of libcairo are you using?

cairo_version = ccall((:cairo_version,Cairo._jl_libcairo),Int32,())
ma-laforge commented 8 years ago

Not sure what the version number means, but I get: 11402

ViralBShah commented 2 months ago

Hopefully old enough to close. Please reopen if still an issue on modern Windows.