forked from KolibriOS/kolibrios
delete libraries/pixman
git-svn-id: svn://kolibrios.org@4354 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
ca0ff73f27
commit
fed5fef52f
@ -1,42 +0,0 @@
|
||||
The following is the MIT license, agreed upon by most contributors.
|
||||
Copyright holders of new code should use this license statement where
|
||||
possible. They may also add themselves to the list below.
|
||||
|
||||
/*
|
||||
* Copyright 1987, 1988, 1989, 1998 The Open Group
|
||||
* Copyright 1987, 1988, 1989 Digital Equipment Corporation
|
||||
* Copyright 1999, 2004, 2008 Keith Packard
|
||||
* Copyright 2000 SuSE, Inc.
|
||||
* Copyright 2000 Keith Packard, member of The XFree86 Project, Inc.
|
||||
* Copyright 2004, 2005, 2007, 2008, 2009, 2010 Red Hat, Inc.
|
||||
* Copyright 2004 Nicholas Miell
|
||||
* Copyright 2005 Lars Knoll & Zack Rusin, Trolltech
|
||||
* Copyright 2005 Trolltech AS
|
||||
* Copyright 2007 Luca Barbato
|
||||
* Copyright 2008 Aaron Plattner, NVIDIA Corporation
|
||||
* Copyright 2008 Rodrigo Kumpera
|
||||
* Copyright 2008 André Tupinambá
|
||||
* Copyright 2008 Mozilla Corporation
|
||||
* Copyright 2008 Frederic Plourde
|
||||
* Copyright 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2009, 2010 Nokia Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
@ -1,82 +0,0 @@
|
||||
|
||||
LIBRARY = pixman-1
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = -U_Win32 -U_WIN32 -U__MINGW32__ -c -O2 -Wall -Winline -fomit-frame-pointer
|
||||
|
||||
LD = ld
|
||||
LDFLAGS = -shared -s -nostdlib -T ../newlib/dll.lds --entry _DllStartup --image-base=0 --out-implib lib$(LIBRARY).dll.a
|
||||
|
||||
STRIP = $(PREFIX)strip
|
||||
|
||||
INCLUDES= -I. -I../newlib/include
|
||||
|
||||
LIBPATH:= -L../newlib
|
||||
|
||||
LIBS:= -ldll -lc.dll -lgcc
|
||||
|
||||
#DEFINES = -DHAVE_CONFIG_H -DPIXMAN_NO_TLS
|
||||
DEFINES = -DHAVE_CONFIG_H
|
||||
|
||||
|
||||
SOURCES = \
|
||||
pixman.c \
|
||||
pixman-access.c \
|
||||
pixman-access-accessors.c \
|
||||
pixman-bits-image.c \
|
||||
pixman-combine32.c \
|
||||
pixman-combine-float.c \
|
||||
pixman-conical-gradient.c \
|
||||
pixman-edge.c \
|
||||
pixman-edge-accessors.c \
|
||||
pixman-fast-path.c \
|
||||
pixman-filter.c \
|
||||
pixman-general.c \
|
||||
pixman-glyph.c \
|
||||
pixman-gradient-walker.c \
|
||||
pixman-image.c \
|
||||
pixman-implementation.c \
|
||||
pixman-linear-gradient.c \
|
||||
pixman-matrix.c \
|
||||
pixman-noop.c \
|
||||
pixman-radial-gradient.c \
|
||||
pixman-region16.c \
|
||||
pixman-region32.c \
|
||||
pixman-solid-fill.c \
|
||||
pixman-timer.c \
|
||||
pixman-trap.c \
|
||||
pixman-utils.c \
|
||||
pixman-x86.c \
|
||||
pixman-mmx.c \
|
||||
pixman-sse2.c \
|
||||
$(NULL)
|
||||
|
||||
OBJECTS = $(patsubst %.c, %.o, $(SOURCES))
|
||||
|
||||
# targets
|
||||
|
||||
all:$(LIBRARY).a $(LIBRARY).dll
|
||||
|
||||
|
||||
$(LIBRARY).a: $(OBJECTS) Makefile
|
||||
ar cvrs $(LIBRARY).a $(OBJECTS)
|
||||
|
||||
$(LIBRARY).dll: $(LIBRARY).def $(OBJECTS) Makefile
|
||||
$(LD) $(LDFLAGS) $(LIBPATH) -o $@ $(LIBRARY).def $(OBJECTS) $(LIBS)
|
||||
$(STRIP) $@
|
||||
sed -f ../newlib/cmd1.sed $(LIBRARY).def > mem
|
||||
sed -f ../newlib/cmd2.sed mem >$(LIBRARY).inc
|
||||
|
||||
%.o : %.c Makefile
|
||||
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ $<
|
||||
|
||||
pixman-mmx.o: pixman-mmx.c Makefile
|
||||
$(CC) $(CFLAGS) -mmmx $(DEFINES) $(INCLUDES) -o $@ $<
|
||||
|
||||
pixman-sse2.o: pixman-sse2.c Makefile
|
||||
$(CC) $(CFLAGS) -msse2 $(DEFINES) $(INCLUDES) -o $@ $<
|
||||
|
||||
|
||||
clean:
|
||||
-rm -f *.o
|
||||
|
@ -1,116 +0,0 @@
|
||||
Pixman is a library that provides low-level pixel manipulation
|
||||
features such as image compositing and trapezoid rasterization.
|
||||
|
||||
Questions, bug reports and patches should be directed to the pixman
|
||||
mailing list:
|
||||
|
||||
http://lists.freedesktop.org/mailman/listinfo/pixman
|
||||
|
||||
You can also file bugs at
|
||||
|
||||
https://bugs.freedesktop.org/enter_bug.cgi?product=pixman
|
||||
|
||||
For real time discussions about pixman, feel free to join the IRC
|
||||
channels #cairo and #xorg-devel on the FreeNode IRC network.
|
||||
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
In order to contribute to pixman, you will need a working knowledge of
|
||||
the git version control system. For a quick getting started guide,
|
||||
there is the "Everyday Git With 20 Commands Or So guide"
|
||||
|
||||
http://www.kernel.org/pub/software/scm/git/docs/everyday.html
|
||||
|
||||
from the Git homepage. For more in depth git documentation, see the
|
||||
resources on the Git community documentation page:
|
||||
|
||||
http://git-scm.com/documentation
|
||||
|
||||
Pixman uses the infrastructure from the freedesktop.org umbrella
|
||||
project. For instructions about how to use the git service on
|
||||
freedesktop.org, see:
|
||||
|
||||
http://www.freedesktop.org/wiki/Infrastructure/git/Developers
|
||||
|
||||
The Pixman master repository can be found at:
|
||||
|
||||
git://anongit.freedesktop.org/git/pixman
|
||||
|
||||
and browsed on the web here:
|
||||
|
||||
http://cgit.freedesktop.org/pixman/
|
||||
|
||||
|
||||
Sending patches
|
||||
---------------
|
||||
|
||||
The general workflow for sending patches is to first make sure that
|
||||
git can send mail on your system. Then,
|
||||
|
||||
- create a branch off of master in your local git repository
|
||||
|
||||
- make your changes as one or more commits
|
||||
|
||||
- use the
|
||||
|
||||
git send-email
|
||||
|
||||
command to send the patch series to pixman@lists.freedesktop.org.
|
||||
|
||||
In order for your patches to be accepted, please consider the
|
||||
following guidelines:
|
||||
|
||||
- This link:
|
||||
|
||||
http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#patch-series
|
||||
|
||||
describes how what a good patch series is, and to create one with
|
||||
git.
|
||||
|
||||
- At each point in the series, pixman should compile and the test
|
||||
suite should pass.
|
||||
|
||||
The exception here is if you are changing the test suite to
|
||||
demonstrate a bug. In this case, make one commit that makes the
|
||||
test suite fail due to the bug, and then another commit that fixes
|
||||
the bug.
|
||||
|
||||
You can run the test suite with
|
||||
|
||||
make check
|
||||
|
||||
It will take around two minutes to run on a modern PC.
|
||||
|
||||
- Follow the coding style described in the CODING_STYLE file
|
||||
|
||||
- For bug fixes, include an update to the test suite to make sure
|
||||
the bug doesn't reappear.
|
||||
|
||||
- For new features, add tests of the feature to the test
|
||||
suite. Also, add a program demonstrating the new feature to the
|
||||
demos/ directory.
|
||||
|
||||
- Write descriptive commit messages. Useful information to include:
|
||||
- Benchmark results, before and after
|
||||
- Description of the bug that was fixed
|
||||
- Detailed rationale for any new API
|
||||
- Alternative approaches that were rejected (and why they
|
||||
don't work)
|
||||
- If review comments were incorporated, a brief version
|
||||
history describing what those changes were.
|
||||
|
||||
- For big patch series, send an introductory email with an overall
|
||||
description of the patch series, including benchmarks and
|
||||
motivation. Each commit message should still be descriptive and
|
||||
include enough information to understand why this particular commit
|
||||
was necessary.
|
||||
|
||||
Pixman has high standards for code quality and so almost everybody
|
||||
should expect to have the first versions of their patches rejected.
|
||||
|
||||
If you think that the reviewers are wrong about something, or that the
|
||||
guidelines above are wrong, feel free to discuss the issue on the
|
||||
list. The purpose of the guidelines and code review is to ensure high
|
||||
code quality; it is not an exercise in compliance.
|
@ -1,174 +0,0 @@
|
||||
/* config.h. Generated from config.h.in by configure. */
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define if building universal (internal helper macro) */
|
||||
/* #undef AC_APPLE_UNIVERSAL_BUILD */
|
||||
|
||||
/* Whether we have alarm() */
|
||||
/* #undef HAVE_ALARM */
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
/* #undef HAVE_DLFCN_H */
|
||||
|
||||
/* Whether we have feenableexcept() */
|
||||
/* #undef HAVE_FEENABLEEXCEPT */
|
||||
|
||||
/* Define to 1 if we have <fenv.h> */
|
||||
#define HAVE_FENV_H 1
|
||||
|
||||
/* Whether the tool chain supports __float128 */
|
||||
#define HAVE_FLOAT128 /**/
|
||||
|
||||
/* Define to 1 if you have the `getisax' function. */
|
||||
/* #undef HAVE_GETISAX */
|
||||
|
||||
/* Whether we have getpagesize() */
|
||||
#define HAVE_GETPAGESIZE 1
|
||||
|
||||
/* Whether we have gettimeofday() */
|
||||
#define HAVE_GETTIMEOFDAY 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the `pixman-1' library (-lpixman-1). */
|
||||
/* #undef HAVE_LIBPIXMAN_1 */
|
||||
|
||||
/* Whether we have libpng */
|
||||
#define HAVE_LIBPNG 1
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Whether we have mmap() */
|
||||
#define HAVE_MMAP
|
||||
|
||||
/* Whether we have mprotect() */
|
||||
#define HAVE_MPROTECT 1
|
||||
|
||||
/* Whether we have posix_memalign() */
|
||||
/* #undef HAVE_POSIX_MEMALIGN */
|
||||
|
||||
/* Whether pthread_setspecific() is supported */
|
||||
/* #undef HAVE_PTHREAD_SETSPECIFIC */
|
||||
|
||||
/* Whether we have sigaction() */
|
||||
/* #undef HAVE_SIGACTION */
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if we have <sys/mman.h> */
|
||||
/* #undef HAVE_SYS_MMAN_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#define LT_OBJDIR ".libs/"
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "pixman"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT "pixman@lists.freedesktop.org"
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "pixman"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "pixman 0.30.2"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "pixman"
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "0.30.2"
|
||||
|
||||
/* enable TIMER_BEGIN/TIMER_END macros */
|
||||
/* #undef PIXMAN_TIMERS */
|
||||
|
||||
/* The size of `long', as computed by sizeof. */
|
||||
#define SIZEOF_LONG 4
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* The compiler supported TLS storage class */
|
||||
#define TLS __thread
|
||||
|
||||
/* Whether the tool chain supports __attribute__((constructor)) */
|
||||
//#define TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR /**/
|
||||
|
||||
/* use ARM IWMMXT compiler intrinsics */
|
||||
/* #undef USE_ARM_IWMMXT */
|
||||
|
||||
/* use ARM NEON assembly optimizations */
|
||||
/* #undef USE_ARM_NEON */
|
||||
|
||||
/* use ARM SIMD assembly optimizations */
|
||||
/* #undef USE_ARM_SIMD */
|
||||
|
||||
/* use GNU-style inline assembler */
|
||||
#define USE_GCC_INLINE_ASM 1
|
||||
|
||||
/* use Loongson Multimedia Instructions */
|
||||
/* #undef USE_LOONGSON_MMI */
|
||||
|
||||
/* use MIPS DSPr2 assembly optimizations */
|
||||
/* #undef USE_MIPS_DSPR2 */
|
||||
|
||||
/* use OpenMP in the test suite */
|
||||
/* #undef USE_OPENMP */
|
||||
|
||||
/* use SSE2 compiler intrinsics */
|
||||
#define USE_SSE2 1
|
||||
|
||||
/* use VMX compiler intrinsics */
|
||||
/* #undef USE_VMX */
|
||||
|
||||
/* use x86 MMX compiler intrinsics */
|
||||
#define USE_X86_MMX 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "0.30.2"
|
||||
|
||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||
significant byte first (like Motorola and SPARC, unlike Intel). */
|
||||
#if defined AC_APPLE_UNIVERSAL_BUILD
|
||||
# if defined __BIG_ENDIAN__
|
||||
# define WORDS_BIGENDIAN 1
|
||||
# endif
|
||||
#else
|
||||
# ifndef WORDS_BIGENDIAN
|
||||
/* # undef WORDS_BIGENDIAN */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#ifndef __cplusplus
|
||||
/* #undef inline */
|
||||
#endif
|
||||
|
||||
/* Define to sqrt if you do not have the `sqrtf' function. */
|
||||
/* #undef sqrtf */
|
@ -1,148 +0,0 @@
|
||||
EXPORTS
|
||||
_pixman_internal_only_get_implementation
|
||||
pixman_add_trapezoids
|
||||
pixman_add_traps
|
||||
pixman_add_triangles
|
||||
pixman_blt
|
||||
pixman_composite_glyphs
|
||||
pixman_composite_glyphs_no_mask
|
||||
pixman_composite_trapezoids
|
||||
pixman_composite_triangles
|
||||
pixman_compute_composite_region
|
||||
pixman_disable_out_of_bounds_workaround
|
||||
pixman_edge_init
|
||||
pixman_edge_step
|
||||
pixman_f_transform_bounds
|
||||
pixman_f_transform_from_pixman_transform
|
||||
pixman_f_transform_init_identity
|
||||
pixman_f_transform_init_rotate
|
||||
pixman_f_transform_init_scale
|
||||
pixman_f_transform_init_translate
|
||||
pixman_f_transform_invert
|
||||
pixman_f_transform_multiply
|
||||
pixman_f_transform_point
|
||||
pixman_f_transform_point_3d
|
||||
pixman_f_transform_rotate
|
||||
pixman_f_transform_scale
|
||||
pixman_f_transform_translate
|
||||
pixman_fill
|
||||
pixman_filter_create_separable_convolution
|
||||
pixman_format_supported_destination
|
||||
pixman_format_supported_source
|
||||
pixman_glyph_cache_create
|
||||
pixman_glyph_cache_destroy
|
||||
pixman_glyph_cache_freeze
|
||||
pixman_glyph_cache_insert
|
||||
pixman_glyph_cache_lookup
|
||||
pixman_glyph_cache_remove
|
||||
pixman_glyph_cache_thaw
|
||||
pixman_glyph_get_extents
|
||||
pixman_glyph_get_mask_format
|
||||
pixman_image_composite
|
||||
pixman_image_composite32
|
||||
pixman_image_create_bits
|
||||
pixman_image_create_bits_no_clear
|
||||
pixman_image_create_conical_gradient
|
||||
pixman_image_create_linear_gradient
|
||||
pixman_image_create_radial_gradient
|
||||
pixman_image_create_solid_fill
|
||||
pixman_image_fill_boxes
|
||||
pixman_image_fill_rectangles
|
||||
pixman_image_get_component_alpha
|
||||
pixman_image_get_data
|
||||
pixman_image_get_depth
|
||||
pixman_image_get_destroy_data
|
||||
pixman_image_get_format
|
||||
pixman_image_get_height
|
||||
pixman_image_get_stride
|
||||
pixman_image_get_width
|
||||
pixman_image_ref
|
||||
pixman_image_set_accessors
|
||||
pixman_image_set_alpha_map
|
||||
pixman_image_set_clip_region
|
||||
pixman_image_set_clip_region32
|
||||
pixman_image_set_component_alpha
|
||||
pixman_image_set_destroy_function
|
||||
pixman_image_set_filter
|
||||
pixman_image_set_has_client_clip
|
||||
pixman_image_set_indexed
|
||||
pixman_image_set_repeat
|
||||
pixman_image_set_source_clipping
|
||||
pixman_image_set_transform
|
||||
pixman_image_unref
|
||||
pixman_line_fixed_edge_init
|
||||
pixman_rasterize_edges
|
||||
pixman_rasterize_trapezoid
|
||||
pixman_region32_clear
|
||||
pixman_region32_contains_point
|
||||
pixman_region32_contains_rectangle
|
||||
pixman_region32_copy
|
||||
pixman_region32_equal
|
||||
pixman_region32_extents
|
||||
pixman_region32_fini
|
||||
pixman_region32_init
|
||||
pixman_region32_init_from_image
|
||||
pixman_region32_init_rect
|
||||
pixman_region32_init_rects
|
||||
pixman_region32_init_with_extents
|
||||
pixman_region32_intersect
|
||||
pixman_region32_intersect_rect
|
||||
pixman_region32_inverse
|
||||
pixman_region32_n_rects
|
||||
pixman_region32_not_empty
|
||||
pixman_region32_rectangles
|
||||
pixman_region32_reset
|
||||
pixman_region32_selfcheck
|
||||
pixman_region32_subtract
|
||||
pixman_region32_translate
|
||||
pixman_region32_union
|
||||
pixman_region32_union_rect
|
||||
pixman_region_clear
|
||||
pixman_region_contains_point
|
||||
pixman_region_contains_rectangle
|
||||
pixman_region_copy
|
||||
pixman_region_equal
|
||||
pixman_region_extents
|
||||
pixman_region_fini
|
||||
pixman_region_init
|
||||
pixman_region_init_from_image
|
||||
pixman_region_init_rect
|
||||
pixman_region_init_rects
|
||||
pixman_region_init_with_extents
|
||||
pixman_region_intersect
|
||||
pixman_region_intersect_rect
|
||||
pixman_region_inverse
|
||||
pixman_region_n_rects
|
||||
pixman_region_not_empty
|
||||
pixman_region_rectangles
|
||||
pixman_region_reset
|
||||
pixman_region_selfcheck
|
||||
pixman_region_set_static_pointers
|
||||
pixman_region_subtract
|
||||
pixman_region_translate
|
||||
pixman_region_union
|
||||
pixman_region_union_rect
|
||||
pixman_sample_ceil_y
|
||||
pixman_sample_floor_y
|
||||
pixman_transform_bounds
|
||||
pixman_transform_from_pixman_f_transform
|
||||
pixman_transform_init_identity
|
||||
pixman_transform_init_rotate
|
||||
pixman_transform_init_scale
|
||||
pixman_transform_init_translate
|
||||
pixman_transform_invert
|
||||
pixman_transform_is_identity
|
||||
pixman_transform_is_int_translate
|
||||
pixman_transform_is_inverse
|
||||
pixman_transform_is_scale
|
||||
pixman_transform_multiply
|
||||
pixman_transform_point
|
||||
pixman_transform_point_31_16
|
||||
pixman_transform_point_31_16_3d
|
||||
pixman_transform_point_31_16_affine
|
||||
pixman_transform_point_3d
|
||||
pixman_transform_rotate
|
||||
pixman_transform_scale
|
||||
pixman_transform_translate
|
||||
pixman_version
|
||||
pixman_version_string
|
@ -1,3 +0,0 @@
|
||||
#define PIXMAN_FB_ACCESSORS
|
||||
|
||||
#include "pixman-access.c"
|
File diff suppressed because it is too large
Load Diff
@ -1,25 +0,0 @@
|
||||
#ifdef PIXMAN_FB_ACCESSORS
|
||||
|
||||
#define READ(img, ptr) \
|
||||
(((bits_image_t *)(img))->read_func ((ptr), sizeof(*(ptr))))
|
||||
#define WRITE(img, ptr,val) \
|
||||
(((bits_image_t *)(img))->write_func ((ptr), (val), sizeof (*(ptr))))
|
||||
|
||||
#define MEMSET_WRAPPED(img, dst, val, size) \
|
||||
do { \
|
||||
size_t _i; \
|
||||
uint8_t *_dst = (uint8_t*)(dst); \
|
||||
for(_i = 0; _i < (size_t) size; _i++) { \
|
||||
WRITE((img), _dst +_i, (val)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define READ(img, ptr) (*(ptr))
|
||||
#define WRITE(img, ptr, val) (*(ptr) = (val))
|
||||
#define MEMSET_WRAPPED(img, dst, val, size) \
|
||||
memset(dst, val, size)
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,272 +0,0 @@
|
||||
#define COMPONENT_SIZE 8
|
||||
#define MASK 0xff
|
||||
#define ONE_HALF 0x80
|
||||
|
||||
#define A_SHIFT 8 * 3
|
||||
#define R_SHIFT 8 * 2
|
||||
#define G_SHIFT 8
|
||||
#define A_MASK 0xff000000
|
||||
#define R_MASK 0xff0000
|
||||
#define G_MASK 0xff00
|
||||
|
||||
#define RB_MASK 0xff00ff
|
||||
#define AG_MASK 0xff00ff00
|
||||
#define RB_ONE_HALF 0x800080
|
||||
#define RB_MASK_PLUS_ONE 0x10000100
|
||||
|
||||
#define ALPHA_8(x) ((x) >> A_SHIFT)
|
||||
#define RED_8(x) (((x) >> R_SHIFT) & MASK)
|
||||
#define GREEN_8(x) (((x) >> G_SHIFT) & MASK)
|
||||
#define BLUE_8(x) ((x) & MASK)
|
||||
|
||||
/*
|
||||
* ARMv6 has UQADD8 instruction, which implements unsigned saturated
|
||||
* addition for 8-bit values packed in 32-bit registers. It is very useful
|
||||
* for UN8x4_ADD_UN8x4, UN8_rb_ADD_UN8_rb and ADD_UN8 macros (which would
|
||||
* otherwise need a lot of arithmetic operations to simulate this operation).
|
||||
* Since most of the major ARM linux distros are built for ARMv7, we are
|
||||
* much less dependent on runtime CPU detection and can get practical
|
||||
* benefits from conditional compilation here for a lot of users.
|
||||
*/
|
||||
|
||||
#if defined(USE_GCC_INLINE_ASM) && defined(__arm__) && \
|
||||
!defined(__aarch64__) && (!defined(__thumb__) || defined(__thumb2__))
|
||||
#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \
|
||||
defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \
|
||||
defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) || \
|
||||
defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_7__) || \
|
||||
defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || \
|
||||
defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
|
||||
|
||||
static force_inline uint32_t
|
||||
un8x4_add_un8x4 (uint32_t x, uint32_t y)
|
||||
{
|
||||
uint32_t t;
|
||||
asm ("uqadd8 %0, %1, %2" : "=r" (t) : "%r" (x), "r" (y));
|
||||
return t;
|
||||
}
|
||||
|
||||
#define UN8x4_ADD_UN8x4(x, y) \
|
||||
((x) = un8x4_add_un8x4 ((x), (y)))
|
||||
|
||||
#define UN8_rb_ADD_UN8_rb(x, y, t) \
|
||||
((t) = un8x4_add_un8x4 ((x), (y)), (x) = (t))
|
||||
|
||||
#define ADD_UN8(x, y, t) \
|
||||
((t) = (x), un8x4_add_un8x4 ((t), (y)))
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Helper macros.
|
||||
*/
|
||||
|
||||
#define MUL_UN8(a, b, t) \
|
||||
((t) = (a) * (uint16_t)(b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT ))
|
||||
|
||||
#define DIV_UN8(a, b) \
|
||||
(((uint16_t) (a) * MASK + ((b) / 2)) / (b))
|
||||
|
||||
#ifndef ADD_UN8
|
||||
#define ADD_UN8(x, y, t) \
|
||||
((t) = (x) + (y), \
|
||||
(uint32_t) (uint8_t) ((t) | (0 - ((t) >> G_SHIFT))))
|
||||
#endif
|
||||
|
||||
#define DIV_ONE_UN8(x) \
|
||||
(((x) + ONE_HALF + (((x) + ONE_HALF) >> G_SHIFT)) >> G_SHIFT)
|
||||
|
||||
/*
|
||||
* The methods below use some tricks to be able to do two color
|
||||
* components at the same time.
|
||||
*/
|
||||
|
||||
/*
|
||||
* x_rb = (x_rb * a) / 255
|
||||
*/
|
||||
#define UN8_rb_MUL_UN8(x, a, t) \
|
||||
do \
|
||||
{ \
|
||||
t = ((x) & RB_MASK) * (a); \
|
||||
t += RB_ONE_HALF; \
|
||||
x = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT; \
|
||||
x &= RB_MASK; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_rb = min (x_rb + y_rb, 255)
|
||||
*/
|
||||
#ifndef UN8_rb_ADD_UN8_rb
|
||||
#define UN8_rb_ADD_UN8_rb(x, y, t) \
|
||||
do \
|
||||
{ \
|
||||
t = ((x) + (y)); \
|
||||
t |= RB_MASK_PLUS_ONE - ((t >> G_SHIFT) & RB_MASK); \
|
||||
x = (t & RB_MASK); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* x_rb = (x_rb * a_rb) / 255
|
||||
*/
|
||||
#define UN8_rb_MUL_UN8_rb(x, a, t) \
|
||||
do \
|
||||
{ \
|
||||
t = (x & MASK) * (a & MASK); \
|
||||
t |= (x & R_MASK) * ((a >> R_SHIFT) & MASK); \
|
||||
t += RB_ONE_HALF; \
|
||||
t = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT; \
|
||||
x = t & RB_MASK; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a) / 255
|
||||
*/
|
||||
#define UN8x4_MUL_UN8(x, a) \
|
||||
do \
|
||||
{ \
|
||||
uint32_t r1__, r2__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
UN8_rb_MUL_UN8 (r1__, (a), t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
UN8_rb_MUL_UN8 (r2__, (a), t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a) / 255 + y_c
|
||||
*/
|
||||
#define UN8x4_MUL_UN8_ADD_UN8x4(x, a, y) \
|
||||
do \
|
||||
{ \
|
||||
uint32_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (y) & RB_MASK; \
|
||||
UN8_rb_MUL_UN8 (r1__, (a), t__); \
|
||||
UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
r3__ = ((y) >> G_SHIFT) & RB_MASK; \
|
||||
UN8_rb_MUL_UN8 (r2__, (a), t__); \
|
||||
UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a + y_c * b) / 255
|
||||
*/
|
||||
#define UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8(x, a, y, b) \
|
||||
do \
|
||||
{ \
|
||||
uint32_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (y); \
|
||||
UN8_rb_MUL_UN8 (r1__, (a), t__); \
|
||||
UN8_rb_MUL_UN8 (r2__, (b), t__); \
|
||||
UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = ((x) >> G_SHIFT); \
|
||||
r3__ = ((y) >> G_SHIFT); \
|
||||
UN8_rb_MUL_UN8 (r2__, (a), t__); \
|
||||
UN8_rb_MUL_UN8 (r3__, (b), t__); \
|
||||
UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a_c) / 255
|
||||
*/
|
||||
#define UN8x4_MUL_UN8x4(x, a) \
|
||||
do \
|
||||
{ \
|
||||
uint32_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (a); \
|
||||
UN8_rb_MUL_UN8_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
r3__ = (a) >> G_SHIFT; \
|
||||
UN8_rb_MUL_UN8_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a_c) / 255 + y_c
|
||||
*/
|
||||
#define UN8x4_MUL_UN8x4_ADD_UN8x4(x, a, y) \
|
||||
do \
|
||||
{ \
|
||||
uint32_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (a); \
|
||||
UN8_rb_MUL_UN8_rb (r1__, r2__, t__); \
|
||||
r2__ = (y) & RB_MASK; \
|
||||
UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = ((x) >> G_SHIFT); \
|
||||
r3__ = ((a) >> G_SHIFT); \
|
||||
UN8_rb_MUL_UN8_rb (r2__, r3__, t__); \
|
||||
r3__ = ((y) >> G_SHIFT) & RB_MASK; \
|
||||
UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \
|
||||
\
|
||||
(x) = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* x_c = (x_c * a_c + y_c * b) / 255
|
||||
*/
|
||||
#define UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8(x, a, y, b) \
|
||||
do \
|
||||
{ \
|
||||
uint32_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x); \
|
||||
r2__ = (a); \
|
||||
UN8_rb_MUL_UN8_rb (r1__, r2__, t__); \
|
||||
r2__ = (y); \
|
||||
UN8_rb_MUL_UN8 (r2__, (b), t__); \
|
||||
UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = (x) >> G_SHIFT; \
|
||||
r3__ = (a) >> G_SHIFT; \
|
||||
UN8_rb_MUL_UN8_rb (r2__, r3__, t__); \
|
||||
r3__ = (y) >> G_SHIFT; \
|
||||
UN8_rb_MUL_UN8 (r3__, (b), t__); \
|
||||
UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \
|
||||
\
|
||||
x = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
x_c = min(x_c + y_c, 255)
|
||||
*/
|
||||
#ifndef UN8x4_ADD_UN8x4
|
||||
#define UN8x4_ADD_UN8x4(x, y) \
|
||||
do \
|
||||
{ \
|
||||
uint32_t r1__, r2__, r3__, t__; \
|
||||
\
|
||||
r1__ = (x) & RB_MASK; \
|
||||
r2__ = (y) & RB_MASK; \
|
||||
UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \
|
||||
\
|
||||
r2__ = ((x) >> G_SHIFT) & RB_MASK; \
|
||||
r3__ = ((y) >> G_SHIFT) & RB_MASK; \
|
||||
UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \
|
||||
\
|
||||
x = r1__ | (r2__ << G_SHIFT); \
|
||||
} while (0)
|
||||
#endif
|
@ -1,232 +0,0 @@
|
||||
/* Pixman uses some non-standard compiler features. This file ensures
|
||||
* they exist
|
||||
*
|
||||
* The features are:
|
||||
*
|
||||
* FUNC must be defined to expand to the current function
|
||||
* PIXMAN_EXPORT should be defined to whatever is required to
|
||||
* export functions from a shared library
|
||||
* limits limits for various types must be defined
|
||||
* inline must be defined
|
||||
* force_inline must be defined
|
||||
*/
|
||||
#if defined (__GNUC__)
|
||||
# define FUNC ((const char*) (__PRETTY_FUNCTION__))
|
||||
#elif defined (__sun) || (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
|
||||
# define FUNC ((const char*) (__func__))
|
||||
#else
|
||||
# define FUNC ((const char*) ("???"))
|
||||
#endif
|
||||
|
||||
#if defined (__GNUC__)
|
||||
# define unlikely(expr) __builtin_expect ((expr), 0)
|
||||
#else
|
||||
# define unlikely(expr) (expr)
|
||||
#endif
|
||||
|
||||
#if defined (__GNUC__)
|
||||
# define MAYBE_UNUSED __attribute__((unused))
|
||||
#else
|
||||
# define MAYBE_UNUSED
|
||||
#endif
|
||||
|
||||
#ifndef INT16_MIN
|
||||
# define INT16_MIN (-32767-1)
|
||||
#endif
|
||||
|
||||
#ifndef INT16_MAX
|
||||
# define INT16_MAX (32767)
|
||||
#endif
|
||||
|
||||
#ifndef INT32_MIN
|
||||
# define INT32_MIN (-2147483647-1)
|
||||
#endif
|
||||
|
||||
#ifndef INT32_MAX
|
||||
# define INT32_MAX (2147483647)
|
||||
#endif
|
||||
|
||||
#ifndef UINT32_MIN
|
||||
# define UINT32_MIN (0)
|
||||
#endif
|
||||
|
||||
#ifndef UINT32_MAX
|
||||
# define UINT32_MAX (4294967295U)
|
||||
#endif
|
||||
|
||||
#ifndef INT64_MIN
|
||||
# define INT64_MIN (-9223372036854775807-1)
|
||||
#endif
|
||||
|
||||
#ifndef INT64_MAX
|
||||
# define INT64_MAX (9223372036854775807)
|
||||
#endif
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
# define SIZE_MAX ((size_t)-1)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef M_PI
|
||||
# define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
/* 'inline' is available only in C++ in MSVC */
|
||||
# define inline __inline
|
||||
# define force_inline __forceinline
|
||||
# define noinline __declspec(noinline)
|
||||
#elif defined __GNUC__ || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
|
||||
# define inline __inline__
|
||||
# define force_inline __inline__ __attribute__ ((__always_inline__))
|
||||
# define noinline __attribute__((noinline))
|
||||
#else
|
||||
# ifndef force_inline
|
||||
# define force_inline inline
|
||||
# endif
|
||||
# ifndef noinline
|
||||
# define noinline
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* GCC visibility */
|
||||
#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(_WIN32)
|
||||
# define PIXMAN_EXPORT __attribute__ ((visibility("default")))
|
||||
/* Sun Studio 8 visibility */
|
||||
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
|
||||
# define PIXMAN_EXPORT __global
|
||||
#else
|
||||
# define PIXMAN_EXPORT
|
||||
#endif
|
||||
|
||||
/* member offsets */
|
||||
#define CONTAINER_OF(type, member, data) \
|
||||
((type *)(((uint8_t *)data) - offsetof (type, member)))
|
||||
|
||||
/* TLS */
|
||||
#if defined(PIXMAN_NO_TLS)
|
||||
|
||||
# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \
|
||||
static type name
|
||||
# define PIXMAN_GET_THREAD_LOCAL(name) \
|
||||
(&name)
|
||||
|
||||
#elif defined(TLS)
|
||||
|
||||
# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \
|
||||
static TLS type name
|
||||
# define PIXMAN_GET_THREAD_LOCAL(name) \
|
||||
(&name)
|
||||
|
||||
#elif defined(__MINGW32__)
|
||||
|
||||
# define _NO_W32_PSEUDO_MODIFIERS
|
||||
# include <windows.h>
|
||||
|
||||
# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \
|
||||
static volatile int tls_ ## name ## _initialized = 0; \
|
||||
static void *tls_ ## name ## _mutex = NULL; \
|
||||
static unsigned tls_ ## name ## _index; \
|
||||
\
|
||||
static type * \
|
||||
tls_ ## name ## _alloc (void) \
|
||||
{ \
|
||||
type *value = calloc (1, sizeof (type)); \
|
||||
if (value) \
|
||||
TlsSetValue (tls_ ## name ## _index, value); \
|
||||
return value; \
|
||||
} \
|
||||
\
|
||||
static force_inline type * \
|
||||
tls_ ## name ## _get (void) \
|
||||
{ \
|
||||
type *value; \
|
||||
if (!tls_ ## name ## _initialized) \
|
||||
{ \
|
||||
if (!tls_ ## name ## _mutex) \
|
||||
{ \
|
||||
void *mutex = CreateMutexA (NULL, 0, NULL); \
|
||||
if (InterlockedCompareExchangePointer ( \
|
||||
&tls_ ## name ## _mutex, mutex, NULL) != NULL) \
|
||||
{ \
|
||||
CloseHandle (mutex); \
|
||||
} \
|
||||
} \
|
||||
WaitForSingleObject (tls_ ## name ## _mutex, 0xFFFFFFFF); \
|
||||
if (!tls_ ## name ## _initialized) \
|
||||
{ \
|
||||
tls_ ## name ## _index = TlsAlloc (); \
|
||||
tls_ ## name ## _initialized = 1; \
|
||||
} \
|
||||
ReleaseMutex (tls_ ## name ## _mutex); \
|
||||
} \
|
||||
if (tls_ ## name ## _index == 0xFFFFFFFF) \
|
||||
return NULL; \
|
||||
value = TlsGetValue (tls_ ## name ## _index); \
|
||||
if (!value) \
|
||||
value = tls_ ## name ## _alloc (); \
|
||||
return value; \
|
||||
}
|
||||
|
||||
# define PIXMAN_GET_THREAD_LOCAL(name) \
|
||||
tls_ ## name ## _get ()
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \
|
||||
static __declspec(thread) type name
|
||||
# define PIXMAN_GET_THREAD_LOCAL(name) \
|
||||
(&name)
|
||||
|
||||
#elif defined(HAVE_PTHREAD_SETSPECIFIC)
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \
|
||||
static pthread_once_t tls_ ## name ## _once_control = PTHREAD_ONCE_INIT; \
|
||||
static pthread_key_t tls_ ## name ## _key; \
|
||||
\
|
||||
static void \
|
||||
tls_ ## name ## _destroy_value (void *value) \
|
||||
{ \
|
||||
free (value); \
|
||||
} \
|
||||
\
|
||||
static void \
|
||||
tls_ ## name ## _make_key (void) \
|
||||
{ \
|
||||
pthread_key_create (&tls_ ## name ## _key, \
|
||||
tls_ ## name ## _destroy_value); \
|
||||
} \
|
||||
\
|
||||
static type * \
|
||||
tls_ ## name ## _alloc (void) \
|
||||
{ \
|
||||
type *value = calloc (1, sizeof (type)); \
|
||||
if (value) \
|
||||
pthread_setspecific (tls_ ## name ## _key, value); \
|
||||
return value; \
|
||||
} \
|
||||
\
|
||||
static force_inline type * \
|
||||
tls_ ## name ## _get (void) \
|
||||
{ \
|
||||
type *value = NULL; \
|
||||
if (pthread_once (&tls_ ## name ## _once_control, \
|
||||
tls_ ## name ## _make_key) == 0) \
|
||||
{ \
|
||||
value = pthread_getspecific (tls_ ## name ## _key); \
|
||||
if (!value) \
|
||||
value = tls_ ## name ## _alloc (); \
|
||||
} \
|
||||
return value; \
|
||||
}
|
||||
|
||||
# define PIXMAN_GET_THREAD_LOCAL(name) \
|
||||
tls_ ## name ## _get ()
|
||||
|
||||
#else
|
||||
|
||||
# error "Unknown thread local support for this system. Pixman will not work with multiple threads. Define PIXMAN_NO_TLS to acknowledge and accept this limitation and compile pixman without thread-safety support."
|
||||
|
||||
#endif
|
@ -1,212 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2000 SuSE, Inc.
|
||||
* Copyright © 2007 Red Hat, Inc.
|
||||
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
|
||||
* 2005 Lars Knoll & Zack Rusin, Trolltech
|
||||
*
|
||||
* 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 Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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 <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "pixman-private.h"
|
||||
|
||||
static force_inline double
|
||||
coordinates_to_parameter (double x, double y, double angle)
|
||||
{
|
||||
double t;
|
||||
|
||||
t = atan2 (y, x) + angle;
|
||||
|
||||
while (t < 0)
|
||||
t += 2 * M_PI;
|
||||
|
||||
while (t >= 2 * M_PI)
|
||||
t -= 2 * M_PI;
|
||||
|
||||
return 1 - t * (1 / (2 * M_PI)); /* Scale t to [0, 1] and
|
||||
* make rotation CCW
|
||||
*/
|
||||
}
|
||||
|
||||
static uint32_t *
|
||||
conical_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
pixman_image_t *image = iter->image;
|
||||
int x = iter->x;
|
||||
int y = iter->y;
|
||||
int width = iter->width;
|
||||
uint32_t *buffer = iter->buffer;
|
||||
|
||||
gradient_t *gradient = (gradient_t *)image;
|
||||
conical_gradient_t *conical = (conical_gradient_t *)image;
|
||||
uint32_t *end = buffer + width;
|
||||
pixman_gradient_walker_t walker;
|
||||
pixman_bool_t affine = TRUE;
|
||||
double cx = 1.;
|
||||
double cy = 0.;
|
||||
double cz = 0.;
|
||||
double rx = x + 0.5;
|
||||
double ry = y + 0.5;
|
||||
double rz = 1.;
|
||||
|
||||
_pixman_gradient_walker_init (&walker, gradient, image->common.repeat);
|
||||
|
||||
if (image->common.transform)
|
||||
{
|
||||
pixman_vector_t v;
|
||||
|
||||
/* reference point is the center of the pixel */
|
||||
v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2;
|
||||
v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
|
||||
v.vector[2] = pixman_fixed_1;
|
||||
|
||||
if (!pixman_transform_point_3d (image->common.transform, &v))
|
||||
return iter->buffer;
|
||||
|
||||
cx = image->common.transform->matrix[0][0] / 65536.;
|
||||
cy = image->common.transform->matrix[1][0] / 65536.;
|
||||
cz = image->common.transform->matrix[2][0] / 65536.;
|
||||
|
||||
rx = v.vector[0] / 65536.;
|
||||
ry = v.vector[1] / 65536.;
|
||||
rz = v.vector[2] / 65536.;
|
||||
|
||||
affine =
|
||||
image->common.transform->matrix[2][0] == 0 &&
|
||||
v.vector[2] == pixman_fixed_1;
|
||||
}
|
||||
|
||||
if (affine)
|
||||
{
|
||||
rx -= conical->center.x / 65536.;
|
||||
ry -= conical->center.y / 65536.;
|
||||
|
||||
while (buffer < end)
|
||||
{
|
||||
if (!mask || *mask++)
|
||||
{
|
||||
double t = coordinates_to_parameter (rx, ry, conical->angle);
|
||||
|
||||
*buffer = _pixman_gradient_walker_pixel (
|
||||
&walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t));
|
||||
}
|
||||
|
||||
++buffer;
|
||||
|
||||
rx += cx;
|
||||
ry += cy;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (buffer < end)
|
||||
{
|
||||
double x, y;
|
||||
|
||||
if (!mask || *mask++)
|
||||
{
|
||||
double t;
|
||||
|
||||
if (rz != 0)
|
||||
{
|
||||
x = rx / rz;
|
||||
y = ry / rz;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = y = 0.;
|
||||
}
|
||||
|
||||
x -= conical->center.x / 65536.;
|
||||
y -= conical->center.y / 65536.;
|
||||
|
||||
t = coordinates_to_parameter (x, y, conical->angle);
|
||||
|
||||
*buffer = _pixman_gradient_walker_pixel (
|
||||
&walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t));
|
||||
}
|
||||
|
||||
++buffer;
|
||||
|
||||
rx += cx;
|
||||
ry += cy;
|
||||
rz += cz;
|
||||
}
|
||||
}
|
||||
|
||||
iter->y++;
|
||||
return iter->buffer;
|
||||
}
|
||||
|
||||
static uint32_t *
|
||||
conical_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
uint32_t *buffer = conical_get_scanline_narrow (iter, NULL);
|
||||
|
||||
pixman_expand_to_float (
|
||||
(argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_conical_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter)
|
||||
{
|
||||
if (iter->iter_flags & ITER_NARROW)
|
||||
iter->get_scanline = conical_get_scanline_narrow;
|
||||
else
|
||||
iter->get_scanline = conical_get_scanline_wide;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT pixman_image_t *
|
||||
pixman_image_create_conical_gradient (const pixman_point_fixed_t * center,
|
||||
pixman_fixed_t angle,
|
||||
const pixman_gradient_stop_t *stops,
|
||||
int n_stops)
|
||||
{
|
||||
pixman_image_t *image = _pixman_image_allocate ();
|
||||
conical_gradient_t *conical;
|
||||
|
||||
if (!image)
|
||||
return NULL;
|
||||
|
||||
conical = &image->conical;
|
||||
|
||||
if (!_pixman_init_gradient (&conical->common, stops, n_stops))
|
||||
{
|
||||
free (image);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
angle = MOD (angle, pixman_int_to_fixed (360));
|
||||
|
||||
image->type = CONICAL;
|
||||
|
||||
conical->center = *center;
|
||||
conical->angle = (pixman_fixed_to_double (angle) / 180.0) * M_PI;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
@ -1,4 +0,0 @@
|
||||
|
||||
#define PIXMAN_FB_ACCESSORS
|
||||
|
||||
#include "pixman-edge.c"
|
@ -1,182 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2004 Keith Packard
|
||||
*
|
||||
* 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 Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL KEITH PACKARD 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.
|
||||
*/
|
||||
|
||||
#ifndef rasterize_span
|
||||
#endif
|
||||
|
||||
static void
|
||||
RASTERIZE_EDGES (pixman_image_t *image,
|
||||
pixman_edge_t *l,
|
||||
pixman_edge_t *r,
|
||||
pixman_fixed_t t,
|
||||
pixman_fixed_t b)
|
||||
{
|
||||
pixman_fixed_t y = t;
|
||||
uint32_t *line;
|
||||
uint32_t *buf = (image)->bits.bits;
|
||||
int stride = (image)->bits.rowstride;
|
||||
int width = (image)->bits.width;
|
||||
|
||||
line = buf + pixman_fixed_to_int (y) * stride;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
pixman_fixed_t lx;
|
||||
pixman_fixed_t rx;
|
||||
int lxi;
|
||||
int rxi;
|
||||
|
||||
lx = l->x;
|
||||
rx = r->x;
|
||||
#if N_BITS == 1
|
||||
/* For the non-antialiased case, round the coordinates up, in effect
|
||||
* sampling just slightly to the left of the pixel. This is so that
|
||||
* when the sample point lies exactly on the line, we round towards
|
||||
* north-west.
|
||||
*
|
||||
* (The AA case does a similar adjustment in RENDER_SAMPLES_X)
|
||||
*/
|
||||
lx += X_FRAC_FIRST(1) - pixman_fixed_e;
|
||||
rx += X_FRAC_FIRST(1) - pixman_fixed_e;
|
||||
#endif
|
||||
/* clip X */
|
||||
if (lx < 0)
|
||||
lx = 0;
|
||||
if (pixman_fixed_to_int (rx) >= width)
|
||||
#if N_BITS == 1
|
||||
rx = pixman_int_to_fixed (width);
|
||||
#else
|
||||
/* Use the last pixel of the scanline, covered 100%.
|
||||
* We can't use the first pixel following the scanline,
|
||||
* because accessing it could result in a buffer overrun.
|
||||
*/
|
||||
rx = pixman_int_to_fixed (width) - 1;
|
||||
#endif
|
||||
|
||||
/* Skip empty (or backwards) sections */
|
||||
if (rx > lx)
|
||||
{
|
||||
|
||||
/* Find pixel bounds for span */
|
||||
lxi = pixman_fixed_to_int (lx);
|
||||
rxi = pixman_fixed_to_int (rx);
|
||||
|
||||
#if N_BITS == 1
|
||||
{
|
||||
|
||||
#define LEFT_MASK(x) \
|
||||
(((x) & 0x1f) ? \
|
||||
SCREEN_SHIFT_RIGHT (0xffffffff, (x) & 0x1f) : 0)
|
||||
#define RIGHT_MASK(x) \
|
||||
(((32 - (x)) & 0x1f) ? \
|
||||
SCREEN_SHIFT_LEFT (0xffffffff, (32 - (x)) & 0x1f) : 0)
|
||||
|
||||
#define MASK_BITS(x,w,l,n,r) { \
|
||||
n = (w); \
|
||||
r = RIGHT_MASK ((x) + n); \
|
||||
l = LEFT_MASK (x); \
|
||||
if (l) { \
|
||||
n -= 32 - ((x) & 0x1f); \
|
||||
if (n < 0) { \
|
||||
n = 0; \
|
||||
l &= r; \
|
||||
r = 0; \
|
||||
} \
|
||||
} \
|
||||
n >>= 5; \
|
||||
}
|
||||
|
||||
uint32_t *a = line;
|
||||
uint32_t startmask;
|
||||
uint32_t endmask;
|
||||
int nmiddle;
|
||||
int width = rxi - lxi;
|
||||
int x = lxi;
|
||||
|
||||
a += x >> 5;
|
||||
x &= 0x1f;
|
||||
|
||||
MASK_BITS (x, width, startmask, nmiddle, endmask);
|
||||
|
||||
if (startmask) {
|
||||
WRITE(image, a, READ(image, a) | startmask);
|
||||
a++;
|
||||
}
|
||||
while (nmiddle--)
|
||||
WRITE(image, a++, 0xffffffff);
|
||||
if (endmask)
|
||||
WRITE(image, a, READ(image, a) | endmask);
|
||||
}
|
||||
#else
|
||||
{
|
||||
DEFINE_ALPHA(line,lxi);
|
||||
int lxs;
|
||||
int rxs;
|
||||
|
||||
/* Sample coverage for edge pixels */
|
||||
lxs = RENDER_SAMPLES_X (lx, N_BITS);
|
||||
rxs = RENDER_SAMPLES_X (rx, N_BITS);
|
||||
|
||||
/* Add coverage across row */
|
||||
if (lxi == rxi)
|
||||
{
|
||||
ADD_ALPHA (rxs - lxs);
|
||||
}
|
||||
else
|
||||
{
|
||||
int xi;
|
||||
|
||||
ADD_ALPHA (N_X_FRAC(N_BITS) - lxs);
|
||||
STEP_ALPHA;
|
||||
for (xi = lxi + 1; xi < rxi; xi++)
|
||||
{
|
||||
ADD_ALPHA (N_X_FRAC(N_BITS));
|
||||
STEP_ALPHA;
|
||||
}
|
||||
ADD_ALPHA (rxs);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (y == b)
|
||||
break;
|
||||
|
||||
#if N_BITS > 1
|
||||
if (pixman_fixed_frac (y) != Y_FRAC_LAST(N_BITS))
|
||||
{
|
||||
RENDER_EDGE_STEP_SMALL (l);
|
||||
RENDER_EDGE_STEP_SMALL (r);
|
||||
y += STEP_Y_SMALL(N_BITS);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
RENDER_EDGE_STEP_BIG (l);
|
||||
RENDER_EDGE_STEP_BIG (r);
|
||||
y += STEP_Y_BIG(N_BITS);
|
||||
line += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef rasterize_span
|
@ -1,385 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2004 Keith Packard
|
||||
*
|
||||
* 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 Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL KEITH PACKARD 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 <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "pixman-private.h"
|
||||
#include "pixman-accessor.h"
|
||||
|
||||
/*
|
||||
* Step across a small sample grid gap
|
||||
*/
|
||||
#define RENDER_EDGE_STEP_SMALL(edge) \
|
||||
{ \
|
||||
edge->x += edge->stepx_small; \
|
||||
edge->e += edge->dx_small; \
|
||||
if (edge->e > 0) \
|
||||
{ \
|
||||
edge->e -= edge->dy; \
|
||||
edge->x += edge->signdx; \
|
||||
} \
|
||||
}
|
||||
|
||||
/*
|
||||
* Step across a large sample grid gap
|
||||
*/
|
||||
#define RENDER_EDGE_STEP_BIG(edge) \
|
||||
{ \
|
||||
edge->x += edge->stepx_big; \
|
||||
edge->e += edge->dx_big; \
|
||||
if (edge->e > 0) \
|
||||
{ \
|
||||
edge->e -= edge->dy; \
|
||||
edge->x += edge->signdx; \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifdef PIXMAN_FB_ACCESSORS
|
||||
#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_accessors
|
||||
#else
|
||||
#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_no_accessors
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 4 bit alpha
|
||||
*/
|
||||
|
||||
#define N_BITS 4
|
||||
#define RASTERIZE_EDGES rasterize_edges_4
|
||||
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
#define SHIFT_4(o) ((o) << 2)
|
||||
#else
|
||||
#define SHIFT_4(o) ((1 - (o)) << 2)
|
||||
#endif
|
||||
|
||||
#define GET_4(x, o) (((x) >> SHIFT_4 (o)) & 0xf)
|
||||
#define PUT_4(x, o, v) \
|
||||
(((x) & ~(0xf << SHIFT_4 (o))) | (((v) & 0xf) << SHIFT_4 (o)))
|
||||
|
||||
#define DEFINE_ALPHA(line, x) \
|
||||
uint8_t *__ap = (uint8_t *) line + ((x) >> 1); \
|
||||
int __ao = (x) & 1
|
||||
|
||||
#define STEP_ALPHA ((__ap += __ao), (__ao ^= 1))
|
||||
|
||||
#define ADD_ALPHA(a) \
|
||||
{ \
|
||||
uint8_t __o = READ (image, __ap); \
|
||||
uint8_t __a = (a) + GET_4 (__o, __ao); \
|
||||
WRITE (image, __ap, PUT_4 (__o, __ao, __a | (0 - ((__a) >> 4)))); \
|
||||
}
|
||||
|
||||
#include "pixman-edge-imp.h"
|
||||
|
||||
#undef ADD_ALPHA
|
||||
#undef STEP_ALPHA
|
||||
#undef DEFINE_ALPHA
|
||||
#undef RASTERIZE_EDGES
|
||||
#undef N_BITS
|
||||
|
||||
|
||||
/*
|
||||
* 1 bit alpha
|
||||
*/
|
||||
|
||||
#define N_BITS 1
|
||||
#define RASTERIZE_EDGES rasterize_edges_1
|
||||
|
||||
#include "pixman-edge-imp.h"
|
||||
|
||||
#undef RASTERIZE_EDGES
|
||||
#undef N_BITS
|
||||
|
||||
/*
|
||||
* 8 bit alpha
|
||||
*/
|
||||
|
||||
static force_inline uint8_t
|
||||
clip255 (int x)
|
||||
{
|
||||
if (x > 255)
|
||||
return 255;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
#define ADD_SATURATE_8(buf, val, length) \
|
||||
do \
|
||||
{ \
|
||||
int i__ = (length); \
|
||||
uint8_t *buf__ = (buf); \
|
||||
int val__ = (val); \
|
||||
\
|
||||
while (i__--) \
|
||||
{ \
|
||||
WRITE (image, (buf__), clip255 (READ (image, (buf__)) + (val__))); \
|
||||
(buf__)++; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* We want to detect the case where we add the same value to a long
|
||||
* span of pixels. The triangles on the end are filled in while we
|
||||
* count how many sub-pixel scanlines contribute to the middle section.
|
||||
*
|
||||
* +--------------------------+
|
||||
* fill_height =| \ /
|
||||
* +------------------+
|
||||
* |================|
|
||||
* fill_start fill_end
|
||||
*/
|
||||
static void
|
||||
rasterize_edges_8 (pixman_image_t *image,
|
||||
pixman_edge_t * l,
|
||||
pixman_edge_t * r,
|
||||
pixman_fixed_t t,
|
||||
pixman_fixed_t b)
|
||||
{
|
||||
pixman_fixed_t y = t;
|
||||
uint32_t *line;
|
||||
int fill_start = -1, fill_end = -1;
|
||||
int fill_size = 0;
|
||||
uint32_t *buf = (image)->bits.bits;
|
||||
int stride = (image)->bits.rowstride;
|
||||
int width = (image)->bits.width;
|
||||
|
||||
line = buf + pixman_fixed_to_int (y) * stride;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
uint8_t *ap = (uint8_t *) line;
|
||||
pixman_fixed_t lx, rx;
|
||||
int lxi, rxi;
|
||||
|
||||
/* clip X */
|
||||
lx = l->x;
|
||||
if (lx < 0)
|
||||
lx = 0;
|
||||
|
||||
rx = r->x;
|
||||
|
||||
if (pixman_fixed_to_int (rx) >= width)
|
||||
{
|
||||
/* Use the last pixel of the scanline, covered 100%.
|
||||
* We can't use the first pixel following the scanline,
|
||||
* because accessing it could result in a buffer overrun.
|
||||
*/
|
||||
rx = pixman_int_to_fixed (width) - 1;
|
||||
}
|
||||
|
||||
/* Skip empty (or backwards) sections */
|
||||
if (rx > lx)
|
||||
{
|
||||
int lxs, rxs;
|
||||
|
||||
/* Find pixel bounds for span. */
|
||||
lxi = pixman_fixed_to_int (lx);
|
||||
rxi = pixman_fixed_to_int (rx);
|
||||
|
||||
/* Sample coverage for edge pixels */
|
||||
lxs = RENDER_SAMPLES_X (lx, 8);
|
||||
rxs = RENDER_SAMPLES_X (rx, 8);
|
||||
|
||||
/* Add coverage across row */
|
||||
if (lxi == rxi)
|
||||
{
|
||||
WRITE (image, ap + lxi,
|
||||
clip255 (READ (image, ap + lxi) + rxs - lxs));
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE (image, ap + lxi,
|
||||
clip255 (READ (image, ap + lxi) + N_X_FRAC (8) - lxs));
|
||||
|
||||
/* Move forward so that lxi/rxi is the pixel span */
|
||||
lxi++;
|
||||
|
||||
/* Don't bother trying to optimize the fill unless
|
||||
* the span is longer than 4 pixels. */
|
||||
if (rxi - lxi > 4)
|
||||
{
|
||||
if (fill_start < 0)
|
||||
{
|
||||
fill_start = lxi;
|
||||
fill_end = rxi;
|
||||
fill_size++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lxi >= fill_end || rxi < fill_start)
|
||||
{
|
||||
/* We're beyond what we saved, just fill it */
|
||||
ADD_SATURATE_8 (ap + fill_start,
|
||||
fill_size * N_X_FRAC (8),
|
||||
fill_end - fill_start);
|
||||
fill_start = lxi;
|
||||
fill_end = rxi;
|
||||
fill_size = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update fill_start */
|
||||
if (lxi > fill_start)
|
||||
{
|
||||
ADD_SATURATE_8 (ap + fill_start,
|
||||
fill_size * N_X_FRAC (8),
|
||||
lxi - fill_start);
|
||||
fill_start = lxi;
|
||||
}
|
||||
else if (lxi < fill_start)
|
||||
{
|
||||
ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8),
|
||||
fill_start - lxi);
|
||||
}
|
||||
|
||||
/* Update fill_end */
|
||||
if (rxi < fill_end)
|
||||
{
|
||||
ADD_SATURATE_8 (ap + rxi,
|
||||
fill_size * N_X_FRAC (8),
|
||||
fill_end - rxi);
|
||||
fill_end = rxi;
|
||||
}
|
||||
else if (fill_end < rxi)
|
||||
{
|
||||
ADD_SATURATE_8 (ap + fill_end,
|
||||
N_X_FRAC (8),
|
||||
rxi - fill_end);
|
||||
}
|
||||
fill_size++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8), rxi - lxi);
|
||||
}
|
||||
|
||||
WRITE (image, ap + rxi, clip255 (READ (image, ap + rxi) + rxs));
|
||||
}
|
||||
}
|
||||
|
||||
if (y == b)
|
||||
{
|
||||
/* We're done, make sure we clean up any remaining fill. */
|
||||
if (fill_start != fill_end)
|
||||
{
|
||||
if (fill_size == N_Y_FRAC (8))
|
||||
{
|
||||
MEMSET_WRAPPED (image, ap + fill_start,
|
||||
0xff, fill_end - fill_start);
|
||||
}
|
||||
else
|
||||
{
|
||||
ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
|
||||
fill_end - fill_start);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (pixman_fixed_frac (y) != Y_FRAC_LAST (8))
|
||||
{
|
||||
RENDER_EDGE_STEP_SMALL (l);
|
||||
RENDER_EDGE_STEP_SMALL (r);
|
||||
y += STEP_Y_SMALL (8);
|
||||
}
|
||||
else
|
||||
{
|
||||
RENDER_EDGE_STEP_BIG (l);
|
||||
RENDER_EDGE_STEP_BIG (r);
|
||||
y += STEP_Y_BIG (8);
|
||||
if (fill_start != fill_end)
|
||||
{
|
||||
if (fill_size == N_Y_FRAC (8))
|
||||
{
|
||||
MEMSET_WRAPPED (image, ap + fill_start,
|
||||
0xff, fill_end - fill_start);
|
||||
}
|
||||
else
|
||||
{
|
||||
ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
|
||||
fill_end - fill_start);
|
||||
}
|
||||
|
||||
fill_start = fill_end = -1;
|
||||
fill_size = 0;
|
||||
}
|
||||
|
||||
line += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef PIXMAN_FB_ACCESSORS
|
||||
static
|
||||
#endif
|
||||
void
|
||||
PIXMAN_RASTERIZE_EDGES (pixman_image_t *image,
|
||||
pixman_edge_t * l,
|
||||
pixman_edge_t * r,
|
||||
pixman_fixed_t t,
|
||||
pixman_fixed_t b)
|
||||
{
|
||||
switch (PIXMAN_FORMAT_BPP (image->bits.format))
|
||||
{
|
||||
case 1:
|
||||
rasterize_edges_1 (image, l, r, t, b);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
rasterize_edges_4 (image, l, r, t, b);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
rasterize_edges_8 (image, l, r, t, b);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef PIXMAN_FB_ACCESSORS
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_rasterize_edges (pixman_image_t *image,
|
||||
pixman_edge_t * l,
|
||||
pixman_edge_t * r,
|
||||
pixman_fixed_t t,
|
||||
pixman_fixed_t b)
|
||||
{
|
||||
return_if_fail (image->type == BITS);
|
||||
return_if_fail (PIXMAN_FORMAT_TYPE (image->bits.format) == PIXMAN_TYPE_A);
|
||||
|
||||
if (image->bits.read_func || image->bits.write_func)
|
||||
pixman_rasterize_edges_accessors (image, l, r, t, b);
|
||||
else
|
||||
pixman_rasterize_edges_no_accessors (image, l, r, t, b);
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,350 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012, Red Hat, Inc.
|
||||
* Copyright 2012, Soren Sandmann
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Author: Soren Sandmann <soren.sandmann@gmail.com>
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include "pixman-private.h"
|
||||
|
||||
typedef double (* kernel_func_t) (double x);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
pixman_kernel_t kernel;
|
||||
kernel_func_t func;
|
||||
double width;
|
||||
} filter_info_t;
|
||||
|
||||
static double
|
||||
impulse_kernel (double x)
|
||||
{
|
||||
return (x == 0.0)? 1.0 : 0.0;
|
||||
}
|
||||
|
||||
static double
|
||||
box_kernel (double x)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static double
|
||||
linear_kernel (double x)
|
||||
{
|
||||
return 1 - fabs (x);
|
||||
}
|
||||
|
||||
static double
|
||||
gaussian_kernel (double x)
|
||||
{
|
||||
#define SQRT2 (1.4142135623730950488016887242096980785696718753769480)
|
||||
#define SIGMA (SQRT2 / 2.0)
|
||||
|
||||
return exp (- x * x / (2 * SIGMA * SIGMA)) / (SIGMA * sqrt (2.0 * M_PI));
|
||||
}
|
||||
|
||||
static double
|
||||
sinc (double x)
|
||||
{
|
||||
if (x == 0.0)
|
||||
return 1.0;
|
||||
else
|
||||
return sin (M_PI * x) / (M_PI * x);
|
||||
}
|
||||
|
||||
static double
|
||||
lanczos (double x, int n)
|
||||
{
|
||||
return sinc (x) * sinc (x * (1.0 / n));
|
||||
}
|
||||
|
||||
static double
|
||||
lanczos2_kernel (double x)
|
||||
{
|
||||
return lanczos (x, 2);
|
||||
}
|
||||
|
||||
static double
|
||||
lanczos3_kernel (double x)
|
||||
{
|
||||
return lanczos (x, 3);
|
||||
}
|
||||
|
||||
static double
|
||||
nice_kernel (double x)
|
||||
{
|
||||
return lanczos3_kernel (x * 0.75);
|
||||
}
|
||||
|
||||
static double
|
||||
general_cubic (double x, double B, double C)
|
||||
{
|
||||
double ax = fabs(x);
|
||||
|
||||
if (ax < 1)
|
||||
{
|
||||
return ((12 - 9 * B - 6 * C) * ax * ax * ax +
|
||||
(-18 + 12 * B + 6 * C) * ax * ax + (6 - 2 * B)) / 6;
|
||||
}
|
||||
else if (ax >= 1 && ax < 2)
|
||||
{
|
||||
return ((-B - 6 * C) * ax * ax * ax +
|
||||
(6 * B + 30 * C) * ax * ax + (-12 * B - 48 * C) *
|
||||
ax + (8 * B + 24 * C)) / 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static double
|
||||
cubic_kernel (double x)
|
||||
{
|
||||
/* This is the Mitchell-Netravali filter.
|
||||
*
|
||||
* (0.0, 0.5) would give us the Catmull-Rom spline,
|
||||
* but that one seems to be indistinguishable from Lanczos2.
|
||||
*/
|
||||
return general_cubic (x, 1/3.0, 1/3.0);
|
||||
}
|
||||
|
||||
static const filter_info_t filters[] =
|
||||
{
|
||||
{ PIXMAN_KERNEL_IMPULSE, impulse_kernel, 0.0 },
|
||||
{ PIXMAN_KERNEL_BOX, box_kernel, 1.0 },
|
||||
{ PIXMAN_KERNEL_LINEAR, linear_kernel, 2.0 },
|
||||
{ PIXMAN_KERNEL_CUBIC, cubic_kernel, 4.0 },
|
||||
{ PIXMAN_KERNEL_GAUSSIAN, gaussian_kernel, 6 * SIGMA },
|
||||
{ PIXMAN_KERNEL_LANCZOS2, lanczos2_kernel, 4.0 },
|
||||
{ PIXMAN_KERNEL_LANCZOS3, lanczos3_kernel, 6.0 },
|
||||
{ PIXMAN_KERNEL_LANCZOS3_STRETCHED, nice_kernel, 8.0 },
|
||||
};
|
||||
|
||||
/* This function scales @kernel2 by @scale, then
|
||||
* aligns @x1 in @kernel1 with @x2 in @kernel2 and
|
||||
* and integrates the product of the kernels across @width.
|
||||
*
|
||||
* This function assumes that the intervals are within
|
||||
* the kernels in question. E.g., the caller must not
|
||||
* try to integrate a linear kernel ouside of [-1:1]
|
||||
*/
|
||||
static double
|
||||
integral (pixman_kernel_t kernel1, double x1,
|
||||
pixman_kernel_t kernel2, double scale, double x2,
|
||||
double width)
|
||||
{
|
||||
/* If the integration interval crosses zero, break it into
|
||||
* two separate integrals. This ensures that filters such
|
||||
* as LINEAR that are not differentiable at 0 will still
|
||||
* integrate properly.
|
||||
*/
|
||||
if (x1 < 0 && x1 + width > 0)
|
||||
{
|
||||
return
|
||||
integral (kernel1, x1, kernel2, scale, x2, - x1) +
|
||||
integral (kernel1, 0, kernel2, scale, x2 - x1, width + x1);
|
||||
}
|
||||
else if (x2 < 0 && x2 + width > 0)
|
||||
{
|
||||
return
|
||||
integral (kernel1, x1, kernel2, scale, x2, - x2) +
|
||||
integral (kernel1, x1 - x2, kernel2, scale, 0, width + x2);
|
||||
}
|
||||
else if (kernel1 == PIXMAN_KERNEL_IMPULSE)
|
||||
{
|
||||
assert (width == 0.0);
|
||||
return filters[kernel2].func (x2 * scale);
|
||||
}
|
||||
else if (kernel2 == PIXMAN_KERNEL_IMPULSE)
|
||||
{
|
||||
assert (width == 0.0);
|
||||
return filters[kernel1].func (x1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Integration via Simpson's rule */
|
||||
#define N_SEGMENTS 128
|
||||
#define SAMPLE(a1, a2) \
|
||||
(filters[kernel1].func ((a1)) * filters[kernel2].func ((a2) * scale))
|
||||
|
||||
double s = 0.0;
|
||||
double h = width / (double)N_SEGMENTS;
|
||||
int i;
|
||||
|
||||
s = SAMPLE (x1, x2);
|
||||
|
||||
for (i = 1; i < N_SEGMENTS; i += 2)
|
||||
{
|
||||
double a1 = x1 + h * i;
|
||||
double a2 = x2 + h * i;
|
||||
|
||||
s += 2 * SAMPLE (a1, a2);
|
||||
|
||||
if (i >= 2 && i < N_SEGMENTS - 1)
|
||||
s += 4 * SAMPLE (a1, a2);
|
||||
}
|
||||
|
||||
s += SAMPLE (x1 + width, x2 + width);
|
||||
|
||||
return h * s * (1.0 / 3.0);
|
||||
}
|
||||
}
|
||||
|
||||
static pixman_fixed_t *
|
||||
create_1d_filter (int *width,
|
||||
pixman_kernel_t reconstruct,
|
||||
pixman_kernel_t sample,
|
||||
double scale,
|
||||
int n_phases)
|
||||
{
|
||||
pixman_fixed_t *params, *p;
|
||||
double step;
|
||||
double size;
|
||||
int i;
|
||||
|
||||
size = scale * filters[sample].width + filters[reconstruct].width;
|
||||
*width = ceil (size);
|
||||
|
||||
p = params = malloc (*width * n_phases * sizeof (pixman_fixed_t));
|
||||
if (!params)
|
||||
return NULL;
|
||||
|
||||
step = 1.0 / n_phases;
|
||||
|
||||
for (i = 0; i < n_phases; ++i)
|
||||
{
|
||||
double frac = step / 2.0 + i * step;
|
||||
pixman_fixed_t new_total;
|
||||
int x, x1, x2;
|
||||
double total;
|
||||
|
||||
/* Sample convolution of reconstruction and sampling
|
||||
* filter. See rounding.txt regarding the rounding
|
||||
* and sample positions.
|
||||
*/
|
||||
|
||||
x1 = ceil (frac - *width / 2.0 - 0.5);
|
||||
x2 = x1 + *width;
|
||||
|
||||
total = 0;
|
||||
for (x = x1; x < x2; ++x)
|
||||
{
|
||||
double pos = x + 0.5 - frac;
|
||||
double rlow = - filters[reconstruct].width / 2.0;
|
||||
double rhigh = rlow + filters[reconstruct].width;
|
||||
double slow = pos - scale * filters[sample].width / 2.0;
|
||||
double shigh = slow + scale * filters[sample].width;
|
||||
double c = 0.0;
|
||||
double ilow, ihigh;
|
||||
|
||||
if (rhigh >= slow && rlow <= shigh)
|
||||
{
|
||||
ilow = MAX (slow, rlow);
|
||||
ihigh = MIN (shigh, rhigh);
|
||||
|
||||
c = integral (reconstruct, ilow,
|
||||
sample, 1.0 / scale, ilow - pos,
|
||||
ihigh - ilow);
|
||||
}
|
||||
|
||||
total += c;
|
||||
*p++ = (pixman_fixed_t)(c * 65535.0 + 0.5);
|
||||
}
|
||||
|
||||
/* Normalize */
|
||||
p -= *width;
|
||||
total = 1 / total;
|
||||
new_total = 0;
|
||||
for (x = x1; x < x2; ++x)
|
||||
{
|
||||
pixman_fixed_t t = (*p) * total + 0.5;
|
||||
|
||||
new_total += t;
|
||||
*p++ = t;
|
||||
}
|
||||
|
||||
if (new_total != pixman_fixed_1)
|
||||
*(p - *width / 2) += (pixman_fixed_1 - new_total);
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
/* Create the parameter list for a SEPARABLE_CONVOLUTION filter
|
||||
* with the given kernels and scale parameters
|
||||
*/
|
||||
PIXMAN_EXPORT pixman_fixed_t *
|
||||
pixman_filter_create_separable_convolution (int *n_values,
|
||||
pixman_fixed_t scale_x,
|
||||
pixman_fixed_t scale_y,
|
||||
pixman_kernel_t reconstruct_x,
|
||||
pixman_kernel_t reconstruct_y,
|
||||
pixman_kernel_t sample_x,
|
||||
pixman_kernel_t sample_y,
|
||||
int subsample_bits_x,
|
||||
int subsample_bits_y)
|
||||
{
|
||||
double sx = fabs (pixman_fixed_to_double (scale_x));
|
||||
double sy = fabs (pixman_fixed_to_double (scale_y));
|
||||
pixman_fixed_t *horz = NULL, *vert = NULL, *params = NULL;
|
||||
int subsample_x, subsample_y;
|
||||
int width, height;
|
||||
|
||||
subsample_x = (1 << subsample_bits_x);
|
||||
subsample_y = (1 << subsample_bits_y);
|
||||
|
||||
horz = create_1d_filter (&width, reconstruct_x, sample_x, sx, subsample_x);
|
||||
vert = create_1d_filter (&height, reconstruct_y, sample_y, sy, subsample_y);
|
||||
|
||||
if (!horz || !vert)
|
||||
goto out;
|
||||
|
||||
*n_values = 4 + width * subsample_x + height * subsample_y;
|
||||
|
||||
params = malloc (*n_values * sizeof (pixman_fixed_t));
|
||||
if (!params)
|
||||
goto out;
|
||||
|
||||
params[0] = pixman_int_to_fixed (width);
|
||||
params[1] = pixman_int_to_fixed (height);
|
||||
params[2] = pixman_int_to_fixed (subsample_bits_x);
|
||||
params[3] = pixman_int_to_fixed (subsample_bits_y);
|
||||
|
||||
memcpy (params + 4, horz,
|
||||
width * subsample_x * sizeof (pixman_fixed_t));
|
||||
memcpy (params + 4 + width * subsample_x, vert,
|
||||
height * subsample_y * sizeof (pixman_fixed_t));
|
||||
|
||||
out:
|
||||
free (horz);
|
||||
free (vert);
|
||||
|
||||
return params;
|
||||
}
|
@ -1,227 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2009 Red Hat, Inc.
|
||||
* Copyright © 2000 SuSE, Inc.
|
||||
* Copyright © 2007 Red Hat, Inc.
|
||||
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
|
||||
* 2005 Lars Knoll & Zack Rusin, Trolltech
|
||||
* 2008 Aaron Plattner, NVIDIA Corporation
|
||||
*
|
||||
* 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 Red Hat not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. Red Hat makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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 <config.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "pixman-private.h"
|
||||
|
||||
static pixman_bool_t
|
||||
general_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
|
||||
{
|
||||
pixman_image_t *image = iter->image;
|
||||
|
||||
if (image->type == LINEAR)
|
||||
_pixman_linear_gradient_iter_init (image, iter);
|
||||
else if (image->type == RADIAL)
|
||||
_pixman_radial_gradient_iter_init (image, iter);
|
||||
else if (image->type == CONICAL)
|
||||
_pixman_conical_gradient_iter_init (image, iter);
|
||||
else if (image->type == BITS)
|
||||
_pixman_bits_image_src_iter_init (image, iter);
|
||||
else if (image->type == SOLID)
|
||||
_pixman_log_error (FUNC, "Solid image not handled by noop");
|
||||
else
|
||||
_pixman_log_error (FUNC, "Pixman bug: unknown image type\n");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static pixman_bool_t
|
||||
general_dest_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
|
||||
{
|
||||
if (iter->image->type == BITS)
|
||||
{
|
||||
_pixman_bits_image_dest_iter_init (iter->image, iter);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
_pixman_log_error (FUNC, "Trying to write to a non-writable image");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct op_info_t op_info_t;
|
||||
struct op_info_t
|
||||
{
|
||||
uint8_t src, dst;
|
||||
};
|
||||
|
||||
#define ITER_IGNORE_BOTH \
|
||||
(ITER_IGNORE_ALPHA | ITER_IGNORE_RGB | ITER_LOCALIZED_ALPHA)
|
||||
|
||||
static const op_info_t op_flags[PIXMAN_N_OPERATORS] =
|
||||
{
|
||||
/* Src Dst */
|
||||
{ ITER_IGNORE_BOTH, ITER_IGNORE_BOTH }, /* CLEAR */
|
||||
{ ITER_LOCALIZED_ALPHA, ITER_IGNORE_BOTH }, /* SRC */
|
||||
{ ITER_IGNORE_BOTH, ITER_LOCALIZED_ALPHA }, /* DST */
|
||||
{ 0, ITER_LOCALIZED_ALPHA }, /* OVER */
|
||||
{ ITER_LOCALIZED_ALPHA, 0 }, /* OVER_REVERSE */
|
||||
{ ITER_LOCALIZED_ALPHA, ITER_IGNORE_RGB }, /* IN */
|
||||
{ ITER_IGNORE_RGB, ITER_LOCALIZED_ALPHA }, /* IN_REVERSE */
|
||||
{ ITER_LOCALIZED_ALPHA, ITER_IGNORE_RGB }, /* OUT */
|
||||
{ ITER_IGNORE_RGB, ITER_LOCALIZED_ALPHA }, /* OUT_REVERSE */
|
||||
{ 0, 0 }, /* ATOP */
|
||||
{ 0, 0 }, /* ATOP_REVERSE */
|
||||
{ 0, 0 }, /* XOR */
|
||||
{ ITER_LOCALIZED_ALPHA, ITER_LOCALIZED_ALPHA }, /* ADD */
|
||||
{ 0, 0 }, /* SATURATE */
|
||||
};
|
||||
|
||||
#define SCANLINE_BUFFER_LENGTH 8192
|
||||
|
||||
static void
|
||||
general_composite_rect (pixman_implementation_t *imp,
|
||||
pixman_composite_info_t *info)
|
||||
{
|
||||
PIXMAN_COMPOSITE_ARGS (info);
|
||||
uint64_t stack_scanline_buffer[(SCANLINE_BUFFER_LENGTH * 3 + 7) / 8];
|
||||
uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer;
|
||||
uint8_t *src_buffer, *mask_buffer, *dest_buffer;
|
||||
pixman_iter_t src_iter, mask_iter, dest_iter;
|
||||
pixman_combine_32_func_t compose;
|
||||
pixman_bool_t component_alpha;
|
||||
iter_flags_t narrow, src_iter_flags;
|
||||
int Bpp;
|
||||
int i;
|
||||
|
||||
if ((src_image->common.flags & FAST_PATH_NARROW_FORMAT) &&
|
||||
(!mask_image || mask_image->common.flags & FAST_PATH_NARROW_FORMAT) &&
|
||||
(dest_image->common.flags & FAST_PATH_NARROW_FORMAT))
|
||||
{
|
||||
narrow = ITER_NARROW;
|
||||
Bpp = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
narrow = 0;
|
||||
Bpp = 16;
|
||||
}
|
||||
|
||||
if (width * Bpp > SCANLINE_BUFFER_LENGTH)
|
||||
{
|
||||
scanline_buffer = pixman_malloc_abc (width, 3, Bpp);
|
||||
|
||||
if (!scanline_buffer)
|
||||
return;
|
||||
}
|
||||
|
||||
src_buffer = scanline_buffer;
|
||||
mask_buffer = src_buffer + width * Bpp;
|
||||
dest_buffer = mask_buffer + width * Bpp;
|
||||
|
||||
if (!narrow)
|
||||
{
|
||||
/* To make sure there aren't any NANs in the buffers */
|
||||
memset (src_buffer, 0, width * Bpp);
|
||||
memset (mask_buffer, 0, width * Bpp);
|
||||
memset (dest_buffer, 0, width * Bpp);
|
||||
}
|
||||
|
||||
/* src iter */
|
||||
src_iter_flags = narrow | op_flags[op].src;
|
||||
|
||||
_pixman_implementation_src_iter_init (imp->toplevel, &src_iter, src_image,
|
||||
src_x, src_y, width, height,
|
||||
src_buffer, src_iter_flags, info->src_flags);
|
||||
|
||||
/* mask iter */
|
||||
if ((src_iter_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) ==
|
||||
(ITER_IGNORE_ALPHA | ITER_IGNORE_RGB))
|
||||
{
|
||||
/* If it doesn't matter what the source is, then it doesn't matter
|
||||
* what the mask is
|
||||
*/
|
||||
mask_image = NULL;
|
||||
}
|
||||
|
||||
component_alpha =
|
||||
mask_image &&
|
||||
mask_image->common.type == BITS &&
|
||||
mask_image->common.component_alpha &&
|
||||
PIXMAN_FORMAT_RGB (mask_image->bits.format);
|
||||
|
||||
_pixman_implementation_src_iter_init (
|
||||
imp->toplevel, &mask_iter, mask_image, mask_x, mask_y, width, height,
|
||||
mask_buffer, narrow | (component_alpha? 0 : ITER_IGNORE_RGB), info->mask_flags);
|
||||
|
||||
/* dest iter */
|
||||
_pixman_implementation_dest_iter_init (
|
||||
imp->toplevel, &dest_iter, dest_image, dest_x, dest_y, width, height,
|
||||
dest_buffer, narrow | op_flags[op].dst, info->dest_flags);
|
||||
|
||||
compose = _pixman_implementation_lookup_combiner (
|
||||
imp->toplevel, op, component_alpha, narrow);
|
||||
|
||||
for (i = 0; i < height; ++i)
|
||||
{
|
||||
uint32_t *s, *m, *d;
|
||||
|
||||
m = mask_iter.get_scanline (&mask_iter, NULL);
|
||||
s = src_iter.get_scanline (&src_iter, m);
|
||||
d = dest_iter.get_scanline (&dest_iter, NULL);
|
||||
|
||||
compose (imp->toplevel, op, d, s, m, width);
|
||||
|
||||
dest_iter.write_back (&dest_iter);
|
||||
}
|
||||
|
||||
if (scanline_buffer != (uint8_t *) stack_scanline_buffer)
|
||||
free (scanline_buffer);
|
||||
}
|
||||
|
||||
static const pixman_fast_path_t general_fast_path[] =
|
||||
{
|
||||
{ PIXMAN_OP_any, PIXMAN_any, 0, PIXMAN_any, 0, PIXMAN_any, 0, general_composite_rect },
|
||||
{ PIXMAN_OP_NONE }
|
||||
};
|
||||
|
||||
pixman_implementation_t *
|
||||
_pixman_implementation_create_general (void)
|
||||
{
|
||||
pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path);
|
||||
|
||||
_pixman_setup_combiner_functions_32 (imp);
|
||||
_pixman_setup_combiner_functions_float (imp);
|
||||
|
||||
imp->src_iter_init = general_src_iter_init;
|
||||
imp->dest_iter_init = general_dest_iter_init;
|
||||
|
||||
return imp;
|
||||
}
|
||||
|
@ -1,670 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010, 2012, Soren Sandmann <sandmann@cs.au.dk>
|
||||
* Copyright 2010, 2011, 2012, Red Hat, Inc
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Author: Soren Sandmann <sandmann@cs.au.dk>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include "pixman-private.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct glyph_metrics_t glyph_metrics_t;
|
||||
typedef struct glyph_t glyph_t;
|
||||
|
||||
#define TOMBSTONE ((glyph_t *)0x1)
|
||||
|
||||
/* XXX: These numbers are arbitrary---we've never done any measurements.
|
||||
*/
|
||||
#define N_GLYPHS_HIGH_WATER (16384)
|
||||
#define N_GLYPHS_LOW_WATER (8192)
|
||||
#define HASH_SIZE (2 * N_GLYPHS_HIGH_WATER)
|
||||
#define HASH_MASK (HASH_SIZE - 1)
|
||||
|
||||
struct glyph_t
|
||||
{
|
||||
void * font_key;
|
||||
void * glyph_key;
|
||||
int origin_x;
|
||||
int origin_y;
|
||||
pixman_image_t * image;
|
||||
pixman_link_t mru_link;
|
||||
};
|
||||
|
||||
struct pixman_glyph_cache_t
|
||||
{
|
||||
int n_glyphs;
|
||||
int n_tombstones;
|
||||
int freeze_count;
|
||||
pixman_list_t mru;
|
||||
glyph_t * glyphs[HASH_SIZE];
|
||||
};
|
||||
|
||||
static void
|
||||
free_glyph (glyph_t *glyph)
|
||||
{
|
||||
pixman_list_unlink (&glyph->mru_link);
|
||||
pixman_image_unref (glyph->image);
|
||||
free (glyph);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
hash (const void *font_key, const void *glyph_key)
|
||||
{
|
||||
size_t key = (size_t)font_key + (size_t)glyph_key;
|
||||
|
||||
/* This hash function is based on one found on Thomas Wang's
|
||||
* web page at
|
||||
*
|
||||
* http://www.concentric.net/~Ttwang/tech/inthash.htm
|
||||
*
|
||||
*/
|
||||
key = (key << 15) - key - 1;
|
||||
key = key ^ (key >> 12);
|
||||
key = key + (key << 2);
|
||||
key = key ^ (key >> 4);
|
||||
key = key + (key << 3) + (key << 11);
|
||||
key = key ^ (key >> 16);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
static glyph_t *
|
||||
lookup_glyph (pixman_glyph_cache_t *cache,
|
||||
void *font_key,
|
||||
void *glyph_key)
|
||||
{
|
||||
unsigned idx;
|
||||
glyph_t *g;
|
||||
|
||||
idx = hash (font_key, glyph_key);
|
||||
while ((g = cache->glyphs[idx++ & HASH_MASK]))
|
||||
{
|
||||
if (g != TOMBSTONE &&
|
||||
g->font_key == font_key &&
|
||||
g->glyph_key == glyph_key)
|
||||
{
|
||||
return g;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
insert_glyph (pixman_glyph_cache_t *cache,
|
||||
glyph_t *glyph)
|
||||
{
|
||||
unsigned idx;
|
||||
glyph_t **loc;
|
||||
|
||||
idx = hash (glyph->font_key, glyph->glyph_key);
|
||||
|
||||
/* Note: we assume that there is room in the table. If there isn't,
|
||||
* this will be an infinite loop.
|
||||
*/
|
||||
do
|
||||
{
|
||||
loc = &cache->glyphs[idx++ & HASH_MASK];
|
||||
} while (*loc && *loc != TOMBSTONE);
|
||||
|
||||
if (*loc == TOMBSTONE)
|
||||
cache->n_tombstones--;
|
||||
cache->n_glyphs++;
|
||||
|
||||
*loc = glyph;
|
||||
}
|
||||
|
||||
static void
|
||||
remove_glyph (pixman_glyph_cache_t *cache,
|
||||
glyph_t *glyph)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
idx = hash (glyph->font_key, glyph->glyph_key);
|
||||
while (cache->glyphs[idx & HASH_MASK] != glyph)
|
||||
idx++;
|
||||
|
||||
cache->glyphs[idx & HASH_MASK] = TOMBSTONE;
|
||||
cache->n_tombstones++;
|
||||
cache->n_glyphs--;
|
||||
|
||||
/* Eliminate tombstones if possible */
|
||||
if (cache->glyphs[(idx + 1) & HASH_MASK] == NULL)
|
||||
{
|
||||
while (cache->glyphs[idx & HASH_MASK] == TOMBSTONE)
|
||||
{
|
||||
cache->glyphs[idx & HASH_MASK] = NULL;
|
||||
cache->n_tombstones--;
|
||||
idx--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clear_table (pixman_glyph_cache_t *cache)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < HASH_SIZE; ++i)
|
||||
{
|
||||
glyph_t *glyph = cache->glyphs[i];
|
||||
|
||||
if (glyph && glyph != TOMBSTONE)
|
||||
free_glyph (glyph);
|
||||
|
||||
cache->glyphs[i] = NULL;
|
||||
}
|
||||
|
||||
cache->n_glyphs = 0;
|
||||
cache->n_tombstones = 0;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT pixman_glyph_cache_t *
|
||||
pixman_glyph_cache_create (void)
|
||||
{
|
||||
pixman_glyph_cache_t *cache;
|
||||
|
||||
if (!(cache = malloc (sizeof *cache)))
|
||||
return NULL;
|
||||
|
||||
memset (cache->glyphs, 0, sizeof (cache->glyphs));
|
||||
cache->n_glyphs = 0;
|
||||
cache->n_tombstones = 0;
|
||||
cache->freeze_count = 0;
|
||||
|
||||
pixman_list_init (&cache->mru);
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_glyph_cache_destroy (pixman_glyph_cache_t *cache)
|
||||
{
|
||||
return_if_fail (cache->freeze_count == 0);
|
||||
|
||||
clear_table (cache);
|
||||
|
||||
free (cache);
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_glyph_cache_freeze (pixman_glyph_cache_t *cache)
|
||||
{
|
||||
cache->freeze_count++;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_glyph_cache_thaw (pixman_glyph_cache_t *cache)
|
||||
{
|
||||
if (--cache->freeze_count == 0 &&
|
||||
cache->n_glyphs + cache->n_tombstones > N_GLYPHS_HIGH_WATER)
|
||||
{
|
||||
if (cache->n_tombstones > N_GLYPHS_HIGH_WATER)
|
||||
{
|
||||
/* More than half the entries are
|
||||
* tombstones. Just dump the whole table.
|
||||
*/
|
||||
clear_table (cache);
|
||||
}
|
||||
|
||||
while (cache->n_glyphs > N_GLYPHS_LOW_WATER)
|
||||
{
|
||||
glyph_t *glyph = CONTAINER_OF (glyph_t, mru_link, cache->mru.tail);
|
||||
|
||||
remove_glyph (cache, glyph);
|
||||
free_glyph (glyph);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT const void *
|
||||
pixman_glyph_cache_lookup (pixman_glyph_cache_t *cache,
|
||||
void *font_key,
|
||||
void *glyph_key)
|
||||
{
|
||||
return lookup_glyph (cache, font_key, glyph_key);
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT const void *
|
||||
pixman_glyph_cache_insert (pixman_glyph_cache_t *cache,
|
||||
void *font_key,
|
||||
void *glyph_key,
|
||||
int origin_x,
|
||||
int origin_y,
|
||||
pixman_image_t *image)
|
||||
{
|
||||
glyph_t *glyph;
|
||||
int32_t width, height;
|
||||
|
||||
return_val_if_fail (cache->freeze_count > 0, NULL);
|
||||
return_val_if_fail (image->type == BITS, NULL);
|
||||
|
||||
width = image->bits.width;
|
||||
height = image->bits.height;
|
||||
|
||||
if (cache->n_glyphs >= HASH_SIZE)
|
||||
return NULL;
|
||||
|
||||
if (!(glyph = malloc (sizeof *glyph)))
|
||||
return NULL;
|
||||
|
||||
glyph->font_key = font_key;
|
||||
glyph->glyph_key = glyph_key;
|
||||
glyph->origin_x = origin_x;
|
||||
glyph->origin_y = origin_y;
|
||||
|
||||
if (!(glyph->image = pixman_image_create_bits (
|
||||
image->bits.format, width, height, NULL, -1)))
|
||||
{
|
||||
free (glyph);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pixman_image_composite32 (PIXMAN_OP_SRC,
|
||||
image, NULL, glyph->image, 0, 0, 0, 0, 0, 0,
|
||||
width, height);
|
||||
|
||||
if (PIXMAN_FORMAT_A (glyph->image->bits.format) != 0 &&
|
||||
PIXMAN_FORMAT_RGB (glyph->image->bits.format) != 0)
|
||||
{
|
||||
pixman_image_set_component_alpha (glyph->image, TRUE);
|
||||
}
|
||||
|
||||
pixman_list_prepend (&cache->mru, &glyph->mru_link);
|
||||
|
||||
_pixman_image_validate (glyph->image);
|
||||
insert_glyph (cache, glyph);
|
||||
|
||||
return glyph;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_glyph_cache_remove (pixman_glyph_cache_t *cache,
|
||||
void *font_key,
|
||||
void *glyph_key)
|
||||
{
|
||||
glyph_t *glyph;
|
||||
|
||||
if ((glyph = lookup_glyph (cache, font_key, glyph_key)))
|
||||
{
|
||||
remove_glyph (cache, glyph);
|
||||
|
||||
free_glyph (glyph);
|
||||
}
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_glyph_get_extents (pixman_glyph_cache_t *cache,
|
||||
int n_glyphs,
|
||||
pixman_glyph_t *glyphs,
|
||||
pixman_box32_t *extents)
|
||||
{
|
||||
int i;
|
||||
|
||||
extents->x1 = extents->y1 = INT32_MAX;
|
||||
extents->x2 = extents->y2 = INT32_MIN;
|
||||
|
||||
for (i = 0; i < n_glyphs; ++i)
|
||||
{
|
||||
glyph_t *glyph = (glyph_t *)glyphs[i].glyph;
|
||||
int x1, y1, x2, y2;
|
||||
|
||||
x1 = glyphs[i].x - glyph->origin_x;
|
||||
y1 = glyphs[i].y - glyph->origin_y;
|
||||
x2 = glyphs[i].x - glyph->origin_x + glyph->image->bits.width;
|
||||
y2 = glyphs[i].y - glyph->origin_y + glyph->image->bits.height;
|
||||
|
||||
if (x1 < extents->x1)
|
||||
extents->x1 = x1;
|
||||
if (y1 < extents->y1)
|
||||
extents->y1 = y1;
|
||||
if (x2 > extents->x2)
|
||||
extents->x2 = x2;
|
||||
if (y2 > extents->y2)
|
||||
extents->y2 = y2;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function returns a format that is suitable for use as a mask for the
|
||||
* set of glyphs in question.
|
||||
*/
|
||||
PIXMAN_EXPORT pixman_format_code_t
|
||||
pixman_glyph_get_mask_format (pixman_glyph_cache_t *cache,
|
||||
int n_glyphs,
|
||||
const pixman_glyph_t *glyphs)
|
||||
{
|
||||
pixman_format_code_t format = PIXMAN_a1;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_glyphs; ++i)
|
||||
{
|
||||
const glyph_t *glyph = glyphs[i].glyph;
|
||||
pixman_format_code_t glyph_format = glyph->image->bits.format;
|
||||
|
||||
if (PIXMAN_FORMAT_TYPE (glyph_format) == PIXMAN_TYPE_A)
|
||||
{
|
||||
if (PIXMAN_FORMAT_A (glyph_format) > PIXMAN_FORMAT_A (format))
|
||||
format = glyph_format;
|
||||
}
|
||||
else
|
||||
{
|
||||
return PIXMAN_a8r8g8b8;
|
||||
}
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
static pixman_bool_t
|
||||
box32_intersect (pixman_box32_t *dest,
|
||||
const pixman_box32_t *box1,
|
||||
const pixman_box32_t *box2)
|
||||
{
|
||||
dest->x1 = MAX (box1->x1, box2->x1);
|
||||
dest->y1 = MAX (box1->y1, box2->y1);
|
||||
dest->x2 = MIN (box1->x2, box2->x2);
|
||||
dest->y2 = MIN (box1->y2, box2->y2);
|
||||
|
||||
return dest->x2 > dest->x1 && dest->y2 > dest->y1;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_composite_glyphs_no_mask (pixman_op_t op,
|
||||
pixman_image_t *src,
|
||||
pixman_image_t *dest,
|
||||
int32_t src_x,
|
||||
int32_t src_y,
|
||||
int32_t dest_x,
|
||||
int32_t dest_y,
|
||||
pixman_glyph_cache_t *cache,
|
||||
int n_glyphs,
|
||||
const pixman_glyph_t *glyphs)
|
||||
{
|
||||
pixman_region32_t region;
|
||||
pixman_format_code_t glyph_format = PIXMAN_null;
|
||||
uint32_t glyph_flags = 0;
|
||||
pixman_format_code_t dest_format;
|
||||
uint32_t dest_flags;
|
||||
pixman_composite_func_t func = NULL;
|
||||
pixman_implementation_t *implementation = NULL;
|
||||
pixman_composite_info_t info;
|
||||
int i;
|
||||
|
||||
_pixman_image_validate (src);
|
||||
_pixman_image_validate (dest);
|
||||
|
||||
dest_format = dest->common.extended_format_code;
|
||||
dest_flags = dest->common.flags;
|
||||
|
||||
pixman_region32_init (®ion);
|
||||
if (!_pixman_compute_composite_region32 (
|
||||
®ion,
|
||||
src, NULL, dest,
|
||||
src_x - dest_x, src_y - dest_y, 0, 0, 0, 0,
|
||||
dest->bits.width, dest->bits.height))
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
info.op = op;
|
||||
info.src_image = src;
|
||||
info.dest_image = dest;
|
||||
info.src_flags = src->common.flags;
|
||||
info.dest_flags = dest->common.flags;
|
||||
|
||||
for (i = 0; i < n_glyphs; ++i)
|
||||
{
|
||||
glyph_t *glyph = (glyph_t *)glyphs[i].glyph;
|
||||
pixman_image_t *glyph_img = glyph->image;
|
||||
pixman_box32_t glyph_box;
|
||||
pixman_box32_t *pbox;
|
||||
uint32_t extra = FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
|
||||
pixman_box32_t composite_box;
|
||||
int n;
|
||||
|
||||
glyph_box.x1 = dest_x + glyphs[i].x - glyph->origin_x;
|
||||
glyph_box.y1 = dest_y + glyphs[i].y - glyph->origin_y;
|
||||
glyph_box.x2 = glyph_box.x1 + glyph->image->bits.width;
|
||||
glyph_box.y2 = glyph_box.y1 + glyph->image->bits.height;
|
||||
|
||||
pbox = pixman_region32_rectangles (®ion, &n);
|
||||
|
||||
info.mask_image = glyph_img;
|
||||
|
||||
while (n--)
|
||||
{
|
||||
if (box32_intersect (&composite_box, pbox, &glyph_box))
|
||||
{
|
||||
if (glyph_img->common.extended_format_code != glyph_format ||
|
||||
glyph_img->common.flags != glyph_flags)
|
||||
{
|
||||
glyph_format = glyph_img->common.extended_format_code;
|
||||
glyph_flags = glyph_img->common.flags;
|
||||
|
||||
_pixman_implementation_lookup_composite (
|
||||
get_implementation(), op,
|
||||
src->common.extended_format_code, src->common.flags,
|
||||
glyph_format, glyph_flags | extra,
|
||||
dest_format, dest_flags,
|
||||
&implementation, &func);
|
||||
}
|
||||
|
||||
info.src_x = src_x + composite_box.x1 - dest_x;
|
||||
info.src_y = src_y + composite_box.y1 - dest_y;
|
||||
info.mask_x = composite_box.x1 - (dest_x + glyphs[i].x - glyph->origin_x);
|
||||
info.mask_y = composite_box.y1 - (dest_y + glyphs[i].y - glyph->origin_y);
|
||||
info.dest_x = composite_box.x1;
|
||||
info.dest_y = composite_box.y1;
|
||||
info.width = composite_box.x2 - composite_box.x1;
|
||||
info.height = composite_box.y2 - composite_box.y1;
|
||||
|
||||
info.mask_flags = glyph_flags;
|
||||
|
||||
func (implementation, &info);
|
||||
}
|
||||
|
||||
pbox++;
|
||||
}
|
||||
pixman_list_move_to_front (&cache->mru, &glyph->mru_link);
|
||||
}
|
||||
|
||||
out:
|
||||
pixman_region32_fini (®ion);
|
||||
}
|
||||
|
||||
static void
|
||||
add_glyphs (pixman_glyph_cache_t *cache,
|
||||
pixman_image_t *dest,
|
||||
int off_x, int off_y,
|
||||
int n_glyphs, const pixman_glyph_t *glyphs)
|
||||
{
|
||||
pixman_format_code_t glyph_format = PIXMAN_null;
|
||||
uint32_t glyph_flags = 0;
|
||||
pixman_composite_func_t func = NULL;
|
||||
pixman_implementation_t *implementation = NULL;
|
||||
pixman_format_code_t dest_format;
|
||||
uint32_t dest_flags;
|
||||
pixman_box32_t dest_box;
|
||||
pixman_composite_info_t info;
|
||||
pixman_image_t *white_img = NULL;
|
||||
pixman_bool_t white_src = FALSE;
|
||||
int i;
|
||||
|
||||
_pixman_image_validate (dest);
|
||||
|
||||
dest_format = dest->common.extended_format_code;
|
||||
dest_flags = dest->common.flags;
|
||||
|
||||
info.op = PIXMAN_OP_ADD;
|
||||
info.dest_image = dest;
|
||||
info.src_x = 0;
|
||||
info.src_y = 0;
|
||||
info.dest_flags = dest_flags;
|
||||
|
||||
dest_box.x1 = 0;
|
||||
dest_box.y1 = 0;
|
||||
dest_box.x2 = dest->bits.width;
|
||||
dest_box.y2 = dest->bits.height;
|
||||
|
||||
for (i = 0; i < n_glyphs; ++i)
|
||||
{
|
||||
glyph_t *glyph = (glyph_t *)glyphs[i].glyph;
|
||||
pixman_image_t *glyph_img = glyph->image;
|
||||
pixman_box32_t glyph_box;
|
||||
pixman_box32_t composite_box;
|
||||
|
||||
if (glyph_img->common.extended_format_code != glyph_format ||
|
||||
glyph_img->common.flags != glyph_flags)
|
||||
{
|
||||
pixman_format_code_t src_format, mask_format;
|
||||
|
||||
glyph_format = glyph_img->common.extended_format_code;
|
||||
glyph_flags = glyph_img->common.flags;
|
||||
|
||||
if (glyph_format == dest->bits.format)
|
||||
{
|
||||
src_format = glyph_format;
|
||||
mask_format = PIXMAN_null;
|
||||
info.src_flags = glyph_flags | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
|
||||
info.mask_flags = FAST_PATH_IS_OPAQUE;
|
||||
info.mask_image = NULL;
|
||||
white_src = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!white_img)
|
||||
{
|
||||
static const pixman_color_t white = { 0xffff, 0xffff, 0xffff, 0xffff };
|
||||
|
||||
if (!(white_img = pixman_image_create_solid_fill (&white)))
|
||||
goto out;
|
||||
|
||||
_pixman_image_validate (white_img);
|
||||
}
|
||||
|
||||
src_format = PIXMAN_solid;
|
||||
mask_format = glyph_format;
|
||||
info.src_flags = white_img->common.flags;
|
||||
info.mask_flags = glyph_flags | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
|
||||
info.src_image = white_img;
|
||||
white_src = TRUE;
|
||||
}
|
||||
|
||||
_pixman_implementation_lookup_composite (
|
||||
get_implementation(), PIXMAN_OP_ADD,
|
||||
src_format, info.src_flags,
|
||||
mask_format, info.mask_flags,
|
||||
dest_format, dest_flags,
|
||||
&implementation, &func);
|
||||
}
|
||||
|
||||
glyph_box.x1 = glyphs[i].x - glyph->origin_x + off_x;
|
||||
glyph_box.y1 = glyphs[i].y - glyph->origin_y + off_y;
|
||||
glyph_box.x2 = glyph_box.x1 + glyph->image->bits.width;
|
||||
glyph_box.y2 = glyph_box.y1 + glyph->image->bits.height;
|
||||
|
||||
if (box32_intersect (&composite_box, &glyph_box, &dest_box))
|
||||
{
|
||||
int src_x = composite_box.x1 - glyph_box.x1;
|
||||
int src_y = composite_box.y1 - glyph_box.y1;
|
||||
|
||||
if (white_src)
|
||||
info.mask_image = glyph_img;
|
||||
else
|
||||
info.src_image = glyph_img;
|
||||
|
||||
info.mask_x = info.src_x = src_x;
|
||||
info.mask_y = info.src_y = src_y;
|
||||
info.dest_x = composite_box.x1;
|
||||
info.dest_y = composite_box.y1;
|
||||
info.width = composite_box.x2 - composite_box.x1;
|
||||
info.height = composite_box.y2 - composite_box.y1;
|
||||
|
||||
func (implementation, &info);
|
||||
|
||||
pixman_list_move_to_front (&cache->mru, &glyph->mru_link);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (white_img)
|
||||
pixman_image_unref (white_img);
|
||||
}
|
||||
|
||||
/* Conceptually, for each glyph, (white IN glyph) is PIXMAN_OP_ADDed to an
|
||||
* infinitely big mask image at the position such that the glyph origin point
|
||||
* is positioned at the (glyphs[i].x, glyphs[i].y) point.
|
||||
*
|
||||
* Then (mask_x, mask_y) in the infinite mask and (src_x, src_y) in the source
|
||||
* image are both aligned with (dest_x, dest_y) in the destination image. Then
|
||||
* these three images are composited within the
|
||||
*
|
||||
* (dest_x, dest_y, dst_x + width, dst_y + height)
|
||||
*
|
||||
* rectangle.
|
||||
*
|
||||
* TODO:
|
||||
* - Trim the mask to the destination clip/image?
|
||||
* - Trim composite region based on sources, when the op ignores 0s.
|
||||
*/
|
||||
PIXMAN_EXPORT void
|
||||
pixman_composite_glyphs (pixman_op_t op,
|
||||
pixman_image_t *src,
|
||||
pixman_image_t *dest,
|
||||
pixman_format_code_t mask_format,
|
||||
int32_t src_x,
|
||||
int32_t src_y,
|
||||
int32_t mask_x,
|
||||
int32_t mask_y,
|
||||
int32_t dest_x,
|
||||
int32_t dest_y,
|
||||
int32_t width,
|
||||
int32_t height,
|
||||
pixman_glyph_cache_t *cache,
|
||||
int n_glyphs,
|
||||
const pixman_glyph_t *glyphs)
|
||||
{
|
||||
pixman_image_t *mask;
|
||||
|
||||
if (!(mask = pixman_image_create_bits (mask_format, width, height, NULL, -1)))
|
||||
return;
|
||||
|
||||
if (PIXMAN_FORMAT_A (mask_format) != 0 &&
|
||||
PIXMAN_FORMAT_RGB (mask_format) != 0)
|
||||
{
|
||||
pixman_image_set_component_alpha (mask, TRUE);
|
||||
}
|
||||
|
||||
add_glyphs (cache, mask, - mask_x, - mask_y, n_glyphs, glyphs);
|
||||
|
||||
pixman_image_composite32 (op, src, mask, dest,
|
||||
src_x, src_y,
|
||||
0, 0,
|
||||
dest_x, dest_y,
|
||||
width, height);
|
||||
|
||||
pixman_image_unref (mask);
|
||||
}
|
@ -1,202 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
|
||||
* 2005 Lars Knoll & Zack Rusin, Trolltech
|
||||
*
|
||||
* 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 Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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 <config.h>
|
||||
#endif
|
||||
#include "pixman-private.h"
|
||||
|
||||
void
|
||||
_pixman_gradient_walker_init (pixman_gradient_walker_t *walker,
|
||||
gradient_t * gradient,
|
||||
pixman_repeat_t repeat)
|
||||
{
|
||||
walker->num_stops = gradient->n_stops;
|
||||
walker->stops = gradient->stops;
|
||||
walker->left_x = 0;
|
||||
walker->right_x = 0x10000;
|
||||
walker->a_s = 0.0f;
|
||||
walker->a_b = 0.0f;
|
||||
walker->r_s = 0.0f;
|
||||
walker->r_b = 0.0f;
|
||||
walker->g_s = 0.0f;
|
||||
walker->g_b = 0.0f;
|
||||
walker->b_s = 0.0f;
|
||||
walker->b_b = 0.0f;
|
||||
walker->repeat = repeat;
|
||||
|
||||
walker->need_reset = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gradient_walker_reset (pixman_gradient_walker_t *walker,
|
||||
pixman_fixed_48_16_t pos)
|
||||
{
|
||||
int32_t x, left_x, right_x;
|
||||
pixman_color_t *left_c, *right_c;
|
||||
int n, count = walker->num_stops;
|
||||
pixman_gradient_stop_t *stops = walker->stops;
|
||||
float la, lr, lg, lb;
|
||||
float ra, rr, rg, rb;
|
||||
float lx, rx;
|
||||
|
||||
if (walker->repeat == PIXMAN_REPEAT_NORMAL)
|
||||
{
|
||||
x = (int32_t)pos & 0xffff;
|
||||
}
|
||||
else if (walker->repeat == PIXMAN_REPEAT_REFLECT)
|
||||
{
|
||||
x = (int32_t)pos & 0xffff;
|
||||
if ((int32_t)pos & 0x10000)
|
||||
x = 0x10000 - x;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = pos;
|
||||
}
|
||||
|
||||
for (n = 0; n < count; n++)
|
||||
{
|
||||
if (x < stops[n].x)
|
||||
break;
|
||||
}
|
||||
|
||||
left_x = stops[n - 1].x;
|
||||
left_c = &stops[n - 1].color;
|
||||
|
||||
right_x = stops[n].x;
|
||||
right_c = &stops[n].color;
|
||||
|
||||
if (walker->repeat == PIXMAN_REPEAT_NORMAL)
|
||||
{
|
||||
left_x += (pos - x);
|
||||
right_x += (pos - x);
|
||||
}
|
||||
else if (walker->repeat == PIXMAN_REPEAT_REFLECT)
|
||||
{
|
||||
if ((int32_t)pos & 0x10000)
|
||||
{
|
||||
pixman_color_t *tmp_c;
|
||||
int32_t tmp_x;
|
||||
|
||||
tmp_x = 0x10000 - right_x;
|
||||
right_x = 0x10000 - left_x;
|
||||
left_x = tmp_x;
|
||||
|
||||
tmp_c = right_c;
|
||||
right_c = left_c;
|
||||
left_c = tmp_c;
|
||||
|
||||
x = 0x10000 - x;
|
||||
}
|
||||
left_x += (pos - x);
|
||||
right_x += (pos - x);
|
||||
}
|
||||
else if (walker->repeat == PIXMAN_REPEAT_NONE)
|
||||
{
|
||||
if (n == 0)
|
||||
right_c = left_c;
|
||||
else if (n == count)
|
||||
left_c = right_c;
|
||||
}
|
||||
|
||||
/* The alpha channel is scaled to be in the [0, 255] interval,
|
||||
* and the red/green/blue channels are scaled to be in [0, 1].
|
||||
* This ensures that after premultiplication all channels will
|
||||
* be in the [0, 255] interval.
|
||||
*/
|
||||
la = (left_c->alpha * (1.0f/257.0f));
|
||||
lr = (left_c->red * (1.0f/257.0f));
|
||||
lg = (left_c->green * (1.0f/257.0f));
|
||||
lb = (left_c->blue * (1.0f/257.0f));
|
||||
|
||||
ra = (right_c->alpha * (1.0f/257.0f));
|
||||
rr = (right_c->red * (1.0f/257.0f));
|
||||
rg = (right_c->green * (1.0f/257.0f));
|
||||
rb = (right_c->blue * (1.0f/257.0f));
|
||||
|
||||
lx = left_x * (1.0f/65536.0f);
|
||||
rx = right_x * (1.0f/65536.0f);
|
||||
|
||||
if (FLOAT_IS_ZERO (rx - lx) || left_x == INT32_MIN || right_x == INT32_MAX)
|
||||
{
|
||||
walker->a_s = walker->r_s = walker->g_s = walker->b_s = 0.0f;
|
||||
walker->a_b = (la + ra) / 2.0f;
|
||||
walker->r_b = (lr + rr) / 510.0f;
|
||||
walker->g_b = (lg + rg) / 510.0f;
|
||||
walker->b_b = (lb + rb) / 510.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
float w_rec = 1.0f / (rx - lx);
|
||||
|
||||
walker->a_b = (la * rx - ra * lx) * w_rec;
|
||||
walker->r_b = (lr * rx - rr * lx) * w_rec * (1.0f/255.0f);
|
||||
walker->g_b = (lg * rx - rg * lx) * w_rec * (1.0f/255.0f);
|
||||
walker->b_b = (lb * rx - rb * lx) * w_rec * (1.0f/255.0f);
|
||||
|
||||
walker->a_s = (ra - la) * w_rec;
|
||||
walker->r_s = (rr - lr) * w_rec * (1.0f/255.0f);
|
||||
walker->g_s = (rg - lg) * w_rec * (1.0f/255.0f);
|
||||
walker->b_s = (rb - lb) * w_rec * (1.0f/255.0f);
|
||||
}
|
||||
|
||||
walker->left_x = left_x;
|
||||
walker->right_x = right_x;
|
||||
|
||||
walker->need_reset = FALSE;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
_pixman_gradient_walker_pixel (pixman_gradient_walker_t *walker,
|
||||
pixman_fixed_48_16_t x)
|
||||
{
|
||||
float a, r, g, b;
|
||||
uint8_t a8, r8, g8, b8;
|
||||
uint32_t v;
|
||||
float y;
|
||||
|
||||
if (walker->need_reset || x < walker->left_x || x >= walker->right_x)
|
||||
gradient_walker_reset (walker, x);
|
||||
|
||||
y = x * (1.0f / 65536.0f);
|
||||
|
||||
a = walker->a_s * y + walker->a_b;
|
||||
r = a * (walker->r_s * y + walker->r_b);
|
||||
g = a * (walker->g_s * y + walker->g_b);
|
||||
b = a * (walker->b_s * y + walker->b_b);
|
||||
|
||||
a8 = a + 0.5f;
|
||||
r8 = r + 0.5f;
|
||||
g8 = g + 0.5f;
|
||||
b8 = b + 0.5f;
|
||||
|
||||
v = ((a8 << 24) & 0xff000000) |
|
||||
((r8 << 16) & 0x00ff0000) |
|
||||
((g8 << 8) & 0x0000ff00) |
|
||||
((b8 >> 0) & 0x000000ff);
|
||||
|
||||
return v;
|
||||
}
|
@ -1,940 +0,0 @@
|
||||
/*
|
||||
* 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 <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 (
|
||||
/* affine and integer translation components in matrix ... */
|
||||
((flags & FAST_PATH_AFFINE_TRANSFORM) &&
|
||||
!pixman_fixed_frac (image->common.transform->matrix[0][2] |
|
||||
image->common.transform->matrix[1][2])) &&
|
||||
(
|
||||
/* ... combined with a simple rotation */
|
||||
(flags & (FAST_PATH_ROTATE_90_TRANSFORM |
|
||||
FAST_PATH_ROTATE_180_TRANSFORM |
|
||||
FAST_PATH_ROTATE_270_TRANSFORM)) ||
|
||||
/* ... or combined with a simple non-rotated translation */
|
||||
(image->common.transform->matrix[0][0] == pixman_fixed_1 &&
|
||||
image->common.transform->matrix[1][1] == pixman_fixed_1 &&
|
||||
image->common.transform->matrix[0][1] == 0 &&
|
||||
image->common.transform->matrix[1][0] == 0)
|
||||
)
|
||||
)
|
||||
{
|
||||
/* 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 map */
|
||||
if (!image->common.alpha_map)
|
||||
{
|
||||
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,
|
||||
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,
|
||||
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 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)
|
||||
{
|
||||
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 * (int) sizeof (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 = (*(uint8_t *)image->bits.bits) << 24;
|
||||
else
|
||||
goto otherwise;
|
||||
}
|
||||
else
|
||||
{
|
||||
pixman_iter_t iter;
|
||||
|
||||
otherwise:
|
||||
_pixman_implementation_src_iter_init (
|
||||
imp, &iter, image, 0, 0, 1, 1,
|
||||
(uint8_t *)&result,
|
||||
ITER_NARROW, image->common.flags);
|
||||
|
||||
result = *iter.get_scanline (&iter, NULL);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
@ -1,398 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2009 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 Red Hat not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. Red Hat makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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 <config.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include "pixman-private.h"
|
||||
|
||||
pixman_implementation_t *
|
||||
_pixman_implementation_create (pixman_implementation_t *fallback,
|
||||
const pixman_fast_path_t *fast_paths)
|
||||
{
|
||||
pixman_implementation_t *imp;
|
||||
|
||||
assert (fast_paths);
|
||||
|
||||
if ((imp = malloc (sizeof (pixman_implementation_t))))
|
||||
{
|
||||
pixman_implementation_t *d;
|
||||
|
||||
memset (imp, 0, sizeof *imp);
|
||||
|
||||
imp->fallback = fallback;
|
||||
imp->fast_paths = fast_paths;
|
||||
|
||||
/* Make sure the whole fallback chain has the right toplevel */
|
||||
for (d = imp; d != NULL; d = d->fallback)
|
||||
d->toplevel = imp;
|
||||
}
|
||||
|
||||
return imp;
|
||||
}
|
||||
|
||||
#define N_CACHED_FAST_PATHS 8
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
pixman_implementation_t * imp;
|
||||
pixman_fast_path_t fast_path;
|
||||
} cache [N_CACHED_FAST_PATHS];
|
||||
} cache_t;
|
||||
|
||||
PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache);
|
||||
|
||||
static void
|
||||
dummy_composite_rect (pixman_implementation_t *imp,
|
||||
pixman_composite_info_t *info)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_implementation_lookup_composite (pixman_implementation_t *toplevel,
|
||||
pixman_op_t op,
|
||||
pixman_format_code_t src_format,
|
||||
uint32_t src_flags,
|
||||
pixman_format_code_t mask_format,
|
||||
uint32_t mask_flags,
|
||||
pixman_format_code_t dest_format,
|
||||
uint32_t dest_flags,
|
||||
pixman_implementation_t **out_imp,
|
||||
pixman_composite_func_t *out_func)
|
||||
{
|
||||
pixman_implementation_t *imp;
|
||||
cache_t *cache;
|
||||
int i;
|
||||
|
||||
/* Check cache for fast paths */
|
||||
cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache);
|
||||
|
||||
for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
|
||||
{
|
||||
const pixman_fast_path_t *info = &(cache->cache[i].fast_path);
|
||||
|
||||
/* Note that we check for equality here, not whether
|
||||
* the cached fast path matches. This is to prevent
|
||||
* us from selecting an overly general fast path
|
||||
* when a more specific one would work.
|
||||
*/
|
||||
if (info->op == op &&
|
||||
info->src_format == src_format &&
|
||||
info->mask_format == mask_format &&
|
||||
info->dest_format == dest_format &&
|
||||
info->src_flags == src_flags &&
|
||||
info->mask_flags == mask_flags &&
|
||||
info->dest_flags == dest_flags &&
|
||||
info->func)
|
||||
{
|
||||
*out_imp = cache->cache[i].imp;
|
||||
*out_func = cache->cache[i].fast_path.func;
|
||||
|
||||
goto update_cache;
|
||||
}
|
||||
}
|
||||
|
||||
for (imp = toplevel; imp != NULL; imp = imp->fallback)
|
||||
{
|
||||
const pixman_fast_path_t *info = imp->fast_paths;
|
||||
|
||||
while (info->op != PIXMAN_OP_NONE)
|
||||
{
|
||||
if ((info->op == op || info->op == PIXMAN_OP_any) &&
|
||||
/* Formats */
|
||||
((info->src_format == src_format) ||
|
||||
(info->src_format == PIXMAN_any)) &&
|
||||
((info->mask_format == mask_format) ||
|
||||
(info->mask_format == PIXMAN_any)) &&
|
||||
((info->dest_format == dest_format) ||
|
||||
(info->dest_format == PIXMAN_any)) &&
|
||||
/* Flags */
|
||||
(info->src_flags & src_flags) == info->src_flags &&
|
||||
(info->mask_flags & mask_flags) == info->mask_flags &&
|
||||
(info->dest_flags & dest_flags) == info->dest_flags)
|
||||
{
|
||||
*out_imp = imp;
|
||||
*out_func = info->func;
|
||||
|
||||
/* Set i to the last spot in the cache so that the
|
||||
* move-to-front code below will work
|
||||
*/
|
||||
i = N_CACHED_FAST_PATHS - 1;
|
||||
|
||||
goto update_cache;
|
||||
}
|
||||
|
||||
++info;
|
||||
}
|
||||
}
|
||||
|
||||
/* We should never reach this point */
|
||||
_pixman_log_error (
|
||||
FUNC,
|
||||
"No composite function found\n"
|
||||
"\n"
|
||||
"The most likely cause of this is that this system has issues with\n"
|
||||
"thread local storage\n");
|
||||
|
||||
*out_imp = NULL;
|
||||
*out_func = dummy_composite_rect;
|
||||
return;
|
||||
|
||||
update_cache:
|
||||
if (i)
|
||||
{
|
||||
while (i--)
|
||||
cache->cache[i + 1] = cache->cache[i];
|
||||
|
||||
cache->cache[0].imp = *out_imp;
|
||||
cache->cache[0].fast_path.op = op;
|
||||
cache->cache[0].fast_path.src_format = src_format;
|
||||
cache->cache[0].fast_path.src_flags = src_flags;
|
||||
cache->cache[0].fast_path.mask_format = mask_format;
|
||||
cache->cache[0].fast_path.mask_flags = mask_flags;
|
||||
cache->cache[0].fast_path.dest_format = dest_format;
|
||||
cache->cache[0].fast_path.dest_flags = dest_flags;
|
||||
cache->cache[0].fast_path.func = *out_func;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dummy_combine (pixman_implementation_t *imp,
|
||||
pixman_op_t op,
|
||||
uint32_t * pd,
|
||||
const uint32_t * ps,
|
||||
const uint32_t * pm,
|
||||
int w)
|
||||
{
|
||||
}
|
||||
|
||||
pixman_combine_32_func_t
|
||||
_pixman_implementation_lookup_combiner (pixman_implementation_t *imp,
|
||||
pixman_op_t op,
|
||||
pixman_bool_t component_alpha,
|
||||
pixman_bool_t narrow)
|
||||
{
|
||||
while (imp)
|
||||
{
|
||||
pixman_combine_32_func_t f = NULL;
|
||||
|
||||
switch ((narrow << 1) | component_alpha)
|
||||
{
|
||||
case 0: /* not narrow, not component alpha */
|
||||
f = (pixman_combine_32_func_t)imp->combine_float[op];
|
||||
break;
|
||||
|
||||
case 1: /* not narrow, component_alpha */
|
||||
f = (pixman_combine_32_func_t)imp->combine_float_ca[op];
|
||||
break;
|
||||
|
||||
case 2: /* narrow, not component alpha */
|
||||
f = imp->combine_32[op];
|
||||
break;
|
||||
|
||||
case 3: /* narrow, component_alpha */
|
||||
f = imp->combine_32_ca[op];
|
||||
break;
|
||||
}
|
||||
|
||||
if (f)
|
||||
return f;
|
||||
|
||||
imp = imp->fallback;
|
||||
}
|
||||
|
||||
/* We should never reach this point */
|
||||
_pixman_log_error (FUNC, "No known combine function\n");
|
||||
return dummy_combine;
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
_pixman_implementation_blt (pixman_implementation_t * imp,
|
||||
uint32_t * src_bits,
|
||||
uint32_t * dst_bits,
|
||||
int src_stride,
|
||||
int dst_stride,
|
||||
int src_bpp,
|
||||
int dst_bpp,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dest_x,
|
||||
int dest_y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
while (imp)
|
||||
{
|
||||
if (imp->blt &&
|
||||
(*imp->blt) (imp, src_bits, dst_bits, src_stride, dst_stride,
|
||||
src_bpp, dst_bpp, src_x, src_y, dest_x, dest_y,
|
||||
width, height))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
imp = imp->fallback;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
_pixman_implementation_fill (pixman_implementation_t *imp,
|
||||
uint32_t * bits,
|
||||
int stride,
|
||||
int bpp,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
uint32_t filler)
|
||||
{
|
||||
while (imp)
|
||||
{
|
||||
if (imp->fill &&
|
||||
((*imp->fill) (imp, bits, stride, bpp, x, y, width, height, filler)))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
imp = imp->fallback;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
_pixman_implementation_src_iter_init (pixman_implementation_t *imp,
|
||||
pixman_iter_t *iter,
|
||||
pixman_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
uint8_t *buffer,
|
||||
iter_flags_t iter_flags,
|
||||
uint32_t image_flags)
|
||||
{
|
||||
iter->image = image;
|
||||
iter->buffer = (uint32_t *)buffer;
|
||||
iter->x = x;
|
||||
iter->y = y;
|
||||
iter->width = width;
|
||||
iter->height = height;
|
||||
iter->iter_flags = iter_flags;
|
||||
iter->image_flags = image_flags;
|
||||
|
||||
while (imp)
|
||||
{
|
||||
if (imp->src_iter_init && (*imp->src_iter_init) (imp, iter))
|
||||
return TRUE;
|
||||
|
||||
imp = imp->fallback;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
_pixman_implementation_dest_iter_init (pixman_implementation_t *imp,
|
||||
pixman_iter_t *iter,
|
||||
pixman_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
uint8_t *buffer,
|
||||
iter_flags_t iter_flags,
|
||||
uint32_t image_flags)
|
||||
{
|
||||
iter->image = image;
|
||||
iter->buffer = (uint32_t *)buffer;
|
||||
iter->x = x;
|
||||
iter->y = y;
|
||||
iter->width = width;
|
||||
iter->height = height;
|
||||
iter->iter_flags = iter_flags;
|
||||
iter->image_flags = image_flags;
|
||||
|
||||
while (imp)
|
||||
{
|
||||
if (imp->dest_iter_init && (*imp->dest_iter_init) (imp, iter))
|
||||
return TRUE;
|
||||
|
||||
imp = imp->fallback;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
_pixman_disabled (const char *name)
|
||||
{
|
||||
const char *env;
|
||||
|
||||
if ((env = getenv ("PIXMAN_DISABLE")))
|
||||
{
|
||||
do
|
||||
{
|
||||
const char *end;
|
||||
int len;
|
||||
|
||||
if ((end = strchr (env, ' ')))
|
||||
len = end - env;
|
||||
else
|
||||
len = strlen (env);
|
||||
|
||||
if (strlen (name) == len && strncmp (name, env, len) == 0)
|
||||
{
|
||||
printf ("pixman: Disabled %s implementation\n", name);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
env += len;
|
||||
}
|
||||
while (*env++);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pixman_implementation_t *
|
||||
_pixman_choose_implementation (void)
|
||||
{
|
||||
pixman_implementation_t *imp;
|
||||
|
||||
imp = _pixman_implementation_create_general();
|
||||
|
||||
if (!_pixman_disabled ("fast"))
|
||||
imp = _pixman_implementation_create_fast_path (imp);
|
||||
|
||||
imp = _pixman_x86_get_implementations (imp);
|
||||
|
||||
imp = _pixman_implementation_create_noop (imp);
|
||||
|
||||
return imp;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,287 +0,0 @@
|
||||
/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
|
||||
/*
|
||||
* Copyright © 2000 SuSE, Inc.
|
||||
* Copyright © 2007 Red Hat, Inc.
|
||||
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
|
||||
* 2005 Lars Knoll & Zack Rusin, Trolltech
|
||||
*
|
||||
* 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 Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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 <config.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include "pixman-private.h"
|
||||
|
||||
static pixman_bool_t
|
||||
linear_gradient_is_horizontal (pixman_image_t *image,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
linear_gradient_t *linear = (linear_gradient_t *)image;
|
||||
pixman_vector_t v;
|
||||
pixman_fixed_32_32_t l;
|
||||
pixman_fixed_48_16_t dx, dy;
|
||||
double inc;
|
||||
|
||||
if (image->common.transform)
|
||||
{
|
||||
/* projective transformation */
|
||||
if (image->common.transform->matrix[2][0] != 0 ||
|
||||
image->common.transform->matrix[2][1] != 0 ||
|
||||
image->common.transform->matrix[2][2] == 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
v.vector[0] = image->common.transform->matrix[0][1];
|
||||
v.vector[1] = image->common.transform->matrix[1][1];
|
||||
v.vector[2] = image->common.transform->matrix[2][2];
|
||||
}
|
||||
else
|
||||
{
|
||||
v.vector[0] = 0;
|
||||
v.vector[1] = pixman_fixed_1;
|
||||
v.vector[2] = pixman_fixed_1;
|
||||
}
|
||||
|
||||
dx = linear->p2.x - linear->p1.x;
|
||||
dy = linear->p2.y - linear->p1.y;
|
||||
|
||||
l = dx * dx + dy * dy;
|
||||
|
||||
if (l == 0)
|
||||
return FALSE;
|
||||
|
||||
/*
|
||||
* compute how much the input of the gradient walked changes
|
||||
* when moving vertically through the whole image
|
||||
*/
|
||||
inc = height * (double) pixman_fixed_1 * pixman_fixed_1 *
|
||||
(dx * v.vector[0] + dy * v.vector[1]) /
|
||||
(v.vector[2] * (double) l);
|
||||
|
||||
/* check that casting to integer would result in 0 */
|
||||
if (-1 < inc && inc < 1)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static uint32_t *
|
||||
linear_get_scanline_narrow (pixman_iter_t *iter,
|
||||
const uint32_t *mask)
|
||||
{
|
||||
pixman_image_t *image = iter->image;
|
||||
int x = iter->x;
|
||||
int y = iter->y;
|
||||
int width = iter->width;
|
||||
uint32_t * buffer = iter->buffer;
|
||||
|
||||
pixman_vector_t v, unit;
|
||||
pixman_fixed_32_32_t l;
|
||||
pixman_fixed_48_16_t dx, dy;
|
||||
gradient_t *gradient = (gradient_t *)image;
|
||||
linear_gradient_t *linear = (linear_gradient_t *)image;
|
||||
uint32_t *end = buffer + width;
|
||||
pixman_gradient_walker_t walker;
|
||||
|
||||
_pixman_gradient_walker_init (&walker, gradient, image->common.repeat);
|
||||
|
||||
/* reference point is the center of the pixel */
|
||||
v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2;
|
||||
v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
|
||||
v.vector[2] = pixman_fixed_1;
|
||||
|
||||
if (image->common.transform)
|
||||
{
|
||||
if (!pixman_transform_point_3d (image->common.transform, &v))
|
||||
return iter->buffer;
|
||||
|
||||
unit.vector[0] = image->common.transform->matrix[0][0];
|
||||
unit.vector[1] = image->common.transform->matrix[1][0];
|
||||
unit.vector[2] = image->common.transform->matrix[2][0];
|
||||
}
|
||||
else
|
||||
{
|
||||
unit.vector[0] = pixman_fixed_1;
|
||||
unit.vector[1] = 0;
|
||||
unit.vector[2] = 0;
|
||||
}
|
||||
|
||||
dx = linear->p2.x - linear->p1.x;
|
||||
dy = linear->p2.y - linear->p1.y;
|
||||
|
||||
l = dx * dx + dy * dy;
|
||||
|
||||
if (l == 0 || unit.vector[2] == 0)
|
||||
{
|
||||
/* affine transformation only */
|
||||
pixman_fixed_32_32_t t, next_inc;
|
||||
double inc;
|
||||
|
||||
if (l == 0 || v.vector[2] == 0)
|
||||
{
|
||||
t = 0;
|
||||
inc = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
double invden, v2;
|
||||
|
||||
invden = pixman_fixed_1 * (double) pixman_fixed_1 /
|
||||
(l * (double) v.vector[2]);
|
||||
v2 = v.vector[2] * (1. / pixman_fixed_1);
|
||||
t = ((dx * v.vector[0] + dy * v.vector[1]) -
|
||||
(dx * linear->p1.x + dy * linear->p1.y) * v2) * invden;
|
||||
inc = (dx * unit.vector[0] + dy * unit.vector[1]) * invden;
|
||||
}
|
||||
next_inc = 0;
|
||||
|
||||
if (((pixman_fixed_32_32_t )(inc * width)) == 0)
|
||||
{
|
||||
register uint32_t color;
|
||||
|
||||
color = _pixman_gradient_walker_pixel (&walker, t);
|
||||
while (buffer < end)
|
||||
*buffer++ = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
while (buffer < end)
|
||||
{
|
||||
if (!mask || *mask++)
|
||||
{
|
||||
*buffer = _pixman_gradient_walker_pixel (&walker,
|
||||
t + next_inc);
|
||||
}
|
||||
i++;
|
||||
next_inc = inc * i;
|
||||
buffer++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* projective transformation */
|
||||
double t;
|
||||
|
||||
t = 0;
|
||||
|
||||
while (buffer < end)
|
||||
{
|
||||
if (!mask || *mask++)
|
||||
{
|
||||
if (v.vector[2] != 0)
|
||||
{
|
||||
double invden, v2;
|
||||
|
||||
invden = pixman_fixed_1 * (double) pixman_fixed_1 /
|
||||
(l * (double) v.vector[2]);
|
||||
v2 = v.vector[2] * (1. / pixman_fixed_1);
|
||||
t = ((dx * v.vector[0] + dy * v.vector[1]) -
|
||||
(dx * linear->p1.x + dy * linear->p1.y) * v2) * invden;
|
||||
}
|
||||
|
||||
*buffer = _pixman_gradient_walker_pixel (&walker, t);
|
||||
}
|
||||
|
||||
++buffer;
|
||||
|
||||
v.vector[0] += unit.vector[0];
|
||||
v.vector[1] += unit.vector[1];
|
||||
v.vector[2] += unit.vector[2];
|
||||
}
|
||||
}
|
||||
|
||||
iter->y++;
|
||||
|
||||
return iter->buffer;
|
||||
}
|
||||
|
||||
static uint32_t *
|
||||
linear_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
uint32_t *buffer = linear_get_scanline_narrow (iter, NULL);
|
||||
|
||||
pixman_expand_to_float (
|
||||
(argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_linear_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter)
|
||||
{
|
||||
if (linear_gradient_is_horizontal (
|
||||
iter->image, iter->x, iter->y, iter->width, iter->height))
|
||||
{
|
||||
if (iter->iter_flags & ITER_NARROW)
|
||||
linear_get_scanline_narrow (iter, NULL);
|
||||
else
|
||||
linear_get_scanline_wide (iter, NULL);
|
||||
|
||||
iter->get_scanline = _pixman_iter_get_scanline_noop;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (iter->iter_flags & ITER_NARROW)
|
||||
iter->get_scanline = linear_get_scanline_narrow;
|
||||
else
|
||||
iter->get_scanline = linear_get_scanline_wide;
|
||||
}
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT pixman_image_t *
|
||||
pixman_image_create_linear_gradient (const pixman_point_fixed_t * p1,
|
||||
const pixman_point_fixed_t * p2,
|
||||
const pixman_gradient_stop_t *stops,
|
||||
int n_stops)
|
||||
{
|
||||
pixman_image_t *image;
|
||||
linear_gradient_t *linear;
|
||||
|
||||
image = _pixman_image_allocate ();
|
||||
|
||||
if (!image)
|
||||
return NULL;
|
||||
|
||||
linear = &image->linear;
|
||||
|
||||
if (!_pixman_init_gradient (&linear->common, stops, n_stops))
|
||||
{
|
||||
free (image);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
linear->p1 = *p1;
|
||||
linear->p2 = *p2;
|
||||
|
||||
image->type = LINEAR;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,176 +0,0 @@
|
||||
/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
|
||||
/*
|
||||
* Copyright © 2011 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "pixman-private.h"
|
||||
#include "pixman-combine32.h"
|
||||
#include "pixman-inlines.h"
|
||||
|
||||
static void
|
||||
noop_composite (pixman_implementation_t *imp,
|
||||
pixman_composite_info_t *info)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
dest_write_back_direct (pixman_iter_t *iter)
|
||||
{
|
||||
iter->buffer += iter->image->bits.rowstride;
|
||||
}
|
||||
|
||||
static uint32_t *
|
||||
noop_get_scanline (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
uint32_t *result = iter->buffer;
|
||||
|
||||
iter->buffer += iter->image->bits.rowstride;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint32_t *
|
||||
get_scanline_null (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static pixman_bool_t
|
||||
noop_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
|
||||
{
|
||||
pixman_image_t *image = iter->image;
|
||||
|
||||
#define FLAGS \
|
||||
(FAST_PATH_STANDARD_FLAGS | FAST_PATH_ID_TRANSFORM)
|
||||
|
||||
if (!image)
|
||||
{
|
||||
iter->get_scanline = get_scanline_null;
|
||||
}
|
||||
else if ((iter->iter_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) ==
|
||||
(ITER_IGNORE_ALPHA | ITER_IGNORE_RGB))
|
||||
{
|
||||
iter->get_scanline = _pixman_iter_get_scanline_noop;
|
||||
}
|
||||
else if (image->common.extended_format_code == PIXMAN_solid &&
|
||||
(iter->image->type == SOLID ||
|
||||
(iter->image_flags & FAST_PATH_NO_ALPHA_MAP)))
|
||||
{
|
||||
if (iter->iter_flags & ITER_NARROW)
|
||||
{
|
||||
uint32_t *buffer = iter->buffer;
|
||||
uint32_t *end = buffer + iter->width;
|
||||
uint32_t color;
|
||||
|
||||
if (image->type == SOLID)
|
||||
color = image->solid.color_32;
|
||||
else
|
||||
color = image->bits.fetch_pixel_32 (&image->bits, 0, 0);
|
||||
|
||||
while (buffer < end)
|
||||
*(buffer++) = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
argb_t *buffer = (argb_t *)iter->buffer;
|
||||
argb_t *end = buffer + iter->width;
|
||||
argb_t color;
|
||||
|
||||
if (image->type == SOLID)
|
||||
color = image->solid.color_float;
|
||||
else
|
||||
color = image->bits.fetch_pixel_float (&image->bits, 0, 0);
|
||||
|
||||
while (buffer < end)
|
||||
*(buffer++) = color;
|
||||
}
|
||||
|
||||
iter->get_scanline = _pixman_iter_get_scanline_noop;
|
||||
}
|
||||
else if (image->common.extended_format_code == PIXMAN_a8r8g8b8 &&
|
||||
(iter->iter_flags & ITER_NARROW) &&
|
||||
(iter->image_flags & FLAGS) == FLAGS &&
|
||||
iter->x >= 0 && iter->y >= 0 &&
|
||||
iter->x + iter->width <= image->bits.width &&
|
||||
iter->y + iter->height <= image->bits.height)
|
||||
{
|
||||
iter->buffer =
|
||||
image->bits.bits + iter->y * image->bits.rowstride + iter->x;
|
||||
|
||||
iter->get_scanline = noop_get_scanline;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static pixman_bool_t
|
||||
noop_dest_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
|
||||
{
|
||||
pixman_image_t *image = iter->image;
|
||||
uint32_t image_flags = iter->image_flags;
|
||||
uint32_t iter_flags = iter->iter_flags;
|
||||
|
||||
if ((image_flags & FAST_PATH_STD_DEST_FLAGS) == FAST_PATH_STD_DEST_FLAGS &&
|
||||
(iter_flags & ITER_NARROW) == ITER_NARROW &&
|
||||
((image->common.extended_format_code == PIXMAN_a8r8g8b8) ||
|
||||
(image->common.extended_format_code == PIXMAN_x8r8g8b8 &&
|
||||
(iter_flags & (ITER_LOCALIZED_ALPHA)))))
|
||||
{
|
||||
iter->buffer = image->bits.bits + iter->y * image->bits.rowstride + iter->x;
|
||||
|
||||
iter->get_scanline = _pixman_iter_get_scanline_noop;
|
||||
iter->write_back = dest_write_back_direct;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static const pixman_fast_path_t noop_fast_paths[] =
|
||||
{
|
||||
{ PIXMAN_OP_DST, PIXMAN_any, 0, PIXMAN_any, 0, PIXMAN_any, 0, noop_composite },
|
||||
{ PIXMAN_OP_NONE },
|
||||
};
|
||||
|
||||
pixman_implementation_t *
|
||||
_pixman_implementation_create_noop (pixman_implementation_t *fallback)
|
||||
{
|
||||
pixman_implementation_t *imp =
|
||||
_pixman_implementation_create (fallback, noop_fast_paths);
|
||||
|
||||
imp->src_iter_init = noop_src_iter_init;
|
||||
imp->dest_iter_init = noop_dest_iter_init;
|
||||
|
||||
return imp;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,471 +0,0 @@
|
||||
/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
|
||||
/*
|
||||
*
|
||||
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
|
||||
* Copyright © 2000 SuSE, Inc.
|
||||
* 2005 Lars Knoll & Zack Rusin, Trolltech
|
||||
* 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 Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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 <config.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "pixman-private.h"
|
||||
|
||||
static inline pixman_fixed_32_32_t
|
||||
dot (pixman_fixed_48_16_t x1,
|
||||
pixman_fixed_48_16_t y1,
|
||||
pixman_fixed_48_16_t z1,
|
||||
pixman_fixed_48_16_t x2,
|
||||
pixman_fixed_48_16_t y2,
|
||||
pixman_fixed_48_16_t z2)
|
||||
{
|
||||
/*
|
||||
* Exact computation, assuming that the input values can
|
||||
* be represented as pixman_fixed_16_16_t
|
||||
*/
|
||||
return x1 * x2 + y1 * y2 + z1 * z2;
|
||||
}
|
||||
|
||||
static inline double
|
||||
fdot (double x1,
|
||||
double y1,
|
||||
double z1,
|
||||
double x2,
|
||||
double y2,
|
||||
double z2)
|
||||
{
|
||||
/*
|
||||
* Error can be unbound in some special cases.
|
||||
* Using clever dot product algorithms (for example compensated
|
||||
* dot product) would improve this but make the code much less
|
||||
* obvious
|
||||
*/
|
||||
return x1 * x2 + y1 * y2 + z1 * z2;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
radial_compute_color (double a,
|
||||
double b,
|
||||
double c,
|
||||
double inva,
|
||||
double dr,
|
||||
double mindr,
|
||||
pixman_gradient_walker_t *walker,
|
||||
pixman_repeat_t repeat)
|
||||
{
|
||||
/*
|
||||
* In this function error propagation can lead to bad results:
|
||||
* - discr can have an unbound error (if b*b-a*c is very small),
|
||||
* potentially making it the opposite sign of what it should have been
|
||||
* (thus clearing a pixel that would have been colored or vice-versa)
|
||||
* or propagating the error to sqrtdiscr;
|
||||
* if discr has the wrong sign or b is very small, this can lead to bad
|
||||
* results
|
||||
*
|
||||
* - the algorithm used to compute the solutions of the quadratic
|
||||
* equation is not numerically stable (but saves one division compared
|
||||
* to the numerically stable one);
|
||||
* this can be a problem if a*c is much smaller than b*b
|
||||
*
|
||||
* - the above problems are worse if a is small (as inva becomes bigger)
|
||||
*/
|
||||
double discr;
|
||||
|
||||
if (a == 0)
|
||||
{
|
||||
double t;
|
||||
|
||||
if (b == 0)
|
||||
return 0;
|
||||
|
||||
t = pixman_fixed_1 / 2 * c / b;
|
||||
if (repeat == PIXMAN_REPEAT_NONE)
|
||||
{
|
||||
if (0 <= t && t <= pixman_fixed_1)
|
||||
return _pixman_gradient_walker_pixel (walker, t);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t * dr >= mindr)
|
||||
return _pixman_gradient_walker_pixel (walker, t);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
discr = fdot (b, a, 0, b, -c, 0);
|
||||
if (discr >= 0)
|
||||
{
|
||||
double sqrtdiscr, t0, t1;
|
||||
|
||||
sqrtdiscr = sqrt (discr);
|
||||
t0 = (b + sqrtdiscr) * inva;
|
||||
t1 = (b - sqrtdiscr) * inva;
|
||||
|
||||
/*
|
||||
* The root that must be used is the biggest one that belongs
|
||||
* to the valid range ([0,1] for PIXMAN_REPEAT_NONE, any
|
||||
* solution that results in a positive radius otherwise).
|
||||
*
|
||||
* If a > 0, t0 is the biggest solution, so if it is valid, it
|
||||
* is the correct result.
|
||||
*
|
||||
* If a < 0, only one of the solutions can be valid, so the
|
||||
* order in which they are tested is not important.
|
||||
*/
|
||||
if (repeat == PIXMAN_REPEAT_NONE)
|
||||
{
|
||||
if (0 <= t0 && t0 <= pixman_fixed_1)
|
||||
return _pixman_gradient_walker_pixel (walker, t0);
|
||||
else if (0 <= t1 && t1 <= pixman_fixed_1)
|
||||
return _pixman_gradient_walker_pixel (walker, t1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t0 * dr >= mindr)
|
||||
return _pixman_gradient_walker_pixel (walker, t0);
|
||||
else if (t1 * dr >= mindr)
|
||||
return _pixman_gradient_walker_pixel (walker, t1);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t *
|
||||
radial_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
/*
|
||||
* Implementation of radial gradients following the PDF specification.
|
||||
* See section 8.7.4.5.4 Type 3 (Radial) Shadings of the PDF Reference
|
||||
* Manual (PDF 32000-1:2008 at the time of this writing).
|
||||
*
|
||||
* In the radial gradient problem we are given two circles (c₁,r₁) and
|
||||
* (c₂,r₂) that define the gradient itself.
|
||||
*
|
||||
* Mathematically the gradient can be defined as the family of circles
|
||||
*
|
||||
* ((1-t)·c₁ + t·(c₂), (1-t)·r₁ + t·r₂)
|
||||
*
|
||||
* excluding those circles whose radius would be < 0. When a point
|
||||
* belongs to more than one circle, the one with a bigger t is the only
|
||||
* one that contributes to its color. When a point does not belong
|
||||
* to any of the circles, it is transparent black, i.e. RGBA (0, 0, 0, 0).
|
||||
* Further limitations on the range of values for t are imposed when
|
||||
* the gradient is not repeated, namely t must belong to [0,1].
|
||||
*
|
||||
* The graphical result is the same as drawing the valid (radius > 0)
|
||||
* circles with increasing t in [-inf, +inf] (or in [0,1] if the gradient
|
||||
* is not repeated) using SOURCE operator composition.
|
||||
*
|
||||
* It looks like a cone pointing towards the viewer if the ending circle
|
||||
* is smaller than the starting one, a cone pointing inside the page if
|
||||
* the starting circle is the smaller one and like a cylinder if they
|
||||
* have the same radius.
|
||||
*
|
||||
* What we actually do is, given the point whose color we are interested
|
||||
* in, compute the t values for that point, solving for t in:
|
||||
*
|
||||
* length((1-t)·c₁ + t·(c₂) - p) = (1-t)·r₁ + t·r₂
|
||||
*
|
||||
* Let's rewrite it in a simpler way, by defining some auxiliary
|
||||
* variables:
|
||||
*
|
||||
* cd = c₂ - c₁
|
||||
* pd = p - c₁
|
||||
* dr = r₂ - r₁
|
||||
* length(t·cd - pd) = r₁ + t·dr
|
||||
*
|
||||
* which actually means
|
||||
*
|
||||
* hypot(t·cdx - pdx, t·cdy - pdy) = r₁ + t·dr
|
||||
*
|
||||
* or
|
||||
*
|
||||
* ⎷((t·cdx - pdx)² + (t·cdy - pdy)²) = r₁ + t·dr.
|
||||
*
|
||||
* If we impose (as stated earlier) that r₁ + t·dr >= 0, it becomes:
|
||||
*
|
||||
* (t·cdx - pdx)² + (t·cdy - pdy)² = (r₁ + t·dr)²
|
||||
*
|
||||
* where we can actually expand the squares and solve for t:
|
||||
*
|
||||
* t²cdx² - 2t·cdx·pdx + pdx² + t²cdy² - 2t·cdy·pdy + pdy² =
|
||||
* = r₁² + 2·r₁·t·dr + t²·dr²
|
||||
*
|
||||
* (cdx² + cdy² - dr²)t² - 2(cdx·pdx + cdy·pdy + r₁·dr)t +
|
||||
* (pdx² + pdy² - r₁²) = 0
|
||||
*
|
||||
* A = cdx² + cdy² - dr²
|
||||
* B = pdx·cdx + pdy·cdy + r₁·dr
|
||||
* C = pdx² + pdy² - r₁²
|
||||
* At² - 2Bt + C = 0
|
||||
*
|
||||
* The solutions (unless the equation degenerates because of A = 0) are:
|
||||
*
|
||||
* t = (B ± ⎷(B² - A·C)) / A
|
||||
*
|
||||
* The solution we are going to prefer is the bigger one, unless the
|
||||
* radius associated to it is negative (or it falls outside the valid t
|
||||
* range).
|
||||
*
|
||||
* Additional observations (useful for optimizations):
|
||||
* A does not depend on p
|
||||
*
|
||||
* A < 0 <=> one of the two circles completely contains the other one
|
||||
* <=> for every p, the radiuses associated with the two t solutions
|
||||
* have opposite sign
|
||||
*/
|
||||
pixman_image_t *image = iter->image;
|
||||
int x = iter->x;
|
||||
int y = iter->y;
|
||||
int width = iter->width;
|
||||
uint32_t *buffer = iter->buffer;
|
||||
|
||||
gradient_t *gradient = (gradient_t *)image;
|
||||
radial_gradient_t *radial = (radial_gradient_t *)image;
|
||||
uint32_t *end = buffer + width;
|
||||
pixman_gradient_walker_t walker;
|
||||
pixman_vector_t v, unit;
|
||||
|
||||
/* reference point is the center of the pixel */
|
||||
v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2;
|
||||
v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
|
||||
v.vector[2] = pixman_fixed_1;
|
||||
|
||||
_pixman_gradient_walker_init (&walker, gradient, image->common.repeat);
|
||||
|
||||
if (image->common.transform)
|
||||
{
|
||||
if (!pixman_transform_point_3d (image->common.transform, &v))
|
||||
return iter->buffer;
|
||||
|
||||
unit.vector[0] = image->common.transform->matrix[0][0];
|
||||
unit.vector[1] = image->common.transform->matrix[1][0];
|
||||
unit.vector[2] = image->common.transform->matrix[2][0];
|
||||
}
|
||||
else
|
||||
{
|
||||
unit.vector[0] = pixman_fixed_1;
|
||||
unit.vector[1] = 0;
|
||||
unit.vector[2] = 0;
|
||||
}
|
||||
|
||||
if (unit.vector[2] == 0 && v.vector[2] == pixman_fixed_1)
|
||||
{
|
||||
/*
|
||||
* Given:
|
||||
*
|
||||
* t = (B ± ⎷(B² - A·C)) / A
|
||||
*
|
||||
* where
|
||||
*
|
||||
* A = cdx² + cdy² - dr²
|
||||
* B = pdx·cdx + pdy·cdy + r₁·dr
|
||||
* C = pdx² + pdy² - r₁²
|
||||
* det = B² - A·C
|
||||
*
|
||||
* Since we have an affine transformation, we know that (pdx, pdy)
|
||||
* increase linearly with each pixel,
|
||||
*
|
||||
* pdx = pdx₀ + n·ux,
|
||||
* pdy = pdy₀ + n·uy,
|
||||
*
|
||||
* we can then express B, C and det through multiple differentiation.
|
||||
*/
|
||||
pixman_fixed_32_32_t b, db, c, dc, ddc;
|
||||
|
||||
/* warning: this computation may overflow */
|
||||
v.vector[0] -= radial->c1.x;
|
||||
v.vector[1] -= radial->c1.y;
|
||||
|
||||
/*
|
||||
* B and C are computed and updated exactly.
|
||||
* If fdot was used instead of dot, in the worst case it would
|
||||
* lose 11 bits of precision in each of the multiplication and
|
||||
* summing up would zero out all the bit that were preserved,
|
||||
* thus making the result 0 instead of the correct one.
|
||||
* This would mean a worst case of unbound relative error or
|
||||
* about 2^10 absolute error
|
||||
*/
|
||||
b = dot (v.vector[0], v.vector[1], radial->c1.radius,
|
||||
radial->delta.x, radial->delta.y, radial->delta.radius);
|
||||
db = dot (unit.vector[0], unit.vector[1], 0,
|
||||
radial->delta.x, radial->delta.y, 0);
|
||||
|
||||
c = dot (v.vector[0], v.vector[1],
|
||||
-((pixman_fixed_48_16_t) radial->c1.radius),
|
||||
v.vector[0], v.vector[1], radial->c1.radius);
|
||||
dc = dot (2 * (pixman_fixed_48_16_t) v.vector[0] + unit.vector[0],
|
||||
2 * (pixman_fixed_48_16_t) v.vector[1] + unit.vector[1],
|
||||
0,
|
||||
unit.vector[0], unit.vector[1], 0);
|
||||
ddc = 2 * dot (unit.vector[0], unit.vector[1], 0,
|
||||
unit.vector[0], unit.vector[1], 0);
|
||||
|
||||
while (buffer < end)
|
||||
{
|
||||
if (!mask || *mask++)
|
||||
{
|
||||
*buffer = radial_compute_color (radial->a, b, c,
|
||||
radial->inva,
|
||||
radial->delta.radius,
|
||||
radial->mindr,
|
||||
&walker,
|
||||
image->common.repeat);
|
||||
}
|
||||
|
||||
b += db;
|
||||
c += dc;
|
||||
dc += ddc;
|
||||
++buffer;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* projective */
|
||||
/* Warning:
|
||||
* error propagation guarantees are much looser than in the affine case
|
||||
*/
|
||||
while (buffer < end)
|
||||
{
|
||||
if (!mask || *mask++)
|
||||
{
|
||||
if (v.vector[2] != 0)
|
||||
{
|
||||
double pdx, pdy, invv2, b, c;
|
||||
|
||||
invv2 = 1. * pixman_fixed_1 / v.vector[2];
|
||||
|
||||
pdx = v.vector[0] * invv2 - radial->c1.x;
|
||||
/* / pixman_fixed_1 */
|
||||
|
||||
pdy = v.vector[1] * invv2 - radial->c1.y;
|
||||
/* / pixman_fixed_1 */
|
||||
|
||||
b = fdot (pdx, pdy, radial->c1.radius,
|
||||
radial->delta.x, radial->delta.y,
|
||||
radial->delta.radius);
|
||||
/* / pixman_fixed_1 / pixman_fixed_1 */
|
||||
|
||||
c = fdot (pdx, pdy, -radial->c1.radius,
|
||||
pdx, pdy, radial->c1.radius);
|
||||
/* / pixman_fixed_1 / pixman_fixed_1 */
|
||||
|
||||
*buffer = radial_compute_color (radial->a, b, c,
|
||||
radial->inva,
|
||||
radial->delta.radius,
|
||||
radial->mindr,
|
||||
&walker,
|
||||
image->common.repeat);
|
||||
}
|
||||
else
|
||||
{
|
||||
*buffer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
++buffer;
|
||||
|
||||
v.vector[0] += unit.vector[0];
|
||||
v.vector[1] += unit.vector[1];
|
||||
v.vector[2] += unit.vector[2];
|
||||
}
|
||||
}
|
||||
|
||||
iter->y++;
|
||||
return iter->buffer;
|
||||
}
|
||||
|
||||
static uint32_t *
|
||||
radial_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
uint32_t *buffer = radial_get_scanline_narrow (iter, NULL);
|
||||
|
||||
pixman_expand_to_float (
|
||||
(argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_radial_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter)
|
||||
{
|
||||
if (iter->iter_flags & ITER_NARROW)
|
||||
iter->get_scanline = radial_get_scanline_narrow;
|
||||
else
|
||||
iter->get_scanline = radial_get_scanline_wide;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT pixman_image_t *
|
||||
pixman_image_create_radial_gradient (const pixman_point_fixed_t * inner,
|
||||
const pixman_point_fixed_t * outer,
|
||||
pixman_fixed_t inner_radius,
|
||||
pixman_fixed_t outer_radius,
|
||||
const pixman_gradient_stop_t *stops,
|
||||
int n_stops)
|
||||
{
|
||||
pixman_image_t *image;
|
||||
radial_gradient_t *radial;
|
||||
|
||||
image = _pixman_image_allocate ();
|
||||
|
||||
if (!image)
|
||||
return NULL;
|
||||
|
||||
radial = &image->radial;
|
||||
|
||||
if (!_pixman_init_gradient (&radial->common, stops, n_stops))
|
||||
{
|
||||
free (image);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
image->type = RADIAL;
|
||||
|
||||
radial->c1.x = inner->x;
|
||||
radial->c1.y = inner->y;
|
||||
radial->c1.radius = inner_radius;
|
||||
radial->c2.x = outer->x;
|
||||
radial->c2.y = outer->y;
|
||||
radial->c2.radius = outer_radius;
|
||||
|
||||
/* warning: this computations may overflow */
|
||||
radial->delta.x = radial->c2.x - radial->c1.x;
|
||||
radial->delta.y = radial->c2.y - radial->c1.y;
|
||||
radial->delta.radius = radial->c2.radius - radial->c1.radius;
|
||||
|
||||
/* computed exactly, then cast to double -> every bit of the double
|
||||
representation is correct (53 bits) */
|
||||
radial->a = dot (radial->delta.x, radial->delta.y, -radial->delta.radius,
|
||||
radial->delta.x, radial->delta.y, radial->delta.radius);
|
||||
if (radial->a != 0)
|
||||
radial->inva = 1. * pixman_fixed_1 / radial->a;
|
||||
|
||||
radial->mindr = -1. * pixman_fixed_1 * radial->c1.radius;
|
||||
|
||||
return image;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2008 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
|
||||
* Red Hat, Inc. not be used in advertising or publicity pertaining to
|
||||
* distribution of the software without specific, written prior
|
||||
* permission. Red Hat, Inc. makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL RED HAT, INC. 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.
|
||||
*
|
||||
* Author: Soren Sandmann <sandmann@redhat.com>
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#undef PIXMAN_DISABLE_DEPRECATED
|
||||
|
||||
#include "pixman-private.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef pixman_box16_t box_type_t;
|
||||
typedef pixman_region16_data_t region_data_type_t;
|
||||
typedef pixman_region16_t region_type_t;
|
||||
typedef int32_t overflow_int_t;
|
||||
|
||||
typedef struct {
|
||||
int x, y;
|
||||
} point_type_t;
|
||||
|
||||
#define PREFIX(x) pixman_region##x
|
||||
|
||||
#define PIXMAN_REGION_MAX INT16_MAX
|
||||
#define PIXMAN_REGION_MIN INT16_MIN
|
||||
|
||||
#include "pixman-region.c"
|
||||
|
||||
/* This function exists only to make it possible to preserve the X ABI -
|
||||
* it should go away at first opportunity.
|
||||
*
|
||||
* The problem is that the X ABI exports the three structs and has used
|
||||
* them through macros. So the X server calls this function with
|
||||
* the addresses of those structs which makes the existing code continue to
|
||||
* work.
|
||||
*/
|
||||
PIXMAN_EXPORT void
|
||||
pixman_region_set_static_pointers (pixman_box16_t *empty_box,
|
||||
pixman_region16_data_t *empty_data,
|
||||
pixman_region16_data_t *broken_data)
|
||||
{
|
||||
pixman_region_empty_box = empty_box;
|
||||
pixman_region_empty_data = empty_data;
|
||||
pixman_broken_data = broken_data;
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2008 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
|
||||
* Red Hat, Inc. not be used in advertising or publicity pertaining to
|
||||
* distribution of the software without specific, written prior
|
||||
* permission. Red Hat, Inc. makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL RED HAT, INC. 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.
|
||||
*
|
||||
* Author: Soren Sandmann <sandmann@redhat.com>
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "pixman-private.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef pixman_box32_t box_type_t;
|
||||
typedef pixman_region32_data_t region_data_type_t;
|
||||
typedef pixman_region32_t region_type_t;
|
||||
typedef int64_t overflow_int_t;
|
||||
|
||||
typedef struct {
|
||||
int x, y;
|
||||
} point_type_t;
|
||||
|
||||
#define PREFIX(x) pixman_region32##x
|
||||
|
||||
#define PIXMAN_REGION_MAX INT32_MAX
|
||||
#define PIXMAN_REGION_MIN INT32_MIN
|
||||
|
||||
#include "pixman-region.c"
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2000 SuSE, Inc.
|
||||
* Copyright © 2007, 2009 Red Hat, Inc.
|
||||
* Copyright © 2009 Soren Sandmann
|
||||
*
|
||||
* 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 <config.h>
|
||||
#endif
|
||||
#include "pixman-private.h"
|
||||
|
||||
static uint32_t
|
||||
color_to_uint32 (const pixman_color_t *color)
|
||||
{
|
||||
return
|
||||
(color->alpha >> 8 << 24) |
|
||||
(color->red >> 8 << 16) |
|
||||
(color->green & 0xff00) |
|
||||
(color->blue >> 8);
|
||||
}
|
||||
|
||||
static argb_t
|
||||
color_to_float (const pixman_color_t *color)
|
||||
{
|
||||
argb_t result;
|
||||
|
||||
result.a = pixman_unorm_to_float (color->alpha, 16);
|
||||
result.r = pixman_unorm_to_float (color->red, 16);
|
||||
result.g = pixman_unorm_to_float (color->green, 16);
|
||||
result.b = pixman_unorm_to_float (color->blue, 16);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT pixman_image_t *
|
||||
pixman_image_create_solid_fill (const pixman_color_t *color)
|
||||
{
|
||||
pixman_image_t *img = _pixman_image_allocate ();
|
||||
|
||||
if (!img)
|
||||
return NULL;
|
||||
|
||||
img->type = SOLID;
|
||||
img->solid.color = *color;
|
||||
img->solid.color_32 = color_to_uint32 (color);
|
||||
img->solid.color_float = color_to_float (color);
|
||||
|
||||
return img;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* 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 Red Hat not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. Red Hat makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
|
||||
* 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 <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "pixman-private.h"
|
||||
|
||||
#ifdef PIXMAN_TIMERS
|
||||
|
||||
static pixman_timer_t *timers;
|
||||
|
||||
static void
|
||||
dump_timers (void)
|
||||
{
|
||||
pixman_timer_t *timer;
|
||||
|
||||
for (timer = timers; timer != NULL; timer = timer->next)
|
||||
{
|
||||
printf ("%s: total: %llu n: %llu avg: %f\n",
|
||||
timer->name,
|
||||
timer->total,
|
||||
timer->n_times,
|
||||
timer->total / (double)timer->n_times);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pixman_timer_register (pixman_timer_t *timer)
|
||||
{
|
||||
static int initialized;
|
||||
|
||||
int atexit (void (*function)(void));
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
atexit (dump_timers);
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
timer->next = timers;
|
||||
timers = timer;
|
||||
}
|
||||
|
||||
#endif
|
@ -1,711 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
|
||||
* Copyright © 2004 Keith Packard
|
||||
*
|
||||
* 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 Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL KEITH PACKARD 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 <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "pixman-private.h"
|
||||
|
||||
/*
|
||||
* Compute the smallest value greater than or equal to y which is on a
|
||||
* grid row.
|
||||
*/
|
||||
|
||||
PIXMAN_EXPORT pixman_fixed_t
|
||||
pixman_sample_ceil_y (pixman_fixed_t y, int n)
|
||||
{
|
||||
pixman_fixed_t f = pixman_fixed_frac (y);
|
||||
pixman_fixed_t i = pixman_fixed_floor (y);
|
||||
|
||||
f = DIV (f - Y_FRAC_FIRST (n) + (STEP_Y_SMALL (n) - pixman_fixed_e), STEP_Y_SMALL (n)) * STEP_Y_SMALL (n) +
|
||||
Y_FRAC_FIRST (n);
|
||||
|
||||
if (f > Y_FRAC_LAST (n))
|
||||
{
|
||||
if (pixman_fixed_to_int (i) == 0x7fff)
|
||||
{
|
||||
f = 0xffff; /* saturate */
|
||||
}
|
||||
else
|
||||
{
|
||||
f = Y_FRAC_FIRST (n);
|
||||
i += pixman_fixed_1;
|
||||
}
|
||||
}
|
||||
return (i | f);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the largest value strictly less than y which is on a
|
||||
* grid row.
|
||||
*/
|
||||
PIXMAN_EXPORT pixman_fixed_t
|
||||
pixman_sample_floor_y (pixman_fixed_t y,
|
||||
int n)
|
||||
{
|
||||
pixman_fixed_t f = pixman_fixed_frac (y);
|
||||
pixman_fixed_t i = pixman_fixed_floor (y);
|
||||
|
||||
f = DIV (f - pixman_fixed_e - Y_FRAC_FIRST (n), STEP_Y_SMALL (n)) * STEP_Y_SMALL (n) +
|
||||
Y_FRAC_FIRST (n);
|
||||
|
||||
if (f < Y_FRAC_FIRST (n))
|
||||
{
|
||||
if (pixman_fixed_to_int (i) == 0x8000)
|
||||
{
|
||||
f = 0; /* saturate */
|
||||
}
|
||||
else
|
||||
{
|
||||
f = Y_FRAC_LAST (n);
|
||||
i -= pixman_fixed_1;
|
||||
}
|
||||
}
|
||||
return (i | f);
|
||||
}
|
||||
|
||||
/*
|
||||
* Step an edge by any amount (including negative values)
|
||||
*/
|
||||
PIXMAN_EXPORT void
|
||||
pixman_edge_step (pixman_edge_t *e,
|
||||
int n)
|
||||
{
|
||||
pixman_fixed_48_16_t ne;
|
||||
|
||||
e->x += n * e->stepx;
|
||||
|
||||
ne = e->e + n * (pixman_fixed_48_16_t) e->dx;
|
||||
|
||||
if (n >= 0)
|
||||
{
|
||||
if (ne > 0)
|
||||
{
|
||||
int nx = (ne + e->dy - 1) / e->dy;
|
||||
e->e = ne - nx * (pixman_fixed_48_16_t) e->dy;
|
||||
e->x += nx * e->signdx;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ne <= -e->dy)
|
||||
{
|
||||
int nx = (-ne) / e->dy;
|
||||
e->e = ne + nx * (pixman_fixed_48_16_t) e->dy;
|
||||
e->x -= nx * e->signdx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A private routine to initialize the multi-step
|
||||
* elements of an edge structure
|
||||
*/
|
||||
static void
|
||||
_pixman_edge_multi_init (pixman_edge_t * e,
|
||||
int n,
|
||||
pixman_fixed_t *stepx_p,
|
||||
pixman_fixed_t *dx_p)
|
||||
{
|
||||
pixman_fixed_t stepx;
|
||||
pixman_fixed_48_16_t ne;
|
||||
|
||||
ne = n * (pixman_fixed_48_16_t) e->dx;
|
||||
stepx = n * e->stepx;
|
||||
|
||||
if (ne > 0)
|
||||
{
|
||||
int nx = ne / e->dy;
|
||||
ne -= nx * (pixman_fixed_48_16_t)e->dy;
|
||||
stepx += nx * e->signdx;
|
||||
}
|
||||
|
||||
*dx_p = ne;
|
||||
*stepx_p = stepx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize one edge structure given the line endpoints and a
|
||||
* starting y value
|
||||
*/
|
||||
PIXMAN_EXPORT void
|
||||
pixman_edge_init (pixman_edge_t *e,
|
||||
int n,
|
||||
pixman_fixed_t y_start,
|
||||
pixman_fixed_t x_top,
|
||||
pixman_fixed_t y_top,
|
||||
pixman_fixed_t x_bot,
|
||||
pixman_fixed_t y_bot)
|
||||
{
|
||||
pixman_fixed_t dx, dy;
|
||||
|
||||
e->x = x_top;
|
||||
e->e = 0;
|
||||
dx = x_bot - x_top;
|
||||
dy = y_bot - y_top;
|
||||
e->dy = dy;
|
||||
e->dx = 0;
|
||||
|
||||
if (dy)
|
||||
{
|
||||
if (dx >= 0)
|
||||
{
|
||||
e->signdx = 1;
|
||||
e->stepx = dx / dy;
|
||||
e->dx = dx % dy;
|
||||
e->e = -dy;
|
||||
}
|
||||
else
|
||||
{
|
||||
e->signdx = -1;
|
||||
e->stepx = -(-dx / dy);
|
||||
e->dx = -dx % dy;
|
||||
e->e = 0;
|
||||
}
|
||||
|
||||
_pixman_edge_multi_init (e, STEP_Y_SMALL (n),
|
||||
&e->stepx_small, &e->dx_small);
|
||||
|
||||
_pixman_edge_multi_init (e, STEP_Y_BIG (n),
|
||||
&e->stepx_big, &e->dx_big);
|
||||
}
|
||||
pixman_edge_step (e, y_start - y_top);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize one edge structure given a line, starting y value
|
||||
* and a pixel offset for the line
|
||||
*/
|
||||
PIXMAN_EXPORT void
|
||||
pixman_line_fixed_edge_init (pixman_edge_t * e,
|
||||
int n,
|
||||
pixman_fixed_t y,
|
||||
const pixman_line_fixed_t *line,
|
||||
int x_off,
|
||||
int y_off)
|
||||
{
|
||||
pixman_fixed_t x_off_fixed = pixman_int_to_fixed (x_off);
|
||||
pixman_fixed_t y_off_fixed = pixman_int_to_fixed (y_off);
|
||||
const pixman_point_fixed_t *top, *bot;
|
||||
|
||||
if (line->p1.y <= line->p2.y)
|
||||
{
|
||||
top = &line->p1;
|
||||
bot = &line->p2;
|
||||
}
|
||||
else
|
||||
{
|
||||
top = &line->p2;
|
||||
bot = &line->p1;
|
||||
}
|
||||
|
||||
pixman_edge_init (e, n, y,
|
||||
top->x + x_off_fixed,
|
||||
top->y + y_off_fixed,
|
||||
bot->x + x_off_fixed,
|
||||
bot->y + y_off_fixed);
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_add_traps (pixman_image_t * image,
|
||||
int16_t x_off,
|
||||
int16_t y_off,
|
||||
int ntrap,
|
||||
const pixman_trap_t *traps)
|
||||
{
|
||||
int bpp;
|
||||
int height;
|
||||
|
||||
pixman_fixed_t x_off_fixed;
|
||||
pixman_fixed_t y_off_fixed;
|
||||
pixman_edge_t l, r;
|
||||
pixman_fixed_t t, b;
|
||||
|
||||
_pixman_image_validate (image);
|
||||
|
||||
height = image->bits.height;
|
||||
bpp = PIXMAN_FORMAT_BPP (image->bits.format);
|
||||
|
||||
x_off_fixed = pixman_int_to_fixed (x_off);
|
||||
y_off_fixed = pixman_int_to_fixed (y_off);
|
||||
|
||||
while (ntrap--)
|
||||
{
|
||||
t = traps->top.y + y_off_fixed;
|
||||
if (t < 0)
|
||||
t = 0;
|
||||
t = pixman_sample_ceil_y (t, bpp);
|
||||
|
||||
b = traps->bot.y + y_off_fixed;
|
||||
if (pixman_fixed_to_int (b) >= height)
|
||||
b = pixman_int_to_fixed (height) - 1;
|
||||
b = pixman_sample_floor_y (b, bpp);
|
||||
|
||||
if (b >= t)
|
||||
{
|
||||
/* initialize edge walkers */
|
||||
pixman_edge_init (&l, bpp, t,
|
||||
traps->top.l + x_off_fixed,
|
||||
traps->top.y + y_off_fixed,
|
||||
traps->bot.l + x_off_fixed,
|
||||
traps->bot.y + y_off_fixed);
|
||||
|
||||
pixman_edge_init (&r, bpp, t,
|
||||
traps->top.r + x_off_fixed,
|
||||
traps->top.y + y_off_fixed,
|
||||
traps->bot.r + x_off_fixed,
|
||||
traps->bot.y + y_off_fixed);
|
||||
|
||||
pixman_rasterize_edges (image, &l, &r, t, b);
|
||||
}
|
||||
|
||||
traps++;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
dump_image (pixman_image_t *image,
|
||||
const char * title)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (!image->type == BITS)
|
||||
printf ("%s is not a regular image\n", title);
|
||||
|
||||
if (!image->bits.format == PIXMAN_a8)
|
||||
printf ("%s is not an alpha mask\n", title);
|
||||
|
||||
printf ("\n\n\n%s: \n", title);
|
||||
|
||||
for (i = 0; i < image->bits.height; ++i)
|
||||
{
|
||||
uint8_t *line =
|
||||
(uint8_t *)&(image->bits.bits[i * image->bits.rowstride]);
|
||||
|
||||
for (j = 0; j < image->bits.width; ++j)
|
||||
printf ("%c", line[j] ? '#' : ' ');
|
||||
|
||||
printf ("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_add_trapezoids (pixman_image_t * image,
|
||||
int16_t x_off,
|
||||
int y_off,
|
||||
int ntraps,
|
||||
const pixman_trapezoid_t *traps)
|
||||
{
|
||||
int i;
|
||||
|
||||
#if 0
|
||||
dump_image (image, "before");
|
||||
#endif
|
||||
|
||||
for (i = 0; i < ntraps; ++i)
|
||||
{
|
||||
const pixman_trapezoid_t *trap = &(traps[i]);
|
||||
|
||||
if (!pixman_trapezoid_valid (trap))
|
||||
continue;
|
||||
|
||||
pixman_rasterize_trapezoid (image, trap, x_off, y_off);
|
||||
}
|
||||
|
||||
#if 0
|
||||
dump_image (image, "after");
|
||||
#endif
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_rasterize_trapezoid (pixman_image_t * image,
|
||||
const pixman_trapezoid_t *trap,
|
||||
int x_off,
|
||||
int y_off)
|
||||
{
|
||||
int bpp;
|
||||
int height;
|
||||
|
||||
pixman_fixed_t y_off_fixed;
|
||||
pixman_edge_t l, r;
|
||||
pixman_fixed_t t, b;
|
||||
|
||||
return_if_fail (image->type == BITS);
|
||||
|
||||
_pixman_image_validate (image);
|
||||
|
||||
if (!pixman_trapezoid_valid (trap))
|
||||
return;
|
||||
|
||||
height = image->bits.height;
|
||||
bpp = PIXMAN_FORMAT_BPP (image->bits.format);
|
||||
|
||||
y_off_fixed = pixman_int_to_fixed (y_off);
|
||||
|
||||
t = trap->top + y_off_fixed;
|
||||
if (t < 0)
|
||||
t = 0;
|
||||
t = pixman_sample_ceil_y (t, bpp);
|
||||
|
||||
b = trap->bottom + y_off_fixed;
|
||||
if (pixman_fixed_to_int (b) >= height)
|
||||
b = pixman_int_to_fixed (height) - 1;
|
||||
b = pixman_sample_floor_y (b, bpp);
|
||||
|
||||
if (b >= t)
|
||||
{
|
||||
/* initialize edge walkers */
|
||||
pixman_line_fixed_edge_init (&l, bpp, t, &trap->left, x_off, y_off);
|
||||
pixman_line_fixed_edge_init (&r, bpp, t, &trap->right, x_off, y_off);
|
||||
|
||||
pixman_rasterize_edges (image, &l, &r, t, b);
|
||||
}
|
||||
}
|
||||
|
||||
static const pixman_bool_t zero_src_has_no_effect[PIXMAN_N_OPERATORS] =
|
||||
{
|
||||
FALSE, /* Clear 0 0 */
|
||||
FALSE, /* Src 1 0 */
|
||||
TRUE, /* Dst 0 1 */
|
||||
TRUE, /* Over 1 1-Aa */
|
||||
TRUE, /* OverReverse 1-Ab 1 */
|
||||
FALSE, /* In Ab 0 */
|
||||
FALSE, /* InReverse 0 Aa */
|
||||
FALSE, /* Out 1-Ab 0 */
|
||||
TRUE, /* OutReverse 0 1-Aa */
|
||||
TRUE, /* Atop Ab 1-Aa */
|
||||
FALSE, /* AtopReverse 1-Ab Aa */
|
||||
TRUE, /* Xor 1-Ab 1-Aa */
|
||||
TRUE, /* Add 1 1 */
|
||||
};
|
||||
|
||||
static pixman_bool_t
|
||||
get_trap_extents (pixman_op_t op, pixman_image_t *dest,
|
||||
const pixman_trapezoid_t *traps, int n_traps,
|
||||
pixman_box32_t *box)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* When the operator is such that a zero source has an
|
||||
* effect on the underlying image, we have to
|
||||
* composite across the entire destination
|
||||
*/
|
||||
if (!zero_src_has_no_effect [op])
|
||||
{
|
||||
box->x1 = 0;
|
||||
box->y1 = 0;
|
||||
box->x2 = dest->bits.width;
|
||||
box->y2 = dest->bits.height;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
box->x1 = INT32_MAX;
|
||||
box->y1 = INT32_MAX;
|
||||
box->x2 = INT32_MIN;
|
||||
box->y2 = INT32_MIN;
|
||||
|
||||
for (i = 0; i < n_traps; ++i)
|
||||
{
|
||||
const pixman_trapezoid_t *trap = &(traps[i]);
|
||||
int y1, y2;
|
||||
|
||||
if (!pixman_trapezoid_valid (trap))
|
||||
continue;
|
||||
|
||||
y1 = pixman_fixed_to_int (trap->top);
|
||||
if (y1 < box->y1)
|
||||
box->y1 = y1;
|
||||
|
||||
y2 = pixman_fixed_to_int (pixman_fixed_ceil (trap->bottom));
|
||||
if (y2 > box->y2)
|
||||
box->y2 = y2;
|
||||
|
||||
#define EXTEND_MIN(x) \
|
||||
if (pixman_fixed_to_int ((x)) < box->x1) \
|
||||
box->x1 = pixman_fixed_to_int ((x));
|
||||
#define EXTEND_MAX(x) \
|
||||
if (pixman_fixed_to_int (pixman_fixed_ceil ((x))) > box->x2) \
|
||||
box->x2 = pixman_fixed_to_int (pixman_fixed_ceil ((x)));
|
||||
|
||||
#define EXTEND(x) \
|
||||
EXTEND_MIN(x); \
|
||||
EXTEND_MAX(x);
|
||||
|
||||
EXTEND(trap->left.p1.x);
|
||||
EXTEND(trap->left.p2.x);
|
||||
EXTEND(trap->right.p1.x);
|
||||
EXTEND(trap->right.p2.x);
|
||||
}
|
||||
|
||||
if (box->x1 >= box->x2 || box->y1 >= box->y2)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* pixman_composite_trapezoids()
|
||||
*
|
||||
* All the trapezoids are conceptually rendered to an infinitely big image.
|
||||
* The (0, 0) coordinates of this image are then aligned with the (x, y)
|
||||
* coordinates of the source image, and then both images are aligned with
|
||||
* the (x, y) coordinates of the destination. Then these three images are
|
||||
* composited across the entire destination.
|
||||
*/
|
||||
PIXMAN_EXPORT void
|
||||
pixman_composite_trapezoids (pixman_op_t op,
|
||||
pixman_image_t * src,
|
||||
pixman_image_t * dst,
|
||||
pixman_format_code_t mask_format,
|
||||
int x_src,
|
||||
int y_src,
|
||||
int x_dst,
|
||||
int y_dst,
|
||||
int n_traps,
|
||||
const pixman_trapezoid_t * traps)
|
||||
{
|
||||
int i;
|
||||
|
||||
return_if_fail (PIXMAN_FORMAT_TYPE (mask_format) == PIXMAN_TYPE_A);
|
||||
|
||||
if (n_traps <= 0)
|
||||
return;
|
||||
|
||||
_pixman_image_validate (src);
|
||||
_pixman_image_validate (dst);
|
||||
|
||||
if (op == PIXMAN_OP_ADD &&
|
||||
(src->common.flags & FAST_PATH_IS_OPAQUE) &&
|
||||
(mask_format == dst->common.extended_format_code) &&
|
||||
!(dst->common.have_clip_region))
|
||||
{
|
||||
for (i = 0; i < n_traps; ++i)
|
||||
{
|
||||
const pixman_trapezoid_t *trap = &(traps[i]);
|
||||
|
||||
if (!pixman_trapezoid_valid (trap))
|
||||
continue;
|
||||
|
||||
pixman_rasterize_trapezoid (dst, trap, x_dst, y_dst);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pixman_image_t *tmp;
|
||||
pixman_box32_t box;
|
||||
int i;
|
||||
|
||||
if (!get_trap_extents (op, dst, traps, n_traps, &box))
|
||||
return;
|
||||
|
||||
if (!(tmp = pixman_image_create_bits (
|
||||
mask_format, box.x2 - box.x1, box.y2 - box.y1, NULL, -1)))
|
||||
return;
|
||||
|
||||
for (i = 0; i < n_traps; ++i)
|
||||
{
|
||||
const pixman_trapezoid_t *trap = &(traps[i]);
|
||||
|
||||
if (!pixman_trapezoid_valid (trap))
|
||||
continue;
|
||||
|
||||
pixman_rasterize_trapezoid (tmp, trap, - box.x1, - box.y1);
|
||||
}
|
||||
|
||||
pixman_image_composite (op, src, tmp, dst,
|
||||
x_src + box.x1, y_src + box.y1,
|
||||
0, 0,
|
||||
x_dst + box.x1, y_dst + box.y1,
|
||||
box.x2 - box.x1, box.y2 - box.y1);
|
||||
|
||||
pixman_image_unref (tmp);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
greater_y (const pixman_point_fixed_t *a, const pixman_point_fixed_t *b)
|
||||
{
|
||||
if (a->y == b->y)
|
||||
return a->x > b->x;
|
||||
return a->y > b->y;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that the definition of this function is a bit odd because
|
||||
* of the X coordinate space (y increasing downwards).
|
||||
*/
|
||||
static int
|
||||
clockwise (const pixman_point_fixed_t *ref,
|
||||
const pixman_point_fixed_t *a,
|
||||
const pixman_point_fixed_t *b)
|
||||
{
|
||||
pixman_point_fixed_t ad, bd;
|
||||
|
||||
ad.x = a->x - ref->x;
|
||||
ad.y = a->y - ref->y;
|
||||
bd.x = b->x - ref->x;
|
||||
bd.y = b->y - ref->y;
|
||||
|
||||
return ((pixman_fixed_32_32_t) bd.y * ad.x -
|
||||
(pixman_fixed_32_32_t) ad.y * bd.x) < 0;
|
||||
}
|
||||
|
||||
static void
|
||||
triangle_to_trapezoids (const pixman_triangle_t *tri, pixman_trapezoid_t *traps)
|
||||
{
|
||||
const pixman_point_fixed_t *top, *left, *right, *tmp;
|
||||
|
||||
top = &tri->p1;
|
||||
left = &tri->p2;
|
||||
right = &tri->p3;
|
||||
|
||||
if (greater_y (top, left))
|
||||
{
|
||||
tmp = left;
|
||||
left = top;
|
||||
top = tmp;
|
||||
}
|
||||
|
||||
if (greater_y (top, right))
|
||||
{
|
||||
tmp = right;
|
||||
right = top;
|
||||
top = tmp;
|
||||
}
|
||||
|
||||
if (clockwise (top, right, left))
|
||||
{
|
||||
tmp = right;
|
||||
right = left;
|
||||
left = tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Two cases:
|
||||
*
|
||||
* + +
|
||||
* / \ / \
|
||||
* / \ / \
|
||||
* / + + \
|
||||
* / -- -- \
|
||||
* / -- -- \
|
||||
* / --- --- \
|
||||
* +-- --+
|
||||
*/
|
||||
|
||||
traps->top = top->y;
|
||||
traps->left.p1 = *top;
|
||||
traps->left.p2 = *left;
|
||||
traps->right.p1 = *top;
|
||||
traps->right.p2 = *right;
|
||||
|
||||
if (right->y < left->y)
|
||||
traps->bottom = right->y;
|
||||
else
|
||||
traps->bottom = left->y;
|
||||
|
||||
traps++;
|
||||
|
||||
*traps = *(traps - 1);
|
||||
|
||||
if (right->y < left->y)
|
||||
{
|
||||
traps->top = right->y;
|
||||
traps->bottom = left->y;
|
||||
traps->right.p1 = *right;
|
||||
traps->right.p2 = *left;
|
||||
}
|
||||
else
|
||||
{
|
||||
traps->top = left->y;
|
||||
traps->bottom = right->y;
|
||||
traps->left.p1 = *left;
|
||||
traps->left.p2 = *right;
|
||||
}
|
||||
}
|
||||
|
||||
static pixman_trapezoid_t *
|
||||
convert_triangles (int n_tris, const pixman_triangle_t *tris)
|
||||
{
|
||||
pixman_trapezoid_t *traps;
|
||||
int i;
|
||||
|
||||
if (n_tris <= 0)
|
||||
return NULL;
|
||||
|
||||
traps = pixman_malloc_ab (n_tris, 2 * sizeof (pixman_trapezoid_t));
|
||||
if (!traps)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < n_tris; ++i)
|
||||
triangle_to_trapezoids (&(tris[i]), traps + 2 * i);
|
||||
|
||||
return traps;
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_composite_triangles (pixman_op_t op,
|
||||
pixman_image_t * src,
|
||||
pixman_image_t * dst,
|
||||
pixman_format_code_t mask_format,
|
||||
int x_src,
|
||||
int y_src,
|
||||
int x_dst,
|
||||
int y_dst,
|
||||
int n_tris,
|
||||
const pixman_triangle_t * tris)
|
||||
{
|
||||
pixman_trapezoid_t *traps;
|
||||
|
||||
if ((traps = convert_triangles (n_tris, tris)))
|
||||
{
|
||||
pixman_composite_trapezoids (op, src, dst, mask_format,
|
||||
x_src, y_src, x_dst, y_dst,
|
||||
n_tris * 2, traps);
|
||||
|
||||
free (traps);
|
||||
}
|
||||
}
|
||||
|
||||
PIXMAN_EXPORT void
|
||||
pixman_add_triangles (pixman_image_t *image,
|
||||
int32_t x_off,
|
||||
int32_t y_off,
|
||||
int n_tris,
|
||||
const pixman_triangle_t *tris)
|
||||
{
|
||||
pixman_trapezoid_t *traps;
|
||||
|
||||
if ((traps = convert_triangles (n_tris, tris)))
|
||||
{
|
||||
pixman_add_trapezoids (image, x_off, y_off,
|
||||
n_tris * 2, traps);
|
||||
|
||||
free (traps);
|
||||
}
|
||||
}
|
@ -1,310 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2000 SuSE, Inc.
|
||||
* Copyright © 1999 Keith Packard
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Author: Keith Packard, SuSE, Inc.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "pixman-private.h"
|
||||
|
||||
pixman_bool_t
|
||||
_pixman_multiply_overflows_size (size_t a, size_t b)
|
||||
{
|
||||
return a >= SIZE_MAX / b;
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
_pixman_multiply_overflows_int (unsigned int a, unsigned int b)
|
||||
{
|
||||
return a >= INT32_MAX / b;
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
_pixman_addition_overflows_int (unsigned int a, unsigned int b)
|
||||
{
|
||||
return a > INT32_MAX - b;
|
||||
}
|
||||
|
||||
void *
|
||||
pixman_malloc_ab (unsigned int a,
|
||||
unsigned int b)
|
||||
{
|
||||
if (a >= INT32_MAX / b)
|
||||
return NULL;
|
||||
|
||||
return malloc (a * b);
|
||||
}
|
||||
|
||||
void *
|
||||
pixman_malloc_abc (unsigned int a,
|
||||
unsigned int b,
|
||||
unsigned int c)
|
||||
{
|
||||
if (a >= INT32_MAX / b)
|
||||
return NULL;
|
||||
else if (a * b >= INT32_MAX / c)
|
||||
return NULL;
|
||||
else
|
||||
return malloc (a * b * c);
|
||||
}
|
||||
|
||||
static force_inline uint16_t
|
||||
float_to_unorm (float f, int n_bits)
|
||||
{
|
||||
uint32_t u;
|
||||
|
||||
if (f > 1.0)
|
||||
f = 1.0;
|
||||
if (f < 0.0)
|
||||
f = 0.0;
|
||||
|
||||
u = f * (1 << n_bits);
|
||||
u -= (u >> n_bits);
|
||||
|
||||
return u;
|
||||
}
|
||||
|
||||
static force_inline float
|
||||
unorm_to_float (uint16_t u, int n_bits)
|
||||
{
|
||||
uint32_t m = ((1 << n_bits) - 1);
|
||||
|
||||
return (u & m) * (1.f / (float)m);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function expands images from a8r8g8b8 to argb_t. To preserve
|
||||
* precision, it needs to know from which source format the a8r8g8b8 pixels
|
||||
* originally came.
|
||||
*
|
||||
* For example, if the source was PIXMAN_x1r5g5b5 and the red component
|
||||
* contained bits 12345, then the 8-bit value is 12345123. To correctly
|
||||
* expand this to floating point, it should be 12345 / 31.0 and not
|
||||
* 12345123 / 255.0.
|
||||
*/
|
||||
void
|
||||
pixman_expand_to_float (argb_t *dst,
|
||||
const uint32_t *src,
|
||||
pixman_format_code_t format,
|
||||
int width)
|
||||
{
|
||||
static const float multipliers[16] = {
|
||||
0.0f,
|
||||
1.0f / ((1 << 1) - 1),
|
||||
1.0f / ((1 << 2) - 1),
|
||||
1.0f / ((1 << 3) - 1),
|
||||
1.0f / ((1 << 4) - 1),
|
||||
1.0f / ((1 << 5) - 1),
|
||||
1.0f / ((1 << 6) - 1),
|
||||
1.0f / ((1 << 7) - 1),
|
||||
1.0f / ((1 << 8) - 1),
|
||||
1.0f / ((1 << 9) - 1),
|
||||
1.0f / ((1 << 10) - 1),
|
||||
1.0f / ((1 << 11) - 1),
|
||||
1.0f / ((1 << 12) - 1),
|
||||
1.0f / ((1 << 13) - 1),
|
||||
1.0f / ((1 << 14) - 1),
|
||||
1.0f / ((1 << 15) - 1),
|
||||
};
|
||||
int a_size, r_size, g_size, b_size;
|
||||
int a_shift, r_shift, g_shift, b_shift;
|
||||
float a_mul, r_mul, g_mul, b_mul;
|
||||
uint32_t a_mask, r_mask, g_mask, b_mask;
|
||||
int i;
|
||||
|
||||
if (!PIXMAN_FORMAT_VIS (format))
|
||||
format = PIXMAN_a8r8g8b8;
|
||||
|
||||
/*
|
||||
* Determine the sizes of each component and the masks and shifts
|
||||
* required to extract them from the source pixel.
|
||||
*/
|
||||
a_size = PIXMAN_FORMAT_A (format);
|
||||
r_size = PIXMAN_FORMAT_R (format);
|
||||
g_size = PIXMAN_FORMAT_G (format);
|
||||
b_size = PIXMAN_FORMAT_B (format);
|
||||
|
||||
a_shift = 32 - a_size;
|
||||
r_shift = 24 - r_size;
|
||||
g_shift = 16 - g_size;
|
||||
b_shift = 8 - b_size;
|
||||
|
||||
a_mask = ((1 << a_size) - 1);
|
||||
r_mask = ((1 << r_size) - 1);
|
||||
g_mask = ((1 << g_size) - 1);
|
||||
b_mask = ((1 << b_size) - 1);
|
||||
|
||||
a_mul = multipliers[a_size];
|
||||
r_mul = multipliers[r_size];
|
||||
g_mul = multipliers[g_size];
|
||||
b_mul = multipliers[b_size];
|
||||
|
||||
/* Start at the end so that we can do the expansion in place
|
||||
* when src == dst
|
||||
*/
|
||||
for (i = width - 1; i >= 0; i--)
|
||||
{
|
||||
const uint32_t pixel = src[i];
|
||||
|
||||
dst[i].a = a_mask? ((pixel >> a_shift) & a_mask) * a_mul : 1.0f;
|
||||
dst[i].r = ((pixel >> r_shift) & r_mask) * r_mul;
|
||||
dst[i].g = ((pixel >> g_shift) & g_mask) * g_mul;
|
||||
dst[i].b = ((pixel >> b_shift) & b_mask) * b_mul;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t
|
||||
pixman_float_to_unorm (float f, int n_bits)
|
||||
{
|
||||
return float_to_unorm (f, n_bits);
|
||||
}
|
||||
|
||||
float
|
||||
pixman_unorm_to_float (uint16_t u, int n_bits)
|
||||
{
|
||||
return unorm_to_float (u, n_bits);
|
||||
}
|
||||
|
||||
void
|
||||
pixman_contract_from_float (uint32_t *dst,
|
||||
const argb_t *src,
|
||||
int width)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < width; ++i)
|
||||
{
|
||||
uint8_t a, r, g, b;
|
||||
|
||||
a = float_to_unorm (src[i].a, 8);
|
||||
r = float_to_unorm (src[i].r, 8);
|
||||
g = float_to_unorm (src[i].g, 8);
|
||||
b = float_to_unorm (src[i].b, 8);
|
||||
|
||||
dst[i] = (a << 24) | (r << 16) | (g << 8) | (b << 0);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t *
|
||||
_pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask)
|
||||
{
|
||||
return iter->buffer;
|
||||
}
|
||||
|
||||
#define N_TMP_BOXES (16)
|
||||
|
||||
pixman_bool_t
|
||||
pixman_region16_copy_from_region32 (pixman_region16_t *dst,
|
||||
pixman_region32_t *src)
|
||||
{
|
||||
int n_boxes, i;
|
||||
pixman_box32_t *boxes32;
|
||||
pixman_box16_t *boxes16;
|
||||
pixman_bool_t retval;
|
||||
|
||||
boxes32 = pixman_region32_rectangles (src, &n_boxes);
|
||||
|
||||
boxes16 = pixman_malloc_ab (n_boxes, sizeof (pixman_box16_t));
|
||||
|
||||
if (!boxes16)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < n_boxes; ++i)
|
||||
{
|
||||
boxes16[i].x1 = boxes32[i].x1;
|
||||
boxes16[i].y1 = boxes32[i].y1;
|
||||
boxes16[i].x2 = boxes32[i].x2;
|
||||
boxes16[i].y2 = boxes32[i].y2;
|
||||
}
|
||||
|
||||
pixman_region_fini (dst);
|
||||
retval = pixman_region_init_rects (dst, boxes16, n_boxes);
|
||||
free (boxes16);
|
||||
return retval;
|
||||
}
|
||||
|
||||
pixman_bool_t
|
||||
pixman_region32_copy_from_region16 (pixman_region32_t *dst,
|
||||
pixman_region16_t *src)
|
||||
{
|
||||
int n_boxes, i;
|
||||
pixman_box16_t *boxes16;
|
||||
pixman_box32_t *boxes32;
|
||||
pixman_box32_t tmp_boxes[N_TMP_BOXES];
|
||||
pixman_bool_t retval;
|
||||
|
||||
boxes16 = pixman_region_rectangles (src, &n_boxes);
|
||||
|
||||
if (n_boxes > N_TMP_BOXES)
|
||||
boxes32 = pixman_malloc_ab (n_boxes, sizeof (pixman_box32_t));
|
||||
else
|
||||
boxes32 = tmp_boxes;
|
||||
|
||||
if (!boxes32)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < n_boxes; ++i)
|
||||
{
|
||||
boxes32[i].x1 = boxes16[i].x1;
|
||||
boxes32[i].y1 = boxes16[i].y1;
|
||||
boxes32[i].x2 = boxes16[i].x2;
|
||||
boxes32[i].y2 = boxes16[i].y2;
|
||||
}
|
||||
|
||||
pixman_region32_fini (dst);
|
||||
retval = pixman_region32_init_rects (dst, boxes32, n_boxes);
|
||||
|
||||
if (boxes32 != tmp_boxes)
|
||||
free (boxes32);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* This function is exported for the sake of the test suite and not part
|
||||
* of the ABI.
|
||||
*/
|
||||
PIXMAN_EXPORT pixman_implementation_t *
|
||||
_pixman_internal_only_get_implementation (void)
|
||||
{
|
||||
return get_implementation ();
|
||||
}
|
||||
|
||||
void
|
||||
_pixman_log_error (const char *function, const char *message)
|
||||
{
|
||||
static int n_messages = 0;
|
||||
|
||||
if (n_messages < 10)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"*** BUG ***\n"
|
||||
"In %s: %s\n"
|
||||
"Set a breakpoint on '_pixman_log_error' to debug\n\n",
|
||||
function, message);
|
||||
|
||||
n_messages++;
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2008 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Author: Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#ifndef PIXMAN_VERSION_H__
|
||||
#define PIXMAN_VERSION_H__
|
||||
|
||||
#ifndef PIXMAN_H__
|
||||
# error pixman-version.h should only be included by pixman.h
|
||||
#endif
|
||||
|
||||
#define PIXMAN_VERSION_MAJOR 0
|
||||
#define PIXMAN_VERSION_MINOR 30
|
||||
#define PIXMAN_VERSION_MICRO 2
|
||||
|
||||
#define PIXMAN_VERSION_STRING "0.30.2"
|
||||
|
||||
#define PIXMAN_VERSION_ENCODE(major, minor, micro) ( \
|
||||
((major) * 10000) \
|
||||
+ ((minor) * 100) \
|
||||
+ ((micro) * 1))
|
||||
|
||||
#define PIXMAN_VERSION PIXMAN_VERSION_ENCODE( \
|
||||
PIXMAN_VERSION_MAJOR, \
|
||||
PIXMAN_VERSION_MINOR, \
|
||||
PIXMAN_VERSION_MICRO)
|
||||
|
||||
#endif /* PIXMAN_VERSION_H__ */
|
@ -1,237 +0,0 @@
|
||||
/*
|
||||
* 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 <config.h>
|
||||
#endif
|
||||
|
||||
#include "pixman-private.h"
|
||||
|
||||
#if defined(USE_X86_MMX) || defined (USE_SSE2)
|
||||
|
||||
/* The CPU detection code needs to be in a file not compiled with
|
||||
* "-mmmx -msse", as gcc would generate CMOV instructions otherwise
|
||||
* that would lead to SIGILL instructions on old CPUs that don't have
|
||||
* it.
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
X86_MMX = (1 << 0),
|
||||
X86_MMX_EXTENSIONS = (1 << 1),
|
||||
X86_SSE = (1 << 2) | X86_MMX_EXTENSIONS,
|
||||
X86_SSE2 = (1 << 3),
|
||||
X86_CMOV = (1 << 4)
|
||||
} cpu_features_t;
|
||||
|
||||
#ifdef HAVE_GETISAX
|
||||
|
||||
#include <sys/auxv.h>
|
||||
|
||||
static cpu_features_t
|
||||
detect_cpu_features (void)
|
||||
{
|
||||
cpu_features_t features = 0;
|
||||
unsigned int result = 0;
|
||||
|
||||
if (getisax (&result, 1))
|
||||
{
|
||||
if (result & AV_386_CMOV)
|
||||
features |= X86_CMOV;
|
||||
if (result & AV_386_MMX)
|
||||
features |= X86_MMX;
|
||||
if (result & AV_386_AMD_MMX)
|
||||
features |= X86_MMX_EXTENSIONS;
|
||||
if (result & AV_386_SSE)
|
||||
features |= X86_SSE;
|
||||
if (result & AV_386_SSE2)
|
||||
features |= X86_SSE2;
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define _PIXMAN_X86_64 \
|
||||
(defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64))
|
||||
|
||||
static pixman_bool_t
|
||||
have_cpuid (void)
|
||||
{
|
||||
#if _PIXMAN_X86_64 || defined (_MSC_VER)
|
||||
|
||||
return TRUE;
|
||||
|
||||
#elif defined (__GNUC__)
|
||||
uint32_t result;
|
||||
|
||||
__asm__ volatile (
|
||||
"pushf" "\n\t"
|
||||
"pop %%eax" "\n\t"
|
||||
"mov %%eax, %%ecx" "\n\t"
|
||||
"xor $0x00200000, %%eax" "\n\t"
|
||||
"push %%eax" "\n\t"
|
||||
"popf" "\n\t"
|
||||
"pushf" "\n\t"
|
||||
"pop %%eax" "\n\t"
|
||||
"xor %%ecx, %%eax" "\n\t"
|
||||
"mov %%eax, %0" "\n\t"
|
||||
: "=r" (result)
|
||||
:
|
||||
: "%eax", "%ecx");
|
||||
|
||||
return !!result;
|
||||
|
||||
#else
|
||||
#error "Unknown compiler"
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
pixman_cpuid (uint32_t feature,
|
||||
uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)
|
||||
{
|
||||
#if defined (__GNUC__)
|
||||
|
||||
#if _PIXMAN_X86_64
|
||||
__asm__ volatile (
|
||||
"cpuid" "\n\t"
|
||||
: "=a" (*a), "=b" (*b), "=c" (*c), "=d" (*d)
|
||||
: "a" (feature));
|
||||
#else
|
||||
/* On x86-32 we need to be careful about the handling of %ebx
|
||||
* and %esp. We can't declare either one as clobbered
|
||||
* since they are special registers (%ebx is the "PIC
|
||||
* register" holding an offset to global data, %esp the
|
||||
* stack pointer), so we need to make sure that %ebx is
|
||||
* preserved, and that %esp has its original value when
|
||||
* accessing the output operands.
|
||||
*/
|
||||
__asm__ volatile (
|
||||
"xchg %%ebx, %1" "\n\t"
|
||||
"cpuid" "\n\t"
|
||||
"xchg %%ebx, %1" "\n\t"
|
||||
: "=a" (*a), "=r" (*b), "=c" (*c), "=d" (*d)
|
||||
: "a" (feature));
|
||||
#endif
|
||||
|
||||
#elif defined (_MSC_VER)
|
||||
int info[4];
|
||||
|
||||
__cpuid (info, feature);
|
||||
|
||||
*a = info[0];
|
||||
*b = info[1];
|
||||
*c = info[2];
|
||||
*d = info[3];
|
||||
#else
|
||||
#error Unknown compiler
|
||||
#endif
|
||||
}
|
||||
|
||||
static cpu_features_t
|
||||
detect_cpu_features (void)
|
||||
{
|
||||
uint32_t a, b, c, d;
|
||||
cpu_features_t features = 0;
|
||||
|
||||
if (!have_cpuid())
|
||||
return features;
|
||||
|
||||
/* Get feature bits */
|
||||
pixman_cpuid (0x01, &a, &b, &c, &d);
|
||||
if (d & (1 << 15))
|
||||
features |= X86_CMOV;
|
||||
if (d & (1 << 23))
|
||||
features |= X86_MMX;
|
||||
if (d & (1 << 25))
|
||||
features |= X86_SSE;
|
||||
if (d & (1 << 26))
|
||||
features |= X86_SSE2;
|
||||
|
||||
/* Check for AMD specific features */
|
||||
if ((features & X86_MMX) && !(features & X86_SSE))
|
||||
{
|
||||
char vendor[13];
|
||||
|
||||
/* Get vendor string */
|
||||
memset (vendor, 0, sizeof vendor);
|
||||
|
||||
pixman_cpuid (0x00, &a, &b, &c, &d);
|
||||
memcpy (vendor + 0, &b, 4);
|
||||
memcpy (vendor + 4, &d, 4);
|
||||
memcpy (vendor + 8, &c, 4);
|
||||
|
||||
if (strcmp (vendor, "AuthenticAMD") == 0 ||
|
||||
strcmp (vendor, "Geode by NSC") == 0)
|
||||
{
|
||||
pixman_cpuid (0x80000000, &a, &b, &c, &d);
|
||||
if (a >= 0x80000001)
|
||||
{
|
||||
pixman_cpuid (0x80000001, &a, &b, &c, &d);
|
||||
|
||||
if (d & (1 << 22))
|
||||
features |= X86_MMX_EXTENSIONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static pixman_bool_t
|
||||
have_feature (cpu_features_t feature)
|
||||
{
|
||||
static pixman_bool_t initialized;
|
||||
static cpu_features_t features;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
features = detect_cpu_features();
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
return (features & feature) == feature;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
pixman_implementation_t *
|
||||
_pixman_x86_get_implementations (pixman_implementation_t *imp)
|
||||
{
|
||||
#define MMX_BITS (X86_MMX | X86_MMX_EXTENSIONS)
|
||||
#define SSE2_BITS (X86_MMX | X86_MMX_EXTENSIONS | X86_SSE | X86_SSE2)
|
||||
|
||||
#ifdef USE_X86_MMX
|
||||
if (!_pixman_disabled ("mmx") && have_feature (MMX_BITS))
|
||||
imp = _pixman_implementation_create_mmx (imp);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSE2
|
||||
if (!_pixman_disabled ("sse2") && have_feature (SSE2_BITS))
|
||||
imp = _pixman_implementation_create_sse2 (imp);
|
||||
#endif
|
||||
|
||||
return imp;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,173 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <config.h>
|
||||
#include "pixman-private.h"
|
||||
#include "pixman.h"
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
/* Randomly decide between 32 and 16 bit
|
||||
*
|
||||
* Allocate bits with random width, stride and height
|
||||
*
|
||||
* Then make up some random offset (dx, dy)
|
||||
*
|
||||
* Then make an image with those values.
|
||||
*
|
||||
* Do this for both source and destination
|
||||
*
|
||||
* Composite them together using OVER.
|
||||
*
|
||||
* The bits in the source and the destination should have
|
||||
* recognizable colors so that the result can be verified.
|
||||
*
|
||||
* Ie., walk the bits and verify that they have been composited.
|
||||
*/
|
||||
|
||||
static int
|
||||
get_rand (int bound)
|
||||
{
|
||||
return rand () % bound;
|
||||
}
|
||||
|
||||
static pixman_image_t *
|
||||
make_image (int width, int height, pixman_bool_t src, int *rx, int *ry)
|
||||
{
|
||||
pixman_format_code_t format;
|
||||
pixman_image_t *image;
|
||||
pixman_region32_t region;
|
||||
uint8_t *bits;
|
||||
int stride;
|
||||
int bpp;
|
||||
int dx, dy;
|
||||
int i, j;
|
||||
|
||||
if (src)
|
||||
format = PIXMAN_a8r8g8b8;
|
||||
else
|
||||
format = PIXMAN_r5g6b5;
|
||||
|
||||
bpp = PIXMAN_FORMAT_BPP (format) / 8;
|
||||
|
||||
stride = width + get_rand (width);
|
||||
stride += (stride & 1); /* Make it an even number */
|
||||
|
||||
bits = malloc (height * stride * bpp);
|
||||
|
||||
for (j = 0; j < height; ++j)
|
||||
{
|
||||
for (i = 0; i < width; ++i)
|
||||
{
|
||||
uint8_t *pixel = bits + (stride * j + i) * bpp;
|
||||
|
||||
if (src)
|
||||
*(uint32_t *)pixel = 0x7f00007f;
|
||||
else
|
||||
*(uint16_t *)pixel = 0xf100;
|
||||
}
|
||||
}
|
||||
|
||||
dx = dy = 0;
|
||||
|
||||
dx = get_rand (500);
|
||||
dy = get_rand (500);
|
||||
|
||||
if (!src)
|
||||
{
|
||||
/* Now simulate the bogus X server translations */
|
||||
bits -= (dy * stride + dx) * bpp;
|
||||
}
|
||||
|
||||
image = pixman_image_create_bits (
|
||||
format, width, height, (uint32_t *)bits, stride * bpp);
|
||||
|
||||
if (!src)
|
||||
{
|
||||
/* And add the bogus clip region */
|
||||
pixman_region32_init_rect (®ion, dx, dy, dx + width, dy + height);
|
||||
|
||||
pixman_image_set_clip_region32 (image, ®ion);
|
||||
}
|
||||
|
||||
pixman_image_set_source_clipping (image, TRUE);
|
||||
|
||||
if (src)
|
||||
{
|
||||
pixman_transform_t trans;
|
||||
|
||||
pixman_transform_init_identity (&trans);
|
||||
|
||||
pixman_transform_translate (&trans,
|
||||
NULL,
|
||||
- pixman_int_to_fixed (width / 2),
|
||||
- pixman_int_to_fixed (height / 2));
|
||||
|
||||
pixman_transform_scale (&trans,
|
||||
NULL,
|
||||
pixman_double_to_fixed (0.5),
|
||||
pixman_double_to_fixed (0.5));
|
||||
|
||||
pixman_transform_translate (&trans,
|
||||
NULL,
|
||||
pixman_int_to_fixed (width / 2),
|
||||
pixman_int_to_fixed (height / 2));
|
||||
|
||||
pixman_image_set_transform (image, &trans);
|
||||
pixman_image_set_filter (image, PIXMAN_FILTER_BILINEAR, NULL, 0);
|
||||
pixman_image_set_repeat (image, PIXMAN_REPEAT_PAD);
|
||||
}
|
||||
|
||||
if (!src)
|
||||
{
|
||||
*rx = dx;
|
||||
*ry = dy;
|
||||
}
|
||||
else
|
||||
{
|
||||
*rx = *ry = 0;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
pixman_image_t *src, *dest;
|
||||
int src_x, src_y, dest_x, dest_y;
|
||||
int i, j;
|
||||
int width = get_rand (499) + 1;
|
||||
int height = get_rand (499) + 1;
|
||||
|
||||
src = make_image (width, height, TRUE, &src_x, &src_y);
|
||||
dest = make_image (width, height, FALSE, &dest_x, &dest_y);
|
||||
|
||||
pixman_image_composite (
|
||||
PIXMAN_OP_OVER, src, NULL, dest,
|
||||
src_x, src_y,
|
||||
-1, -1,
|
||||
dest_x, dest_y,
|
||||
width, height);
|
||||
|
||||
for (i = 0; i < height; ++i)
|
||||
{
|
||||
for (j = 0; j < width; ++j)
|
||||
{
|
||||
uint8_t *bits = (uint8_t *)dest->bits.bits;
|
||||
int bpp = PIXMAN_FORMAT_BPP (dest->bits.format) / 8;
|
||||
int stride = dest->bits.rowstride * 4;
|
||||
|
||||
uint8_t *pixel =
|
||||
bits + (i + dest_y) * stride + (j + dest_x) * bpp;
|
||||
|
||||
if (*(uint16_t *)pixel != 0x788f)
|
||||
{
|
||||
printf ("bad pixel %x\n", *(uint16_t *)pixel);
|
||||
assert (*(uint16_t *)pixel == 0x788f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user