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

Quelle  pixman-image.c   Sprache: C

 
/*
 * Copyright © 2000 SuSE, Inc.
 * Copyright © 2007 Red Hat, Inc.
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of SuSE not be used in advertising or
 * publicity pertaining to distribution of the software without specific,
 * written prior permission.  SuSE makes no representations about the
 * suitability of this software for any purpose.  It is provided "as is"
 * without express or implied warranty.
 *
 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */


#ifdef HAVE_CONFIG_H
#include <pixman-config.h>
#endif

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>

#include "pixman-private.h"

static const pixman_color_t transparent_black = { 0, 0, 0, 0 };

static void
gradient_property_changed (pixman_image_t *image)
{
    gradient_t *gradient = &image->gradient;
    int n = gradient->n_stops;
    pixman_gradient_stop_t *stops = gradient->stops;
    pixman_gradient_stop_t *begin = &(gradient->stops[-1]);
    pixman_gradient_stop_t *end = &(gradient->stops[n]);

    switch (gradient->common.repeat)
    {
    default:
    case PIXMAN_REPEAT_NONE:
 begin->x = INT32_MIN;
 begin->color = transparent_black;
 end->x = INT32_MAX;
 end->color = transparent_black;
 break;

    case PIXMAN_REPEAT_NORMAL:
 begin->x = stops[n - 1].x - pixman_fixed_1;
 begin->color = stops[n - 1].color;
 end->x = stops[0].x + pixman_fixed_1;
 end->color = stops[0].color;
 break;

    case PIXMAN_REPEAT_REFLECT:
 begin->x = - stops[0].x;
 begin->color = stops[0].color;
 end->x = pixman_int_to_fixed (2) - stops[n - 1].x;
 end->color = stops[n - 1].color;
 break;

    case PIXMAN_REPEAT_PAD:
 begin->x = INT32_MIN;
 begin->color = stops[0].color;
 end->x = INT32_MAX;
 end->color = stops[n - 1].color;
 break;
    }
}

pixman_bool_t
_pixman_init_gradient (gradient_t *                  gradient,
                       const pixman_gradient_stop_t *stops,
                       int                           n_stops)
{
    return_val_if_fail (n_stops > 0, FALSE);

    /* We allocate two extra stops, one before the beginning of the stop list,
     * and one after the end. These stops are initialized to whatever color
     * would be used for positions outside the range of the stop list.
     *
     * This saves a bit of computation in the gradient walker.
     *
     * The pointer we store in the gradient_t struct still points to the
     * first user-supplied struct, so when freeing, we will have to
     * subtract one.
     */

    gradient->stops =
 pixman_malloc_ab (n_stops + 2, sizeof (pixman_gradient_stop_t));
    if (!gradient->stops)
 return FALSE;

    gradient->stops += 1;
    memcpy (gradient->stops, stops, n_stops * sizeof (pixman_gradient_stop_t));
    gradient->n_stops = n_stops;

    gradient->common.property_changed = gradient_property_changed;

    return TRUE;
}

void
_pixman_image_init (pixman_image_t *image)
{
    image_common_t *common = &image->common;

    pixman_region32_init (&common->clip_region);

    common->alpha_count = 0;
    common->have_clip_region = FALSE;
    common->clip_sources = FALSE;
    common->transform = NULL;
    common->repeat = PIXMAN_REPEAT_NONE;
    common->filter = PIXMAN_FILTER_NEAREST;
    common->filter_params = NULL;
    common->n_filter_params = 0;
    common->alpha_map = NULL;
    common->component_alpha = FALSE;
    common->ref_count = 1;
    common->property_changed = NULL;
    common->client_clip = FALSE;
    common->destroy_func = NULL;
    common->destroy_data = NULL;
    common->dirty = TRUE;
}

