Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/gfx/cairo/cairo/src/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 17 kB image not shown  

Quelle  cairo-xcb-surface-core.c   Sprache: C

 
/* cairo - a vector graphics library with display and print output
 *
 * Copyright © 2009 Intel Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it either under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation
 * (the "LGPL") or, at your option, under the terms of the Mozilla
 * Public License Version 1.1 (the "MPL"). If you do not alter this
 * notice, a recipient may use your version of this file under either
 * the MPL or the LGPL.
 *
 * You should have received a copy of the LGPL along with this library
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
 * You should have received a copy of the MPL along with this library
 * in the file COPYING-MPL-1.1
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
 * the specific language governing rights and limitations.
 *
 * Contributor(s):
 * Chris Wilson <chris@chris-wilson.co.uk>
 */


#include "cairoint.h"

#include "cairo-boxes-private.h"
#include "cairo-xcb-private.h"
#include "cairo-image-surface-private.h"
#include "cairo-surface-backend-private.h"

/* XXX dithering */

typedef struct _cairo_xcb_pixmap {
    cairo_surface_t base;

    cairo_xcb_connection_t *connection;
    cairo_xcb_screen_t *screen;

    cairo_surface_t *owner;
    xcb_pixmap_t pixmap;
    int width;
    int height;
    int depth;
    int x0, y0;
    cairo_bool_t repeat;
} cairo_xcb_pixmap_t;

static cairo_status_t
_cairo_xcb_pixmap_finish (void *abstract_surface)
{
    cairo_xcb_pixmap_t *surface = abstract_surface;
    cairo_status_t status;

    if (surface->owner != NULL) {
 cairo_surface_destroy (surface->owner);
    } else {
 status = _cairo_xcb_connection_acquire (surface->connection);
 if (unlikely (status))
     return status;

 xcb_free_pixmap (surface->connection->xcb_connection,
        surface->pixmap);
 _cairo_xcb_connection_release (surface->connection);
    }

    return CAIRO_STATUS_SUCCESS;
}

static const cairo_surface_backend_t _cairo_xcb_pixmap_backend = {
    CAIRO_SURFACE_TYPE_XCB,
    _cairo_xcb_pixmap_finish,
};

static cairo_xcb_pixmap_t *
_cairo_xcb_pixmap_create (cairo_xcb_surface_t *target,
     int width, int height)
{
    cairo_xcb_pixmap_t *surface;

    surface = _cairo_malloc (sizeof (cairo_xcb_pixmap_t));
    if (unlikely (surface == NULL))
 return (cairo_xcb_pixmap_t *)
     _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));

    _cairo_surface_init (&surface->base,
    &_cairo_xcb_pixmap_backend,
    NULL,
    target->base.content,
    FALSE); /* is_vector */

    surface->connection = target->connection;
    surface->screen = target->screen;
    surface->owner = NULL;
    surface->width = width;
    surface->height = height;
    surface->depth = target->depth;
    surface->x0 = surface->y0 = 0;
    surface->repeat = FALSE;

    surface->pixmap =
 _cairo_xcb_connection_create_pixmap (surface->connection,
          surface->depth,
          target->drawable,
          width, height);

    return surface;
}

static cairo_xcb_pixmap_t *
_cairo_xcb_pixmap_copy (cairo_xcb_surface_t *target)
{
    cairo_xcb_pixmap_t *surface;

    surface = _cairo_malloc (sizeof (cairo_xcb_pixmap_t));
    if (unlikely (surface == NULL))
 return (cairo_xcb_pixmap_t *)
     _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));

    _cairo_surface_init (&surface->base,
    &_cairo_xcb_pixmap_backend,
    NULL,
    target->base.content,
    FALSE); /* is_vector */

    surface->connection = target->connection;
    surface->screen = target->screen;
    surface->pixmap = target->drawable;
    surface->owner = cairo_surface_reference (&target->base);
    surface->width = target->width;
    surface->height = target->height;
    surface->depth = target->depth;
    surface->x0 = surface->y0 = 0;
    surface->repeat = FALSE;

    return surface;
}

