Пример #1
0
static gboolean
_adg_get_map(GtkWidget *widget, gboolean local_space,
             cairo_matrix_t *map, cairo_matrix_t *inverted)
{
    AdgGtkAreaPrivate *data;
    AdgEntity *entity;

    data = ((AdgGtkArea *) widget)->data;
    entity = (AdgEntity *) data->canvas;
    if (entity == NULL)
        return FALSE;

    if (local_space) {
        adg_matrix_copy(map, adg_entity_get_local_map(entity));

        /* The inverted map is subject to the global matrix */
        adg_matrix_copy(inverted, adg_entity_get_global_matrix(entity));
        adg_matrix_transform(inverted, map, ADG_TRANSFORM_BEFORE);
    } else {
        adg_matrix_copy(map, adg_entity_get_global_map(entity));
        adg_matrix_copy(inverted, map);
    }

    return cairo_matrix_invert(inverted) == CAIRO_STATUS_SUCCESS;
}
Пример #2
0
static void
_adg_arrange(AdgEntity *entity)
{
    AdgAlignmentPrivate *data;
    const CpmlExtents *extents;
    CpmlExtents new_extents;
    cairo_matrix_t ctm, ctm_inverted, old_map;

    if (_ADG_OLD_ENTITY_CLASS->arrange == NULL)
        return;

    data = adg_alignment_get_instance_private((AdgAlignment *) entity);
    extents = adg_entity_get_extents(entity);
    data->shift.x = 0;
    data->shift.y = 0;

    /* The shift is performed only when relevant */
    if (data->factor.x != 0 || data->factor.y != 0) {
        /* Force the ctm to be the identity matrix */
        adg_matrix_copy(&old_map, adg_entity_get_global_map(entity));
        adg_matrix_copy(&ctm, adg_entity_get_global_map(entity));
        adg_matrix_transform(&ctm, adg_entity_get_local_matrix(entity),
                             ADG_TRANSFORM_AFTER);
        adg_matrix_copy(&ctm_inverted, &ctm);
        cairo_matrix_invert(&ctm_inverted);
        adg_entity_transform_global_map(entity, &ctm_inverted,
                                        ADG_TRANSFORM_AFTER);
        adg_entity_global_changed(entity);

        /* Calculating the shift */
        _ADG_OLD_ENTITY_CLASS->arrange(entity);
        extents = adg_entity_get_extents(entity);
        if (extents->is_defined) {
            data->shift.x = -extents->size.x * data->factor.x;
            data->shift.y = -extents->size.y * data->factor.y;
            cpml_vector_transform(&data->shift, &ctm);
        }

        /* Restore the old global map */
        adg_entity_set_global_map(entity, &old_map);
        adg_entity_global_changed(entity);
    }

    /* Add the shift to the extents */
    _ADG_OLD_ENTITY_CLASS->arrange(entity);
    cpml_extents_copy(&new_extents, adg_entity_get_extents(entity));
    new_extents.org.x += data->shift.x;
    new_extents.org.y += data->shift.y;
    adg_entity_set_extents(entity, &new_extents);
}
Пример #3
0
static void
_adg_set_property(GObject *object, guint prop_id,
                  const GValue *value, GParamSpec *pspec)
{
    AdgGtkAreaPrivate *data = adg_gtk_area_get_instance_private((AdgGtkArea *) object);
    AdgCanvas *new_canvas, *old_canvas;

    switch (prop_id) {
    case PROP_CANVAS:
        new_canvas = g_value_get_object(value);
        old_canvas = data->canvas;
        if (new_canvas != old_canvas) {
            if (new_canvas != NULL)
                g_object_ref(new_canvas);
            if (old_canvas != NULL)
                g_object_unref(old_canvas);
            data->canvas = new_canvas;
            g_signal_emit(object, _adg_signals[CANVAS_CHANGED], 0, old_canvas);
        }
        break;
    case PROP_FACTOR:
        data->factor = g_value_get_double(value);
        break;
    case PROP_AUTOZOOM:
        data->autozoom = g_value_get_boolean(value);
        break;
    case PROP_RENDER_MAP:
        adg_matrix_copy(&data->render_map, g_value_get_boxed(value));
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
        break;
    }
}
Пример #4
0
/**
 * adg_gtk_area_transform_render_map:
 * @area: an #AdgGtkArea object
 * @transformation: the transformation to apply
 * @mode: how @transformation should be applied
 *
 * Convenient function to change the render map of @area by
 * applying @tranformation using the @mode operator. This is
 * logically equivalent to the following:
 *
 * <informalexample><programlisting language="C">
 * cairo_matrix_t map;
 * adg_matrix_copy(&map, adg_gtk_area_get_render_map(area));
 * adg_matrix_transform(&map, transformation, mode);
 * adg_gtk_area_set_render_map(area, &map);
 * </programlisting></informalexample>
 *
 * <note><para>
 * The render map is an implementation detail and this function
 * is expected to be used only by #AdgGtkArea derived objects.
 * </para></note>
 *
 * Since: 1.0
 **/
