Esempio n. 1
0
/* A convenience function for when one needs to coerce an image
 * surface to an alternate format. */
cairo_image_surface_t *
_cairo_image_surface_clone (cairo_image_surface_t	*surface,
			    cairo_format_t		 format)
{
    cairo_image_surface_t *clone;
    cairo_status_t status;
    cairo_t *cr;
    double x, y;

    clone = (cairo_image_surface_t *)
	cairo_image_surface_create (format,
				    surface->width, surface->height);

    cairo_surface_get_device_offset (&surface->base, &x, &y);
    cairo_surface_set_device_offset (&clone->base, x, y);
    clone->transparency = CAIRO_IMAGE_UNKNOWN;

    /* XXX Use _cairo_surface_composite directly */
    cr = cairo_create (&clone->base);
    cairo_set_source_surface (cr, &surface->base, 0, 0);
    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
    cairo_paint (cr);
    status = cairo_status (cr);
    cairo_destroy (cr);

    if (status) {
	cairo_surface_destroy (&clone->base);
	return (cairo_image_surface_t *) _cairo_surface_create_in_error (status);
    }

    return clone;
}
Esempio n. 2
0
gfxPoint
gfxASurface::GetDeviceOffset() const
{
    gfxPoint pt;
    cairo_surface_get_device_offset(mSurface, &pt.x, &pt.y);
    return pt;
}
Esempio n. 3
0
static PyObject *
surface_get_device_offset (PycairoSurface *o)
{
    double x_offset, y_offset;
    cairo_surface_get_device_offset (o->surface, &x_offset, &y_offset);
    return Py_BuildValue("(dd)", x_offset, y_offset);
}
Esempio n. 4
0
already_AddRefed<gfxASurface>
gfxContext::CurrentSurface(gfxFloat *dx, gfxFloat *dy)
{
    cairo_surface_t *s = cairo_get_group_target(mCairo);
    if (s == mSurface->CairoSurface()) {
        if (dx && dy)
            cairo_surface_get_device_offset(s, dx, dy);
        gfxASurface *ret = mSurface;
        NS_ADDREF(ret);
        return ret;
    }

    if (dx && dy)
        cairo_surface_get_device_offset(s, dx, dy);
    return gfxASurface::Wrap(s);
}
Esempio n. 5
0
IoObject *IoCairoSurface_getDeviceOffset(IoCairoSurface *self, IoObject *locals, IoMessage *m)
{
	double x = 0, y = 0;

	cairo_surface_get_device_offset(SURFACE(self), &x, &y);
	CHECK_STATUS(self);
	return IoSeq_newWithX_y_(IOSTATE, x, y);
}
Esempio n. 6
0
static cairo_test_status_t
test_cairo_surface_get_device_offset (cairo_surface_t *surface)
{
    double x, y;

    cairo_surface_get_device_offset (surface, &x, &y);
    return CAIRO_TEST_SUCCESS;
}
Esempio n. 7
0
static int
surface_get_device_offset (lua_State *L) {
    cairo_surface_t **obj = luaL_checkudata(L, 1, OOCAIRO_MT_NAME_SURFACE);
    double x, y;
    cairo_surface_get_device_offset(*obj, &x, &y);
    lua_pushnumber(L, x);
    lua_pushnumber(L, y);
    return 2;
}
Esempio n. 8
0
static VALUE
cr_surface_get_device_offset (VALUE self)
{
  double x_offset, y_offset;

  cairo_surface_get_device_offset (_SELF, &x_offset, &y_offset);
  cr_surface_check_status (_SELF);
  return rb_ary_new3 (2, rb_float_new (x_offset), rb_float_new (y_offset));
}
Esempio n. 9
0
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    cairo_surface_t *group;
    double x, y;

    /* First paint background in blue. */
    cairo_set_source_rgb (cr, 0.0, 0.0, 1.0);
    cairo_paint (cr);

    /* Then clip so that the group surface ends up smaller than the
     * original surface. */
    cairo_rectangle (cr, PAD, PAD, width - 2 * PAD, height - 2 * PAD);
    cairo_clip (cr);

    /* Paint the clipped region in red (which should all be overwritten later). */
    cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
    cairo_paint (cr);

    /* Redirect to a new group and get that surface. */
    cairo_push_group (cr);
    group = cairo_get_group_target (cr);

    /* Then paint in green what we query the group surface size to be. */
    cairo_set_source_rgb (cr, 0.0, 1.0, 0.0);
    cairo_surface_get_device_offset (group, &x, &y);
    /* Or rather, we calculate the group surface size based on the
     * only thing we can query which is the device offset. Ideally,
     * the size would always be the minimal (width - 2 * PAD, height -
     * 2 * PAD) based on the clip. But currently, group targets are
     * created oversized for paginated surfaces, so we only subtract
     * anything from the size if there is a non-zero device offfset.
     *
     * The calculation below might also be less confusing if the sign
     * convention on the device offset were reversed, but it is what
     * it is. Oh well. */
    cairo_rectangle (cr,
		     -x, -y,
		     width + 2 * x,
		     height + 2 * y);
    cairo_fill (cr);

    /* Finish up the group painting. */
    cairo_pop_group_to_source (cr);
    cairo_paint (cr);

    return CAIRO_TEST_SUCCESS;
}
Esempio n. 10
0
cairo_surface_t *
Context::Surface::Cairo ()
{
	if (!surface) {
		surface = native->Cairo ();

		/* replace device offset */
		if (!box.IsEmpty ()) {
			cairo_surface_get_device_offset (surface,
							 &device_offset.x,
							 &device_offset.y);
			cairo_surface_set_device_offset (surface,
							 -box.x,
							 -box.y);
		}
	}

	return cairo_surface_reference (surface);
}
Esempio n. 11
0
static SeedValue
seed_cairo_surface_get_device_offset(SeedContext ctx,
				     SeedObject this_object,
				     SeedString property_name,
				     SeedException *exception)
{
  SeedValue offsets[2];
  cairo_surface_t *surf;
  gdouble x, y;
  CHECK_THIS();

  surf = seed_object_to_cairo_surface (ctx, this_object, exception);
  cairo_surface_get_device_offset (surf, &x, &y);

  offsets[0] = seed_value_from_double (ctx, x, exception);
  offsets[1] = seed_value_from_double (ctx, y, exception);

  return seed_make_array (ctx, offsets, 2, exception);
}
/**
 * Try the direct path.
 * @return True if we took the direct path
 */