#if CAIRO_HAS_XCB_SHM_FUNCTIONS
static cairo_status_t
_cairo_xcb_shm_image_create_shm (cairo_xcb_connection_t *connection,
     pixman_format_code_t pixman_format,
     int width, int height,
     cairo_image_surface_t **image_out,
     cairo_xcb_shm_info_t **shm_info_out)
{
    cairo_surface_t *image = NULL;
    cairo_xcb_shm_info_t *shm_info = NULL;
    cairo_status_t status;
    size_t size, stride;

    if (! (connection->flags & CAIRO_XCB_HAS_SHM))
 return CAIRO_INT_STATUS_UNSUPPORTED;

    if (unlikely (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX))
 return CAIRO_INT_STATUS_UNSUPPORTED;

    stride = CAIRO_STRIDE_FOR_WIDTH_BPP (width, PIXMAN_FORMAT_BPP (pixman_format));
    size = stride * height;
    if (size <= CAIRO_XCB_SHM_SMALL_IMAGE)
 return CAIRO_INT_STATUS_UNSUPPORTED;

    status = _cairo_xcb_connection_allocate_shm_info (connection, size,
            FALSE, &shm_info);
    if (unlikely (status))
 return status;

    image = _cairo_image_surface_create_with_pixman_format (shm_info->mem,
           pixman_format,
           width, height,
           stride);
    status = image->status;
    if (unlikely (status)) {
 _cairo_xcb_shm_info_destroy (shm_info);
 return status;
    }

    status = _cairo_user_data_array_set_data (&image->user_data,
           (const cairo_user_data_key_t *) connection,
           shm_info,
           (cairo_destroy_func_t) _cairo_xcb_shm_info_destroy);

    if (unlikely (status)) {
 cairo_surface_destroy (image);
 _cairo_xcb_shm_info_destroy (shm_info);
 return status;
    }

    *image_out = (cairo_image_surface_t *) image;
    *shm_info_out = shm_info;
    return CAIRO_STATUS_SUCCESS;
}
#else
static cairo_status_t
_cairo_xcb_shm_image_create_shm (cairo_xcb_connection_t *connection,
     pixman_format_code_t pixman_format,
     int width, int height,
     cairo_image_surface_t **image_out,
     cairo_xcb_shm_info_t **shm_info_out)
{
    return CAIRO_INT_STATUS_UNSUPPORTED;
}
#endif

cairo_status_t
_cairo_xcb_shm_image_create (cairo_xcb_connection_t *connection,
        pixman_format_code_t pixman_format,
        int width, int height,
        cairo_image_surface_t **image_out,
        cairo_xcb_shm_info_t **shm_info_out)
{
    cairo_surface_t *image = NULL;
    cairo_xcb_shm_info_t *shm_info = NULL;
    cairo_status_t status;

    status = _cairo_xcb_shm_image_create_shm (connection,
           pixman_format,
           width,
           height,
           image_out,
           shm_info_out);

    if (status != CAIRO_STATUS_SUCCESS) {
 image = _cairo_image_surface_create_with_pixman_format (NULL,
        pixman_format,
        width, height,
        0);
 status = image->status;
 if (unlikely (status))
     return status;

 *image_out = (cairo_image_surface_t *) image;
 *shm_info_out = shm_info;
    }

    return CAIRO_STATUS_SUCCESS;
}

static cairo_xcb_pixmap_t *
_pixmap_from_image (cairo_xcb_surface_t *target,
      xcb_render_pictformat_t format,
      cairo_image_surface_t *image,
      cairo_xcb_shm_info_t *shm_info)
{
    xcb_gcontext_t gc;
    cairo_xcb_pixmap_t *pixmap;

    pixmap = _cairo_xcb_pixmap_create (target,
           image->width,
           image->height);
    if (unlikely (pixmap->base.status))
 return pixmap;

    gc = _cairo_xcb_screen_get_gc (target->screen, pixmap->pixmap, image->depth);

    if (shm_info != NULL) {
 _cairo_xcb_connection_shm_put_image (target->connection,
          pixmap->pixmap, gc,
          image->width, image->height,
          0, 0,
          image->width, image->height,
          0, 0,
          image->depth,
          shm_info->shm,
          shm_info->offset);
    } else {
 int len;

 /* Do we need to trim the image? */
 len = CAIRO_STRIDE_FOR_WIDTH_BPP (image->width,
       PIXMAN_FORMAT_BPP (image->pixman_format));
 if (len == image->stride) {
     _cairo_xcb_connection_put_image (target->connection,
          pixmap->pixmap, gc,
          image->width, image->height,
          0, 0,
          image->depth,
          image->stride,
          image->data);
 } else {
     _cairo_xcb_connection_put_subimage (target->connection,
      pixmap->pixmap, gc,
      0, 0,
      image->width, image->height,
      PIXMAN_FORMAT_BPP (image->pixman_format) / 8,
      image->stride,
      0, 0,
      image->depth,
      image->data);

 }
    }

    _cairo_xcb_screen_put_gc (target->screen, image->depth, gc);

    return pixmap;
}

