/* 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) returnFALSE;
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);
/* 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)
{
}
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;
} elseif (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;
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);
}
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);
}
/* 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 (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--;
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);
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.