pixman_bool_t
_pixman_image_fini (pixman_image_t *image)
{
    image_common_t *common = (image_common_t *)image;

    common->ref_count--;

    if (common->ref_count == 0)
    {
 if (image->common.destroy_func)
     image->common.destroy_func (image, image->common.destroy_data);

 pixman_region32_fini (&common->clip_region);

 free (common->transform);
 free (common->filter_params);

 if (common->alpha_map)
     pixman_image_unref ((pixman_image_t *)common->alpha_map);

 if (image->type == LINEAR ||
     image->type == RADIAL ||
     image->type == CONICAL)
 {
     if (image->gradient.stops)
     {
  /* See _pixman_init_gradient() for an explanation of the - 1 */
  free (image->gradient.stops - 1);
     }

     /* This will trigger if someone adds a property_changed
     * method to the linear/radial/conical gradient overwriting
     * the general one.
     */

     assert (
  image->common.property_changed == gradient_property_changed);
 }

 if (image->type == BITS && image->bits.free_me)
     free (image->bits.free_me);

 return TRUE;
    }

    return FALSE;
}

pixman_image_t *
_pixman_image_allocate (void)
{
    pixman_image_t *image = malloc (sizeof (pixman_image_t));

    if (image)
 _pixman_image_init (image);

    return image;
}

static void
image_property_changed (pixman_image_t *image)
{
    image->common.dirty = TRUE;
}

/* Ref Counting */
PIXMAN_EXPORT pixman_image_t *
pixman_image_ref (pixman_image_t *image)
{
    image->common.ref_count++;

    return image;
}

/* returns TRUE when the image is freed */
PIXMAN_EXPORT pixman_bool_t
pixman_image_unref (pixman_image_t *image)
{
    if (_pixman_image_fini (image))
    {
 free (image);
 return TRUE;
    }

    return FALSE;
}

PIXMAN_EXPORT void
pixman_image_set_destroy_function (pixman_image_t *            image,
                                   pixman_image_destroy_func_t func,
                                   void *                      data)
{
    image->common.destroy_func = func;
    image->common.destroy_data = data;
}

PIXMAN_EXPORT void *
pixman_image_get_destroy_data (pixman_image_t *image)
{
  return image->common.destroy_data;
}

void
_pixman_image_reset_clip_region (pixman_image_t *image)
{
    image->common.have_clip_region = FALSE;
}

/* Executive Summary: This function is a no-op that only exists
 * for historical reasons.
 *
 * There used to be a bug in the X server where it would rely on
 * out-of-bounds accesses when it was asked to composite with a
 * window as the source. It would create a pixman image pointing
 * to some bogus position in memory, but then set a clip region
 * to the position where the actual bits were.
 *
 * Due to a bug in old versions of pixman, where it would not clip
 * against the image bounds when a clip region was set, this would
 * actually work. So when the pixman bug was fixed, a workaround was
 * added to allow certain out-of-bound accesses. This function disabled
 * those workarounds.
 *
 * Since 0.21.2, pixman doesn't do these workarounds anymore, so now
 * this function is a no-op.
 */

PIXMAN_EXPORT void
pixman_disable_out_of_bounds_workaround (void)
{
}