static cairo_xcb_pixmap_t *
_render_to_pixmap (cairo_xcb_surface_t *target,
     const cairo_pattern_t *pattern,
     const cairo_rectangle_int_t *extents)
{
    cairo_image_surface_t *image;
    cairo_xcb_shm_info_t *shm_info;
    cairo_pattern_union_t copy;
    cairo_status_t status;
    cairo_xcb_pixmap_t *pixmap;

    status = _cairo_xcb_shm_image_create (target->screen->connection,
       target->pixman_format,
       extents->width, extents->height,
       &image, &shm_info);
    if (unlikely (status))
 return (cairo_xcb_pixmap_t *) _cairo_surface_create_in_error (status);

    _cairo_pattern_init_static_copy (©.base, pattern);
    cairo_matrix_translate (©.base.matrix, -extents->x, -extents->y);
    status = _cairo_surface_paint (&image->base,
       CAIRO_OPERATOR_SOURCE,
       ©.base,
       NULL);
    if (unlikely (status)) {
 cairo_surface_destroy (&image->base);
 return (cairo_xcb_pixmap_t *) _cairo_surface_create_in_error (status);
    }

    pixmap = _pixmap_from_image (target, target->xrender_format, image, shm_info);
    cairo_surface_destroy (&image->base);

    if (unlikely (pixmap->base.status))
 return pixmap;

    pixmap->x0 = -extents->x;
    pixmap->y0 = -extents->y;
    return pixmap;
}

static cairo_xcb_pixmap_t *
_copy_to_pixmap (cairo_xcb_surface_t *source)
{
    cairo_xcb_pixmap_t *pixmap;

    /* If the source may be a window, we need to copy it and its children
     * via a temporary pixmap so that we can IncludeInferiors on the source
     * and use ClipByChildren on the destination.
     */

    if (source->owns_pixmap) {
 pixmap = _cairo_xcb_pixmap_copy (source);
 if (unlikely (pixmap->base.status))
     return pixmap;
    } else {
 uint32_t values[1];
 xcb_gcontext_t gc;

 pixmap = _cairo_xcb_pixmap_create (source,
        source->width,
        source->height);
 if (unlikely (pixmap->base.status))
     return pixmap;

 gc = _cairo_xcb_screen_get_gc (source->screen,
           pixmap->pixmap,
           pixmap->depth);

 values[0] = TRUE;
 _cairo_xcb_connection_change_gc (pixmap->connection, gc,
      XCB_GC_SUBWINDOW_MODE, values);

 _cairo_xcb_connection_copy_area (pixmap->connection,
      source->drawable,
      pixmap->pixmap, gc,
      0, 0,
      0, 0,
      source->width,
      source->height);

 values[0] = FALSE;
 _cairo_xcb_connection_change_gc (pixmap->connection, gc,
      XCB_GC_SUBWINDOW_MODE, values);

 _cairo_xcb_screen_put_gc (source->screen,
      pixmap->depth,
      gc);
    }

    return pixmap;
}
static cairo_xcb_pixmap_t *
_cairo_xcb_surface_pixmap (cairo_xcb_surface_t *target,
      const cairo_surface_pattern_t *pattern,
      const cairo_rectangle_int_t *extents,
      int tx, int ty)
{
    cairo_surface_t *source;
    cairo_xcb_pixmap_t *pixmap;

    source =  pattern->surface;
    pixmap = (cairo_xcb_pixmap_t *)
 _cairo_surface_has_snapshot (source, &_cairo_xcb_pixmap_backend);
    if (pixmap != NULL && pixmap->screen == target->screen)
 return (cairo_xcb_pixmap_t *) cairo_surface_reference (&pixmap->base);

    if (_cairo_surface_is_xcb(source) &&
 ((cairo_xcb_surface_t *) source)->screen == target->screen)
    {
 cairo_xcb_surface_t *xcb_source = (cairo_xcb_surface_t *) source;

 if (xcb_source->depth == target->depth)
     pixmap = _copy_to_pixmap (xcb_source);
    }
#if CAIRO_HAS_XLIB_XCB_FUNCTIONS
    else if (source->type == CAIRO_SURFACE_TYPE_XLIB &&
      ((cairo_xlib_xcb_surface_t *) source)->xcb->screen == target->screen)
    {
 cairo_xcb_surface_t *xcb_source = ((cairo_xlib_xcb_surface_t *) source)->xcb;

 if (xcb_source->depth == target->depth)
     pixmap = _copy_to_pixmap (xcb_source);
    }
#endif

    if (pixmap == NULL) {
 cairo_rectangle_int_t rect;

 if (! _cairo_surface_get_extents (source, &rect)) {
     rect.x = rect.y = 0;
     rect.width  = target->width;
     rect.height = target->height;
 }

 pixmap = _render_to_pixmap (target, &pattern->base, &rect);
    }

    if (unlikely (pixmap->base.status))
 return pixmap;

    _cairo_surface_attach_snapshot (source, &pixmap->base, NULL);

    if (pattern->base.extend != CAIRO_EXTEND_NONE) {
 if (extents->x < 0 || extents->y < 0 ||
     extents->x + extents->width  > pixmap->width ||
     extents->y + extents->height > pixmap->height)
 {
     pixmap->repeat = TRUE;
 }
    }

    pixmap->x0 += tx;
    pixmap->y0 += ty;

    return pixmap;
}

