Esempio n. 1
0
static void
gwy_vruler_real_draw_ticks(GwyRuler *ruler,
                           gint pixelsize,
                           gint min_label_spacing,
                           gint min_tick_spacing)
{
    gdouble lower, upper, max;
    gint text_size, labels, i, scale_depth;
    gdouble range, measure, base, step, first;
    GwyScaleScale scale;
    GwySIValueFormat *format;
    PangoLayout *layout;
    PangoRectangle rect;
    gchar *unit_str;
    gint unitstr_len, j;
    gint width, tick_length, xthickness, ythickness;
    gboolean units_drawn;
    GtkWidget *widget;
    GdkGC *gc;
    gint digit_width, digit_xoffset;
    const gchar *utf8p, *utf8next;
    gint ascent, descent, ypos;
    struct { GwyScaleScale scale; double base; } tick_info[4];

    widget = GTK_WIDGET(ruler);
    xthickness = widget->style->xthickness;
    ythickness = widget->style->ythickness;

    format = ruler->vformat;
    upper = ruler->upper;
    lower = ruler->lower;
    if (upper <= lower || pixelsize < 2 || pixelsize > 10000)
        return;
    max = ruler->max_size;
    if (max == 0)
        max = MAX(fabs(lower), fabs(upper));

    range = upper - lower;
    measure = range/format->magnitude / pixelsize;
    max /= format->magnitude;

    switch (ruler->units_placement && ruler->units) {
        case GWY_UNITS_PLACEMENT_AT_ZERO:
        unit_str
            = g_strdup_printf("%d %s",
                              (lower > 0) ? (gint)(lower/format->magnitude) : 0,
                              format->units);
        break;

        default:
        unit_str = g_strdup_printf("%d", (gint)max);
        break;
    }

    layout = gtk_widget_create_pango_layout(widget, "012456789");
    pango_layout_get_extents(layout, NULL, &rect);

    digit_width = PANGO_PIXELS(rect.width)/10 + 1;
    digit_xoffset = rect.x;

    pango_layout_set_markup(layout, unit_str, -1);
    pango_layout_get_extents(layout, &rect, NULL);
    ascent = PANGO_ASCENT(rect);
    descent = PANGO_DESCENT(rect);

    text_size = g_utf8_strlen(pango_layout_get_text(layout), -1);
    text_size = PANGO_PIXELS(ascent + descent)*text_size;

    /* reallocate unit_str with some margin */
    unitstr_len = strlen(unit_str) + 16;
    unit_str = g_renew(gchar, unit_str, unitstr_len);

    /* fit as many labels as you can */
    labels = floor(pixelsize/(text_size + ythickness + min_label_spacing));
    labels = MAX(labels, 1);
    if (labels > 6)
        labels = 6 + (labels - 5)/2;

    step = range/format->magnitude / labels;
    base = compute_base(step, 10);
    step /= base;
    if (step >= 5.0 || base < 1.0) {
        scale = GWY_SCALE_1;
        base *= 10;
    }
    else if (step >= 2.5)
        scale = GWY_SCALE_5;
    else if (step >= 2.0)
        scale = GWY_SCALE_2_5;
    else
        scale = GWY_SCALE_2;
    step = steps[scale];

    /* draw labels */
    width = widget->allocation.width - 2*xthickness;
    units_drawn = FALSE;
    first = floor(lower/format->magnitude / (base*step))*base*step;
    for (i = 0; ; i++) {
        gint pos;
        gdouble val;

        val = i*step*base + first;
        pos = floor((val - lower/format->magnitude)/measure);
        if (pos >= pixelsize)
            break;
        if (pos < 0)
            continue;
        if (!units_drawn
            && (upper < 0 || val >= 0)
            && ruler->units_placement == GWY_UNITS_PLACEMENT_AT_ZERO
            && ruler->units) {
            g_snprintf(unit_str, unitstr_len, "%d %s",
                       ROUND(val), format->units);
            units_drawn = TRUE;
        }
        else
            g_snprintf(unit_str, unitstr_len, "%d", ROUND(val));

        pango_layout_set_markup(layout, unit_str, -1);
        utf8p = unit_str;
        utf8next = g_utf8_next_char(utf8p);
        j = 0;
        ypos = pos + ythickness + 1;
        while (*utf8p) {
            pango_layout_set_text(layout, utf8p, utf8next - utf8p);
            pango_layout_get_extents(layout, &rect, NULL);
            gtk_paint_layout(widget->style,
                             ruler->backing_store,
                             GTK_WIDGET_STATE(widget),
                             FALSE,
                             NULL,
                             widget,
                             "vruler",
                             xthickness + 1 + PANGO_PIXELS(digit_xoffset),
                             ypos,
                             layout);
            utf8p = utf8next;
            utf8next = g_utf8_next_char(utf8p);
            ypos += PANGO_PIXELS(PANGO_ASCENT(rect) + PANGO_DESCENT(rect)) + 2;
            j++;
        }
    }

    /* draw tick marks, from smallest to largest */
    scale_depth = 0;
    while (scale && scale_depth < (gint)G_N_ELEMENTS(tick_info)) {
        tick_info[scale_depth].scale = scale;
        tick_info[scale_depth].base = base;
        scale = next_scale(scale, &base, measure, min_tick_spacing);
        scale_depth++;
    }
    scale_depth--;

    gc = widget->style->fg_gc[GTK_STATE_NORMAL];
    while (scale_depth > -1) {
        tick_length = width/(scale_depth + 1) - 2;
        scale = tick_info[scale_depth].scale;
        base = tick_info[scale_depth].base;
        step = steps[scale];
        first = floor(lower/format->magnitude / (base*step))*base*step;
        for (i = 0; ; i++) {
            gint pos;
            gdouble val;

            val = (i + 0.000001)*step*base + first;
            pos = floor((val - lower/format->magnitude)/measure);
            if (pos >= pixelsize)
                break;
            if (pos < 0)
                continue;

            gdk_draw_line(ruler->backing_store, gc,
                          width + xthickness - tick_length, pos,
                          width + xthickness, pos);
        }
        scale_depth--;
    }

    g_free(unit_str);
    g_object_unref(layout);
}
Esempio n. 2
0
IMPCORE_BEGIN_INTERNAL_NAMESPACE

Referential::Referential(Model* m, ParticleIndex pi)
    : m_(m), pi_(pi), centroid_(compute_centroid()), base_(compute_base()),
      q_(compute_quaternion()) {}