Re: Pango, Cairo, Scale, and Ink Rectangles



On Tue, Nov 25, 2014 at 1:34 PM, Behdad Esfahbod <behdad behdad org> wrote:
On 14-11-24 07:13 PM, Yclept Nemo wrote:
> On Mon, Nov 24, 2014 at 5:12 PM, Behdad Esfahbod <behdad behdad org
> <mailto:behdad behdad org>> wrote:
>
>     On 14-11-23 11:15 AM, Yclept Nemo wrote:
>     > This seems impossible if the glyph width/height ratios vary with scale/dpi.
>
>     Turn hinting off.  Like this:
>
>       https://git.gnome.org/browse/pango/tree/examples/cairotwisted.c#n477
>
>
> Thanks,
>
> It is a necessary suggestion, but unfortunately the glyph width/height ratios
> continue to vary.

Continue to vary in the exact same way?  Or varies, but much much closer to
eachother? Please attach full C test code as well as a pointer to the font,
with actual and expected output.

I've attached (inline, below) equivalent C and Python3 examples
 * Output is identical with or without the proposed font options CAIRO_HINT_STYLE_NONE and CAIRO_HINT_METRICS_OFF (ie, vary in the exact same way).
 * with_pango_resolution(...) output is identical between C and Python.
 * with_cairo_transformation(...) output differs between C and Python. Probably a (another?) bug. In Python, I know that scaling the cairo context scales the font. I'm unclear if the C results imply the font is scaled proportionally, or simply not scaled at all. Either case is immaterial as I am only interested in Python results.

I'm not sure what you mean by pointer to the font. Whether using a custom PangoFontDescription as in the examples below or the default font, the width/height ratios continue to vary extremely. While yours was a necessary suggestion, I doubt hinting is responsible for squashing the glyph "8" into a 5x5 square (first message, example, using default font).

Output, C:
-----------------------------------------------
0.000000            3.000000            8.000000            10.000000           
1.000000            5.000000            14.000000           20.000000           
0.000000            1.000000            4.000000            7.000000            
0.000000            0.000000            0.694336            1.388672            
0.000000            3.000000            8.000000            10.000000           
-----------------------------------------------
-----------------------------------------------
0.000000            3.000000            8.000000            10.000000           
0.000000            3.000000            8.000000            10.000000           
0.000000            3.000000            8.000000            10.000000           
0.000000            3.000000            8.000000            10.000000           
0.000000            3.000000            8.000000            10.000000           
-----------------------------------------------

Output, Python:
-----------------------------------------------
0.0                 3.0                 8.0                 10.0                
1.0                 5.0                 14.0                20.0                
0.0                 1.0                 4.0                 7.0                 
0.0                 0.0                 0.6943359375        1.388671875         
0.0                 3.0                 8.0                 10.0                
-----------------------------------------------
-----------------------------------------------
0.0                 3.0                 8.0                 10.0                
0.0                 2.0                 8.0                 14.0                
0.5                 2.5                 7.0                 10.0                
0.8330078125        2.447265625         6.3544921875        10.15625            
0.0                 3.0                 8.0                 10.0                
-----------------------------------------------

I expect the ratio of the last two columns' values to remain constant between tests (between dotted lines), implying the glyph width/height ratio is invariant across scale and dpi.

Sincerely,




Example, C:

#include <stdio.h>
#include <pango/pangocairo.h>

void with_pango_resolution(cairo_t* ctx, PangoFontDescription* fd, double dpi){
    PangoContext* pctx;
    PangoLayout* layout;
    PangoRectangle ink_rect;
    double x,y,w,h;

    cairo_identity_matrix(ctx);
    pctx = pango_cairo_create_context(ctx);
    pango_cairo_context_set_resolution(pctx, dpi);
    layout = pango_layout_new(pctx);
    pango_layout_set_font_description(layout, fd);
    pango_layout_set_text(layout, "8", 1);
    pango_layout_get_extents(layout, &ink_rect, NULL);

    x = (float)ink_rect.x / PANGO_SCALE;
    y = (float)ink_rect.y / PANGO_SCALE;
    w = (float)ink_rect.width / PANGO_SCALE;
    h = (float)ink_rect.height / PANGO_SCALE;

    fprintf(stdout, "%-20f%-20f%-20f%-20f\n", x, y, w, h);

    g_object_unref(layout);
    g_object_unref(pctx);
}