static cairo_xcb_pixmap_t *
_cairo_xcb_pixmap_for_pattern (cairo_xcb_surface_t *target,
          const cairo_pattern_t *pattern,
          const cairo_rectangle_int_t *extents)
{
    int tx, ty;

    switch (pattern->type) {
    case CAIRO_PATTERN_TYPE_SURFACE:
 /* Core can only perform a native, unscaled blit, but can handle tiles */
 if (_cairo_matrix_is_integer_translation (&pattern->matrix, &tx, &ty)) {
     switch (pattern->extend) {
     case CAIRO_EXTEND_NONE:
     case CAIRO_EXTEND_REPEAT:
  return _cairo_xcb_surface_pixmap (target,
        (cairo_surface_pattern_t *) pattern,
        extents, tx, ty);

     default:
     case CAIRO_EXTEND_PAD:
     case CAIRO_EXTEND_REFLECT:
  break;
     }
 }
 /* fallthrough */
    case CAIRO_PATTERN_TYPE_LINEAR:
    case CAIRO_PATTERN_TYPE_RADIAL:
    case CAIRO_PATTERN_TYPE_MESH:
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
 return _render_to_pixmap (target, pattern, extents);

    default:
    case CAIRO_PATTERN_TYPE_SOLID:
 ASSERT_NOT_REACHED;
 return NULL;
    }
}