bool
gfxXlibNativeRenderer::DrawDirect(gfxContext *ctx, nsIntSize size,
                                  PRUint32 flags,
                                  Screen *screen, Visual *visual)
{
    cairo_t *cr = ctx->GetCairo();

    /* Check that the target surface is an xlib surface. */
    cairo_surface_t *target = cairo_get_group_target (cr);
    if (cairo_surface_get_type (target) != CAIRO_SURFACE_TYPE_XLIB) {
        NATIVE_DRAWING_NOTE("FALLBACK: non-X surface");
        return false;
    }
    
    cairo_matrix_t matrix;
    cairo_get_matrix (cr, &matrix);
    double device_offset_x, device_offset_y;
    cairo_surface_get_device_offset (target, &device_offset_x, &device_offset_y);

    /* Draw() checked that the matrix contained only a very-close-to-integer
       translation.  Here (and in several other places and thebes) device
       offsets are assumed to be integer. */
    NS_ASSERTION(PRInt32(device_offset_x) == device_offset_x &&
                 PRInt32(device_offset_y) == device_offset_y,
                 "Expected integer device offsets");
    nsIntPoint offset(NS_lroundf(matrix.x0 + device_offset_x),
                      NS_lroundf(matrix.y0 + device_offset_y));
    
    int max_rectangles = 0;
    if (flags & DRAW_SUPPORTS_CLIP_RECT) {
      max_rectangles = 1;
    }
    if (flags & DRAW_SUPPORTS_CLIP_LIST) {
      max_rectangles = MAX_STATIC_CLIP_RECTANGLES;
    }

    /* The client won't draw outside the surface so consider this when
       analysing clip rectangles. */
    nsIntRect bounds(offset, size);
    bounds.IntersectRect(bounds,
                         nsIntRect(0, 0,
                                   cairo_xlib_surface_get_width(target),
                                   cairo_xlib_surface_get_height(target)));

    bool needs_clip = true;
    nsIntRect rectangles[MAX_STATIC_CLIP_RECTANGLES];
    int rect_count = 0;

    /* Check that the clip is rectangular and aligned on unit boundaries. */
    /* Temporarily set the matrix for _get_rectangular_clip. It's basically
       the identity matrix, but we must adjust for the fact that our
       offset-rect is in device coordinates. */
    cairo_identity_matrix (cr);
    cairo_translate (cr, -device_offset_x, -device_offset_y);
    bool have_rectangular_clip =
        _get_rectangular_clip (cr, bounds, &needs_clip,
                               rectangles, max_rectangles, &rect_count);
    cairo_set_matrix (cr, &matrix);
    if (!have_rectangular_clip)
        return false;

    /* Stop now if everything is clipped out */
    if (needs_clip && rect_count == 0)
        return true;
      
    /* Check that the screen is supported.
       Visuals belong to screens, so, if alternate visuals are not supported,
       then alternate screens cannot be supported. */  
    bool supports_alternate_visual =
        (flags & DRAW_SUPPORTS_ALTERNATE_VISUAL) != 0;
    bool supports_alternate_screen = supports_alternate_visual &&
        (flags & DRAW_SUPPORTS_ALTERNATE_SCREEN);
    if (!supports_alternate_screen &&
        cairo_xlib_surface_get_screen (target) != screen) {
        NATIVE_DRAWING_NOTE("FALLBACK: non-default screen");
        return false;
    }
        
    /* Check that there is a visual */
    Visual *target_visual = cairo_xlib_surface_get_visual (target);
    if (!target_visual) {
        NATIVE_DRAWING_NOTE("FALLBACK: no Visual for surface");
        return false;
    }        
    /* Check that the visual is supported */
    if (!supports_alternate_visual && target_visual != visual) {
        // Only the format of the visual is important (not the GLX properties)
        // for Xlib or XRender drawing.
        XRenderPictFormat *target_format =
            cairo_xlib_surface_get_xrender_format (target);
        if (!target_format ||
            (target_format !=
             XRenderFindVisualFormat (DisplayOfScreen(screen), visual))) {
            NATIVE_DRAWING_NOTE("FALLBACK: unsupported Visual");
            return false;
        }
    }
  
    /* we're good to go! */
    NATIVE_DRAWING_NOTE("TAKING FAST PATH\n");
    cairo_surface_flush (target);
    nsRefPtr<gfxASurface> surface = gfxASurface::Wrap(target);
    nsresult rv = DrawWithXlib(static_cast<gfxXlibSurface*>(surface.get()),
                               offset, rectangles,
                               needs_clip ? rect_count : 0);
    if (NS_SUCCEEDED(rv)) {
        cairo_surface_mark_dirty (target);
        return true;
    }
    return false;
}
Esempio n. 13
0
/* This is always called with the paint context current */
void
gdk_gl_texture_from_surface (cairo_surface_t *surface,
                             cairo_region_t  *region)
{
    GdkGLContext *paint_context;
    cairo_surface_t *image;
    double device_x_offset, device_y_offset;
    cairo_rectangle_int_t rect, e;
    int n_rects, i;
    GdkWindow *window;
    int unscaled_window_height;
    unsigned int texture_id;
    int window_scale;
    double sx, sy;
    float umax, vmax;
    gboolean use_texture_rectangle;
    guint target;
    paint_context = gdk_gl_context_get_current ();
    if ((_gdk_gl_flags & GDK_GL_SOFTWARE_DRAW_SURFACE) == 0 &&
            paint_context &&
            GDK_GL_CONTEXT_GET_CLASS (paint_context)->texture_from_surface &&
            GDK_GL_CONTEXT_GET_CLASS (paint_context)->texture_from_surface (paint_context, surface, region))
        return;

    /* Software fallback */
    use_texture_rectangle = gdk_gl_context_use_texture_rectangle (paint_context);

    window = gdk_gl_context_get_window (paint_context);
    window_scale = gdk_window_get_scale_factor (window);
    gdk_window_get_unscaled_size (window, NULL, &unscaled_window_height);

    sx = sy = 1;
    cairo_surface_get_device_scale (window->current_paint.surface, &sx, &sy);

    cairo_surface_get_device_offset (surface,
                                     &device_x_offset, &device_y_offset);

    glGenTextures (1, &texture_id);
    if (use_texture_rectangle)
        target = GL_TEXTURE_RECTANGLE_ARB;
    else
        target = GL_TEXTURE_2D;

    glBindTexture (target, texture_id);
    glEnable (GL_SCISSOR_TEST);

    glTexParameteri (target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri (target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    n_rects = cairo_region_num_rectangles (region);

#define FLIP_Y(_y) (unscaled_window_height - (_y))

    for (i = 0; i < n_rects; i++)
    {
        cairo_region_get_rectangle (region, i, &rect);

        glScissor (rect.x * window_scale, FLIP_Y ((rect.y + rect.height) * window_scale),
                   rect.width * window_scale, rect.height * window_scale);

        e = rect;
        e.x *= sx;
        e.y *= sy;
        e.x += (int)device_x_offset;
        e.y += (int)device_y_offset;
        e.width *= sx;
        e.height *= sy;
        image = cairo_surface_map_to_image (surface, &e);

        gdk_gl_context_upload_texture (paint_context, image, e.width, e.height, target);

        cairo_surface_unmap_image (surface, image);

        if (use_texture_rectangle)
        {
            umax = rect.width * sx;
            vmax = rect.height * sy;
        }
        else
        {
            umax = 1.0;
            vmax = 1.0;
        }

        {
            GdkTexturedQuad quad = {
                rect.x * window_scale, FLIP_Y(rect.y * window_scale),
                (rect.x + rect.width) * window_scale, FLIP_Y((rect.y + rect.height) * window_scale),
                0, 0,
                umax, vmax,
            };

            /* We don't want to combine the quads here, because they have different textures.
             * And we don't want to upload the unused source areas to make it one texture. */
            gdk_gl_texture_quads (paint_context, target, 1, &quad);
        }
    }

#undef FLIP_Y

    glDisable (GL_SCISSOR_TEST);
    glDeleteTextures (1, &texture_id);
}
/**
 * Try the direct path.
 * @param status the status returned by the callback, if we took the direct path
 * @return True if we took the direct path
 */
static cairo_bool_t
_draw_with_xlib_direct (cairo_t *cr,
                        Display *default_display,
                        cairo_xlib_drawing_callback callback,
                        void *closure,
                        int bounds_width, int bounds_height,
                        cairo_xlib_drawing_support_t capabilities)
{
    cairo_surface_t *target;
    Drawable d;
    cairo_matrix_t matrix;
    short offset_x, offset_y;
    cairo_bool_t needs_clip;
    XRectangle rectangles[MAX_STATIC_CLIP_RECTANGLES];
    int rect_count;
    double device_offset_x, device_offset_y;
    int max_rectangles;
    Screen *screen;
    Visual *visual;
    cairo_bool_t have_rectangular_clip;

    target = cairo_get_group_target (cr);
    cairo_surface_get_device_offset (target, &device_offset_x, &device_offset_y);
    d = cairo_xlib_surface_get_drawable (target);

    cairo_get_matrix (cr, &matrix);
    
    /* Check that the matrix is a pure translation */
    /* XXX test some approximation to == 1.0 here? */
    if (matrix.xx != 1.0 || matrix.yy != 1.0 || matrix.xy != 0.0 || matrix.yx != 0.0) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: matrix not a pure translation\n");
        return False;
    }
    /* Check that the matrix translation offsets (adjusted for
       device offset) are integers */
    if (!_convert_coord_to_short (matrix.x0 + device_offset_x, &offset_x) ||
        !_convert_coord_to_short (matrix.y0 + device_offset_y, &offset_y)) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: non-integer offset\n");
        return False;
    }
    
    max_rectangles = 0;
    if (capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_CLIP_RECT) {
      max_rectangles = 1;
    }
    if (capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_CLIP_LIST) {
      max_rectangles = MAX_STATIC_CLIP_RECTANGLES;
    }
    
    /* Check that the clip is rectangular and aligned on unit boundaries. */
    /* Temporarily set the matrix for _get_rectangular_clip. It's basically
       the identity matrix, but we must adjust for the fact that our
       offset-rect is in device coordinates. */
    cairo_identity_matrix (cr);
    cairo_translate (cr, -device_offset_x, -device_offset_y);
    have_rectangular_clip =
        _get_rectangular_clip (cr,
                               offset_x, offset_y, bounds_width, bounds_height,
                               &needs_clip,
                               rectangles, max_rectangles, &rect_count);
    cairo_set_matrix (cr, &matrix);
    if (!have_rectangular_clip) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: unsupported clip\n");
        return False;
    }

    /* Stop now if everything is clipped out */
    if (needs_clip && rect_count == 0) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING FAST PATH: all clipped\n");
        return True;
    }
      
    /* Check that the operator is OVER */
    if (cairo_get_operator (cr) != CAIRO_OPERATOR_OVER) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: non-OVER operator\n");
        return False;
    }
    
    /* Check that the offset is supported */  
    if (!(capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_OFFSET) &&
        (offset_x != 0 || offset_y != 0)) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: unsupported offset\n");
        return False;
    }
    
    /* Check that the target surface is an xlib surface. Do this late because
       we might complete early above when when the object to be drawn is
       completely clipped out. */
    if (!d) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: non-X surface\n");
        return False;
    }
    
    /* Check that the display is supported */  
    screen = cairo_xlib_surface_get_screen (target);
    if (!(capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_ALTERNATE_SCREEN) &&
        screen != DefaultScreenOfDisplay (default_display)) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: non-default display\n");
        return False;
    }
        
    /* Check that there is a visual */
    visual = cairo_xlib_surface_get_visual (target);
    if (!visual) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: no Visual for surface\n");
        return False;
    }        
    /* Check that the visual is supported */
    if (!(capabilities & CAIRO_XLIB_DRAWING_SUPPORTS_NONDEFAULT_VISUAL) &&
        DefaultVisualOfScreen (screen) != visual) {
        CAIRO_XLIB_DRAWING_NOTE("TAKING SLOW PATH: non-default visual\n");
        return False;
    }
  
    /* we're good to go! */
    CAIRO_XLIB_DRAWING_NOTE("TAKING FAST PATH\n");
    cairo_surface_flush (target);
    callback (closure, screen, d, visual, offset_x, offset_y, rectangles,
              needs_clip ? rect_count : 0);
    cairo_surface_mark_dirty (target);
    return True;
}