static void
compute_image_info (pixman_image_t *image)
{
    pixman_format_code_t code;
    uint32_t flags = 0;

    /* Transform */
    if (!image->common.transform)
    {
 flags |= (FAST_PATH_ID_TRANSFORM |
    FAST_PATH_X_UNIT_POSITIVE |
    FAST_PATH_Y_UNIT_ZERO  |
    FAST_PATH_AFFINE_TRANSFORM);
    }
    else
    {
 flags |= FAST_PATH_HAS_TRANSFORM;

 if (image->common.transform->matrix[2][0] == 0   &&
     image->common.transform->matrix[2][1] == 0   &&
     image->common.transform->matrix[2][2] == pixman_fixed_1)
 {
     flags |= FAST_PATH_AFFINE_TRANSFORM;

     if (image->common.transform->matrix[0][1] == 0 &&
  image->common.transform->matrix[1][0] == 0)
     {
  if (image->common.transform->matrix[0][0] == -pixman_fixed_1 &&
      image->common.transform->matrix[1][1] == -pixman_fixed_1)
  {
      flags |= FAST_PATH_ROTATE_180_TRANSFORM;
  }
  flags |= FAST_PATH_SCALE_TRANSFORM;
     }
     else if (image->common.transform->matrix[0][0] == 0 &&
              image->common.transform->matrix[1][1] == 0)
     {
  pixman_fixed_t m01 = image->common.transform->matrix[0][1];
  pixman_fixed_t m10 = image->common.transform->matrix[1][0];

  if (m01 == -pixman_fixed_1 && m10 == pixman_fixed_1)
      flags |= FAST_PATH_ROTATE_90_TRANSFORM;
  else if (m01 == pixman_fixed_1 && m10 == -pixman_fixed_1)
      flags |= FAST_PATH_ROTATE_270_TRANSFORM;
     }
 }

 if (image->common.transform->matrix[0][0] > 0)
     flags |= FAST_PATH_X_UNIT_POSITIVE;

 if (image->common.transform->matrix[1][0] == 0)
     flags |= FAST_PATH_Y_UNIT_ZERO;
    }

    /* Filter */
    switch (image->common.filter)
    {
    case PIXMAN_FILTER_NEAREST:
    case PIXMAN_FILTER_FAST:
 flags |= (FAST_PATH_NEAREST_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
 break;

    case PIXMAN_FILTER_BILINEAR:
    case PIXMAN_FILTER_GOOD:
    case PIXMAN_FILTER_BEST:
 flags |= (FAST_PATH_BILINEAR_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);

 /* Here we have a chance to optimize BILINEAR filter to NEAREST if
 * they are equivalent for the currently used transformation matrix.
 */

 if (flags & FAST_PATH_ID_TRANSFORM)
 {
     flags |= FAST_PATH_NEAREST_FILTER;
 }
 else if (flags & FAST_PATH_AFFINE_TRANSFORM)
 {
     /* Suppose the transform is
     *
     *    [ t00, t01, t02 ]
     *    [ t10, t11, t12 ]
     *    [   0,   0,   1 ]
     *
     * and the destination coordinates are (n + 0.5, m + 0.5). Then
     * the transformed x coordinate is:
     *
     *     tx = t00 * (n + 0.5) + t01 * (m + 0.5) + t02
     *        = t00 * n + t01 * m + t02 + (t00 + t01) * 0.5
     *
     * which implies that if t00, t01 and t02 are all integers
     * and (t00 + t01) is odd, then tx will be an integer plus 0.5,
     * which means a BILINEAR filter will reduce to NEAREST. The same
     * applies in the y direction
     */

     pixman_fixed_t (*t)[3] = image->common.transform->matrix;

     if ((pixman_fixed_frac (
       t[0][0] | t[0][1] | t[0][2] |
       t[1][0] | t[1][1] | t[1][2]) == 0)   &&
  (pixman_fixed_to_int (
      (t[0][0] + t[0][1]) & (t[1][0] + t[1][1])) % 2) == 1)
     {
  /* FIXME: there are some affine-test failures, showing that
 * handling of BILINEAR and NEAREST filter is not quite
 * equivalent when getting close to 32K for the translation
 * components of the matrix. That's likely some bug, but for
 * now just skip BILINEAR->NEAREST optimization in this case.
 */

  pixman_fixed_t magic_limit = pixman_int_to_fixed (30000);
  if (image->common.transform->matrix[0][2] <= magic_limit  &&
      image->common.transform->matrix[1][2] <= magic_limit  &&
      image->common.transform->matrix[0][2] >= -magic_limit &&
      image->common.transform->matrix[1][2] >= -magic_limit)
  {
      flags |= FAST_PATH_NEAREST_FILTER;
  }
     }
 }
 break;

    case PIXMAN_FILTER_CONVOLUTION:
 break;

    case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
 flags |= FAST_PATH_SEPARABLE_CONVOLUTION_FILTER;
 break;

    default:
 flags |= FAST_PATH_NO_CONVOLUTION_FILTER;
 break;
    }

    /* Repeat mode */
    switch (image->common.repeat)
    {
    case PIXMAN_REPEAT_NONE:
 flags |=
     FAST_PATH_NO_REFLECT_REPEAT  |
     FAST_PATH_NO_PAD_REPEAT  |
     FAST_PATH_NO_NORMAL_REPEAT;
 break;

    case PIXMAN_REPEAT_REFLECT:
 flags |=
     FAST_PATH_NO_PAD_REPEAT  |
     FAST_PATH_NO_NONE_REPEAT  |
     FAST_PATH_NO_NORMAL_REPEAT;
 break;

    case PIXMAN_REPEAT_PAD:
 flags |=
     FAST_PATH_NO_REFLECT_REPEAT  |
     FAST_PATH_NO_NONE_REPEAT  |
     FAST_PATH_NO_NORMAL_REPEAT;
 break;

    default:
 flags |=
     FAST_PATH_NO_REFLECT_REPEAT  |
     FAST_PATH_NO_PAD_REPEAT  |
     FAST_PATH_NO_NONE_REPEAT;
 break;
    }

    /* Component alpha */
    if (image->common.component_alpha)
 flags |= FAST_PATH_COMPONENT_ALPHA;
    else
 flags |= FAST_PATH_UNIFIED_ALPHA;

    flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NARROW_FORMAT);

    /* Type specific checks */
    switch (image->type)
    {
    case SOLID:
 code = PIXMAN_solid;

 if (image->solid.color.alpha == 0xffff)
     flags |= FAST_PATH_IS_OPAQUE;
 break;

    case BITS:
 if (image->bits.width == 1 &&
     image->bits.height == 1 &&
     image->common.repeat != PIXMAN_REPEAT_NONE)
 {
     code = PIXMAN_solid;
 }
 else
 {
     code = image->bits.format;
     flags |= FAST_PATH_BITS_IMAGE;
 }

 if (!PIXMAN_FORMAT_A (image->bits.format)    &&
     PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_GRAY  &&
     PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_COLOR)
 {
     flags |= FAST_PATH_SAMPLES_OPAQUE;

     if (image->common.repeat != PIXMAN_REPEAT_NONE)
  flags |= FAST_PATH_IS_OPAQUE;
 }

 if (image->bits.read_func || image->bits.write_func)
     flags &= ~FAST_PATH_NO_ACCESSORS;

 if (PIXMAN_FORMAT_IS_WIDE (image->bits.format))
     flags &= ~FAST_PATH_NARROW_FORMAT;
 break;

    case RADIAL:
 code = PIXMAN_unknown;

 /*
 * As explained in pixman-radial-gradient.c, every point of
 * the plane has a valid associated radius (and thus will be
 * colored) if and only if a is negative (i.e. one of the two
 * circles contains the other one).
 */


        if (image->radial.a >= 0)
     break;

 /* Fall through */

    case CONICAL:
    case LINEAR:
 code = PIXMAN_unknown;

 if (image->common.repeat != PIXMAN_REPEAT_NONE)
 {
     int i;

     flags |= FAST_PATH_IS_OPAQUE;
     for (i = 0; i < image->gradient.n_stops; ++i)
     {
  if (image->gradient.stops[i].color.alpha != 0xffff)
  {
      flags &= ~FAST_PATH_IS_OPAQUE;
      break;
  }
     }
 }
 break;

    default:
 code = PIXMAN_unknown;
 break;
    }

    /* Alpha maps are only supported for BITS images, so it's always
     * safe to ignore their presense for non-BITS images
     */

    if (!image->common.alpha_map || image->type != BITS)
    {
 flags |= FAST_PATH_NO_ALPHA_MAP;
    }
    else
    {
 if (PIXMAN_FORMAT_IS_WIDE (image->common.alpha_map->format))
     flags &= ~FAST_PATH_NARROW_FORMAT;
    }

    /* Both alpha maps and convolution filters can introduce
     * non-opaqueness in otherwise opaque images. Also
     * an image with component alpha turned on is only opaque
     * if all channels are opaque, so we simply turn it off
     * unconditionally for those images.
     */

    if (image->common.alpha_map      ||
 image->common.filter == PIXMAN_FILTER_CONVOLUTION  ||
        image->common.filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION     ||
 image->common.component_alpha)
    {
 flags &= ~(FAST_PATH_IS_OPAQUE | FAST_PATH_SAMPLES_OPAQUE);
    }

    image->common.flags = flags;
    image->common.extended_format_code = code;
}