cairo_status_t
_cairo_xcb_surface_core_copy_boxes (cairo_xcb_surface_t  *dst,
       const cairo_pattern_t *src_pattern,
       const cairo_rectangle_int_t *extents,
       const cairo_boxes_t  *boxes)
{
    cairo_xcb_pixmap_t *src;
    const struct _cairo_boxes_chunk *chunk;
    xcb_gcontext_t gc;
    cairo_status_t status;

    status = _cairo_xcb_connection_acquire (dst->connection);
    if (unlikely (status))
 return status;

    src = _cairo_xcb_pixmap_for_pattern (dst, src_pattern, extents);
    status = src->base.status;
    if (unlikely (status))
 goto CLEANUP_CONNECTION;

    assert (src->depth == dst->depth);

    gc = _cairo_xcb_screen_get_gc (dst->screen, src->pixmap, src->depth);

    if (src->repeat) {
 uint32_t mask =
     XCB_GC_FILL_STYLE |
     XCB_GC_TILE |
     XCB_GC_TILE_STIPPLE_ORIGIN_X |
     XCB_GC_TILE_STIPPLE_ORIGIN_Y;
 uint32_t values[] = {
     XCB_FILL_STYLE_TILED,
     src->pixmap,
     - src->x0, - src->y0,
 };
 xcb_rectangle_t *xcb_rects;

 _cairo_xcb_connection_change_gc (dst->connection, gc, mask, values);

 for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
     int i;

     xcb_rects = (xcb_rectangle_t *) chunk->base;

     for (i = 0; i < chunk->count; i++) {
  int x1 = _cairo_fixed_integer_round (chunk->base[i].p1.x);
  int x2 = _cairo_fixed_integer_round (chunk->base[i].p2.x);
  int y1 = _cairo_fixed_integer_round (chunk->base[i].p1.y);
  int y2 = _cairo_fixed_integer_round (chunk->base[i].p2.y);

  xcb_rects[i].x = x1;
  xcb_rects[i].y = y1;
  xcb_rects[i].width  = x2 - x1;
  xcb_rects[i].height = y2 - y1;
     }
     _cairo_xcb_connection_poly_fill_rectangle (dst->connection,
             dst->drawable,
             gc, chunk->count, xcb_rects);
 }

 values[0] = 0;
 _cairo_xcb_connection_change_gc (dst->connection, gc, XCB_GC_FILL_STYLE, values);
    } else {
 for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
     int i;

     for (i = 0; i < chunk->count; i++) {
  int x1 = _cairo_fixed_integer_round (chunk->base[i].p1.x);
  int x2 = _cairo_fixed_integer_round (chunk->base[i].p2.x);
  int y1 = _cairo_fixed_integer_round (chunk->base[i].p1.y);
  int y2 = _cairo_fixed_integer_round (chunk->base[i].p2.y);

  _cairo_xcb_connection_copy_area (dst->connection,
       src->pixmap,
       dst->drawable, gc,
       src->x0 + x1,
       src->y0 + y1,
       x1, y1,
       x2 - x1, y2 - y1);
     }
 }
    }

    _cairo_xcb_screen_put_gc (dst->screen, src->depth, gc);
    cairo_surface_destroy (&src->base);

  CLEANUP_CONNECTION:
    _cairo_xcb_connection_release (dst->connection);

    return status;
}

cairo_status_t
_cairo_xcb_surface_core_fill_boxes (cairo_xcb_surface_t *dst,
        const cairo_color_t *color,
        cairo_boxes_t *boxes)
{
    struct _cairo_boxes_chunk *chunk;
    xcb_gcontext_t gc;
    cairo_status_t status;

    status = _cairo_xcb_connection_acquire (dst->connection);
    if (unlikely (status))
 return status;

    gc = _cairo_xcb_screen_get_gc (dst->screen, dst->drawable, dst->depth);

#if 0
    xcb_pixmap_t source;

    source = _dither_source (dst, color);
    XSetTSOrigin (surface->dpy, gc, 0, 0);
    XSetTile (surface->dpy, gc, source);
#endif

    for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
 xcb_rectangle_t *xcb_rects;
 int i;

 xcb_rects = (xcb_rectangle_t *) chunk->base;
 for (i = 0; i < chunk->count; i++) {
     int x1 = _cairo_fixed_integer_round (chunk->base[i].p1.x);
     int x2 = _cairo_fixed_integer_round (chunk->base[i].p2.x);
     int y1 = _cairo_fixed_integer_round (chunk->base[i].p1.y);
     int y2 = _cairo_fixed_integer_round (chunk->base[i].p2.y);

     xcb_rects[i].x = x1;
     xcb_rects[i].y = y1;
     xcb_rects[i].width  = x2 - x1;
     xcb_rects[i].height = y2 - y1;
 }

 _cairo_xcb_connection_poly_fill_rectangle (dst->connection,
         dst->drawable, gc,
         chunk->count, xcb_rects);
    }

    _cairo_xcb_screen_put_gc (dst->screen, dst->depth, gc);
    _cairo_xcb_connection_release (dst->connection);

    return CAIRO_STATUS_SUCCESS;
}

Messung V0.5
C=99 H=92 G=95

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.