void
adg_gtk_area_transform_render_map(AdgGtkArea *area,
                                  const cairo_matrix_t *transformation,
                                  AdgTransformMode mode)
{
    AdgGtkAreaPrivate *data;
    cairo_matrix_t map;

    g_return_if_fail(ADG_GTK_IS_AREA(area));
    g_return_if_fail(transformation != NULL);

    data = adg_gtk_area_get_instance_private(area);

    adg_matrix_copy(&map, &data->render_map);
    adg_matrix_transform(&map, transformation, mode);

    g_object_set(area, "render-map", &map, NULL);
}
Пример #5
0
static void
_adg_arrange(AdgEntity *entity)
{
    AdgADim *adim;
    AdgDim *dim;
    AdgADimPrivate *data;
    AdgAlignment *quote;
    const cairo_matrix_t *global, *local;
    CpmlPair ref1, ref2, base1, base12, base2;
    CpmlPair pair;
    CpmlExtents extents;
    AdgEntity *marker_entity;

    if (_ADG_OLD_ENTITY_CLASS->arrange)
        _ADG_OLD_ENTITY_CLASS->arrange(entity);

    adim = (AdgADim *) entity;

    if (! _adg_update_geometry(adim))
        return;

    dim = (AdgDim *) adim;
    data = adim->data;
    quote = adg_dim_get_quote(dim);

    _adg_update_entities(adim);

    if (data->cairo.path.status == CAIRO_STATUS_SUCCESS) {
        AdgEntity *quote_entity = (AdgEntity *) quote;
        adg_entity_set_global_map(quote_entity, &data->quote.global_map);
        return;
    }

    global = adg_entity_get_global_matrix(entity);
    local = adg_entity_get_local_matrix(entity);
    extents.is_defined = FALSE;

    cpml_pair_copy(&ref1, (CpmlPair *) adg_dim_get_ref1(dim));
    cpml_pair_copy(&ref2, (CpmlPair *) adg_dim_get_ref2(dim));
    cpml_pair_copy(&base1, &data->point.base1);
    cpml_pair_copy(&base12, &data->point.base12);
    cpml_pair_copy(&base2, &data->point.base2);

    /* Apply the local matrix to the relevant points */
    cpml_pair_transform(&ref1, local);
    cpml_pair_transform(&ref2, local);
    cpml_pair_transform(&base1, local);
    cpml_pair_transform(&base12, local);
    cpml_pair_transform(&base2, local);

    /* Combine points and global shifts to build the path */
    pair.x = ref1.x + data->shift.from1.x;
    pair.y = ref1.y + data->shift.from1.y;
    cpml_pair_to_cairo(&pair, &data->cairo.data[6]);

    pair.x = base1.x + data->shift.base1.x;
    pair.y = base1.y + data->shift.base1.y;
    cpml_pair_to_cairo(&pair, &data->cairo.data[1]);

    pair.x += data->shift.to1.x;
    pair.y += data->shift.to1.y;
    cpml_pair_to_cairo(&pair, &data->cairo.data[8]);

    pair.x = base12.x + data->shift.base12.x;
    pair.y = base12.y + data->shift.base12.y;
    cpml_pair_to_cairo(&pair, &data->cairo.data[3]);

    pair.x = ref2.x + data->shift.from2.x;
    pair.y = ref2.y + data->shift.from2.y;
    cpml_pair_to_cairo(&pair, &data->cairo.data[10]);

    pair.x = base2.x + data->shift.base2.x;
    pair.y = base2.y + data->shift.base2.y;
    cpml_pair_to_cairo(&pair, &data->cairo.data[4]);

    pair.x += data->shift.to2.x;
    pair.y += data->shift.to2.y;
    cpml_pair_to_cairo(&pair, &data->cairo.data[12]);

    /* Play with header lengths to show or hide the extension lines */
    if (data->has_extension1) {
        data->cairo.data[7].header.length = data->has_extension2 ? 2 : 6;
    } else {
        data->cairo.data[2].header.length = data->has_extension2 ? 7 : 11;
    }

    data->cairo.path.status = CAIRO_STATUS_SUCCESS;

    /* Arrange the quote */
    if (quote != NULL) {
        AdgEntity *quote_entity;
        gdouble angle;
        cairo_matrix_t map;

        quote_entity = (AdgEntity *) quote;
        angle = adg_dim_quote_angle(dim, (data->angle1 + data->angle2) / 2 + G_PI_2);
        cpml_pair_from_cairo(&pair, &data->cairo.data[3]);

        adg_alignment_set_factor_explicit(quote, 0.5, 0);

        cairo_matrix_init_translate(&map, pair.x, pair.y);
        cairo_matrix_rotate(&map, angle);
        adg_entity_set_global_map(quote_entity, &map);
        adg_entity_arrange(quote_entity);
        cpml_extents_add(&extents, adg_entity_get_extents(quote_entity));

        adg_matrix_copy(&data->quote.global_map, &map);
    }

    /* Arrange the trail */
    if (data->trail != NULL) {
        CpmlExtents trail_extents;
        cpml_extents_copy(&trail_extents, adg_trail_get_extents(data->trail));
        cpml_extents_transform(&trail_extents, global);
        cpml_extents_add(&extents, &trail_extents);
    } else {
        _adg_dispose_markers(adim);
    }

    /* Arrange the markers */
    if (data->marker1 != NULL) {
        marker_entity = (AdgEntity *) data->marker1;
        adg_marker_set_segment(data->marker1, data->trail, 1);
        adg_entity_local_changed(marker_entity);
        adg_entity_arrange(marker_entity);
        cpml_extents_add(&extents, adg_entity_get_extents(marker_entity));
    }
    if (data->marker2 != NULL) {
        marker_entity = (AdgEntity *) data->marker2;
        adg_marker_set_segment(data->marker2, data->trail, 1);
        adg_entity_local_changed(marker_entity);
        adg_entity_arrange(marker_entity);
        cpml_extents_add(&extents, adg_entity_get_extents(marker_entity));
    }

    adg_entity_set_extents(entity, &extents);
}