void with_cairo_transformation(cairo_t* ctx, PangoFontDescription* fd, double scale){
    PangoLayout* layout;
    PangoRectangle ink_rect;
    double x,y,w,h;

    cairo_identity_matrix(ctx);
    cairo_scale(ctx, scale, scale);
    layout = pango_cairo_create_layout(ctx);
    pango_layout_set_font_description(layout, fd);
    pango_layout_set_text(layout, "8", 1);
    pango_layout_get_extents(layout, &ink_rect, NULL);

    x = ink_rect.x / PANGO_SCALE;
    y = ink_rect.y / PANGO_SCALE;
    w = ink_rect.width / PANGO_SCALE;
    h = ink_rect.height / PANGO_SCALE;

    fprintf(stdout, "%-20f%-20f%-20f%-20f\n", x, y, w, h);

    g_object_unref(layout);
}

int main(){
    cairo_surface_t* target;
    cairo_t* context;
    cairo_font_options_t* fontoptions;
    PangoFontDescription* fontdescription;

    target = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1024, 1024);

    context = cairo_create(target);
    cairo_surface_destroy(target);

    fontoptions = cairo_font_options_create();

    cairo_font_options_set_hint_style(fontoptions, CAIRO_HINT_STYLE_NONE);
    cairo_font_options_set_hint_style(fontoptions, CAIRO_HINT_METRICS_OFF);

    cairo_set_font_options(context, fontoptions);
    cairo_font_options_destroy(fontoptions);

    fontdescription = pango_font_description_from_string("Monospace 10");

    fprintf(stdout, "-----------------------------------------------\n");
    with_pango_resolution(context, fontdescription, 96);
    with_pango_resolution(context, fontdescription, 192);
    with_pango_resolution(context, fontdescription, 48);
    with_pango_resolution(context, fontdescription, 5);
    with_pango_resolution(context, fontdescription, 96);
    fprintf(stdout, "-----------------------------------------------\n");

    fprintf(stdout, "-----------------------------------------------\n");
    with_cairo_transformation(context, fontdescription, 1);
    with_cairo_transformation(context, fontdescription, 1/2);
    with_cairo_transformation(context, fontdescription, 2);
    with_cairo_transformation(context, fontdescription, 19.2);
    with_cairo_transformation(context, fontdescription, 1);
    fprintf(stdout, "-----------------------------------------------\n");

    pango_font_description_free(fontdescription);
    cairo_destroy(context);
}




Example, Python:

from gi.repository import Pango, PangoCairo
import cairo


def with_pango_resolution(ctx, fd, dpi):
    ctx.identity_matrix()
    pctx = PangoCairo.create_context(ctx)
    PangoCairo.context_set_resolution(pctx, dpi)
    layout = Pango.Layout(pctx)
    layout.set_font_description(fd)
    layout.set_text("8", 1)
    ink_rect = layout.get_extents()[0]

    x = ink_rect.x / Pango.SCALE
    y = ink_rect.y / Pango.SCALE
    w = ink_rect.width / Pango.SCALE
    h = ink_rect.height / Pango.SCALE

    print(("{:<20}"*4).format(x, y, w, h))

def with_cairo_transformation(ctx, fd, scale):
    ctx.identity_matrix()
    ctx.scale(scale, scale)
    layout = PangoCairo.create_layout(ctx)
    layout.set_font_description(fd)
    layout.set_text("8", 1)
    ink_rect = layout.get_extents()[0]
   
    x = ink_rect.x / Pango.SCALE
    y = ink_rect.y / Pango.SCALE
    w = ink_rect.width / Pango.SCALE
    h = ink_rect.height / Pango.SCALE

    print(("{:<20}"*4).format(x, y, w, h))


target = cairo.ImageSurface(cairo.FORMAT_ARGB32, 1024, 1024)

context = cairo.Context(target)

fontoptions = cairo.FontOptions()

fontoptions.set_hint_metrics(cairo.HINT_METRICS_OFF)
fontoptions.set_hint_style(cairo.HINT_STYLE_NONE)

context.set_font_options(fontoptions)

fontdescription = Pango.FontDescription("Monospace 10")


print("-----------------------------------------------");
with_pango_resolution(context, fontdescription, 96);
with_pango_resolution(context, fontdescription, 192);
with_pango_resolution(context, fontdescription, 48);
with_pango_resolution(context, fontdescription, 5);
with_pango_resolution(context, fontdescription, 96);
print("-----------------------------------------------");

print("-----------------------------------------------");
with_cairo_transformation(context, fontdescription, 1);
with_cairo_transformation(context, fontdescription, 1/2);
with_cairo_transformation(context, fontdescription, 2);
with_cairo_transformation(context, fontdescription, 19.2);
with_cairo_transformation(context, fontdescription, 1);
print("-----------------------------------------------");


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]