void
_pixman_image_validate (pixman_image_t *image)
{
    if (image->common.dirty)
    {
 compute_image_info (image);

 /* It is important that property_changed is
 * called *after* compute_image_info() because
 * property_changed() can make use of the flags
 * to set up accessors etc.
 */

 if (image->common.property_changed)
     image->common.property_changed (image);

 image->common.dirty = FALSE;
    }

    if (image->common.alpha_map)
 _pixman_image_validate ((pixman_image_t *)image->common.alpha_map);
}

PIXMAN_EXPORT pixman_bool_t
pixman_image_set_clip_region32 (pixman_image_t *   image,
                                const pixman_region32_t *region)
{
    image_common_t *common = (image_common_t *)image;
    pixman_bool_t result;

    if (region)
    {
 if ((result = pixman_region32_copy (&common->clip_region, region)))
     image->common.have_clip_region = TRUE;
    }
    else
    {
 _pixman_image_reset_clip_region (image);

 result = TRUE;
    }

    image_property_changed (image);

    return result;
}

PIXMAN_EXPORT pixman_bool_t
pixman_image_set_clip_region (pixman_image_t *   image,
                              const pixman_region16_t *region)
{
    image_common_t *common = (image_common_t *)image;
    pixman_bool_t result;

    if (region)
    {
 if ((result = pixman_region32_copy_from_region16 (&common->clip_region, region)))
     image->common.have_clip_region = TRUE;
    }
    else
    {
 _pixman_image_reset_clip_region (image);

 result = TRUE;
    }

    image_property_changed (image);

    return result;
}

PIXMAN_EXPORT void
pixman_image_set_has_client_clip (pixman_image_t *image,
                                  pixman_bool_t   client_clip)
{
    image->common.client_clip = client_clip;
}

PIXMAN_EXPORT pixman_bool_t
pixman_image_set_transform (pixman_image_t *          image,
                            const pixman_transform_t *transform)
{
    static const pixman_transform_t id =
    {
 { { pixman_fixed_1, 0, 0 },
   { 0, pixman_fixed_1, 0 },
   { 0, 0, pixman_fixed_1 } }
    };

    image_common_t *common = (image_common_t *)image;
    pixman_bool_t result;

    if (common->transform == transform)
 return TRUE;

    if (!transform || memcmp (&id, transform, sizeof (pixman_transform_t)) == 0)
    {
 free (common->transform);
 common->transform = NULL;
 result = TRUE;

 goto out;
    }

    if (common->transform &&
 memcmp (common->transform, transform, sizeof (pixman_transform_t)) == 0)
    {
 return TRUE;
    }

    if (common->transform == NULL)
 common->transform = malloc (sizeof (pixman_transform_t));

    if (common->transform == NULL)
    {
 result = FALSE;

 goto out;
    }

    memcpy (common->transform, transform, sizeof(pixman_transform_t));

    result = TRUE;

out:
    image_property_changed (image);

    return result;
}

PIXMAN_EXPORT void
pixman_image_set_repeat (pixman_image_t *image,
                         pixman_repeat_t repeat)
{
    if (image->common.repeat == repeat)
 return;

    image->common.repeat = repeat;

    image_property_changed (image);
}

PIXMAN_EXPORT void
pixman_image_set_dither (pixman_image_t *image,
    pixman_dither_t dither)
{
    if (image->type == BITS)
    {
 if (image->bits.dither == dither)
     return;

 image->bits.dither = dither;

 image_property_changed (image);
    }
}

PIXMAN_EXPORT void
pixman_image_set_dither_offset (pixman_image_t *image,
    int             offset_x,
    int             offset_y)
{
    if (image->type == BITS)
    {
 if (image->bits.dither_offset_x == offset_x &&
     image->bits.dither_offset_y == offset_y)
 {
     return;
 }

 image->bits.dither_offset_x = offset_x;
 image->bits.dither_offset_y = offset_y;

 image_property_changed (image);
    }
}

PIXMAN_EXPORT pixman_bool_t
pixman_image_set_filter (pixman_image_t *      image,
                         pixman_filter_t       filter,
                         const pixman_fixed_t *params,
                         int                   n_params)
{
    image_common_t *common = (image_common_t *)image;
    pixman_fixed_t *new_params;

    if (params == common->filter_params && filter == common->filter)
 return TRUE;

    if (filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION)
    {
 int width = pixman_fixed_to_int (params[0]);
 int height = pixman_fixed_to_int (params[1]);
 int x_phase_bits = pixman_fixed_to_int (params[2]);
 int y_phase_bits = pixman_fixed_to_int (params[3]);
 int n_x_phases = (1 << x_phase_bits);
 int n_y_phases = (1 << y_phase_bits);

 return_val_if_fail (
     n_params == 4 + n_x_phases * width + n_y_phases * height, FALSE);
    }
    
    new_params = NULL;
    if (params)
    {
 new_params = pixman_malloc_ab (n_params, sizeof (pixman_fixed_t));
 if (!new_params)
     return FALSE;

 memcpy (new_params,
         params, n_params * sizeof (pixman_fixed_t));
    }

    common->filter = filter;

    if (common->filter_params)
 free (common->filter_params);

    common->filter_params = new_params;
    common->n_filter_params = n_params;

    image_property_changed (image);
    return TRUE;
}

PIXMAN_EXPORT void
pixman_image_set_source_clipping (pixman_image_t *image,
                                  pixman_bool_t   clip_sources)
{
    if (image->common.clip_sources == clip_sources)
 return;

    image->common.clip_sources = clip_sources;

    image_property_changed (image);
}

/* Unlike all the other property setters, this function does not
 * copy the content of indexed. Doing this copying is simply
 * way, way too expensive.
 */

PIXMAN_EXPORT void
pixman_image_set_indexed (pixman_image_t *        image,
                          const pixman_indexed_t *indexed)
{
    bits_image_t *bits = (bits_image_t *)image;

    if (bits->indexed == indexed)
 return;

    bits->indexed = indexed;

    image_property_changed (image);
}

PIXMAN_EXPORT void
pixman_image_set_alpha_map (pixman_image_t *image,
                            pixman_image_t *alpha_map,
                            int16_t         x,
                            int16_t         y)
{
    image_common_t *common = (image_common_t *)image;

    return_if_fail (!alpha_map || alpha_map->type == BITS);

    if (alpha_map && common->alpha_count > 0)
    {
 /* If this image is being used as an alpha map itself,
 * then you can't give it an alpha map of its own.
 */

 return;
    }

    if (alpha_map && alpha_map->common.alpha_map)
    {
 /* If the image has an alpha map of its own,
 * then it can't be used as an alpha map itself
 */

 return;
    }

    if (common->alpha_map != (bits_image_t *)alpha_map)
    {
 if (common->alpha_map)
 {
     common->alpha_map->common.alpha_count--;

     pixman_image_unref ((pixman_image_t *)common->alpha_map);
 }

 if (alpha_map)
 {
     common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map);

     common->alpha_map->common.alpha_count++;
 }
 else
 {
     common->alpha_map = NULL;
 }
    }

    common->alpha_origin_x = x;
    common->alpha_origin_y = y;

    image_property_changed (image);
}

PIXMAN_EXPORT void
pixman_image_set_component_alpha   (pixman_image_t *image,
                                    pixman_bool_t   component_alpha)
{
    if (image->common.component_alpha == component_alpha)
 return;

    image->common.component_alpha = component_alpha;

    image_property_changed (image);
}

PIXMAN_EXPORT pixman_bool_t
pixman_image_get_component_alpha   (pixman_image_t       *image)
{
    return image->common.component_alpha;
}

PIXMAN_EXPORT void
pixman_image_set_accessors (pixman_image_t *           image,
                            pixman_read_memory_func_t  read_func,
                            pixman_write_memory_func_t write_func)
{
    return_if_fail (image != NULL);

    if (image->type == BITS)
    {
 /* Accessors only work for <= 32 bpp. */
 if (PIXMAN_FORMAT_BPP(image->bits.format) > 32)
     return_if_fail (!read_func && !write_func);

 image->bits.read_func = read_func;
 image->bits.write_func = write_func;

 image_property_changed (image);
    }
}

PIXMAN_EXPORT uint32_t *
pixman_image_get_data (pixman_image_t *image)
{
    if (image->type == BITS)
 return image->bits.bits;

    return NULL;
}

PIXMAN_EXPORT int
pixman_image_get_width (pixman_image_t *image)
{
    if (image->type == BITS)
 return image->bits.width;

    return 0;
}

PIXMAN_EXPORT int
pixman_image_get_height (pixman_image_t *image)
{
    if (image->type == BITS)
 return image->bits.height;

    return 0;
}

PIXMAN_EXPORT int
pixman_image_get_stride (pixman_image_t *image)
{
    if (image->type == BITS)
 return image->bits.rowstride * (intsizeof (uint32_t);

    return 0;
}

PIXMAN_EXPORT int
pixman_image_get_depth (pixman_image_t *image)
{
    if (image->type == BITS)
 return PIXMAN_FORMAT_DEPTH (image->bits.format);

    return 0;
}

PIXMAN_EXPORT pixman_format_code_t
pixman_image_get_format (pixman_image_t *image)
{
    if (image->type == BITS)
 return image->bits.format;

    return PIXMAN_null;
}

uint32_t
_pixman_image_get_solid (pixman_implementation_t *imp,
    pixman_image_t *         image,
                         pixman_format_code_t     format)
{
    uint32_t result;

    if (image->type == SOLID)
    {
 result = image->solid.color_32;
    }
    else if (image->type == BITS)
    {
 if (image->bits.format == PIXMAN_a8r8g8b8)
     result = image->bits.bits[0];
 else if (image->bits.format == PIXMAN_x8r8g8b8)
     result = image->bits.bits[0] | 0xff000000;
 else if (image->bits.format == PIXMAN_a8)
     result = (uint32_t)(*(uint8_t *)image->bits.bits) << 24;
 else
     goto otherwise;
    }
    else
    {
 pixman_iter_t iter;

    otherwise:
 _pixman_implementation_iter_init (
     imp, &iter, image, 0, 0, 1, 1,
     (uint8_t *)&result,
     ITER_NARROW | ITER_SRC, image->common.flags);
 
 result = *iter.get_scanline (&iter, NULL);

 if (iter.fini)
     iter.fini (&iter);
    }

    /* If necessary, convert RGB <--> BGR. */
    if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB
 && PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB_SRGB)
    {
 result = (((result & 0xff000000) >>  0) |
           ((result & 0x00ff0000) >> 16) |
           ((result & 0x0000ff00) >>  0) |
           ((result & 0x000000ff) << 16));
    }

    return result;
}

Messung V0.5
C=91 H=97 G=93

¤ Dauer der Verarbeitung: 0.32 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.