Upgrade cairo to latest cairo trunk, along with some still-in-review patches

This commit is contained in:
vladimir%pobox.com 2006-01-10 22:56:57 +00:00
Родитель 71e7b476c8
Коммит e882f0f837
102 изменённых файлов: 12654 добавлений и 5125 удалений

Просмотреть файл

@ -10,14 +10,27 @@ http://www.cairographics.org/.
VERSIONS:
cairo 1.1.1 (cvs)
glitz 0.5.0
cairo 1.1.1 (cvs - 2006-01-10)
glitz 0.5.2 (cvs - 2006-01-10)
***** NOTE FOR VISUAL C++ 6.0 *****
VC6 cannot build pixman from cairo. Therefore, VC6 builds are not supported
if cairo is enabled. Please upgrade to VC7.1/8.
==== Patches ====
win32-glyph-path.diff - upstream merged patch, fixes glyph->path conversion.
mozilla-misc.patch
- Misc compilation fixes for pixman (submitted upstream)
- temporary moz_cairo_set_target API (not for upstream)
cairo-debug-helpers.patch
- some stuff for cairo-debug.[ch]
device-offset-scale.path
- Move device offset/scale handling into surface layer; large rework
of device offset/scale. (submitted upstream)
push-pop-group.patch
- Implementation of push/pop group API; depends on device-offset-scale.
(submitted upstream)

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -84,7 +84,9 @@ CSRCS = \
cairo-scaled-font.c \
cairo-slope.c \
cairo-spline.c \
cairo-stroke-style.c \
cairo-surface.c \
cairo-surface-fallback.c \
cairo-traps.c \
cairo-unicode.c \
cairo-wideint.c \
@ -113,6 +115,10 @@ CSRCS += cairo-font-subset.c \
EXPORTS += cairo-ps.h cairo-pdf.h
endif
ifdef BUILD_CAIRO_SVG
CSRCS += cairo-svg-surface.c
EXPORTS += cairo-svg.h
endif
ifdef MOZ_X11
CSRCS += cairo-xlib-surface.c \

Просмотреть файл

@ -32,10 +32,25 @@
*
* Contributor(s):
* Kristian Høgsberg <krh@redhat.com>
* Carl Worth <cworth@cworth.org>
*/
#include "cairoint.h"
/**
* _cairo_array_init:
*
* Initialize a new cairo_array object to store objects each of size
* @element_size.
*
* The #cairo_array_t object provides grow-by-doubling storage. It
* never intereprets the data passed to it, nor does it provide any
* sort of callback mechanism for freeing resources held onto by
* stored objects.
*
* When finished using the array, _cairo_array_fini() should be
* called to free resources allocated during use of the array.
**/
void
_cairo_array_init (cairo_array_t *array, int element_size)
{
@ -43,14 +58,57 @@ _cairo_array_init (cairo_array_t *array, int element_size)
array->num_elements = 0;
array->element_size = element_size;
array->elements = NULL;
array->is_snapshot = FALSE;
}
/**
* _cairo_array_init_snapshot:
* @array: A #cairo_array_t to be initialized as a snapshot
* @other: The #cairo_array_t from which to create the snapshot
*
* Initialize @array as an immutable copy of @other. It is an error to
* call an array-modifying function (other than _cairo_array_fini) on
* @array after calling this function.
**/
void
_cairo_array_init_snapshot (cairo_array_t *array,
const cairo_array_t *other)
{
array->size = other->size;
array->num_elements = other->num_elements;
array->element_size = other->element_size;
array->elements = other->elements;
array->is_snapshot = TRUE;
}
/**
* _cairo_array_fini:
*
* Free all resources associated with @array. After this call, @array
* should not be used again without a subsequent call to
* _cairo_array_init() again first.
**/
void
_cairo_array_fini (cairo_array_t *array)
{
free (array->elements);
if (array->is_snapshot)
return;
if (array->elements) {
free (* array->elements);
free (array->elements);
}
}
/**
* _cairo_array_grow_by:
*
* Increase the size of @array (if needed) so that there are at least
* @additional free spaces in the array. The actual size of the array
* is always increased by doubling as many times as necessary.
**/
cairo_status_t
_cairo_array_grow_by (cairo_array_t *array, int additional)
{
@ -59,6 +117,8 @@ _cairo_array_grow_by (cairo_array_t *array, int additional)
int required_size = array->num_elements + additional;
int new_size;
assert (! array->is_snapshot);
if (required_size <= old_size)
return CAIRO_STATUS_SUCCESS;
@ -70,8 +130,15 @@ _cairo_array_grow_by (cairo_array_t *array, int additional)
while (new_size < required_size)
new_size = new_size * 2;
if (array->elements == NULL) {
array->elements = malloc (sizeof (char *));
if (array->elements == NULL)
return CAIRO_STATUS_NO_MEMORY;
*array->elements = NULL;
}
array->size = new_size;
new_elements = realloc (array->elements,
new_elements = realloc (*array->elements,
array->size * array->element_size);
if (new_elements == NULL) {
@ -79,54 +146,174 @@ _cairo_array_grow_by (cairo_array_t *array, int additional)
return CAIRO_STATUS_NO_MEMORY;
}
array->elements = new_elements;
*array->elements = new_elements;
return CAIRO_STATUS_SUCCESS;
}
/**
* _cairo_array_truncate:
*
* Truncate size of the array to @num_elements if less than the
* current size. No memory is actually freed. The stored objects
* beyond @num_elements are simply "forgotten".
**/
void
_cairo_array_truncate (cairo_array_t *array, int num_elements)
{
assert (! array->is_snapshot);
if (num_elements < array->num_elements)
array->num_elements = num_elements;
}
/**
* _cairo_array_index:
*
* Return value: A pointer to object stored at @index. If the
* resulting value is assigned to a pointer to an object of the same
* element_size as initially passed to _cairo_array_init() then that
* pointer may be used for further direct indexing with []. For
* example:
*
* cairo_array_t array;
* double *values;
*
* _cairo_array_init (&array, sizeof(double));
* ... calls to _cairo_array_append() here ...
*
* values = _cairo_array_index (&array, 0);
* for (i = 0; i < _cairo_array_num_elements (&array); i++)
* ... use values[i] here ...
**/
void *
_cairo_array_index (cairo_array_t *array, int index)
{
/* We allow an index of 0 for the no-elements case.
* This makes for cleaner calling code which will often look like:
*
* elements = _cairo_array_index (array, num_elements);
* for (i=0; i < num_elements; i++) {
* ... use elements[i] here ...
* }
*
* which in the num_elements==0 case gets the NULL pointer here,
* but never dereferences it.
*/
if (array->elements == NULL) {
assert (index == 0);
return NULL;
}
assert (0 <= index && index < array->num_elements);
return (void *) &array->elements[index * array->element_size];
return (void *) &(*array->elements)[index * array->element_size];
}
/**
* _cairo_array_copy_element:
*
* Copy a single element out of the array from index @index into the
* location pointed to by @dst.
**/
void
_cairo_array_copy_element (cairo_array_t *array, int index, void *dst)
{
memcpy (dst, _cairo_array_index (array, index), array->element_size);
}
void *
_cairo_array_append (cairo_array_t *array,
const void *elements, int num_elements)
/**
* _cairo_array_append:
*
* Append a single item onto the array by growing the array by at
* least one element, then copying element_size bytes from @element
* into the array. The address of the resulting object within the
* array can be determined with:
*
* _cairo_array_index (array, _cairo_array_num_elements (array) - 1);
*
* Return value: CAIRO_STATUS_SUCCESS if successful or
* CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
* operation.
**/
cairo_status_t
_cairo_array_append (cairo_array_t *array,
const void *element)
{
assert (! array->is_snapshot);
return _cairo_array_append_multiple (array, element, 1);
}
/**
* _cairo_array_append:
*
* Append one or more items onto the array by growing the array by
* @num_elements, then copying @num_elements * element_size bytes from
* @elements into the array.
*
* Return value: CAIRO_STATUS_SUCCESS if successful or
* CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
* operation.
**/
cairo_status_t
_cairo_array_append_multiple (cairo_array_t *array,
const void *elements,
int num_elements)
{
cairo_status_t status;
void *dest;
assert (! array->is_snapshot);
status = _cairo_array_allocate (array, num_elements, &dest);
if (status)
return status;
memcpy (dest, elements, num_elements * array->element_size);
return CAIRO_STATUS_SUCCESS;
}
/**
* _cairo_array_allocate:
*
* Allocate space at the end of the array for @num_elements additional
* elements, providing the address of the new memory chunk in
* @elements. This memory will be unitialized, but will be accounted
* for in the return value of _cairo_array_num_elements().
*
* Return value: CAIRO_STATUS_SUCCESS if successful or
* CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
* operation.
**/
cairo_status_t
_cairo_array_allocate (cairo_array_t *array,
int num_elements,
void **elements)
{
cairo_status_t status;
assert (! array->is_snapshot);
status = _cairo_array_grow_by (array, num_elements);
if (status != CAIRO_STATUS_SUCCESS)
return NULL;
if (status)
return status;
assert (array->num_elements + num_elements <= array->size);
dest = &array->elements[array->num_elements * array->element_size];
*elements = &(*array->elements)[array->num_elements * array->element_size];
array->num_elements += num_elements;
if (elements != NULL)
memcpy (dest, elements, num_elements * array->element_size);
return dest;
return CAIRO_STATUS_SUCCESS;
}
/**
* _cairo_array_num_elements:
*
* Return value: The number of elements stored in @array.
**/
int
_cairo_array_num_elements (cairo_array_t *array)
{
@ -170,7 +357,7 @@ _cairo_user_data_array_fini (cairo_user_data_array_t *array)
cairo_user_data_slot_t *slots;
num_slots = array->num_elements;
slots = (cairo_user_data_slot_t *) array->elements;
slots = _cairo_array_index (array, 0);
for (i = 0; i < num_slots; i++) {
if (slots[i].user_data != NULL && slots[i].destroy != NULL)
slots[i].destroy (slots[i].user_data);
@ -204,7 +391,7 @@ _cairo_user_data_array_get_data (cairo_user_data_array_t *array,
return NULL;
num_slots = array->num_elements;
slots = (cairo_user_data_slot_t *) array->elements;
slots = _cairo_array_index (array, 0);
for (i = 0; i < num_slots; i++) {
if (slots[i].key == key)
return slots[i].user_data;
@ -235,44 +422,44 @@ _cairo_user_data_array_set_data (cairo_user_data_array_t *array,
void *user_data,
cairo_destroy_func_t destroy)
{
cairo_status_t status;
int i, num_slots;
cairo_user_data_slot_t *slots, *s;
cairo_user_data_slot_t *slots, *slot, new_slot;
s = NULL;
if (user_data) {
new_slot.key = key;
new_slot.user_data = user_data;
new_slot.destroy = destroy;
} else {
new_slot.key = NULL;
new_slot.user_data = NULL;
new_slot.destroy = NULL;
}
slot = NULL;
num_slots = array->num_elements;
slots = (cairo_user_data_slot_t *) array->elements;
slots = _cairo_array_index (array, 0);
for (i = 0; i < num_slots; i++) {
if (slots[i].key == key) {
if (slots[i].user_data != NULL && slots[i].destroy != NULL)
slots[i].destroy (slots[i].user_data);
s = &slots[i];
slot = &slots[i];
if (slot->destroy && slot->user_data)
slot->destroy (slot->user_data);
break;
}
if (user_data && slots[i].user_data == NULL) {
s = &slots[i]; /* Have to keep searching for an exact match */
slot = &slots[i]; /* Have to keep searching for an exact match */
}
}
if (user_data == NULL) {
if (s != NULL) {
s->key = NULL;
s->user_data = NULL;
s->destroy = NULL;
}
if (slot) {
*slot = new_slot;
return CAIRO_STATUS_SUCCESS;
} else {
if (s == NULL)
s = _cairo_array_append (array, NULL, 1);
if (s == NULL)
return CAIRO_STATUS_NO_MEMORY;
s->key = key;
s->user_data = user_data;
s->destroy = destroy;
}
status = _cairo_array_append (array, &new_slot);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}

Просмотреть файл

@ -38,16 +38,8 @@
#include "cairo-atsui.h"
#include "cairoint.h"
#include "cairo.h"
#include "cairo-quartz-private.h"
/*
* FixedToFloat/FloatToFixed are 10.3+ SDK items - include definitions
* here so we can use older SDKs.
*/
#ifndef FixedToFloat
#define fixed1 ((Fixed) 0x00010000L)
#define FixedToFloat(a) ((float)(a) / fixed1)
#define FloatToFixed(a) ((Fixed)((float)(a) * fixed1))
#endif
typedef struct _cairo_atsui_font_face cairo_atsui_font_face_t;
typedef struct _cairo_atsui_font cairo_atsui_font_t;
@ -62,7 +54,6 @@ static cairo_status_t _cairo_atsui_font_create_scaled (cairo_font_face_t *font_f
struct _cairo_atsui_font {
cairo_scaled_font_t base;
cairo_matrix_t scale;
ATSUStyle style;
ATSUStyle unscaled_style;
ATSUFontID fontID;
@ -128,7 +119,7 @@ cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id)
static CGAffineTransform
CGAffineTransformMakeWithCairoFontScale(cairo_matrix_t *scale)
CGAffineTransformMakeWithCairoFontScale(const cairo_matrix_t *scale)
{
return CGAffineTransformMake(scale->xx, scale->yx,
scale->xy, scale->yy,
@ -136,7 +127,7 @@ CGAffineTransformMakeWithCairoFontScale(cairo_matrix_t *scale)
}
static ATSUStyle
CreateSizedCopyOfStyle(ATSUStyle inStyle, cairo_matrix_t *scale)
CreateSizedCopyOfStyle(ATSUStyle inStyle, const cairo_matrix_t *scale)
{
ATSUStyle style;
OSStatus err;
@ -176,17 +167,17 @@ _cairo_atsui_font_set_metrics (cairo_atsui_font_t *font)
&metrics);
if (err == noErr) {
cairo_font_extents_t extents;
cairo_font_extents_t extents;
extents.ascent = metrics.ascent;
extents.descent = metrics.descent;
extents.descent = -metrics.descent;
extents.height = metrics.capHeight;
extents.max_x_advance = metrics.maxAdvanceWidth;
// The FT backend doesn't handle max_y_advance either, so we'll ignore it for now.
extents.max_y_advance = 0.0;
_cairo_scaled_font_set_metrics (&font->base, &extents);
_cairo_scaled_font_set_metrics (&font->base, &extents);
return CAIRO_STATUS_SUCCESS;
}
@ -205,7 +196,6 @@ _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face,
cairo_scaled_font_t **font_out)
{
cairo_atsui_font_t *font = NULL;
cairo_matrix_t scale;
OSStatus err;
cairo_status_t status;
@ -214,8 +204,7 @@ _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face,
_cairo_scaled_font_init(&font->base, font_face, font_matrix, ctm, options,
&cairo_atsui_scaled_font_backend);
cairo_matrix_multiply(&scale, font_matrix, ctm);
font->style = CreateSizedCopyOfStyle(style, &scale);
font->style = CreateSizedCopyOfStyle(style, &font->base.scale);
Fixed theSize = FloatToFixed(1.0);
const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag };
@ -229,7 +218,6 @@ _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face,
font->unscaled_style = style;
font->fontID = font_id;
font->scale = scale;
*font_out = &font->base;
@ -550,18 +538,18 @@ _cairo_atsui_font_text_to_glyphs (void *abstract_font,
}
static cairo_int_status_t
_cairo_atsui_font_show_glyphs (void *abstract_font,
cairo_operator_t operator,
cairo_pattern_t *pattern,
cairo_surface_t *generic_surface,
int source_x,
int source_y,
int dest_x,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
int num_glyphs)
_cairo_atsui_font_old_show_glyphs (void *abstract_font,
cairo_operator_t op,
cairo_pattern_t *pattern,
cairo_surface_t *generic_surface,
int source_x,
int source_y,
int dest_x,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_atsui_font_t *font = abstract_font;
CGContextRef myBitmapContext;
@ -596,7 +584,7 @@ _cairo_atsui_font_show_glyphs (void *abstract_font,
CGContextSetFont(myBitmapContext, cgFont);
CGAffineTransform textTransform =
CGAffineTransformMakeWithCairoFontScale(&font->scale);
CGAffineTransformMakeWithCairoFontScale(&font->base.scale);
textTransform = CGAffineTransformScale(textTransform, 1.0f, -1.0f);
@ -615,13 +603,43 @@ _cairo_atsui_font_show_glyphs (void *abstract_font,
CGContextSetRGBFillColor(myBitmapContext, 0.0f, 0.0f, 0.0f, 0.0f);
}
if (_cairo_surface_is_quartz (generic_surface)) {
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *)generic_surface;
if (surface->clip_region) {
pixman_box16_t *boxes = pixman_region_rects (surface->clip_region);
int num_boxes = pixman_region_num_rects (surface->clip_region);
CGRect stack_rects[10];
CGRect *rects;
int i;
if (num_boxes > 10)
rects = malloc (sizeof (CGRect) * num_boxes);
else
rects = stack_rects;
for (i = 0; i < num_boxes; i++) {
rects[i].origin.x = boxes[i].x1;
rects[i].origin.y = boxes[i].y1;
rects[i].size.width = boxes[i].x2 - boxes[i].x1;
rects[i].size.height = boxes[i].y2 - boxes[i].y1;
}
CGContextClipToRects (myBitmapContext, rects, num_boxes);
if (rects != stack_rects)
free(rects);
}
} else {
/* XXX: Need to get the text clipped */
}
// TODO - bold and italic text
//
// We could draw the text using ATSUI and get bold, italics
// etc. for free, but ATSUI does a lot of text layout work
// that we don't really need...
for (i = 0; i < num_glyphs; i++) {
CGGlyph theGlyph = glyphs[i].index;
@ -650,6 +668,6 @@ const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend = {
_cairo_atsui_font_scaled_glyph_init,
_cairo_atsui_font_text_to_glyphs,
NULL, /* ucs4_to_index */
_cairo_atsui_font_show_glyphs,
_cairo_atsui_font_old_show_glyphs,
};

Просмотреть файл

@ -0,0 +1,61 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Christian Biesinger <cbiesinger@web.de>
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Christian Biesinger
* <cbiesinger@web.de>
*
* Contributor(s):
*/
#ifndef CAIRO_BEOS_H
#define CAIRO_BEOS_H
#include <cairo.h>
#if CAIRO_HAS_BEOS_SURFACE
#include <View.h>
CAIRO_BEGIN_DECLS
cairo_public cairo_surface_t *
cairo_beos_surface_create (BView* view);
cairo_public cairo_surface_t *
cairo_beos_surface_create_for_bitmap (BView* view,
BBitmap* bmp);
CAIRO_END_DECLS
#else /* CAIRO_HAS_BEOS_SURFACE */
# error Cairo was not compiled with support for the beos backend
#endif /* CAIRO_HAS_BEOS_SURFACE */
#endif /* CAIRO_BEOS_H */

Просмотреть файл

@ -38,12 +38,6 @@
#include "cairo-path-fixed-private.h"
enum _cairo_clip_mode {
CAIRO_CLIP_MODE_PATH,
CAIRO_CLIP_MODE_REGION,
CAIRO_CLIP_MODE_MASK
};
struct _cairo_clip_path {
unsigned int ref_count;
cairo_path_fixed_t path;
@ -114,7 +108,7 @@ _cairo_clip_intersect_to_region (cairo_clip_t *clip,
cairo_private cairo_status_t
_cairo_clip_combine_to_surface (cairo_clip_t *clip,
cairo_operator_t operator,
cairo_operator_t op,
cairo_surface_t *dst,
int dst_x,
int dst_y,

Просмотреть файл

@ -49,60 +49,71 @@ void
_cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target)
{
clip->mode = _cairo_surface_get_clip_mode (target);
clip->region = NULL;
clip->surface = NULL;
clip->surface_rect.x = 0;
clip->surface_rect.y = 0;
clip->surface_rect.width = 0;
clip->surface_rect.height = 0;
clip->serial = 0;
clip->region = NULL;
clip->path = NULL;
}
void
_cairo_clip_fini (cairo_clip_t *clip)
{
if (clip->surface)
cairo_surface_destroy (clip->surface);
cairo_surface_destroy (clip->surface);
clip->surface = NULL;
if (clip->path)
_cairo_clip_path_destroy (clip->path);
clip->path = NULL;
clip->serial = 0;
if (clip->region)
pixman_region_destroy (clip->region);
clip->region = NULL;
clip->serial = 0;
_cairo_clip_path_destroy (clip->path);
clip->path = NULL;
}
void
_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
{
if (other->region) {
clip->mode = other->mode;
clip->surface = cairo_surface_reference (other->surface);
clip->surface_rect = other->surface_rect;
clip->serial = other->serial;
if (other->region == NULL) {
clip->region = other->region;
} else {
clip->region = pixman_region_create ();
pixman_region_copy (clip->region, other->region);
}
cairo_surface_reference (other->surface);
clip->surface = other->surface;
_cairo_clip_path_reference (other->path);
clip->path = other->path;
clip->path = _cairo_clip_path_reference (other->path);
}
cairo_status_t
_cairo_clip_reset (cairo_clip_t *clip)
{
/* destroy any existing clip-region artifacts */
if (clip->surface)
cairo_surface_destroy (clip->surface);
cairo_surface_destroy (clip->surface);
clip->surface = NULL;
clip->serial = 0;
if (clip->region)
pixman_region_destroy (clip->region);
clip->region = NULL;
if (clip->path)
_cairo_clip_path_destroy (clip->path);
_cairo_clip_path_destroy (clip->path);
clip->path = NULL;
clip->serial = 0;
return CAIRO_STATUS_SUCCESS;
}
@ -111,6 +122,9 @@ cairo_status_t
_cairo_clip_intersect_to_rectangle (cairo_clip_t *clip,
cairo_rectangle_t *rectangle)
{
if (!clip)
return CAIRO_STATUS_SUCCESS;
if (clip->path) {
/* Intersect path extents here. */
}
@ -148,6 +162,9 @@ cairo_status_t
_cairo_clip_intersect_to_region (cairo_clip_t *clip,
pixman_region16_t *region)
{
if (!clip)
return CAIRO_STATUS_SUCCESS;
if (clip->path) {
/* Intersect clip path into region. */
}
@ -185,7 +202,7 @@ _cairo_clip_intersect_to_region (cairo_clip_t *clip,
*/
cairo_status_t
_cairo_clip_combine_to_surface (cairo_clip_t *clip,
cairo_operator_t operator,
cairo_operator_t op,
cairo_surface_t *dst,
int dst_x,
int dst_y,
@ -196,7 +213,7 @@ _cairo_clip_combine_to_surface (cairo_clip_t *clip,
_cairo_pattern_init_for_surface (&pattern.surface, clip->surface);
status = _cairo_surface_composite (operator,
status = _cairo_surface_composite (op,
&pattern.base,
NULL,
dst,

Просмотреть файл

@ -70,3 +70,153 @@ cairo_debug_reset_static_data (void)
#endif
}
/*
* path dumper
*/
typedef struct _cairo_debug_path_dump_closure {
unsigned int op_count;
FILE *fp;
} cairo_debug_path_dump_closure_t;
static cairo_status_t
_cairo_debug_path_move_to (void *closure,
cairo_point_t *point)
{
cairo_debug_path_dump_closure_t *fdc =
(cairo_debug_path_dump_closure_t*) closure;
fprintf (fdc->fp, "%d: moveto (%f, %f)\n",
fdc->op_count++,
_cairo_fixed_to_double(point->x),
_cairo_fixed_to_double(point->y));
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_debug_path_line_to (void *closure,
cairo_point_t *point)
{
cairo_debug_path_dump_closure_t *fdc =
(cairo_debug_path_dump_closure_t*) closure;
fprintf (fdc->fp, "%d: lineto (%f, %f)\n",
fdc->op_count++,
_cairo_fixed_to_double(point->x),
_cairo_fixed_to_double(point->y));
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_debug_path_curve_to (void *closure,
cairo_point_t *p0,
cairo_point_t *p1,
cairo_point_t *p2)
{
cairo_debug_path_dump_closure_t *fdc =
(cairo_debug_path_dump_closure_t*) closure;
fprintf (fdc->fp, "%d: curveto (%f, %f) (%f, %f) (%f, %f)\n",
fdc->op_count++,
_cairo_fixed_to_double(p0->x),
_cairo_fixed_to_double(p0->y),
_cairo_fixed_to_double(p1->x),
_cairo_fixed_to_double(p1->y),
_cairo_fixed_to_double(p2->x),
_cairo_fixed_to_double(p2->y));
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_debug_path_close_path (void *closure)
{
cairo_debug_path_dump_closure_t *fdc =
(cairo_debug_path_dump_closure_t*) closure;
fprintf (fdc->fp, "%d: close\n",
fdc->op_count++);
return CAIRO_STATUS_SUCCESS;
}
/**
* cairo_debug_dump_path
* @path: a #cairo_path_fixed_t
* @fp: the file pointer where to dump the given path
*
* Dumps @path in human-readable form to @fp.
*/
void
cairo_debug_dump_path (cairo_path_fixed_t *path,
FILE *fp)
{
cairo_debug_path_dump_closure_t fdc;
fdc.fp = fp;
fdc.op_count = 0;
fprintf (fp, "=== path %p ===\n", path);
_cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
_cairo_debug_path_move_to,
_cairo_debug_path_line_to,
_cairo_debug_path_curve_to,
_cairo_debug_path_close_path,
&fdc);
fprintf (fp, "======================\n");
}
/*
* traps dumping
*/
/**
* cairo_debug_dump_traps
* @traps: a #cairo_traps_t
* @fp: the file pointer where to dump the traps
*
* Dumps @traps in human-readable form to @fp.
*/
void
cairo_debug_dump_traps (cairo_traps_t *traps,
FILE *fp)
{
fprintf (fp, "=== traps %p ===\n", traps);
fprintf (fp, "extents: (%f, %f) (%f, %f)\n",
_cairo_fixed_to_double (traps->extents.p1.x),
_cairo_fixed_to_double (traps->extents.p1.y),
_cairo_fixed_to_double (traps->extents.p2.x),
_cairo_fixed_to_double (traps->extents.p2.y));
cairo_debug_dump_trapezoid_array (traps->traps,
traps->num_traps,
fp);
fprintf (fp, "=======================\n");
}
/**
* cairo_debug_dump_trapezoid_array
* @traps: a #cairo_trapezoid_t pointer
* @num_traps: the number of trapezoids in @traps
* @fp: the file pointer where to dump the traps
*
* Dumps num_traps in the @traps array in human-readable form to @fp.
*/
void
cairo_debug_dump_trapezoid_array (cairo_trapezoid_t *traps,
int num_traps,
FILE *fp)
{
int i;
for (i = 0; i < num_traps; i++) {
fprintf (fp, "% 3d: t: %f b: %f l: (%f,%f)->(%f,%f) r: (%f,%f)->(%f,%f)\n",
i,
_cairo_fixed_to_double (traps[i].top),
_cairo_fixed_to_double (traps[i].bottom),
_cairo_fixed_to_double (traps[i].left.p1.x),
_cairo_fixed_to_double (traps[i].left.p1.y),
_cairo_fixed_to_double (traps[i].left.p2.x),
_cairo_fixed_to_double (traps[i].left.p2.y),
_cairo_fixed_to_double (traps[i].right.p1.x),
_cairo_fixed_to_double (traps[i].right.p1.y),
_cairo_fixed_to_double (traps[i].right.p2.x),
_cairo_fixed_to_double (traps[i].right.p2.y));
}
}

Просмотреть файл

@ -37,12 +37,30 @@
#define CAIRO_DEBUG_H
#include <cairo-features.h>
#include <stdio.h>
CAIRO_BEGIN_DECLS
struct _cairo_path_fixed;
struct _cairo_traps;
struct _cairo_trapezoid;
void
cairo_debug_reset_static_data (void);
void
cairo_debug_dump_path (struct _cairo_path_fixed *path,
FILE *fp);
void
cairo_debug_dump_traps (struct _cairo_traps *traps,
FILE *fp);
void
cairo_debug_dump_trapezoid_array (struct _cairo_trapezoid *traps,
int num_traps,
FILE *fp);
CAIRO_END_DECLS
#endif /* CAIRO_H */

Просмотреть файл

@ -0,0 +1,804 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2003 University of Southern California
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is University of Southern
* California.
*
* Contributor(s):
* Michael Emmel <mike.emmel@gmail.com>
*/
#include <stdio.h>
#include <directfb.h>
#include "cairo-directfb.h"
#include "cairoint.h"
#define DFB_UNSUPPORTED -1
#define DFB_SUPPORTED 1
/*
Glyph support not working
*/
#define DFB_SHOW_GLYPHS 0
/*
Composite support not working
*/
#define DFB_COMPOSITE 0
#if DFB_SHOW_GLYPHS
static cairo_int_status_t
_cairo_directfb_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_surface,
int source_x,
int source_y,
int dest_x,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
int num_glyphs);
#endif
typedef struct _cairo_directfb_surface {
cairo_surface_t base;
cairo_format_t format;
IDirectFB *dfb;
IDirectFBSurface *main_surface;
IDirectFBSurface *buffer;
pixman_region16_t *clip;
cairo_surface_t *buffer_image;
void *buffer_data;
int width;
int height;
} cairo_directfb_surface_t;
static int
_dfb_set_operator (cairo_operator_t operator,IDirectFBSurface *dest)
{
dest->SetDrawingFlags(dest,DSDRAW_BLEND);
dest->SetPorterDuff(dest,DSPD_NONE);
switch (operator) {
case CAIRO_OPERATOR_CLEAR:
dest->SetPorterDuff(dest,DSPD_CLEAR);
break;
case CAIRO_OPERATOR_SOURCE:
dest->SetPorterDuff(dest,DSPD_SRC);
break;
case CAIRO_OPERATOR_OVER:
dest->SetPorterDuff(dest,DSPD_SRC_OVER);
break;
case CAIRO_OPERATOR_IN:
dest->SetPorterDuff(dest,DSPD_SRC_IN);
break;
case CAIRO_OPERATOR_OUT:
dest->SetPorterDuff(dest,DSPD_SRC_OUT);
break;
case CAIRO_OPERATOR_DEST_OVER:
dest->SetPorterDuff(dest,DSPD_DST_OVER);
break;
case CAIRO_OPERATOR_DEST_IN:
dest->SetPorterDuff(dest,DSPD_DST_IN);
break;
case CAIRO_OPERATOR_DEST_OUT:
dest->SetPorterDuff(dest,DSPD_DST_OUT);
break;
/*not sure about these yet */
case CAIRO_OPERATOR_ATOP:
return DFB_UNSUPPORTED;
break;
case CAIRO_OPERATOR_DEST:
return DFB_UNSUPPORTED;
break;
case CAIRO_OPERATOR_DEST_ATOP:
return DFB_UNSUPPORTED;
break;
case CAIRO_OPERATOR_XOR:
dest->SetDrawingFlags(dest,DSDRAW_XOR);
break;
case CAIRO_OPERATOR_ADD:
return DFB_UNSUPPORTED;
break;
case CAIRO_OPERATOR_SATURATE:
return DFB_UNSUPPORTED;
break;
default:
return DFB_UNSUPPORTED;
}
return DFB_SUPPORTED;
}
static inline int cairo_to_directfb_format(cairo_format_t format ) {
switch( format ) {
case CAIRO_FORMAT_RGB24:
return DSPF_RGB24;
case CAIRO_FORMAT_ARGB32:
return DSPF_ARGB;
case CAIRO_FORMAT_A8:
return DSPF_A8;
case CAIRO_FORMAT_A1:
return DSPF_A1;
default:
{
//assert(0);
return DSPF_UNKNOWN;
}
}
}
static inline int directfb_to_cairo_format(DFBSurfacePixelFormat dfbformat ) {
switch( dfbformat ) {
case DSPF_RGB24 :
case DSPF_RGB32 :
return CAIRO_FORMAT_RGB24;
break;
case DSPF_AiRGB :
case DSPF_ARGB :
return CAIRO_FORMAT_ARGB32;
break;
case DSPF_A8 :
return CAIRO_FORMAT_A8;
break;
case DSPF_A1 :
return CAIRO_FORMAT_A1;
break;
case DSPF_UNKNOWN :
case DSPF_ARGB1555 :
case DSPF_RGB16 :
case DSPF_YUY2 :
case DSPF_RGB332 :
case DSPF_UYVY :
case DSPF_I420 :
case DSPF_ALUT44 :
case DSPF_NV12 :
case DSPF_NV16 :
default :
return DFB_UNSUPPORTED;
}
}
static IDirectFBSurface *cairo_directfb_buffer_surface_create(IDirectFB *dfb,void *data,int pitch, int format,
int width, int height) {
DFBResult ret;
IDirectFBSurface *buffer;
DFBSurfaceDescription dsc;
dsc.flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT;
dsc.caps = DSCAPS_NONE;
dsc.width = width;
dsc.height = height;
dsc.pixelformat = format;
if( data ) {
dsc.flags |= DSDESC_CAPS;
dsc.flags |= DSDESC_PREALLOCATED;
dsc.caps = DSCAPS_NONE;
dsc.preallocated[0].data = data;
dsc.preallocated[0].pitch = pitch;
dsc.preallocated[1].data = NULL;
dsc.preallocated[1].pitch = 0;
}
ret =dfb->CreateSurface (dfb, &dsc, &buffer);
if (ret) {
DirectFBError ("cairo_directfb_buffer_surface_create failed ", ret);
assert(0);
return NULL;
}
#if 0
{
DFBSurfacePixelFormat dfbformat;
int nwidth=0;
int nheight=0;
int npitch;
void *ndata;
buffer->GetSize(buffer,&nwidth,&nheight);
buffer->GetPixelFormat(buffer,&dfbformat);
buffer->Lock(buffer,DSLF_READ,&ndata,&npitch);
buffer->Unlock(buffer);
assert( ( nwidth == width) && (nheight == height));
}
#endif
return buffer;
}
static cairo_status_t
_cairo_directfb_surface_get_image (cairo_directfb_surface_t *surface,
cairo_rectangle_t *interest,
cairo_image_surface_t **image_out,
cairo_rectangle_t *rect_out,
DFBSurfaceLockFlags flags)
{
int pitch;
void *data;
(void)interest;
if( surface->buffer->Lock(surface->buffer,flags,&data,&pitch) != DFB_OK )
return CAIRO_STATUS_NO_MEMORY;
/*lock the dest agianst other changes*/
if( surface->buffer_image ) {
if( surface->buffer_data == data ) {
cairo_surface_reference(surface->buffer_image);
}
}
if( surface->buffer_data != data ){
/* new off screen buffer */
int width;
int height;
DFBSurfacePixelFormat dfbformat;
/*surface moved free image if allocated */
if( surface->buffer_image ) {
cairo_surface_destroy (surface->buffer_image);
surface->buffer_image=NULL;
surface->buffer_data=NULL;
}
surface->buffer->Unlock(surface->buffer);
surface->main_surface->GetSize(surface->main_surface,&width,&height);
surface->main_surface->GetPixelFormat(surface->main_surface,&dfbformat);
surface->format = directfb_to_cairo_format(dfbformat);
if( surface->format == DFB_UNSUPPORTED ) {
surface->format = CAIRO_FORMAT_ARGB32;
surface->buffer = cairo_directfb_buffer_surface_create(surface->dfb,NULL,
0,DSPF_ARGB,width,height);
if( !surface->buffer )
return CAIRO_STATUS_NO_MEMORY;
/*Have to flip the main surface if its double buffered to blit the buffer*/
surface->main_surface->Flip(surface->main_surface,NULL,0);
surface->buffer->Blit(surface->buffer,surface->main_surface,NULL,0,0);
}else {
surface->buffer = surface->main_surface;
}
surface->width=width;
surface->height=height;
if( surface->buffer->Lock(surface->buffer,flags,&data,&pitch) != DFB_OK )
return CAIRO_STATUS_NO_MEMORY;
surface->buffer_data = data;
surface->buffer_image = cairo_image_surface_create_for_data (
(unsigned char *)data,surface->format,width, height, pitch);
if( surface->buffer_image == NULL ) {
surface->buffer->Release(surface->buffer);
surface->buffer = NULL;
surface->buffer_data = NULL;
return CAIRO_STATUS_NO_MEMORY;
}
#if 0
if( surface->clip)
_cairo_image_surface_set_clip_region (
(cairo_image_surface_t *)surface->buffer_image,surface->clip);
#endif
}
if (rect_out) {
rect_out->x = 0;
rect_out->y = 0;
rect_out->width = surface->width;
rect_out->height = surface->height;
}
if( image_out )
*image_out=(cairo_image_surface_t *)surface->buffer_image;
return CAIRO_STATUS_SUCCESS;
}
static cairo_surface_t *
_cairo_directfb_surface_create_similar (void *abstract_src,
cairo_content_t content,
int width,
int height)
{
cairo_format_t format = _cairo_format_from_content (content);
int dfbformat;
switch( content ) {
case CAIRO_CONTENT_COLOR:
dfbformat=DSPF_ARGB;
break;
case CAIRO_CONTENT_ALPHA:
dfbformat=DSPF_A8;
break;
case CAIRO_CONTENT_COLOR_ALPHA:
dfbformat= DSPF_ARGB;
break;
default:
{
return cairo_image_surface_create (format, width, height);
}
}
cairo_directfb_surface_t *src = abstract_src;
IDirectFBSurface *buffer =cairo_directfb_buffer_surface_create(src->dfb,
NULL,0,dfbformat,width,height);
cairo_surface_t *sur =cairo_directfb_surface_create (src->dfb,buffer);
((cairo_directfb_surface_t *)sur)->format = format;
return sur;
}
static cairo_status_t
_cairo_directfb_surface_finish (void *data ) {
cairo_directfb_surface_t *surface=(cairo_directfb_surface_t *)data;
if( surface->buffer_image )
cairo_surface_destroy (surface->buffer_image);
if (surface->clip)
pixman_region_destroy (surface->clip);
if( surface->main_surface != surface->buffer ) {
surface->main_surface->SetClip (surface->main_surface,NULL);
surface->main_surface->Blit(surface->main_surface,surface->buffer,NULL,0,0);
surface->buffer->Release (surface->buffer);
surface->buffer=NULL;
}
#if 0 /* No don't do this */
surface->main_surface->Flip(surface->main_surface,NULL,0);
#endif
surface->main_surface->Release (surface->main_surface);
surface->main_surface=NULL;
surface->dfb->Release(surface->dfb);
surface->dfb=NULL;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_directfb_surface_acquire_source_image (void *abstract_surface,
cairo_image_surface_t **image_out,
void **image_extra)
{
cairo_directfb_surface_t *surface = abstract_surface;
*image_extra = surface;
return _cairo_directfb_surface_get_image (surface, NULL,image_out,NULL,DSLF_READ);
}
static void
_cairo_directfb_surface_release_source_image (void *abstract_surface,
cairo_image_surface_t *image,
void *image_extra)
{
cairo_directfb_surface_t *surface = abstract_surface;
surface->buffer->Unlock(surface->buffer);
}
static cairo_status_t
_cairo_directfb_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_t *image_rect_out,
void **image_extra)
{
cairo_directfb_surface_t *surface = abstract_surface;
*image_extra = interest_rect;
return _cairo_directfb_surface_get_image (surface, interest_rect,image_out,
image_rect_out,DSLF_READ|DSLF_WRITE);
}
static void
_cairo_directfb_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_t *image_rect,
void *image_extra)
{
cairo_directfb_surface_t *surface = abstract_surface;
IDirectFBSurface *buffer=surface->buffer;
buffer->Unlock(buffer);
}
static cairo_status_t
_cairo_directfb_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
cairo_surface_t **clone_out)
{
cairo_directfb_surface_t *surface = abstract_surface;
cairo_directfb_surface_t *clone;
if (src->backend == surface->base.backend) {
*clone_out = src;
cairo_surface_reference (src);
return CAIRO_STATUS_SUCCESS;
} else if (_cairo_surface_is_image (src)) {
cairo_image_surface_t *image_src = (cairo_image_surface_t *) src;
clone = (cairo_directfb_surface_t *)
_cairo_directfb_surface_create_similar (surface, image_src->format,
image_src->width,
image_src->height);
if (!clone)
return CAIRO_STATUS_NO_MEMORY;
IDirectFBSurface *tmpbuffer;
int format = cairo_to_directfb_format(image_src->format);
tmpbuffer =cairo_directfb_buffer_surface_create(surface->dfb,
(void *)image_src->data,image_src->stride,format,
image_src->width,image_src->height);
if (!tmpbuffer){
cairo_surface_destroy((cairo_surface_t *)surface);
return CAIRO_STATUS_NO_MEMORY;
}
clone->buffer->Blit(clone->buffer,tmpbuffer,NULL,0,0);
tmpbuffer->Release(tmpbuffer);
*clone_out = &clone->base;
return CAIRO_STATUS_SUCCESS;
}
return CAIRO_INT_STATUS_UNSUPPORTED;
}
#if DFB_COMPOSITE
static cairo_int_status_t
_cairo_directfb_surface_composite (cairo_operator_t op,
cairo_pattern_t *src_pattern,
cairo_pattern_t *mask_pattern,
void *abstract_dst,
int src_x,
int src_y,
int mask_x,
int mask_y,
int dst_x,
int dst_y,
unsigned int width,
unsigned int height)
{
cairo_directfb_surface_t *dst = abstract_dst;
cairo_directfb_surface_t *src;
cairo_surface_pattern_t *src_surface_pattern;
int alpha;
int integer_transform;
int itx, ity;
cairo_directfb_surface_t *surface = abstract_dst;
if( _dfb_set_operator(op,surface->buffer) == DFB_UNSUPPORTED )
return CAIRO_INT_STATUS_UNSUPPORTED;
if (src_pattern->type == CAIRO_PATTERN_SOLID ) {
} else if (src_pattern->type != CAIRO_PATTERN_SURFACE ||
src_pattern->extend != CAIRO_EXTEND_NONE) {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
if (mask_pattern) {
/* FIXME: When we fully support RENDER style 4-channel
* masks we need to check r/g/b != 1.0.
*/
if (mask_pattern->type != CAIRO_PATTERN_SOLID)
return CAIRO_INT_STATUS_UNSUPPORTED;
alpha = ((cairo_solid_pattern_t *)mask_pattern)->color.alpha_short >> 8;
} else {
alpha = 255;
}
src_surface_pattern = (cairo_surface_pattern_t *)src_pattern;
src = (cairo_directfb_surface_t *)src_surface_pattern->surface;
if (src->base.backend != dst->base.backend){
return CAIRO_INT_STATUS_UNSUPPORTED;
}
integer_transform = _cairo_matrix_is_integer_translation (&src_pattern->matrix, &itx, &ity);
if (!integer_transform) {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
surface->buffer->SetPorterDuff(surface->buffer,DSPD_NONE);
return CAIRO_INT_STATUS_UNSUPPORTED;
}
#endif
static cairo_int_status_t
_cairo_directfb_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int n_rects)
{
int i,k;
cairo_directfb_surface_t *surface = abstract_surface;
IDirectFBSurface *buffer = surface->buffer;
if( _dfb_set_operator(op,buffer) == DFB_UNSUPPORTED ) {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
buffer->SetColor(buffer,color->red_short >> 8,
color->green_short >> 8,
color->blue_short >> 8,
color->alpha_short >> 8 );
/*Not optimized not sure of the sorting on region*/
if( surface->clip ) {
DFBRegion region;
int n_boxes = pixman_region_num_rects (surface->clip);
pixman_box16_t *boxes = pixman_region_rects (surface->clip);
for( k = 0; k < n_boxes; k++ ) {
region.x1 = boxes[k].x1;
region.y1 = boxes[k].y1;
region.x2 = boxes[k].x2;
region.y2 = boxes[k].y2;
buffer->SetClip (buffer,&region);
for (i = 0; i < n_rects; i++) {
buffer->FillRectangle(buffer,rects[i].x,rects[i].y,
rects[i].width,rects[i].height);
}
}
buffer->SetClip (buffer, NULL);
}else {
buffer->SetClip (buffer, NULL);
for (i = 0; i < n_rects; i++) {
buffer->FillRectangle(buffer,rects[i].x,rects[i].y,
rects[i].width,rects[i].height);
}
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_directfb_surface_set_clip_region (void *abstract_surface,
pixman_region16_t *region)
{
cairo_directfb_surface_t *surface = abstract_surface;
if( region == NULL ) {
pixman_region_destroy (surface->clip);
surface->clip = NULL;
}else {
if (!surface->clip) {
surface->clip = pixman_region_create ();
if (!surface->clip)
return CAIRO_STATUS_NO_MEMORY;
}
pixman_region_copy (surface->clip, region);
}
#if 0
if( surface->buffer_image )
_cairo_image_surface_set_clip_region (
(cairo_image_surface_t *)surface->buffer_image,region);
#endif
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_directfb_abstract_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
{
if( rectangle ) {
cairo_directfb_surface_t *surface = abstract_surface;
rectangle->x = 0;
rectangle->y = 0;
rectangle->width = surface->width;
rectangle->height = surface->height;
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_directfb_surface_mark_dirty_rectangle (void * abstract_surface,
int x,
int y,
int width,
int height)
{
cairo_directfb_surface_t *surface = abstract_surface;
if( surface->main_surface != surface->buffer) {
DFBRegion region;
region.x1=x;
region.y1=y;
region.x2=x+width;
region.y2=y+height;
surface->buffer->SetClip (surface->buffer,&region);
surface->buffer->Blit(surface->buffer,surface->main_surface,NULL,0,0);
surface->buffer->SetClip (surface->buffer,NULL);
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_directfb_surface_flush (void *abstract_surface)
{
cairo_directfb_surface_t *surface = abstract_surface;
if( surface->main_surface != surface->buffer)
surface->main_surface->Blit(surface->main_surface,surface->buffer,NULL,0,0);
return CAIRO_STATUS_SUCCESS;
}
#if DFB_SHOW_GLYPHS
static void
_cairo_directfb_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font)
{
cairo_directfb_surface_font_private_t *font_private;
font_private = scaled_font->surface_private;
if (font_private)
{
xxx_destroy (font_private);
}
}
#endif
#if DFB_SHOW_GLYPHS
static void
_cairo_directfb_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
cairo_scaled_font_t *scaled_font)
{
cairo_directfb_surface_glyph_private_t *glyph_private;
glyph_private = scaled_glyph->surface_private;
if (glyph_private)
{
xxx_release(glyph_private);
}
}
#endif
static const cairo_surface_backend_t cairo_directfb_surface_backend = {
_cairo_directfb_surface_create_similar,
_cairo_directfb_surface_finish,
_cairo_directfb_surface_acquire_source_image,
_cairo_directfb_surface_release_source_image,
_cairo_directfb_surface_acquire_dest_image,
_cairo_directfb_surface_release_dest_image,
_cairo_directfb_surface_clone_similar,
#if DFB_COMPOSITE
_cairo_directfb_surface_composite,
#else
NULL,
#endif
_cairo_directfb_surface_fill_rectangles,
NULL,/*composite_trapezoids*/
NULL, /* copy_page */
NULL, /* show_page */
_cairo_directfb_surface_set_clip_region,
NULL, /* intersect_clip_path */
_cairo_directfb_abstract_surface_get_extents,
#if DFB_SHOW_GLYPHS
_cairo_directfb_surface_show_glyphs,
#else
NULL,
#endif
NULL, /* get_font_options */
_cairo_directfb_surface_flush,
_cairo_directfb_surface_mark_dirty_rectangle,
#if DFB_SHOW_GLYPHS
_cairo_directfb_surface_scaled_font_fini,
_cairo_directfb_surface_scaled_glyph_fini
#else
NULL,
NULL
#endif
};
#if DFB_SHOW_GLYPHS
static cairo_int_status_t
_cairo_directfb_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_surface,
int source_x,
int source_y,
int dest_x,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
int num_glyphs)
{
int i;
cairo_int_status_t status;
cairo_directfb_surface_t *surface = abstract_surface;
cairo_scaled_glyph_t *scaled_glyph;
if ((scaled_font->surface_backend != NULL &&
scaled_font->surface_backend != &cairo_directfb_surface_backend) )
return CAIRO_INT_STATUS_UNSUPPORTED;
if (scaled_font->surface_backend == NULL) {
scaled_font->surface_backend = &cairo_directfb_surface_backend;
}
/* Send all unsent glyphs to the server */
for (i = 0; i < num_glyphs; i++) {
IDirectFBSurface *tmpbuffer;
int x;
int y;
cairo_image_surface_t *glyph_img;
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
&scaled_glyph);
glyph_img = scaled_glyph->surface;
if (status != CAIRO_STATUS_SUCCESS)
return status;
/* its a space or something*/
if( !glyph_img->data ) {
continue;
}
if (scaled_glyph->surface_private == NULL ) {
int dfbformat = cairo_to_directfb_format(glyph_img->format);
if( dfbformat == DSPF_UNKNOWN ) {
printf(" BAD IMAGE FORMAT[%d] cf=%d dfbf=%d data=%p \n",i,glyph_img->format,dfbformat,glyph_img->data);
continue;
}
tmpbuffer = cairo_directfb_buffer_surface_create(surface->dfb,
(void *)glyph_img->data,glyph_img->stride,dfbformat,glyph_img->width,glyph_img->height);
/*scaled_glyph->surface_private = tmpbuffer;*/
}else {
tmpbuffer = (IDirectFBSurface *)scaled_glyph->surface_private;
}
if( !tmpbuffer ) {
assert(0); /*something really bad happend*/
return CAIRO_INT_STATUS_UNSUPPORTED;
}
/* round glyph locations to the nearest pixel */
x = (int) floor (glyphs[i].x +
glyph_img->base.device_x_offset +
0.5);
y = (int) floor (glyphs[i].y +
glyph_img->base.device_y_offset +
0.5);
x +=dest_x;
y +=dest_y;
printf(" IMAGE FORMAT[%d] src_x=%d src_y=%d cf=%d data=%p x=%d y=%d w=%d h=%d\n",i,source_x,source_y,glyph_img->format,glyph_img->data,x,y,glyph_img->width,glyph_img->height);
#if 0
surface->buffer->SetColor(surface->buffer,0,0xff,0,0xff);
surface->buffer->FillRectangle(surface->buffer,x,y,glyph_img->width,glyph_img->height);
surface->buffer->SetColor(surface->buffer,0,0xff,0xff,0xff);
#endif
surface->buffer->Blit(surface->buffer,tmpbuffer,NULL,x,y);
}
return CAIRO_INT_STATUS_UNSUPPORTED;
}
#endif
cairo_surface_t *
cairo_directfb_surface_create (IDirectFB *dfb,IDirectFBSurface *dfbsurface)
{
cairo_directfb_surface_t *surface = calloc(1,sizeof(cairo_directfb_surface_t));
if( surface == NULL )
return NULL;
_cairo_surface_init (&surface->base, &cairo_directfb_surface_backend);
/*Reference the surface */
dfb->AddRef(dfb);
dfbsurface->AddRef(dfbsurface);
surface->dfb=dfb;
surface->main_surface = dfbsurface;
dfbsurface->GetSize(dfbsurface,&surface->width,&surface->height);
surface->buffer = surface->main_surface;
surface->format = DFB_UNSUPPORTED;
surface->clip=NULL;
return ((cairo_surface_t *)surface);
}

Просмотреть файл

@ -0,0 +1,60 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2003 University of Southern California
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is University of Southern
* California.
*
* Contributor(s):
* Carl D. Worth <cworth@isi.edu>
*/
#ifndef CAIRO_DIRECTFB_H
#define CAIRO_DIRECTFB_H
#include <cairo.h>
#ifdef CAIRO_HAS_DIRECTFB_SURFACE
CAIRO_BEGIN_DECLS
cairo_surface_t * cairo_directfb_surface_create (IDirectFB *dfb,IDirectFBSurface *surface);
CAIRO_END_DECLS
#endif /*CAIRO_HAS_DIRECTFB_SURFACE*/
#endif /*CAIRO_DIRECTFB_H*/

Просмотреть файл

@ -37,8 +37,6 @@
#ifndef CAIRO_FEATURES_H
#define CAIRO_FEATURES_H
#include "cairo-platform.h"
#ifdef __cplusplus
# define CAIRO_BEGIN_DECLS extern "C" {
# define CAIRO_END_DECLS }
@ -47,6 +45,10 @@
# define CAIRO_END_DECLS
#endif
#ifndef cairo_public
# define cairo_public
#endif
#define CAIRO_VERSION_MAJOR 1
#define CAIRO_VERSION_MINOR 1
#define CAIRO_VERSION_MICRO 1
@ -57,6 +59,8 @@
@PDF_SURFACE_FEATURE@
@SVG_SURFACE_FEATURE@
@XLIB_SURFACE_FEATURE@
@QUARTZ_SURFACE_FEATURE@
@ -65,8 +69,12 @@
@WIN32_SURFACE_FEATURE@
@BEOS_SURFACE_FEATURE@
@GLITZ_SURFACE_FEATURE@
@DIRECTFB_SURFACE_FEATURE@
@FT_FONT_FEATURE@
@WIN32_FONT_FEATURE@

Просмотреть файл

@ -61,6 +61,16 @@ _cairo_font_options_init_default (cairo_font_options_t *options)
options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT;
}
void
_cairo_font_options_init_copy (cairo_font_options_t *options,
const cairo_font_options_t *other)
{
options->antialias = other->antialias;
options->subpixel_order = other->subpixel_order;
options->hint_style = other->hint_style;
options->hint_metrics = other->hint_metrics;
}
/**
* cairo_font_options_create:
*
@ -107,7 +117,7 @@ cairo_font_options_copy (const cairo_font_options_t *original)
if (!options)
return (cairo_font_options_t *)&cairo_font_options_nil;
*options = *original;
_cairo_font_options_init_copy (options, original);
return options;
}

Просмотреть файл

@ -34,9 +34,9 @@
*/
#include "cairoint.h"
#include "cairo-pdf.h"
/* XXX: Eventually, we need to handle other font backends */
#include "cairo-font-subset-private.h"
/* XXX: Eventually, we need to handle other font backends */
#include "cairo-ft-private.h"
#include <ft2build.h>
@ -231,17 +231,31 @@ cairo_pdf_ft_font_destroy (void *abstract_font)
free (font);
}
static void *
static cairo_status_t
cairo_pdf_ft_font_allocate_write_buffer (cairo_pdf_ft_font_t *font,
size_t length,
unsigned char **buffer)
{
cairo_status_t status;
status = _cairo_array_allocate (&font->output, length, (void **) buffer);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_pdf_ft_font_write (cairo_pdf_ft_font_t *font,
const void *data, size_t length)
{
void *p;
cairo_status_t status;
p = _cairo_array_append (&font->output, data, length);
if (p == NULL)
font->status = CAIRO_STATUS_NO_MEMORY;
status = _cairo_array_append_multiple (&font->output, data, length);
if (status)
return status;
return p;
return CAIRO_STATUS_SUCCESS;
}
static void
@ -266,12 +280,15 @@ cairo_pdf_ft_font_write_be32 (cairo_pdf_ft_font_t *font, unsigned long value)
static unsigned long
cairo_pdf_ft_font_align_output (cairo_pdf_ft_font_t *font)
{
int length, aligned;
static const char pad[4];
int length, aligned, pad;
unsigned char *ignored;
length = _cairo_array_num_elements (&font->output);
aligned = (length + 3) & ~3;
cairo_pdf_ft_font_write (font, pad, aligned - length);
pad = aligned - length;
if (pad)
cairo_pdf_ft_font_allocate_write_buffer (font, pad, &ignored);
return aligned;
}
@ -305,12 +322,14 @@ static int
cairo_pdf_ft_font_write_generic_table (cairo_pdf_ft_font_t *font,
unsigned long tag)
{
cairo_status_t status;
unsigned char *buffer;
unsigned long size;
size = 0;
FT_Load_Sfnt_Table (font->face, tag, 0, NULL, &size);
buffer = cairo_pdf_ft_font_write (font, NULL, size);
status = cairo_pdf_ft_font_allocate_write_buffer (font, size, &buffer);
/* XXX: Need to check status here. */
FT_Load_Sfnt_Table (font->face, tag, 0, buffer, &size);
return 0;
@ -376,6 +395,7 @@ static int
cairo_pdf_ft_font_write_glyf_table (cairo_pdf_ft_font_t *font,
unsigned long tag)
{
cairo_status_t status;
unsigned long start_offset, index, size;
TT_Header *header;
unsigned long begin, end;
@ -416,8 +436,8 @@ cairo_pdf_ft_font_write_glyf_table (cairo_pdf_ft_font_t *font,
font->glyphs[i].location =
cairo_pdf_ft_font_align_output (font) - start_offset;
buffer = cairo_pdf_ft_font_write (font, NULL, size);
if (buffer == NULL)
status = cairo_pdf_ft_font_allocate_write_buffer (font, size, &buffer);
if (status)
break;
if (size != 0) {
FT_Load_Sfnt_Table (font->face, TTAG_glyf, begin, buffer, &size);
@ -506,13 +526,16 @@ static int
cairo_pdf_ft_font_write_hmtx_table (cairo_pdf_ft_font_t *font,
unsigned long tag)
{
cairo_status_t status;
unsigned long entry_size;
short *p;
int i;
for (i = 0; i < font->base.num_glyphs; i++) {
entry_size = 2 * sizeof (short);
p = cairo_pdf_ft_font_write (font, NULL, entry_size);
status = cairo_pdf_ft_font_allocate_write_buffer (font, entry_size,
(unsigned char **) &p);
/* XXX: Need to check status here. */
FT_Load_Sfnt_Table (font->face, TTAG_hmtx,
font->glyphs[i].parent_index * entry_size,
(FT_Byte *) p, &entry_size);
@ -597,6 +620,9 @@ static const table_t truetype_tables[] = {
static cairo_status_t
cairo_pdf_ft_font_write_offset_table (cairo_pdf_ft_font_t *font)
{
cairo_status_t status;
unsigned char *table_buffer;
size_t table_buffer_length;
unsigned short search_range, entry_selector, range_shift;
int num_tables;
@ -616,7 +642,14 @@ cairo_pdf_ft_font_write_offset_table (cairo_pdf_ft_font_t *font)
cairo_pdf_ft_font_write_be16 (font, entry_selector);
cairo_pdf_ft_font_write_be16 (font, range_shift);
cairo_pdf_ft_font_write (font, NULL, ARRAY_LENGTH (truetype_tables) * 16);
/* XXX: Why are we allocating a table here and then ignoring the
* returned buffer? This should result in garbage in the output
* file, correct? Is this just unfinished code? -cworth. */
table_buffer_length = ARRAY_LENGTH (truetype_tables) * 16;
status = cairo_pdf_ft_font_allocate_write_buffer (font, table_buffer_length,
&table_buffer);
if (status)
return status;
return font->status;
}

Просмотреть файл

@ -401,7 +401,7 @@ _cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern)
_cairo_ft_unscaled_font_init_key (&key, filename, id);
/* Return exsiting unscaled font if it exists in the hash table. */
/* Return existing unscaled font if it exists in the hash table. */
if (_cairo_hash_table_lookup (font_map->hash_table, &key.base.hash_entry,
(cairo_hash_entry_t **) &unscaled))
{
@ -1890,7 +1890,7 @@ _cairo_ft_ucs4_to_index (void *abstract_font,
static cairo_int_status_t
_cairo_ft_show_glyphs (void *abstract_font,
cairo_operator_t operator,
cairo_operator_t op,
cairo_pattern_t *pattern,
cairo_surface_t *surface,
int source_x,

Просмотреть файл

@ -92,7 +92,11 @@ _cairo_glitz_surface_create_similar (void *abstract_src,
return (cairo_surface_t*) &_cairo_surface_nil;
}
surface = glitz_surface_create (drawable, gformat, width, height, 0, NULL);
surface = glitz_surface_create (drawable, gformat,
width <= 0 ? 1 : width,
height <= 0 ? 1 : height,
0, NULL);
if (surface == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t*) &_cairo_surface_nil;
@ -153,7 +157,7 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
rect_out->height = height;
}
if (surface->format->type == GLITZ_FORMAT_TYPE_COLOR) {
if (surface->format->color.fourcc == GLITZ_FOURCC_RGB) {
if (surface->format->color.red_size > 0) {
format.bpp = 32;
@ -178,6 +182,7 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
format.blue_mask = 0xff;
}
pf.fourcc = GLITZ_FOURCC_RGB;
pf.masks.bpp = format.bpp;
pf.masks.alpha_mask = format.alpha_mask;
pf.masks.red_mask = format.red_mask;
@ -201,6 +206,10 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
return CAIRO_STATUS_NO_MEMORY;
}
/* clear out the glitz clip; the clip affects glitz_get_pixels */
glitz_surface_set_clip_region (surface->surface,
0, 0, NULL, 0);
glitz_get_pixels (surface->surface,
x1, y1,
width, height,
@ -209,6 +218,10 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
glitz_buffer_destroy (buffer);
/* restore the clip, if any */
surface->base.current_clip_serial = 0;
_cairo_surface_set_clip (&surface->base, surface->base.clip);
image = (cairo_image_surface_t *)
_cairo_image_surface_create_with_masks (pixels,
&format,
@ -246,6 +259,7 @@ _cairo_glitz_surface_set_image (void *abstract_surface,
pixman_format_get_masks (format, &pf.masks.bpp, &am, &rm, &gm, &bm);
pf.fourcc = GLITZ_FOURCC_RGB;
pf.masks.alpha_mask = am;
pf.masks.red_mask = rm;
pf.masks.green_mask = gm;
@ -475,7 +489,7 @@ _glitz_ensure_target (glitz_surface_t *surface)
width = glitz_surface_get_width (surface);
height = glitz_surface_get_height (surface);
if (format->type != GLITZ_FORMAT_TYPE_COLOR)
if (format->color.fourcc != GLITZ_FOURCC_RGB)
return CAIRO_INT_STATUS_UNSUPPORTED;
templ.color = format->color;
@ -545,10 +559,10 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
glitz_fixed16_16_t *params;
int n_params;
unsigned int *pixels;
int i;
unsigned char alpha;
int i, n_base_params;
glitz_buffer_t *buffer;
static glitz_pixel_format_t format = {
GLITZ_FOURCC_RGB,
{
32,
0xff000000,
@ -570,41 +584,15 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
if (gradient->n_stops < 2)
break;
/* glitz doesn't support inner and outer circle with different
center points. */
if (pattern->type == CAIRO_PATTERN_RADIAL)
{
cairo_radial_pattern_t *grad = (cairo_radial_pattern_t *) pattern;
if (grad->center0.x != grad->center1.x ||
grad->center0.y != grad->center1.y)
break;
}
if (!CAIRO_GLITZ_FEATURE_OK (dst->surface, FRAGMENT_PROGRAM))
break;
if (pattern->filter != CAIRO_FILTER_BILINEAR &&
pattern->filter != CAIRO_FILTER_GOOD &&
pattern->filter != CAIRO_FILTER_BEST)
break;
if (pattern->type == CAIRO_PATTERN_RADIAL)
n_base_params = 6;
else
n_base_params = 4;
alpha = gradient->stops[0].color.alpha * 0xff;
for (i = 1; i < gradient->n_stops; i++)
{
unsigned char a;
a = gradient->stops[i].color.alpha * 0xff;
if (a != alpha)
break;
}
/* we can't have color stops with different alpha as gradient color
interpolation should be done to unpremultiplied colors. */
if (i < gradient->n_stops)
break;
n_params = gradient->n_stops * 3 + 4;
n_params = gradient->n_stops * 3 + n_base_params;
data = malloc (sizeof (glitz_fixed16_16_t) * n_params +
sizeof (unsigned int) * gradient->n_stops);
@ -636,14 +624,14 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
for (i = 0; i < gradient->n_stops; i++)
{
pixels[i] =
(((int) alpha) << 24) |
(((int) gradient->stops[i].color.red * alpha) << 16) |
(((int) gradient->stops[i].color.green * alpha) << 8) |
(((int) gradient->stops[i].color.blue * alpha));
(((int) (gradient->stops[i].color.alpha >> 8)) << 24) |
(((int) (gradient->stops[i].color.red >> 8)) << 16) |
(((int) (gradient->stops[i].color.green >> 8)) << 8) |
(((int) (gradient->stops[i].color.blue >> 8)));
params[4 + 3 * i] = gradient->stops[i].offset;
params[5 + 3 * i] = i << 16;
params[6 + 3 * i] = 0;
params[n_base_params + 3 * i + 0] = gradient->stops[i].x;
params[n_base_params + 3 * i + 1] = i << 16;
params[n_base_params + 3 * i + 2] = 0;
}
glitz_set_pixels (src->surface, 0, 0, gradient->n_stops, 1,
@ -655,26 +643,28 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
{
cairo_linear_pattern_t *grad = (cairo_linear_pattern_t *) pattern;
params[0] = _cairo_fixed_from_double (grad->point0.x);
params[1] = _cairo_fixed_from_double (grad->point0.y);
params[2] = _cairo_fixed_from_double (grad->point1.x);
params[3] = _cairo_fixed_from_double (grad->point1.y);
params[0] = grad->gradient.p1.x;
params[1] = grad->gradient.p1.y;
params[2] = grad->gradient.p2.x;
params[3] = grad->gradient.p2.y;
attr->filter = GLITZ_FILTER_LINEAR_GRADIENT;
}
else
{
cairo_radial_pattern_t *grad = (cairo_radial_pattern_t *) pattern;
params[0] = _cairo_fixed_from_double (grad->center0.x);
params[1] = _cairo_fixed_from_double (grad->center0.y);
params[2] = _cairo_fixed_from_double (grad->radius0);
params[3] = _cairo_fixed_from_double (grad->radius1);
params[0] = grad->gradient.inner.x;
params[1] = grad->gradient.inner.y;
params[2] = grad->gradient.inner.radius;
params[3] = grad->gradient.outer.x;
params[4] = grad->gradient.outer.y;
params[5] = grad->gradient.outer.radius;
attr->filter = GLITZ_FILTER_RADIAL_GRADIENT;
}
switch (pattern->extend) {
case CAIRO_EXTEND_NONE:
attr->fill = GLITZ_FILL_NEAREST;
attr->fill = GLITZ_FILL_TRANSPARENT;
break;
case CAIRO_EXTEND_REPEAT:
attr->fill = GLITZ_FILL_REPEAT;
@ -682,6 +672,9 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
case CAIRO_EXTEND_REFLECT:
attr->fill = GLITZ_FILL_REFLECT;
break;
case CAIRO_EXTEND_PAD:
attr->fill = GLITZ_FILL_NEAREST;
break;
}
attr->params = params;
@ -717,6 +710,10 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
case CAIRO_EXTEND_REFLECT:
attr->fill = GLITZ_FILL_REFLECT;
break;
case CAIRO_EXTEND_PAD:
default:
attr->fill = GLITZ_FILL_NEAREST;
break;
}
switch (attr->base.filter) {
@ -1008,6 +1005,10 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
cairo_int_status_t status;
unsigned short alpha;
if (antialias != CAIRO_ANTIALIAS_DEFAULT &&
antialias != CAIRO_ANTIALIAS_GRAY)
return CAIRO_INT_STATUS_UNSUPPORTED;
if (dst->base.status)
return dst->base.status;
@ -1818,6 +1819,7 @@ _cairo_glitz_surface_add_glyph (cairo_glitz_surface_t *surface,
pixman_format_get_masks (format, &pf.masks.bpp, &am, &rm, &gm, &bm);
pf.fourcc = GLITZ_FOURCC_RGB;
pf.masks.alpha_mask = am;
pf.masks.red_mask = rm;
pf.masks.green_mask = gm;
@ -1856,18 +1858,18 @@ _cairo_glitz_surface_add_glyph (cairo_glitz_surface_t *surface,
#define N_STACK_BUF 256
static cairo_int_status_t
_cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t op,
cairo_pattern_t *pattern,
void *abstract_surface,
int src_x,
int src_y,
int dst_x,
int dst_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
int num_glyphs)
_cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t op,
cairo_pattern_t *pattern,
void *abstract_surface,
int src_x,
int src_y,
int dst_x,
int dst_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_glitz_surface_attributes_t attributes;
cairo_glitz_surface_glyph_private_t *glyph_private;
@ -2108,6 +2110,16 @@ UNLOCK:
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_glitz_surface_flush (void *abstract_surface)
{
cairo_glitz_surface_t *surface = abstract_surface;
glitz_surface_flush (surface->surface);
return CAIRO_STATUS_SUCCESS;
}
static const cairo_surface_backend_t cairo_glitz_surface_backend = {
_cairo_glitz_surface_create_similar,
_cairo_glitz_surface_finish,
@ -2124,10 +2136,9 @@ static const cairo_surface_backend_t cairo_glitz_surface_backend = {
_cairo_glitz_surface_set_clip_region,
NULL, /* intersect_clip_path */
_cairo_glitz_surface_get_extents,
_cairo_glitz_surface_show_glyphs,
NULL, /* fill_path */
_cairo_glitz_surface_old_show_glyphs,
NULL, /* get_font_options */
NULL, /* flush */
_cairo_glitz_surface_flush,
NULL, /* mark_dirty_rectangle */
_cairo_glitz_surface_scaled_font_fini,
_cairo_glitz_surface_scaled_glyph_fini

Просмотреть файл

@ -39,23 +39,15 @@
#include "cairo-clip-private.h"
struct _cairo_gstate {
cairo_operator_t operator;
cairo_operator_t op;
double tolerance;
cairo_antialias_t antialias;
/* stroke style */
double line_width;
cairo_line_cap_t line_cap;
cairo_line_join_t line_join;
double miter_limit;
cairo_stroke_style_t stroke_style;
cairo_fill_rule_t fill_rule;
double *dash;
int num_dashes;
double dash_offset;
cairo_font_face_t *font_face;
cairo_scaled_font_t *scaled_font; /* Specific to the current CTM */
cairo_matrix_t font_matrix;
@ -63,14 +55,14 @@ struct _cairo_gstate {
cairo_clip_t clip;
cairo_surface_t *target;
cairo_surface_t *target; /* The target to which all rendering is directed */
cairo_surface_t *parent_target; /* The previous target which was receiving rendering */
cairo_surface_t *original_target; /* The original target the initial gstate was created with */
cairo_matrix_t ctm;
cairo_matrix_t ctm_inverse;
cairo_matrix_t source_ctm_inverse; /* At the time ->source was set */
cairo_pen_t pen_regular;
cairo_pattern_t *source;
struct _cairo_gstate *next;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -51,7 +51,7 @@ _cairo_format_bpp (cairo_format_t format)
}
}
static cairo_surface_t *
cairo_surface_t *
_cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
cairo_format_t format)
{
@ -80,6 +80,46 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
return &surface->base;
}
/* Try to recover a cairo_format_t from a pixman_format
* by looking at the bpp and masks values. */
static cairo_format_t
_cairo_format_from_pixman_format (pixman_format_t *pixman_format)
{
int bpp, am, rm, gm, bm;
pixman_format_get_masks (pixman_format, &bpp, &am, &rm, &gm, &bm);
if (bpp == 32 &&
am == 0xff000000 &&
rm == 0x00ff0000 &&
gm == 0x0000ff00 &&
bm == 0x000000ff)
return CAIRO_FORMAT_ARGB32;
if (bpp == 32 &&
am == 0x0 &&
rm == 0x00ff0000 &&
gm == 0x0000ff00 &&
bm == 0x000000ff)
return CAIRO_FORMAT_RGB24;
if (bpp == 8 &&
am == 0xff &&
rm == 0x0 &&
gm == 0x0 &&
bm == 0x0)
return CAIRO_FORMAT_A8;
if (bpp == 1 &&
am == 0x1 &&
rm == 0x0 &&
gm == 0x0 &&
bm == 0x0)
return CAIRO_FORMAT_A1;
return (cairo_format_t) -1;
}
cairo_surface_t *
_cairo_image_surface_create_with_masks (unsigned char *data,
cairo_format_masks_t *format,
@ -90,6 +130,7 @@ _cairo_image_surface_create_with_masks (unsigned char *data,
cairo_surface_t *surface;
pixman_format_t *pixman_format;
pixman_image_t *pixman_image;
cairo_format_t cairo_format;
pixman_format = pixman_format_create_masks (format->bpp,
format->alpha_mask,
@ -102,6 +143,8 @@ _cairo_image_surface_create_with_masks (unsigned char *data,
return (cairo_surface_t*) &_cairo_surface_nil;
}
cairo_format = _cairo_format_from_pixman_format (pixman_format);
pixman_image = pixman_image_create_for_data ((pixman_bits_t *) data, pixman_format,
width, height, format->bpp, stride);
@ -113,7 +156,7 @@ _cairo_image_surface_create_with_masks (unsigned char *data,
}
surface = _cairo_image_surface_create_for_pixman_image (pixman_image,
(cairo_format_t)-1);
cairo_format);
return surface;
}
@ -341,7 +384,7 @@ _cairo_image_surface_create_similar (void *abstract_src,
}
static cairo_status_t
_cairo_image_abstract_surface_finish (void *abstract_surface)
_cairo_image_surface_finish (void *abstract_surface)
{
cairo_image_surface_t *surface = abstract_surface;
@ -433,17 +476,7 @@ _cairo_image_surface_set_matrix (cairo_image_surface_t *surface,
{
pixman_transform_t pixman_transform;
pixman_transform.matrix[0][0] = _cairo_fixed_from_double (matrix->xx);
pixman_transform.matrix[0][1] = _cairo_fixed_from_double (matrix->xy);
pixman_transform.matrix[0][2] = _cairo_fixed_from_double (matrix->x0);
pixman_transform.matrix[1][0] = _cairo_fixed_from_double (matrix->yx);
pixman_transform.matrix[1][1] = _cairo_fixed_from_double (matrix->yy);
pixman_transform.matrix[1][2] = _cairo_fixed_from_double (matrix->y0);
pixman_transform.matrix[2][0] = 0;
pixman_transform.matrix[2][1] = 0;
pixman_transform.matrix[2][2] = _cairo_fixed_from_double (1);
_cairo_matrix_to_pixman_matrix (matrix, &pixman_transform);
pixman_image_set_transform (surface->pixman_image, &pixman_transform);
@ -480,14 +513,6 @@ _cairo_image_surface_set_filter (cairo_image_surface_t *surface, cairo_filter_t
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_image_surface_set_repeat (cairo_image_surface_t *surface, int repeat)
{
pixman_image_set_repeat (surface->pixman_image, repeat);
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_image_surface_set_attributes (cairo_image_surface_t *surface,
cairo_surface_attributes_t *attributes)
@ -500,14 +525,16 @@ _cairo_image_surface_set_attributes (cairo_image_surface_t *surface,
switch (attributes->extend) {
case CAIRO_EXTEND_NONE:
_cairo_image_surface_set_repeat (surface, 0);
pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_NONE);
break;
case CAIRO_EXTEND_REPEAT:
_cairo_image_surface_set_repeat (surface, 1);
pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_NORMAL);
break;
case CAIRO_EXTEND_REFLECT:
/* XXX: Obviously wrong. */
_cairo_image_surface_set_repeat (surface, 1);
pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_REFLECT);
break;
case CAIRO_EXTEND_PAD:
pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_PAD);
break;
}
@ -522,9 +549,9 @@ _cairo_image_surface_set_attributes (cairo_image_surface_t *surface,
* things in pixman I think).
*/
static pixman_operator_t
_pixman_operator (cairo_operator_t operator)
_pixman_operator (cairo_operator_t op)
{
switch (operator) {
switch (op) {
case CAIRO_OPERATOR_CLEAR:
return PIXMAN_OPERATOR_CLEAR;
@ -562,7 +589,7 @@ _pixman_operator (cairo_operator_t operator)
}
static cairo_int_status_t
_cairo_image_surface_composite (cairo_operator_t operator,
_cairo_image_surface_composite (cairo_operator_t op,
cairo_pattern_t *src_pattern,
cairo_pattern_t *mask_pattern,
void *abstract_dst,
@ -602,7 +629,7 @@ _cairo_image_surface_composite (cairo_operator_t operator,
if (status)
goto CLEANUP_SURFACES;
pixman_composite (_pixman_operator (operator),
pixman_composite (_pixman_operator (op),
src->pixman_image,
mask->pixman_image,
dst->pixman_image,
@ -615,7 +642,7 @@ _cairo_image_surface_composite (cairo_operator_t operator,
}
else
{
pixman_composite (_pixman_operator (operator),
pixman_composite (_pixman_operator (op),
src->pixman_image,
NULL,
dst->pixman_image,
@ -626,9 +653,7 @@ _cairo_image_surface_composite (cairo_operator_t operator,
width, height);
}
if (!_cairo_operator_bounded (operator) ||
operator == CAIRO_OPERATOR_SOURCE ||
operator == CAIRO_OPERATOR_CLEAR)
if (!_cairo_operator_bounded_by_source (op))
status = _cairo_surface_composite_fixup_unbounded (&dst->base,
&src_attr, src->width, src->height,
mask ? &mask_attr : NULL,
@ -649,7 +674,7 @@ _cairo_image_surface_composite (cairo_operator_t operator,
static cairo_int_status_t
_cairo_image_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t operator,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects)
@ -664,7 +689,7 @@ _cairo_image_surface_fill_rectangles (void *abstract_surface,
pixman_color.alpha = color->alpha_short;
/* XXX: The pixman_rectangle_t cast is evil... it needs to go away somehow. */
pixman_fill_rectangles (_pixman_operator(operator), surface->pixman_image,
pixman_fill_rectangles (_pixman_operator(op), surface->pixman_image,
&pixman_color, (pixman_rectangle_t *) rects, num_rects);
return CAIRO_STATUS_SUCCESS;
@ -685,7 +710,7 @@ _cairo_image_surface_is_alpha_only (cairo_image_surface_t *surface)
}
static cairo_int_status_t
_cairo_image_surface_composite_trapezoids (cairo_operator_t operator,
_cairo_image_surface_composite_trapezoids (cairo_operator_t op,
cairo_pattern_t *pattern,
void *abstract_dst,
cairo_antialias_t antialias,
@ -721,7 +746,7 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t operator,
* falling through to the general case when the surface is clipped
* since libpixman would have to generate an intermediate mask anyways.
*/
if (operator == CAIRO_OPERATOR_ADD &&
if (op == CAIRO_OPERATOR_ADD &&
_cairo_pattern_is_opaque_solid (pattern) &&
_cairo_image_surface_is_alpha_only (dst) &&
!dst->has_clip &&
@ -781,7 +806,7 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t operator,
pixman_add_trapezoids (mask, - dst_x, - dst_y,
(pixman_trapezoid_t *) traps, num_traps);
pixman_composite (_pixman_operator (operator),
pixman_composite (_pixman_operator (op),
src->pixman_image,
mask,
dst->pixman_image,
@ -791,7 +816,7 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t operator,
dst_x, dst_y,
width, height);
if (!_cairo_operator_bounded (operator))
if (!_cairo_operator_bounded_by_mask (op))
status = _cairo_surface_composite_shape_fixup_unbounded (&dst->base,
&attributes, src->width, src->height,
width, height,
@ -810,18 +835,11 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t operator,
}
static cairo_int_status_t
_cairo_image_abstract_surface_set_clip_region (void *abstract_surface,
pixman_region16_t *region)
_cairo_image_surface_set_clip_region (void *abstract_surface,
pixman_region16_t *region)
{
cairo_image_surface_t *surface = (cairo_image_surface_t *) abstract_surface;
return _cairo_image_surface_set_clip_region (surface, region);
}
cairo_int_status_t
_cairo_image_surface_set_clip_region (cairo_image_surface_t *surface,
pixman_region16_t *region)
{
pixman_image_set_clip_region (surface->pixman_image, region);
surface->has_clip = region != NULL;
@ -830,9 +848,11 @@ _cairo_image_surface_set_clip_region (cairo_image_surface_t *surface,
}
static cairo_int_status_t
_cairo_image_surface_get_extents (cairo_image_surface_t *surface,
_cairo_image_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
{
cairo_image_surface_t *surface = abstract_surface;
rectangle->x = 0;
rectangle->y = 0;
rectangle->width = surface->width;
@ -841,15 +861,6 @@ _cairo_image_surface_get_extents (cairo_image_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_image_abstract_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
{
cairo_image_surface_t *surface = abstract_surface;
return _cairo_image_surface_get_extents (surface, rectangle);
}
/**
* _cairo_surface_is_image:
* @surface: a #cairo_surface_t
@ -859,14 +870,14 @@ _cairo_image_abstract_surface_get_extents (void *abstract_surface,
* Return value: TRUE if the surface is an image surface
**/
cairo_bool_t
_cairo_surface_is_image (cairo_surface_t *surface)
_cairo_surface_is_image (const cairo_surface_t *surface)
{
return surface->backend == &cairo_image_surface_backend;
}
const cairo_surface_backend_t cairo_image_surface_backend = {
_cairo_image_surface_create_similar,
_cairo_image_abstract_surface_finish,
_cairo_image_surface_finish,
_cairo_image_surface_acquire_source_image,
_cairo_image_surface_release_source_image,
_cairo_image_surface_acquire_dest_image,
@ -877,8 +888,8 @@ const cairo_surface_backend_t cairo_image_surface_backend = {
_cairo_image_surface_composite_trapezoids,
NULL, /* copy_page */
NULL, /* show_page */
_cairo_image_abstract_surface_set_clip_region,
_cairo_image_surface_set_clip_region,
NULL, /* intersect_clip_path */
_cairo_image_abstract_surface_get_extents,
NULL /* show_glyphs */
_cairo_image_surface_get_extents,
NULL /* old_show_glyphs */
};

Просмотреть файл

@ -700,3 +700,20 @@ _cairo_matrix_transformed_circle_major_axis (cairo_matrix_t *matrix, double radi
* double min = radius * sqrt (f - sqrt (g*g+h*h));
*/
}
void
_cairo_matrix_to_pixman_matrix (const cairo_matrix_t *matrix,
pixman_transform_t *pixman_transform)
{
pixman_transform->matrix[0][0] = _cairo_fixed_from_double (matrix->xx);
pixman_transform->matrix[0][1] = _cairo_fixed_from_double (matrix->xy);
pixman_transform->matrix[0][2] = _cairo_fixed_from_double (matrix->x0);
pixman_transform->matrix[1][0] = _cairo_fixed_from_double (matrix->yx);
pixman_transform->matrix[1][1] = _cairo_fixed_from_double (matrix->yy);
pixman_transform->matrix[1][2] = _cairo_fixed_from_double (matrix->y0);
pixman_transform->matrix[2][0] = 0;
pixman_transform->matrix[2][1] = 0;
pixman_transform->matrix[2][2] = _cairo_fixed_from_double (1);
}

Просмотреть файл

@ -40,59 +40,66 @@
#include "cairo-path-fixed-private.h"
typedef enum {
CAIRO_COMMAND_COMPOSITE,
CAIRO_COMMAND_FILL_RECTANGLES,
CAIRO_COMMAND_COMPOSITE_TRAPEZOIDS,
CAIRO_COMMAND_SET_CLIP_REGION,
CAIRO_COMMAND_INTERSECT_CLIP_PATH,
/* The 5 basic drawing operations. */
CAIRO_COMMAND_PAINT,
CAIRO_COMMAND_MASK,
CAIRO_COMMAND_STROKE,
CAIRO_COMMAND_FILL,
CAIRO_COMMAND_SHOW_GLYPHS,
CAIRO_COMMAND_FILL_PATH
/* Other junk. For most of these, we should be able to assert that
* they never get called except as part of fallbacks for the 5
* basic drawing operations (which we implement already so the
* fallbacks should never get triggered). So the plan is to
* eliminate as many of these as possible. */
CAIRO_COMMAND_INTERSECT_CLIP_PATH,
} cairo_command_type_t;
typedef struct _cairo_command_composite {
cairo_command_type_t type;
cairo_operator_t operator;
cairo_pattern_union_t src_pattern;
cairo_pattern_union_t mask_pattern;
cairo_pattern_t *mask_pattern_pointer;
int src_x;
int src_y;
int mask_x;
int mask_y;
int dst_x;
int dst_y;
unsigned int width;
unsigned int height;
} cairo_command_composite_t;
typedef struct _cairo_command_paint {
cairo_command_type_t type;
cairo_operator_t op;
cairo_pattern_union_t source;
} cairo_command_paint_t;
typedef struct _cairo_command_fill_rectangles {
cairo_command_type_t type;
cairo_operator_t operator;
cairo_color_t color;
cairo_rectangle_t *rects;
int num_rects;
} cairo_command_fill_rectangles_t;
typedef struct _cairo_command_mask {
cairo_command_type_t type;
cairo_operator_t op;
cairo_pattern_union_t source;
cairo_pattern_union_t mask;
} cairo_command_mask_t;
typedef struct _cairo_command_composite_trapezoids {
cairo_command_type_t type;
cairo_operator_t operator;
cairo_pattern_union_t pattern;
cairo_antialias_t antialias;
int x_src;
int y_src;
int x_dst;
int y_dst;
unsigned int width;
unsigned int height;
cairo_trapezoid_t *traps;
int num_traps;
} cairo_command_composite_trapezoids_t;
typedef struct _cairo_command_stroke {
cairo_command_type_t type;
cairo_operator_t op;
cairo_pattern_union_t source;
cairo_path_fixed_t path;
cairo_stroke_style_t style;
cairo_matrix_t ctm;
cairo_matrix_t ctm_inverse;
double tolerance;
cairo_antialias_t antialias;
} cairo_command_stroke_t;
typedef struct _cairo_command_set_clip_region {
cairo_command_type_t type;
pixman_region16_t *region;
unsigned int serial;
} cairo_command_set_clip_region_t;
typedef struct _cairo_command_fill {
cairo_command_type_t type;
cairo_operator_t op;
cairo_pattern_union_t source;
cairo_path_fixed_t path;
cairo_fill_rule_t fill_rule;
double tolerance;
cairo_antialias_t antialias;
} cairo_command_fill_t;
typedef struct _cairo_command_show_glyphs {
cairo_command_type_t type;
cairo_operator_t op;
cairo_pattern_union_t source;
cairo_glyph_t *glyphs;
int num_glyphs;
cairo_scaled_font_t *scaled_font;
} cairo_command_show_glyphs_t;
typedef struct _cairo_command_intersect_clip_path {
cairo_command_type_t type;
@ -103,53 +110,41 @@ typedef struct _cairo_command_intersect_clip_path {
cairo_antialias_t antialias;
} cairo_command_intersect_clip_path_t;
typedef struct _cairo_command_show_glyphs {
cairo_command_type_t type;
cairo_scaled_font_t *scaled_font;
cairo_operator_t operator;
cairo_pattern_union_t pattern;
int source_x;
int source_y;
int dest_x;
int dest_y;
unsigned int width;
unsigned int height;
cairo_glyph_t *glyphs;
int num_glyphs;
} cairo_command_show_glyphs_t;
typedef struct _cairo_command_fill_path {
cairo_command_type_t type;
cairo_operator_t operator;
cairo_pattern_union_t pattern;
cairo_path_fixed_t path;
cairo_fill_rule_t fill_rule;
double tolerance;
cairo_antialias_t antialias;
} cairo_command_fill_path_t;
typedef union _cairo_command {
cairo_command_type_t type;
cairo_command_composite_t composite;
cairo_command_fill_rectangles_t fill_rectangles;
cairo_command_composite_trapezoids_t composite_trapezoids;
cairo_command_set_clip_region_t set_clip_region;
cairo_command_intersect_clip_path_t intersect_clip_path;
/* The 5 basic drawing operations. */
cairo_command_paint_t paint;
cairo_command_mask_t mask;
cairo_command_stroke_t stroke;
cairo_command_fill_t fill;
cairo_command_show_glyphs_t show_glyphs;
cairo_command_fill_path_t fill_path;
/* The other junk. */
cairo_command_intersect_clip_path_t intersect_clip_path;
} cairo_command_t;
typedef struct _cairo_meta_surface {
cairo_surface_t base;
double width, height;
/* A meta-surface is logically unbounded, but when used as a
* source we need to render it to an image, so we need a size at
* which to create that image. */
int width_pixels;
int height_pixels;
cairo_array_t commands;
cairo_surface_t *commands_owner;
} cairo_meta_surface_t;
cairo_private cairo_surface_t *
_cairo_meta_surface_create (double width, double height);
_cairo_meta_surface_create (int width_pixels, int height_pixels);
cairo_private cairo_int_status_t
cairo_private cairo_status_t
_cairo_meta_surface_replay (cairo_surface_t *surface,
cairo_surface_t *target);
cairo_private cairo_bool_t
_cairo_surface_is_meta (const cairo_surface_t *surface);
#endif /* CAIRO_META_SURFACE_H */

Просмотреть файл

@ -31,16 +31,36 @@
*
* Contributor(s):
* Kristian Høgsberg <krh@redhat.com>
* Carl Worth <cworth@cworth.org>
*/
/* A meta surface is a surface that records all drawing operations at
* the highest level of the surface backend interface, (that is, the
* level of paint, mask, stroke, fill, and show_glyphs). The meta
* surface can then be "replayed" against any target surface with:
*
* _cairo_meta_surface_replay (meta, target);
*
* after which the results in target will be identical to the results
* that would have been obtained if the original operations applied to
* the meta surface had instead been applied to the target surface.
*
* The recording phase of the meta surface is careful to snapshot all
* necessary objects (paths, patterns, etc.), in order to acheive
* accurate replay. The efficiency of the meta surface could be
* improved by improving the implementation of snapshot for the
* various objects. For example, it would be nice to have a
* copy-on-write implementation for _cairo_surface_snapshot.
*/
#include "cairoint.h"
#include "cairo-meta-surface-private.h"
#include "cairo-gstate-private.h"
#include "cairo-clip-private.h"
static const cairo_surface_backend_t cairo_meta_surface_backend;
cairo_surface_t *
_cairo_meta_surface_create (double width, double height)
_cairo_meta_surface_create (int width_pixels, int height_pixels)
{
cairo_meta_surface_t *meta;
@ -50,10 +70,13 @@ _cairo_meta_surface_create (double width, double height)
return (cairo_surface_t*) &_cairo_surface_nil;
}
meta->width = width;
meta->height = height;
_cairo_surface_init (&meta->base, &cairo_meta_surface_backend);
meta->width_pixels = width_pixels;
meta->height_pixels = height_pixels;
_cairo_array_init (&meta->commands, sizeof (cairo_command_t *));
meta->commands_owner = NULL;
return &meta->base;
}
@ -75,45 +98,54 @@ _cairo_meta_surface_finish (void *abstract_surface)
cairo_command_t **elements;
int i, num_elements;
if (meta->commands_owner) {
cairo_surface_destroy (meta->commands_owner);
return CAIRO_STATUS_SUCCESS;
}
num_elements = meta->commands.num_elements;
elements = (cairo_command_t **) meta->commands.elements;
elements = _cairo_array_index (&meta->commands, 0);
for (i = 0; i < num_elements; i++) {
command = elements[i];
switch (command->type) {
case CAIRO_COMMAND_COMPOSITE:
_cairo_pattern_fini (&command->composite.src_pattern.base);
if (command->composite.mask_pattern_pointer)
_cairo_pattern_fini (command->composite.mask_pattern_pointer);
/* 5 basic drawing operations */
case CAIRO_COMMAND_PAINT:
_cairo_pattern_fini (&command->paint.source.base);
free (command);
break;
case CAIRO_COMMAND_FILL_RECTANGLES:
free (command->fill_rectangles.rects);
case CAIRO_COMMAND_MASK:
_cairo_pattern_fini (&command->mask.source.base);
_cairo_pattern_fini (&command->mask.mask.base);
free (command);
break;
case CAIRO_COMMAND_STROKE:
_cairo_pattern_fini (&command->stroke.source.base);
_cairo_path_fixed_fini (&command->stroke.path);
_cairo_stroke_style_fini (&command->stroke.style);
free (command);
break;
case CAIRO_COMMAND_COMPOSITE_TRAPEZOIDS:
_cairo_pattern_fini (&command->composite_trapezoids.pattern.base);
free (command->composite_trapezoids.traps);
free (command);
break;
case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
if (command->intersect_clip_path.path_pointer)
_cairo_path_fixed_fini (&command->intersect_clip_path.path);
case CAIRO_COMMAND_FILL:
_cairo_pattern_fini (&command->fill.source.base);
_cairo_path_fixed_fini (&command->fill.path);
free (command);
break;
case CAIRO_COMMAND_SHOW_GLYPHS:
cairo_scaled_font_destroy (command->show_glyphs.scaled_font);
_cairo_pattern_fini (&command->show_glyphs.pattern.base);
_cairo_pattern_fini (&command->show_glyphs.source.base);
free (command->show_glyphs.glyphs);
cairo_scaled_font_destroy (command->show_glyphs.scaled_font);
free (command);
break;
case CAIRO_COMMAND_FILL_PATH:
_cairo_pattern_fini (&command->fill_path.pattern.base);
_cairo_path_fixed_fini (&command->fill_path.path);
/* Other junk. */
case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
if (command->intersect_clip_path.path_pointer)
_cairo_path_fixed_fini (&command->intersect_clip_path.path);
free (command);
break;
@ -127,142 +159,322 @@ _cairo_meta_surface_finish (void *abstract_surface)
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_meta_surface_composite (cairo_operator_t operator,
cairo_pattern_t *src_pattern,
cairo_pattern_t *mask_pattern,
void *abstract_surface,
int src_x,
int src_y,
int mask_x,
int mask_y,
int dst_x,
int dst_y,
unsigned int width,
unsigned int height)
static cairo_status_t
_cairo_meta_surface_acquire_source_image (void *abstract_surface,
cairo_image_surface_t **image_out,
void **image_extra)
{
cairo_meta_surface_t *meta = abstract_surface;
cairo_command_composite_t *command;
cairo_status_t status;
cairo_meta_surface_t *surface = abstract_surface;
cairo_surface_t *image;
command = malloc (sizeof (cairo_command_composite_t));
if (command == NULL)
return CAIRO_STATUS_NO_MEMORY;
image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
surface->width_pixels,
surface->height_pixels);
command->type = CAIRO_COMMAND_COMPOSITE;
command->operator = operator;
_cairo_pattern_init_copy (&command->src_pattern.base, src_pattern);
if (mask_pattern) {
_cairo_pattern_init_copy (&command->mask_pattern.base, mask_pattern);
command->mask_pattern_pointer = &command->mask_pattern.base;
} else {
command->mask_pattern_pointer = NULL;
status = _cairo_meta_surface_replay (&surface->base, image);
if (status) {
cairo_surface_destroy (image);
return status;
}
command->src_x = src_x;
command->src_y = src_y;
command->mask_x = mask_x;
command->mask_y = mask_y;
command->dst_x = dst_x;
command->dst_y = dst_y;
command->width = width;
command->height = height;
if (_cairo_array_append (&meta->commands, &command, 1) == NULL) {
_cairo_pattern_fini (&command->src_pattern.base);
_cairo_pattern_fini (command->mask_pattern_pointer);
free (command);
return CAIRO_STATUS_NO_MEMORY;
*image_out = (cairo_image_surface_t *) image;
*image_extra = NULL;
return status;
}
static void
_cairo_meta_surface_release_source_image (void *abstract_surface,
cairo_image_surface_t *image,
void *image_extra)
{
cairo_surface_destroy (&image->base);
}
static cairo_status_t
_init_pattern_with_snapshot (cairo_pattern_t *pattern,
const cairo_pattern_t *other)
{
_cairo_pattern_init_copy (pattern, other);
if (pattern->type == CAIRO_PATTERN_SURFACE) {
cairo_surface_pattern_t *surface_pattern =
(cairo_surface_pattern_t *) pattern;
cairo_surface_t *surface = surface_pattern->surface;
surface_pattern->surface = _cairo_surface_snapshot (surface);
cairo_surface_destroy (surface);
if (surface_pattern->surface->status)
return surface_pattern->surface->status;
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_meta_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t operator,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects)
_cairo_meta_surface_paint (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source)
{
cairo_status_t status;
cairo_meta_surface_t *meta = abstract_surface;
cairo_command_fill_rectangles_t *command;
cairo_command_paint_t *command;
command = malloc (sizeof (cairo_command_fill_rectangles_t));
command = malloc (sizeof (cairo_command_paint_t));
if (command == NULL)
return CAIRO_STATUS_NO_MEMORY;
command->type = CAIRO_COMMAND_FILL_RECTANGLES;
command->operator = operator;
command->color = *color;
command->type = CAIRO_COMMAND_PAINT;
command->op = op;
command->rects = malloc (sizeof (cairo_rectangle_t) * num_rects);
if (command->rects == NULL) {
free (command);
return CAIRO_STATUS_NO_MEMORY;
}
memcpy (command->rects, rects, sizeof (cairo_rectangle_t) * num_rects);
command->num_rects = num_rects;
if (_cairo_array_append (&meta->commands, &command, 1) == NULL) {
free (command->rects);
free (command);
return CAIRO_STATUS_NO_MEMORY;
}
status = _init_pattern_with_snapshot (&command->source.base, source);
if (status)
goto CLEANUP_COMMAND;
status = _cairo_array_append (&meta->commands, &command);
if (status)
goto CLEANUP_SOURCE;
return CAIRO_STATUS_SUCCESS;
CLEANUP_SOURCE:
_cairo_pattern_fini (&command->source.base);
CLEANUP_COMMAND:
free (command);
return status;
}
static cairo_int_status_t
_cairo_meta_surface_composite_trapezoids (cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_surface,
cairo_antialias_t antialias,
int x_src,
int y_src,
int x_dst,
int y_dst,
unsigned int width,
unsigned int height,
cairo_trapezoid_t *traps,
int num_traps)
_cairo_meta_surface_mask (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_pattern_t *mask)
{
cairo_status_t status;
cairo_meta_surface_t *meta = abstract_surface;
cairo_command_composite_trapezoids_t *command;
cairo_command_mask_t *command;
command = malloc (sizeof (cairo_command_composite_trapezoids_t));
command = malloc (sizeof (cairo_command_mask_t));
if (command == NULL)
return CAIRO_STATUS_NO_MEMORY;
command->type = CAIRO_COMMAND_COMPOSITE_TRAPEZOIDS;
command->operator = operator;
_cairo_pattern_init_copy (&command->pattern.base, pattern);
command->type = CAIRO_COMMAND_MASK;
command->op = op;
status = _init_pattern_with_snapshot (&command->source.base, source);
if (status)
goto CLEANUP_COMMAND;
status = _init_pattern_with_snapshot (&command->mask.base, mask);
if (status)
goto CLEANUP_SOURCE;
status = _cairo_array_append (&meta->commands, &command);
if (status)
goto CLEANUP_MASK;
return CAIRO_STATUS_SUCCESS;
CLEANUP_MASK:
_cairo_pattern_fini (&command->mask.base);
CLEANUP_SOURCE:
_cairo_pattern_fini (&command->source.base);
CLEANUP_COMMAND:
free (command);
return status;
}
static cairo_int_status_t
_cairo_meta_surface_stroke (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_stroke_style_t *style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias)
{
cairo_status_t status;
cairo_meta_surface_t *meta = abstract_surface;
cairo_command_stroke_t *command;
command = malloc (sizeof (cairo_command_stroke_t));
if (command == NULL)
return CAIRO_STATUS_NO_MEMORY;
command->type = CAIRO_COMMAND_STROKE;
command->op = op;
status = _init_pattern_with_snapshot (&command->source.base, source);
if (status)
goto CLEANUP_COMMAND;
status = _cairo_path_fixed_init_copy (&command->path, path);
if (status)
goto CLEANUP_SOURCE;
status = _cairo_stroke_style_init_copy (&command->style, style);
if (status)
goto CLEANUP_PATH;
command->ctm = *ctm;
command->ctm_inverse = *ctm_inverse;
command->tolerance = tolerance;
command->antialias = antialias;
command->x_src = x_src;
command->y_src = y_src;
command->x_dst = x_dst;
command->y_dst = y_dst;
command->width = width;
command->height = height;
command->traps = malloc (sizeof (cairo_trapezoid_t) * num_traps);
if (command->traps == NULL) {
_cairo_pattern_fini (&command->pattern.base);
free (command);
return CAIRO_STATUS_NO_MEMORY;
}
memcpy (command->traps, traps, sizeof (cairo_trapezoid_t) * num_traps);
command->num_traps = num_traps;
if (_cairo_array_append (&meta->commands, &command, 1) == NULL) {
_cairo_pattern_fini (&command->pattern.base);
free (command->traps);
free (command);
return CAIRO_STATUS_NO_MEMORY;
}
status = _cairo_array_append (&meta->commands, &command);
if (status)
goto CLEANUP_STYLE;
return CAIRO_STATUS_SUCCESS;
CLEANUP_STYLE:
_cairo_stroke_style_fini (&command->style);
CLEANUP_PATH:
_cairo_path_fixed_fini (&command->path);
CLEANUP_SOURCE:
_cairo_pattern_fini (&command->source.base);
CLEANUP_COMMAND:
free (command);
return status;
}
static cairo_int_status_t
_cairo_meta_surface_fill (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias)
{
cairo_status_t status;
cairo_meta_surface_t *meta = abstract_surface;
cairo_command_fill_t *command;
command = malloc (sizeof (cairo_command_fill_t));
if (command == NULL)
return CAIRO_STATUS_NO_MEMORY;
command->type = CAIRO_COMMAND_FILL;
command->op = op;
status = _init_pattern_with_snapshot (&command->source.base, source);
if (status)
goto CLEANUP_COMMAND;
status = _cairo_path_fixed_init_copy (&command->path, path);
if (status)
goto CLEANUP_SOURCE;
command->fill_rule = fill_rule;
command->tolerance = tolerance;
command->antialias = antialias;
status = _cairo_array_append (&meta->commands, &command);
if (status)
goto CLEANUP_PATH;
return CAIRO_STATUS_SUCCESS;
CLEANUP_PATH:
_cairo_path_fixed_fini (&command->path);
CLEANUP_SOURCE:
_cairo_pattern_fini (&command->source.base);
CLEANUP_COMMAND:
free (command);
return status;
}
static cairo_int_status_t
_cairo_meta_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{
cairo_status_t status;
cairo_meta_surface_t *meta = abstract_surface;
cairo_command_show_glyphs_t *command;
command = malloc (sizeof (cairo_command_show_glyphs_t));
if (command == NULL)
return CAIRO_STATUS_NO_MEMORY;
command->type = CAIRO_COMMAND_SHOW_GLYPHS;
command->op = op;
status = _init_pattern_with_snapshot (&command->source.base, source);
if (status)
goto CLEANUP_COMMAND;
command->glyphs = malloc (sizeof (cairo_glyph_t) * num_glyphs);
if (command->glyphs == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto CLEANUP_SOURCE;
}
memcpy (command->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
command->num_glyphs = num_glyphs;
command->scaled_font = cairo_scaled_font_reference (scaled_font);
status = _cairo_array_append (&meta->commands, &command);
if (status)
goto CLEANUP_SCALED_FONT;
return CAIRO_STATUS_SUCCESS;
CLEANUP_SCALED_FONT:
cairo_scaled_font_destroy (command->scaled_font);
free (command->glyphs);
CLEANUP_SOURCE:
_cairo_pattern_fini (&command->source.base);
CLEANUP_COMMAND:
free (command);
return status;
}
/**
* _cairo_meta_surface_snapshot
* @surface: a #cairo_surface_t which must be a meta surface
*
* Make an immutable copy of @surface. It is an error to call a
* surface-modifying function on the result of this function.
*
* The caller owns the return value and should call
* cairo_surface_destroy when finished with it. This function will not
* return NULL, but will return a nil surface instead.
*
* Return value: The snapshot surface.
**/
static cairo_surface_t *
_cairo_meta_surface_snapshot (void *abstract_other)
{
cairo_meta_surface_t *other = abstract_other;
cairo_meta_surface_t *meta;
meta = malloc (sizeof (cairo_meta_surface_t));
if (meta == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t*) &_cairo_surface_nil;
}
_cairo_surface_init (&meta->base, &cairo_meta_surface_backend);
meta->base.is_snapshot = TRUE;
meta->width_pixels = other->width_pixels;
meta->height_pixels = other->height_pixels;
_cairo_array_init_snapshot (&meta->commands, &other->commands);
meta->commands_owner = cairo_surface_reference (&other->base);
return &meta->base;
}
static cairo_int_status_t
@ -296,146 +508,88 @@ _cairo_meta_surface_intersect_clip_path (void *dst,
command->tolerance = tolerance;
command->antialias = antialias;
if (_cairo_array_append (&meta->commands, &command, 1) == NULL) {
status = _cairo_array_append (&meta->commands, &command);
if (status) {
if (path)
_cairo_path_fixed_fini (&command->path);
free (command);
return CAIRO_STATUS_NO_MEMORY;
return status;
}
return CAIRO_STATUS_SUCCESS;
}
/* A meta-surface is logically unbounded, but when it is used as a
* source, the drawing code can optimize based on the extents of the
* surface.
*
* XXX: The optimization being attempted here would only actually work
* if the meta-surface kept track of its extents as commands were
* added to it.
*/
static cairo_int_status_t
_cairo_meta_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
_cairo_meta_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
{
cairo_meta_surface_t *meta = abstract_surface;
/* Currently this is used for getting the extents of the surface
* before calling cairo_paint(). This is the only this that
* requires the meta surface to have an explicit size. If paint
* was just a backend function, this would not be necessary. */
rectangle->x = 0;
rectangle->y = 0;
rectangle->width = meta->width;
rectangle->height = meta->height;
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_meta_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_surface,
int source_x,
int source_y,
int dest_x,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_meta_surface_t *meta = abstract_surface;
cairo_command_show_glyphs_t *command;
command = malloc (sizeof (cairo_command_show_glyphs_t));
if (command == NULL)
return CAIRO_STATUS_NO_MEMORY;
command->type = CAIRO_COMMAND_SHOW_GLYPHS;
command->scaled_font = cairo_scaled_font_reference (scaled_font);
command->operator = operator;
_cairo_pattern_init_copy (&command->pattern.base, pattern);
command->source_x = source_x;
command->source_y = source_y;
command->dest_x = dest_x;
command->dest_y = dest_y;
command->width = width;
command->height = height;
command->glyphs = malloc (sizeof (cairo_glyph_t) * num_glyphs);
if (command->glyphs == NULL) {
_cairo_pattern_fini (&command->pattern.base);
free (command);
return CAIRO_STATUS_NO_MEMORY;
}
memcpy (command->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
command->num_glyphs = num_glyphs;
if (_cairo_array_append (&meta->commands, &command, 1) == NULL) {
_cairo_pattern_fini (&command->pattern.base);
free (command->glyphs);
free (command);
return CAIRO_STATUS_NO_MEMORY;
}
rectangle->width = CAIRO_MAXSHORT;
rectangle->height = CAIRO_MAXSHORT;
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_meta_surface_fill_path (cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_surface,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance)
/**
* _cairo_surface_is_meta:
* @surface: a #cairo_surface_t
*
* Checks if a surface is a #cairo_meta_surface_t
*
* Return value: TRUE if the surface is a meta surface
**/
cairo_bool_t
_cairo_surface_is_meta (const cairo_surface_t *surface)
{
cairo_meta_surface_t *meta = abstract_surface;
cairo_command_fill_path_t *command;
cairo_status_t status;
command = malloc (sizeof (cairo_command_fill_path_t));
if (command == NULL)
return CAIRO_STATUS_NO_MEMORY;
command->type = CAIRO_COMMAND_FILL_PATH;
command->operator = operator;
_cairo_pattern_init_copy (&command->pattern.base, pattern);
status = _cairo_path_fixed_init_copy (&command->path, path);
if (status) {
_cairo_pattern_fini (&command->pattern.base);
free (command);
return CAIRO_STATUS_NO_MEMORY;
}
command->fill_rule = fill_rule;
command->tolerance = tolerance;
if (_cairo_array_append (&meta->commands, &command, 1) == NULL) {
_cairo_path_fixed_fini (&command->path);
_cairo_pattern_fini (&command->pattern.base);
free (command);
return CAIRO_STATUS_NO_MEMORY;
}
return CAIRO_STATUS_SUCCESS;
return surface->backend == &cairo_meta_surface_backend;
}
static const cairo_surface_backend_t cairo_meta_surface_backend = {
_cairo_meta_surface_create_similar,
_cairo_meta_surface_finish,
NULL, /* acquire_source_image */
NULL, /* release_source_image */
_cairo_meta_surface_acquire_source_image,
_cairo_meta_surface_release_source_image,
NULL, /* acquire_dest_image */
NULL, /* release_dest_image */
NULL, /* clone_similar */
_cairo_meta_surface_composite,
_cairo_meta_surface_fill_rectangles,
_cairo_meta_surface_composite_trapezoids,
NULL, /* composite */
NULL, /* fill_rectangles */
NULL, /* composite_trapezoids */
NULL, /* copy_page */
NULL, /* show_page */
NULL, /* set_clip_region */
_cairo_meta_surface_intersect_clip_path,
_cairo_meta_surface_get_extents,
NULL, /* old_show_glyphs */
NULL, /* get_font_options */
NULL, /* flush */
NULL, /* mark_dirty_rectangle */
NULL, /* scaled_font_fini */
NULL, /* scaled_glyph_fini */
/* Here are the 5 basic drawing operations, (which are in some
* sense the only things that cairo_meta_surface should need to
* implement). */
_cairo_meta_surface_paint,
_cairo_meta_surface_mask,
_cairo_meta_surface_stroke,
_cairo_meta_surface_fill,
_cairo_meta_surface_show_glyphs,
_cairo_meta_surface_fill_path,
_cairo_meta_surface_snapshot
};
cairo_int_status_t
cairo_status_t
_cairo_meta_surface_replay (cairo_surface_t *surface,
cairo_surface_t *target)
{
@ -443,7 +597,6 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
cairo_command_t *command, **elements;
int i, num_elements;
cairo_int_status_t status;
cairo_traps_t traps;
cairo_clip_t clip;
meta = (cairo_meta_surface_t *) surface;
@ -452,61 +605,72 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
_cairo_clip_init (&clip, target);
num_elements = meta->commands.num_elements;
elements = (cairo_command_t **) meta->commands.elements;
elements = _cairo_array_index (&meta->commands, 0);
for (i = 0; i < num_elements; i++) {
command = elements[i];
switch (command->type) {
case CAIRO_COMMAND_COMPOSITE:
case CAIRO_COMMAND_PAINT:
status = _cairo_surface_set_clip (target, &clip);
if (status)
break;
status = _cairo_surface_composite
(command->composite.operator,
&command->composite.src_pattern.base,
command->composite.mask_pattern_pointer,
target,
command->composite.src_x,
command->composite.src_y,
command->composite.mask_x,
command->composite.mask_y,
command->composite.dst_x,
command->composite.dst_y,
command->composite.width,
command->composite.height);
status = _cairo_surface_paint (target,
command->paint.op,
&command->paint.source.base);
break;
case CAIRO_COMMAND_FILL_RECTANGLES:
case CAIRO_COMMAND_MASK:
status = _cairo_surface_set_clip (target, &clip);
if (status)
break;
status = _cairo_surface_fill_rectangles
(target,
command->fill_rectangles.operator,
&command->fill_rectangles.color,
command->fill_rectangles.rects,
command->fill_rectangles.num_rects);
status = _cairo_surface_mask (target,
command->mask.op,
&command->mask.source.base,
&command->mask.mask.base);
break;
case CAIRO_COMMAND_COMPOSITE_TRAPEZOIDS:
case CAIRO_COMMAND_STROKE:
status = _cairo_surface_set_clip (target, &clip);
if (status)
break;
status = _cairo_surface_composite_trapezoids
(command->composite_trapezoids.operator,
&command->composite_trapezoids.pattern.base,
target,
command->composite_trapezoids.antialias,
command->composite_trapezoids.x_src,
command->composite_trapezoids.y_src,
command->composite_trapezoids.x_dst,
command->composite_trapezoids.y_dst,
command->composite_trapezoids.width,
command->composite_trapezoids.height,
command->composite_trapezoids.traps,
command->composite_trapezoids.num_traps);
status = _cairo_surface_stroke (target,
command->stroke.op,
&command->stroke.source.base,
&command->stroke.path,
&command->stroke.style,
&command->stroke.ctm,
&command->stroke.ctm_inverse,
command->stroke.tolerance,
command->stroke.antialias);
break;
case CAIRO_COMMAND_FILL:
status = _cairo_surface_set_clip (target, &clip);
if (status)
break;
status = _cairo_surface_fill (target,
command->fill.op,
&command->fill.source.base,
&command->fill.path,
command->fill.fill_rule,
command->fill.tolerance,
command->fill.antialias);
break;
case CAIRO_COMMAND_SHOW_GLYPHS:
status = _cairo_surface_set_clip (target, &clip);
if (status)
break;
status = _cairo_surface_show_glyphs (target,
command->show_glyphs.op,
&command->show_glyphs.source.base,
command->show_glyphs.glyphs,
command->show_glyphs.num_glyphs,
command->show_glyphs.scaled_font);
break;
case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
@ -523,78 +687,6 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
target);
break;
case CAIRO_COMMAND_SHOW_GLYPHS:
status = _cairo_surface_set_clip (target, &clip);
if (status)
break;
status = _cairo_surface_show_glyphs
(command->show_glyphs.scaled_font,
command->show_glyphs.operator,
&command->show_glyphs.pattern.base,
target,
command->show_glyphs.source_x,
command->show_glyphs.source_y,
command->show_glyphs.dest_x,
command->show_glyphs.dest_y,
command->show_glyphs.width,
command->show_glyphs.height,
command->show_glyphs.glyphs,
command->show_glyphs.num_glyphs);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
break;
status = (*command->show_glyphs.scaled_font->backend->
show_glyphs) (command->show_glyphs.scaled_font,
command->show_glyphs.operator,
&command->show_glyphs.pattern.base,
target,
command->show_glyphs.source_x,
command->show_glyphs.source_y,
command->show_glyphs.dest_x,
command->show_glyphs.dest_y,
command->show_glyphs.width,
command->show_glyphs.height,
command->show_glyphs.glyphs,
command->show_glyphs.num_glyphs);
break;
case CAIRO_COMMAND_FILL_PATH:
status = _cairo_surface_set_clip (target, &clip);
if (status)
break;
status = _cairo_surface_fill_path (command->fill_path.operator,
&command->fill_path.pattern.base,
target,
&command->fill_path.path,
command->fill_path.fill_rule,
command->fill_path.tolerance);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
break;
_cairo_traps_init (&traps);
status = _cairo_path_fixed_fill_to_traps (&command->fill_path.path,
command->fill_path.fill_rule,
command->fill_path.tolerance,
&traps);
if (status) {
_cairo_traps_fini (&traps);
break;
}
status = _cairo_surface_clip_and_composite_trapezoids (&command->fill_path.pattern.base,
command->fill_path.operator,
target,
&traps,
&clip,
command->fill_path.antialias);
_cairo_traps_fini (&traps);
break;
default:
ASSERT_NOT_REACHED;
}

Просмотреть файл

@ -119,8 +119,8 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream,
* http://mail.gnome.org/archives/gtk-devel-list/2001-October/msg00087.html
*/
static int
dtostr (char *buffer, size_t size, double d)
int
_cairo_dtostr (char *buffer, size_t size, double d)
{
struct lconv *locale_data;
const char *decimal_point;
@ -233,7 +233,7 @@ _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
snprintf (buffer, sizeof buffer, "%s", va_arg (ap, const char *));
break;
case 'f':
dtostr (buffer, sizeof buffer, va_arg (ap, double));
_cairo_dtostr (buffer, sizeof buffer, va_arg (ap, double));
break;
case 'c':
buffer[0] = va_arg (ap, int);

Просмотреть файл

@ -0,0 +1,46 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Carl Worth <cworth@cworth.org>
*/
#ifndef CAIRO_PAGINATED_SURFACE_H
#define CAIRO_PAGINATED_SURFACE_H
#include "cairoint.h"
cairo_private cairo_surface_t *
_cairo_paginated_surface_create (cairo_surface_t *target,
int width,
int height);
#endif /* CAIRO_PAGINATED_SURFACE_H */

Просмотреть файл

@ -0,0 +1,400 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Carl Worth <cworth@cworth.org>
*/
/* The paginated surface layer exists to provide as much code sharing
* as possible for the various paginated surface backends in cairo
* (PostScript, PDF, etc.).
*
* The concept is that a surface which uses a paginated surface merely
* needs to implement backend operations which it can accurately
* provide, (and return CAIRO_INT_STATUS_UNSUPPORTED or leave backend
* function pointers NULL otherwise). The paginated surface is the
* responsible for collecting operations that aren't supported,
* replaying them against the image surface, and then supplying the
* resulting images to the target surface.
*
* When created, a paginated surface accepts the target surface to
* which the final drawing will eventually be performed. The paginated
* surface then uses cairo_meta_surface_t to record all drawing
* operations up until each show_page operation.
*
* At the time of show_page, the paginated surface replays the meta
* surface against the target surface and maintains regions of the
* result that will come from the nativ surface and regions that will
* need to come from image fallbacks. It then replays the necessary
* portions against image surface and provides those results to the
* target surface through existing interfaces.
*
* This way the target surface is never even aware of any distinction
* between native drawing operations vs. results that are supplied by
* image fallbacks. Instead the surface need only implement as much of
* the surface backend interface as it can do correctly, and let the
* paginated surface take care of all the messy details.
*/
#include "cairoint.h"
#include "cairo-paginated-surface-private.h"
#include "cairo-meta-surface-private.h"
typedef struct _cairo_paginated_surface {
cairo_surface_t base;
/* XXX: These shouldn't actually exist. We inherit this ugliness
* from _cairo_meta_surface_create. The width/height parameters
* from that function also should not exist. The fix that will
* allow us to remove all of these is to fix acquire_source_image
* to pass an interest rectangle. */
int width;
int height;
/* The target surface to hold the final result. */
cairo_surface_t *target;
/* A cairo_meta_surface to record all operations. To be replayed
* against target, and also against image surface as necessary for
* fallbacks. */
cairo_surface_t *meta;
} cairo_paginated_surface_t;
const cairo_private cairo_surface_backend_t cairo_paginated_surface_backend;
static cairo_int_status_t
_cairo_paginated_surface_show_page (void *abstract_surface);
cairo_surface_t *
_cairo_paginated_surface_create (cairo_surface_t *target,
int width,
int height)
{
cairo_paginated_surface_t *surface;
surface = malloc (sizeof (cairo_paginated_surface_t));
if (surface == NULL)
goto FAIL;
_cairo_surface_init (&surface->base, &cairo_paginated_surface_backend);
surface->width = width;
surface->height = height;
surface->target = target;
surface->meta = _cairo_meta_surface_create (width, height);
if (cairo_surface_status (surface->meta))
goto FAIL_CLEANUP_SURFACE;
return &surface->base;
FAIL_CLEANUP_SURFACE:
free (surface);
FAIL:
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t*) &_cairo_surface_nil;
}
static cairo_status_t
_cairo_paginated_surface_finish (void *abstract_surface)
{
cairo_paginated_surface_t *surface = abstract_surface;
cairo_surface_destroy (surface->meta);
cairo_surface_destroy (surface->target);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_paginated_surface_acquire_source_image (void *abstract_surface,
cairo_image_surface_t **image_out,
void **image_extra)
{
cairo_paginated_surface_t *surface = abstract_surface;
cairo_surface_t *image;
cairo_rectangle_t extents;
_cairo_surface_get_extents (surface->target, &extents);
image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
extents.width, extents.height);
_cairo_meta_surface_replay (surface->meta, image);
*image_out = (cairo_image_surface_t*) image;
*image_extra = NULL;
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_paginated_surface_release_source_image (void *abstract_surface,
cairo_image_surface_t *image,
void *image_extra)
{
cairo_surface_destroy (&image->base);
}
static void
_paint_page (cairo_paginated_surface_t *surface)
{
cairo_surface_t *image;
cairo_pattern_t *pattern;
image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
surface->width, surface->height);
_cairo_meta_surface_replay (surface->meta, image);
pattern = cairo_pattern_create_for_surface (image);
_cairo_surface_paint (surface->target, CAIRO_OPERATOR_SOURCE, pattern);
cairo_pattern_destroy (pattern);
cairo_surface_destroy (image);
}
static cairo_int_status_t
_cairo_paginated_surface_copy_page (void *abstract_surface)
{
cairo_paginated_surface_t *surface = abstract_surface;
cairo_int_status_t status;
_paint_page (surface);
status = _cairo_surface_copy_page (surface->target);
/* If the surface does not support copy_page then we use show_page
* instead, and we leave the meta-surface untouched so that its
* contents will remain for the next page. */
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
status = _cairo_surface_show_page (surface->target);
/* And if the surface doesn't support show_page either, we
* also fall through and clear the meta-surface. */
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
}
/* Otherwise, we clear the meta-surface since the target surface
* has already taken care of any copying in its implementation of
* copy_page. */
cairo_surface_destroy (surface->meta);
surface->meta = _cairo_meta_surface_create (surface->width, surface->height);
if (cairo_surface_status (surface->meta))
return cairo_surface_status (surface->meta);
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_paginated_surface_show_page (void *abstract_surface)
{
cairo_paginated_surface_t *surface = abstract_surface;
_paint_page (surface);
_cairo_surface_show_page (surface->target);
cairo_surface_destroy (surface->meta);
surface->meta = _cairo_meta_surface_create (surface->width, surface->height);
if (cairo_surface_status (surface->meta))
return cairo_surface_status (surface->meta);
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_paginated_surface_intersect_clip_path (void *abstract_surface,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias)
{
cairo_paginated_surface_t *surface = abstract_surface;
return _cairo_surface_intersect_clip_path (surface->meta,
path, fill_rule,
tolerance, antialias);
}
static cairo_int_status_t
_cairo_paginated_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
{
cairo_paginated_surface_t *surface = abstract_surface;
return _cairo_surface_get_extents (surface->target, rectangle);
}
static cairo_int_status_t
_cairo_paginated_surface_paint (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source)
{
cairo_paginated_surface_t *surface = abstract_surface;
return _cairo_surface_paint (surface->meta, op, source);
}
static cairo_int_status_t
_cairo_paginated_surface_mask (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_pattern_t *mask)
{
cairo_paginated_surface_t *surface = abstract_surface;
return _cairo_surface_mask (surface->meta, op, source, mask);
}
static cairo_int_status_t
_cairo_paginated_surface_stroke (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_stroke_style_t *style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias)
{
cairo_paginated_surface_t *surface = abstract_surface;
return _cairo_surface_stroke (surface->meta, op, source,
path, style,
ctm, ctm_inverse,
tolerance, antialias);
}
static cairo_int_status_t
_cairo_paginated_surface_fill (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias)
{
cairo_paginated_surface_t *surface = abstract_surface;
return _cairo_surface_fill (surface->meta, op, source,
path, fill_rule,
tolerance, antialias);
}
static cairo_int_status_t
_cairo_paginated_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{
cairo_paginated_surface_t *surface = abstract_surface;
return _cairo_surface_show_glyphs (surface->meta, op, source,
glyphs, num_glyphs,
scaled_font);
}
static cairo_surface_t *
_cairo_paginated_surface_snapshot (void *abstract_other)
{
cairo_paginated_surface_t *other = abstract_other;
/* XXX: Just making a snapshot of other->meta is what we really
* want. But this currently triggers a bug somewhere (the "mask"
* test from the test suite segfaults).
*
* For now, we'll create a new image surface and replay onto
* that. It would be tempting to replay into other->image and then
* return a snapshot of that, but that will cause the self-copy
* test to fail, (since our replay will be affected by a clip that
* should not have any effect on the use of the resulting snapshot
* as a source).
*/
#if 0
return _cairo_surface_snapshot (other->meta);
#else
cairo_rectangle_t extents;
cairo_surface_t *surface;
_cairo_surface_get_extents (other->target, &extents);
surface = cairo_surface_create_similar (other->target,
CAIRO_CONTENT_COLOR_ALPHA,
extents.width,
extents.height);
_cairo_meta_surface_replay (other->meta, surface);
return surface;
#endif
}
const cairo_surface_backend_t cairo_paginated_surface_backend = {
NULL, /* create_similar */
_cairo_paginated_surface_finish,
_cairo_paginated_surface_acquire_source_image,
_cairo_paginated_surface_release_source_image,
NULL, /* acquire_dest_image */
NULL, /* release_dest_image */
NULL, /* clone_similar */
NULL, /* composite */
NULL, /* fill_rectangles */
NULL, /* composite_trapezoids */
_cairo_paginated_surface_copy_page,
_cairo_paginated_surface_show_page,
NULL, /* set_clip_region */
_cairo_paginated_surface_intersect_clip_path,
_cairo_paginated_surface_get_extents,
NULL, /* old_show_glyphs */
NULL, /* get_font_options */
NULL, /* flush */
NULL, /* mark_dirty_rectangle */
NULL, /* scaled_font_fini */
NULL, /* scaled_glyph_fini */
_cairo_paginated_surface_paint,
_cairo_paginated_surface_mask,
_cairo_paginated_surface_stroke,
_cairo_paginated_surface_fill,
_cairo_paginated_surface_show_glyphs,
_cairo_paginated_surface_snapshot
};

Просмотреть файл

@ -36,12 +36,17 @@
#include "cairoint.h"
#include "cairo-gstate-private.h"
typedef struct cairo_stroker {
cairo_gstate_t *gstate;
cairo_stroke_style_t *style;
cairo_matrix_t *ctm;
cairo_matrix_t *ctm_inverse;
double tolerance;
cairo_traps_t *traps;
cairo_pen_t pen;
cairo_bool_t has_current_point;
cairo_point_t current_point;
cairo_point_t first_point;
@ -60,7 +65,12 @@ typedef struct cairo_stroker {
/* private functions */
static void
_cairo_stroker_init (cairo_stroker_t *stroker, cairo_gstate_t *gstate, cairo_traps_t *traps);
_cairo_stroker_init (cairo_stroker_t *stroker,
cairo_stroke_style_t *stroke_style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_traps_t *traps);
static void
_cairo_stroker_fini (cairo_stroker_t *stroker);
@ -101,49 +111,59 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
static void
_cairo_stroker_start_dash (cairo_stroker_t *stroker)
{
cairo_gstate_t *gstate = stroker->gstate;
double offset;
int on = 1;
int i = 0;
offset = gstate->dash_offset;
while (offset >= gstate->dash[i]) {
offset -= gstate->dash[i];
offset = stroker->style->dash_offset;
while (offset >= stroker->style->dash[i]) {
offset -= stroker->style->dash[i];
on = 1-on;
if (++i == gstate->num_dashes)
if (++i == stroker->style->num_dashes)
i = 0;
}
stroker->dashed = TRUE;
stroker->dash_index = i;
stroker->dash_on = on;
stroker->dash_remain = gstate->dash[i] - offset;
stroker->dash_remain = stroker->style->dash[i] - offset;
}
static void
_cairo_stroker_step_dash (cairo_stroker_t *stroker, double step)
{
cairo_gstate_t *gstate = stroker->gstate;
stroker->dash_remain -= step;
if (stroker->dash_remain <= 0) {
stroker->dash_index++;
if (stroker->dash_index == gstate->num_dashes)
if (stroker->dash_index == stroker->style->num_dashes)
stroker->dash_index = 0;
stroker->dash_on = 1-stroker->dash_on;
stroker->dash_remain = gstate->dash[stroker->dash_index];
stroker->dash_remain = stroker->style->dash[stroker->dash_index];
}
}
static void
_cairo_stroker_init (cairo_stroker_t *stroker, cairo_gstate_t *gstate, cairo_traps_t *traps)
_cairo_stroker_init (cairo_stroker_t *stroker,
cairo_stroke_style_t *stroke_style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_traps_t *traps)
{
stroker->gstate = gstate;
stroker->style = stroke_style;
stroker->ctm = ctm;
stroker->ctm_inverse = ctm_inverse;
stroker->tolerance = tolerance;
stroker->traps = traps;
_cairo_pen_init (&stroker->pen,
stroke_style->line_width / 2.0,
tolerance, ctm);
stroker->has_current_point = FALSE;
stroker->has_current_face = FALSE;
stroker->has_first_face = FALSE;
if (gstate->dash)
if (stroker->style->dash)
_cairo_stroker_start_dash (stroker);
else
stroker->dashed = FALSE;
@ -152,7 +172,7 @@ _cairo_stroker_init (cairo_stroker_t *stroker, cairo_gstate_t *gstate, cairo_tra
static void
_cairo_stroker_fini (cairo_stroker_t *stroker)
{
/* nothing to do here */
_cairo_pen_fini (&stroker->pen);
}
static void
@ -177,8 +197,7 @@ static cairo_status_t
_cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_stroke_face_t *out)
{
cairo_status_t status;
cairo_gstate_t *gstate = stroker->gstate;
int clockwise = _cairo_stroker_face_clockwise (out, in);
int clockwise = _cairo_stroker_face_clockwise (out, in);
cairo_point_t *inpt, *outpt;
if (in->cw.x == out->cw.x
@ -196,12 +215,12 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
outpt = &out->cw;
}
switch (gstate->line_join) {
switch (stroker->style->line_join) {
case CAIRO_LINE_JOIN_ROUND: {
int i;
int start, step, stop;
cairo_point_t tri[3];
cairo_pen_t *pen = &gstate->pen_regular;
cairo_pen_t *pen = &stroker->pen;
tri[0] = in->point;
if (clockwise) {
@ -237,7 +256,7 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
/* dot product of incoming slope vector with outgoing slope vector */
double in_dot_out = ((-in->usr_vector.x * out->usr_vector.x)+
(-in->usr_vector.y * out->usr_vector.y));
double ml = gstate->miter_limit;
double ml = stroker->style->miter_limit;
/*
* Check the miter limit -- lines meeting at an acute angle
@ -285,14 +304,14 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
y1 = _cairo_fixed_to_double (inpt->y);
dx1 = in->usr_vector.x;
dy1 = in->usr_vector.y;
cairo_matrix_transform_distance (&gstate->ctm, &dx1, &dy1);
cairo_matrix_transform_distance (stroker->ctm, &dx1, &dy1);
/* outer point of outgoing line face */
x2 = _cairo_fixed_to_double (outpt->x);
y2 = _cairo_fixed_to_double (outpt->y);
dx2 = out->usr_vector.x;
dy2 = out->usr_vector.y;
cairo_matrix_transform_distance (&gstate->ctm, &dx2, &dy2);
cairo_matrix_transform_distance (stroker->ctm, &dx2, &dy2);
/*
* Compute the location of the outer corner of the miter.
@ -344,18 +363,17 @@ static cairo_status_t
_cairo_stroker_add_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
{
cairo_status_t status;
cairo_gstate_t *gstate = stroker->gstate;
if (gstate->line_cap == CAIRO_LINE_CAP_BUTT)
if (stroker->style->line_cap == CAIRO_LINE_CAP_BUTT)
return CAIRO_STATUS_SUCCESS;
switch (gstate->line_cap) {
switch (stroker->style->line_cap) {
case CAIRO_LINE_CAP_ROUND: {
int i;
int start, stop;
cairo_slope_t slope;
cairo_point_t tri[3];
cairo_pen_t *pen = &gstate->pen_regular;
cairo_pen_t *pen = &stroker->pen;
slope = f->dev_vector;
_cairo_pen_find_active_cw_vertex_index (pen, &slope, &start);
@ -383,9 +401,9 @@ _cairo_stroker_add_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
dx = f->usr_vector.x;
dy = f->usr_vector.y;
dx *= gstate->line_width / 2.0;
dy *= gstate->line_width / 2.0;
cairo_matrix_transform_distance (&gstate->ctm, &dx, &dy);
dx *= stroker->style->line_width / 2.0;
dy *= stroker->style->line_width / 2.0;
cairo_matrix_transform_distance (stroker->ctm, &dx, &dy);
fvector.dx = _cairo_fixed_from_double (dx);
fvector.dy = _cairo_fixed_from_double (dy);
occw.x = f->ccw.x + fvector.dx;
@ -460,7 +478,7 @@ _cairo_stroker_add_caps (cairo_stroker_t *stroker)
}
static void
_compute_face (cairo_point_t *point, cairo_slope_t *slope, cairo_gstate_t *gstate, cairo_stroke_face_t *face)
_compute_face (cairo_point_t *point, cairo_slope_t *slope, cairo_stroker_t *stroker, cairo_stroke_face_t *face)
{
double mag, det;
double line_dx, line_dy;
@ -472,7 +490,7 @@ _compute_face (cairo_point_t *point, cairo_slope_t *slope, cairo_gstate_t *gstat
line_dy = _cairo_fixed_to_double (slope->dy);
/* faces are normal in user space, not device space */
cairo_matrix_transform_distance (&gstate->ctm_inverse, &line_dx, &line_dy);
cairo_matrix_transform_distance (stroker->ctm_inverse, &line_dx, &line_dy);
mag = sqrt (line_dx * line_dx + line_dy * line_dy);
if (mag == 0) {
@ -494,20 +512,20 @@ _compute_face (cairo_point_t *point, cairo_slope_t *slope, cairo_gstate_t *gstat
* whether the ctm reflects or not, and that can be determined
* by looking at the determinant of the matrix.
*/
_cairo_matrix_compute_determinant (&gstate->ctm, &det);
_cairo_matrix_compute_determinant (stroker->ctm, &det);
if (det >= 0)
{
face_dx = - line_dy * (gstate->line_width / 2.0);
face_dy = line_dx * (gstate->line_width / 2.0);
face_dx = - line_dy * (stroker->style->line_width / 2.0);
face_dy = line_dx * (stroker->style->line_width / 2.0);
}
else
{
face_dx = line_dy * (gstate->line_width / 2.0);
face_dy = - line_dx * (gstate->line_width / 2.0);
face_dx = line_dy * (stroker->style->line_width / 2.0);
face_dy = - line_dx * (stroker->style->line_width / 2.0);
}
/* back to device space */
cairo_matrix_transform_distance (&gstate->ctm, &face_dx, &face_dy);
cairo_matrix_transform_distance (stroker->ctm, &face_dx, &face_dy);
offset_ccw.x = _cairo_fixed_from_double (face_dx);
offset_ccw.y = _cairo_fixed_from_double (face_dy);
@ -533,7 +551,6 @@ _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_
cairo_stroke_face_t *start, cairo_stroke_face_t *end)
{
cairo_status_t status;
cairo_gstate_t *gstate = stroker->gstate;
cairo_polygon_t polygon;
cairo_slope_t slope;
@ -545,12 +562,12 @@ _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_
}
_cairo_slope_init (&slope, p1, p2);
_compute_face (p1, &slope, gstate, start);
_compute_face (p1, &slope, stroker, start);
/* XXX: This could be optimized slightly by not calling
_compute_face again but rather translating the relevant
fields from start. */
_compute_face (p2, &slope, gstate, end);
_compute_face (p2, &slope, stroker, end);
/* XXX: I should really check the return value of the
move_to/line_to functions here to catch out of memory
@ -648,7 +665,6 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_stroker_t *stroker = closure;
cairo_gstate_t *gstate = stroker->gstate;
double mag, remain, tmp;
double dx, dy;
double dx2, dy2;
@ -664,7 +680,7 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
dx = _cairo_fixed_to_double (p2->x - p1->x);
dy = _cairo_fixed_to_double (p2->y - p1->y);
cairo_matrix_transform_distance (&gstate->ctm_inverse, &dx, &dy);
cairo_matrix_transform_distance (stroker->ctm_inverse, &dx, &dy);
mag = sqrt (dx *dx + dy * dy);
remain = mag;
@ -676,7 +692,7 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
remain -= tmp;
dx2 = dx * (mag - remain)/mag;
dy2 = dy * (mag - remain)/mag;
cairo_matrix_transform_distance (&gstate->ctm, &dx2, &dy2);
cairo_matrix_transform_distance (stroker->ctm, &dx2, &dy2);
fd2.x = _cairo_fixed_from_double (dx2);
fd2.y = _cairo_fixed_from_double (dy2);
fd2.x += p1->x;
@ -764,7 +780,6 @@ _cairo_stroker_curve_to (void *closure,
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_stroker_t *stroker = closure;
cairo_gstate_t *gstate = stroker->gstate;
cairo_spline_t spline;
cairo_pen_t pen;
cairo_stroke_face_t start, end;
@ -775,12 +790,12 @@ _cairo_stroker_curve_to (void *closure,
if (status == CAIRO_INT_STATUS_DEGENERATE)
return CAIRO_STATUS_SUCCESS;
status = _cairo_pen_init_copy (&pen, &gstate->pen_regular);
status = _cairo_pen_init_copy (&pen, &stroker->pen);
if (status)
goto CLEANUP_SPLINE;
_compute_face (a, &spline.initial_slope, gstate, &start);
_compute_face (d, &spline.final_slope, gstate, &end);
_compute_face (a, &spline.initial_slope, stroker, &start);
_compute_face (d, &spline.final_slope, stroker, &end);
if (stroker->has_current_face) {
status = _cairo_stroker_join (stroker, &stroker->current_face, &start);
@ -812,7 +827,7 @@ _cairo_stroker_curve_to (void *closure,
if (status)
goto CLEANUP_PEN;
status = _cairo_pen_stroke_spline (&pen, &spline, gstate->tolerance, stroker->traps);
status = _cairo_pen_stroke_spline (&pen, &spline, stroker->tolerance, stroker->traps);
if (status)
goto CLEANUP_PEN;
@ -852,7 +867,6 @@ _cairo_stroker_curve_to_dashed (void *closure,
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_stroker_t *stroker = closure;
cairo_gstate_t *gstate = stroker->gstate;
cairo_spline_t spline;
cairo_point_t *a = &stroker->current_point;
cairo_line_join_t line_join_save;
@ -864,15 +878,15 @@ _cairo_stroker_curve_to_dashed (void *closure,
/* If the line width is so small that the pen is reduced to a
single point, then we have nothing to do. */
if (gstate->pen_regular.num_vertices <= 1)
if (stroker->pen.num_vertices <= 1)
goto CLEANUP_SPLINE;
/* Temporarily modify the gstate to use round joins to guarantee
/* Temporarily modify the stroker to use round joins to guarantee
* smooth stroked curves. */
line_join_save = gstate->line_join;
gstate->line_join = CAIRO_LINE_JOIN_ROUND;
line_join_save = stroker->style->line_join;
stroker->style->line_join = CAIRO_LINE_JOIN_ROUND;
status = _cairo_spline_decompose (&spline, gstate->tolerance);
status = _cairo_spline_decompose (&spline, stroker->tolerance);
if (status)
goto CLEANUP_GSTATE;
@ -886,7 +900,7 @@ _cairo_stroker_curve_to_dashed (void *closure,
}
CLEANUP_GSTATE:
gstate->line_join = line_join_save;
stroker->style->line_join = line_join_save;
CLEANUP_SPLINE:
_cairo_spline_fini (&spline);
@ -923,16 +937,21 @@ _cairo_stroker_close_path (void *closure)
}
cairo_status_t
_cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
cairo_gstate_t *gstate,
cairo_traps_t *traps)
_cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
cairo_stroke_style_t *stroke_style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_traps_t *traps)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_stroker_t stroker;
_cairo_stroker_init (&stroker, gstate, traps);
_cairo_stroker_init (&stroker, stroke_style,
ctm, ctm_inverse, tolerance,
traps);
if (gstate->dash)
if (stroker.style->dash)
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
_cairo_stroker_move_to,

Просмотреть файл

@ -548,3 +548,40 @@ _cairo_path_fixed_interpret (cairo_path_fixed_t *path,
return CAIRO_STATUS_SUCCESS;
}
void
_cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path,
cairo_fixed_t offx,
cairo_fixed_t offy,
cairo_fixed_t scalex,
cairo_fixed_t scaley)
{
cairo_path_arg_buf_t *arg_buf = path->arg_buf_head;
int i;
cairo_int64_t i64temp;
cairo_fixed_t fixedtemp;
while (arg_buf) {
for (i = 0; i < arg_buf->num_points; i++) {
/* CAIRO_FIXED_ONE? */
if (scalex == 0x00010000) {
arg_buf->points[i].x += offx;
} else {
fixedtemp = arg_buf->points[i].x + offx;
i64temp = _cairo_int32x32_64_mul (fixedtemp, scalex);
arg_buf->points[i].x = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16));
}
if (scaley == 0x00010000) {
arg_buf->points[i].y += offy;
} else {
fixedtemp = arg_buf->points[i].y + offy;
i64temp = _cairo_int32x32_64_mul (fixedtemp, scaley);
arg_buf->points[i].y = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16));
}
}
arg_buf = arg_buf->next;
}
}

Просмотреть файл

@ -22,35 +22,20 @@
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: David Reveman <davidr@novell.com>
* Authors: David Reveman <davidr@novell.com>
* Keith Packard <keithp@keithp.com>
* Carl Worth <cworth@cworth.org>
*/
#include "cairoint.h"
typedef struct _cairo_shader_color_stop {
cairo_fixed_t offset;
cairo_fixed_48_16_t scale;
int id;
unsigned char color_char[4];
} cairo_shader_color_stop_t;
typedef struct _cairo_shader_op {
cairo_shader_color_stop_t *stops;
int n_stops;
cairo_extend_t extend;
} cairo_shader_op_t;
#define MULTIPLY_COLORCOMP(c1, c2) \
((unsigned char) \
((((unsigned char) (c1)) * (int) ((unsigned char) (c2))) / 0xff))
const cairo_solid_pattern_t cairo_pattern_nil = {
{ CAIRO_PATTERN_SOLID, /* type */
(unsigned int)-1, /* ref_count */
CAIRO_STATUS_NO_MEMORY, /* status */
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
CAIRO_FILTER_DEFAULT, /* filter */
CAIRO_EXTEND_DEFAULT }, /* extend */
CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */
};
static const cairo_solid_pattern_t cairo_pattern_nil_null_pointer = {
@ -59,7 +44,7 @@ static const cairo_solid_pattern_t cairo_pattern_nil_null_pointer = {
CAIRO_STATUS_NULL_POINTER,/* status */
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
CAIRO_FILTER_DEFAULT, /* filter */
CAIRO_EXTEND_DEFAULT }, /* extend */
CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */
};
static const cairo_solid_pattern_t cairo_pattern_nil_file_not_found = {
@ -68,7 +53,7 @@ static const cairo_solid_pattern_t cairo_pattern_nil_file_not_found = {
CAIRO_STATUS_FILE_NOT_FOUND, /* status */
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
CAIRO_FILTER_DEFAULT, /* filter */
CAIRO_EXTEND_DEFAULT }, /* extend */
CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */
};
static const cairo_solid_pattern_t cairo_pattern_nil_read_error = {
@ -77,7 +62,7 @@ static const cairo_solid_pattern_t cairo_pattern_nil_read_error = {
CAIRO_STATUS_READ_ERROR, /* status */
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
CAIRO_FILTER_DEFAULT, /* filter */
CAIRO_EXTEND_DEFAULT }, /* extend */
CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */
};
static const cairo_pattern_t *
@ -131,7 +116,12 @@ _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
pattern->type = type;
pattern->ref_count = 1;
pattern->status = CAIRO_STATUS_SUCCESS;
pattern->extend = CAIRO_EXTEND_DEFAULT;
if (type == CAIRO_PATTERN_SURFACE)
pattern->extend = CAIRO_EXTEND_SURFACE_DEFAULT;
else
pattern->extend = CAIRO_EXTEND_GRADIENT_DEFAULT;
pattern->filter = CAIRO_FILTER_DEFAULT;
cairo_matrix_init_identity (&pattern->matrix);
@ -158,14 +148,15 @@ _cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t *pattern,
if (other->n_stops)
{
pattern->stops = malloc (other->n_stops * sizeof (cairo_color_stop_t));
pattern->stops = malloc (other->n_stops *
sizeof (pixman_gradient_stop_t));
if (pattern->stops == NULL) {
_cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY);
return;
}
memcpy (pattern->stops, other->stops,
other->n_stops * sizeof (cairo_color_stop_t));
other->n_stops * sizeof (pixman_gradient_stop_t));
}
}
@ -266,11 +257,11 @@ _cairo_pattern_init_linear (cairo_linear_pattern_t *pattern,
double x0, double y0, double x1, double y1)
{
_cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_LINEAR);
pattern->point0.x = x0;
pattern->point0.y = y0;
pattern->point1.x = x1;
pattern->point1.y = y1;
pattern->gradient.p1.x = _cairo_fixed_from_double (x0);
pattern->gradient.p1.y = _cairo_fixed_from_double (y0);
pattern->gradient.p2.x = _cairo_fixed_from_double (x1);
pattern->gradient.p2.y = _cairo_fixed_from_double (y1);
}
void
@ -280,12 +271,12 @@ _cairo_pattern_init_radial (cairo_radial_pattern_t *pattern,
{
_cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_RADIAL);
pattern->center0.x = cx0;
pattern->center0.y = cy0;
pattern->radius0 = fabs (radius0);
pattern->center1.x = cx1;
pattern->center1.y = cy1;
pattern->radius1 = fabs (radius1);
pattern->gradient.inner.x = _cairo_fixed_from_double (cx0);
pattern->gradient.inner.y = _cairo_fixed_from_double (cy0);
pattern->gradient.inner.radius = _cairo_fixed_from_double (fabs (radius0));
pattern->gradient.outer.x = _cairo_fixed_from_double (cx1);
pattern->gradient.outer.y = _cairo_fixed_from_double (cy1);
pattern->gradient.outer.radius = _cairo_fixed_from_double (fabs (radius1));
}
cairo_pattern_t *
@ -579,25 +570,45 @@ cairo_pattern_destroy (cairo_pattern_t *pattern)
static void
_cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
double offset,
cairo_color_t *color)
double red,
double green,
double blue,
double alpha)
{
cairo_color_stop_t *stop;
cairo_color_stop_t *new_stops;
pixman_gradient_stop_t *new_stops;
cairo_fixed_t x;
int i;
pattern->n_stops++;
new_stops = realloc (pattern->stops,
pattern->n_stops * sizeof (cairo_color_stop_t));
if (new_stops == NULL) {
new_stops = realloc (pattern->stops, (pattern->n_stops + 1) *
sizeof (pixman_gradient_stop_t));
if (new_stops == NULL)
{
_cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY);
return;
}
pattern->stops = new_stops;
stop = &pattern->stops[pattern->n_stops - 1];
x = _cairo_fixed_from_double (offset);
for (i = 0; i < pattern->n_stops; i++)
{
if (x < new_stops[i].x)
{
memmove (&new_stops[i + 1], &new_stops[i],
sizeof (pixman_gradient_stop_t) * (pattern->n_stops - i));
stop->offset = _cairo_fixed_from_double (offset);
stop->color = *color;
break;
}
}
new_stops[i].x = x;
new_stops[i].color.red = red * 65535.0;
new_stops[i].color.green = green * 65535.0;
new_stops[i].color.blue = blue * 65535.0;
new_stops[i].color.alpha = alpha * 65535.0;
pattern->n_stops++;
}
/**
@ -627,8 +638,6 @@ cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
double green,
double blue)
{
cairo_color_t color;
if (pattern->status)
return;
@ -644,10 +653,8 @@ cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
_cairo_restrict_value (&green, 0.0, 1.0);
_cairo_restrict_value (&blue, 0.0, 1.0);
_cairo_color_init_rgb (&color, red, green, blue);
_cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
offset,
&color);
offset, red, green, blue, 1.0);
}
/**
@ -679,8 +686,6 @@ cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
double blue,
double alpha)
{
cairo_color_t color;
if (pattern->status)
return;
@ -697,10 +702,8 @@ cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
_cairo_restrict_value (&blue, 0.0, 1.0);
_cairo_restrict_value (&alpha, 0.0, 1.0);
_cairo_color_init_rgba (&color, red, green, blue, alpha);
_cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
offset,
&color);
offset, red, green, blue, alpha);
}
/**
@ -773,6 +776,16 @@ cairo_pattern_get_filter (cairo_pattern_t *pattern)
return pattern->filter;
}
/**
* cairo_pattern_set_extend:
* @pattern: a #cairo_pattern_t
* @extend: a #cairo_extend_t describing how the area outside of the
* pattern will be drawn
*
* Sets the mode to be used for drawing outside the area of a pattern.
* See #cairo_extend_t for details on the semantics of each extend
* strategy.
**/
void
cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend)
{
@ -782,6 +795,16 @@ cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend)
pattern->extend = extend;
}
/**
* cairo_pattern_get_extend:
* @pattern: a #cairo_pattern_t
*
* Gets the current extend mode for a pattern. See #cairo_extend_t
* for details on the semantics of each extend strategy.
*
* Return value: the current extend strategy used for drawing the
* pattern.
**/
cairo_extend_t
cairo_pattern_get_extend (cairo_pattern_t *pattern)
{
@ -797,230 +820,6 @@ _cairo_pattern_transform (cairo_pattern_t *pattern,
cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix);
}
#define INTERPOLATE_COLOR_LINEAR(c1, c2, factor) \
(((c2 * factor) + (c1 * (65536 - factor))) / 65536)
static void
_cairo_pattern_shader_linear (unsigned char *color0,
unsigned char *color1,
cairo_fixed_t factor,
uint32_t *pixel)
{
*pixel = ((INTERPOLATE_COLOR_LINEAR (color0[3], color1[3], factor) << 24) |
(INTERPOLATE_COLOR_LINEAR (color0[0], color1[0], factor) << 16) |
(INTERPOLATE_COLOR_LINEAR (color0[1], color1[1], factor) << 8) |
(INTERPOLATE_COLOR_LINEAR (color0[2], color1[2], factor) << 0));
}
#undef INTERPOLATE_COLOR_LINEAR
static int
_cairo_shader_color_stop_compare (const void *elem1, const void *elem2)
{
cairo_shader_color_stop_t *s1 = (cairo_shader_color_stop_t *) elem1;
cairo_shader_color_stop_t *s2 = (cairo_shader_color_stop_t *) elem2;
return
(s1->offset == s2->offset) ?
/* equal offsets, sort on id */
((s1->id < s2->id) ? -1 : 1) :
/* sort on offset */
((s1->offset < s2->offset) ? -1 : 1);
}
static cairo_status_t
_cairo_pattern_shader_init (cairo_gradient_pattern_t *pattern,
cairo_shader_op_t *op)
{
int i;
op->stops = malloc (pattern->n_stops * sizeof (cairo_shader_color_stop_t));
if (!op->stops)
return CAIRO_STATUS_NO_MEMORY;
for (i = 0; i < pattern->n_stops; i++)
{
op->stops[i].color_char[0] = pattern->stops[i].color.red * 0xff;
op->stops[i].color_char[1] = pattern->stops[i].color.green * 0xff;
op->stops[i].color_char[2] = pattern->stops[i].color.blue * 0xff;
op->stops[i].color_char[3] = pattern->stops[i].color.alpha * 0xff;
op->stops[i].offset = pattern->stops[i].offset;
op->stops[i].id = i;
}
/* sort stops in ascending order */
qsort (op->stops, pattern->n_stops, sizeof (cairo_shader_color_stop_t),
_cairo_shader_color_stop_compare);
/* this scale value is used only when computing gradient values
* before the defined range, in which case stop 0 is used for both
* ends of the interpolation, making the value of 'scale' not
* actually matter, except that valgrind notices we're using
* an undefined value.
*/
op->stops[0].scale = 0;
for (i = 0; i < pattern->n_stops - 1; i++)
{
op->stops[i + 1].scale = op->stops[i + 1].offset - op->stops[i].offset;
if (op->stops[i + 1].scale == 65536)
op->stops[i + 1].scale = 0;
}
op->n_stops = pattern->n_stops;
op->extend = pattern->base.extend;
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_pattern_shader_fini (cairo_shader_op_t *op)
{
if (op->stops)
free (op->stops);
}
/* Find two color stops bounding the given offset. If the given offset
* is before the first or after the last stop offset, the nearest
* offset is returned twice.
*/
static void
_cairo_shader_op_find_color_stops (cairo_shader_op_t *op,
cairo_fixed_t offset,
cairo_shader_color_stop_t *stops[2])
{
int i;
/* Before first stop. */
if (offset <= op->stops[0].offset) {
stops[0] = &op->stops[0];
stops[1] = &op->stops[0];
return;
}
/* Between two stops. */
for (i = 0; i < op->n_stops - 1; i++) {
if (offset <= op->stops[i + 1].offset) {
stops[0] = &op->stops[i];
stops[1] = &op->stops[i + 1];
return;
}
}
/* After last stop. */
stops[0] = &op->stops[op->n_stops - 1];
stops[1] = &op->stops[op->n_stops - 1];
}
static void
_cairo_pattern_calc_color_at_pixel (cairo_shader_op_t *op,
cairo_fixed_t factor,
uint32_t *pixel)
{
cairo_shader_color_stop_t *stops[2];
switch (op->extend) {
case CAIRO_EXTEND_REPEAT:
factor -= factor & 0xffff0000;
break;
case CAIRO_EXTEND_REFLECT:
if (factor < 0 || factor > 65536) {
if ((factor >> 16) % 2)
factor = 65536 - (factor - (factor & 0xffff0000));
else
factor -= factor & 0xffff0000;
}
break;
case CAIRO_EXTEND_NONE:
break;
}
_cairo_shader_op_find_color_stops (op, factor, stops);
/* take offset as new 0 of coordinate system */
factor -= stops[0]->offset;
/* difference between two offsets == 0, abrubt change */
if (stops[1]->scale)
factor = ((cairo_fixed_48_16_t) factor << 16) /
stops[1]->scale;
_cairo_pattern_shader_linear (stops[0]->color_char,
stops[1]->color_char,
factor, pixel);
/* multiply alpha */
if (((unsigned char) (*pixel >> 24)) != 0xff) {
*pixel = (*pixel & 0xff000000) |
(MULTIPLY_COLORCOMP (*pixel >> 16, *pixel >> 24) << 16) |
(MULTIPLY_COLORCOMP (*pixel >> 8, *pixel >> 24) << 8) |
(MULTIPLY_COLORCOMP (*pixel >> 0, *pixel >> 24) << 0);
}
}
static cairo_status_t
_cairo_image_data_set_linear (cairo_linear_pattern_t *pattern,
double offset_x,
double offset_y,
uint32_t *pixels,
int width,
int height)
{
int x, y;
cairo_point_double_t point0, point1;
double a, b, c, d, tx, ty;
double scale, start, dx, dy, factor;
cairo_shader_op_t op;
cairo_status_t status;
status = _cairo_pattern_shader_init (&pattern->base, &op);
if (status)
return status;
/* We compute the position in the linear gradient for
* a point q as:
*
* [q . (p1 - p0) - p0 . (p1 - p0)] / (p1 - p0) ^ 2
*
* The computation is done in pattern space. The
* calculation could be heavily optimized by using the
* fact that 'factor' increases linearly in both
* directions.
*/
point0.x = pattern->point0.x;
point0.y = pattern->point0.y;
point1.x = pattern->point1.x;
point1.y = pattern->point1.y;
_cairo_matrix_get_affine (&pattern->base.base.matrix,
&a, &b, &c, &d, &tx, &ty);
dx = point1.x - point0.x;
dy = point1.y - point0.y;
scale = dx * dx + dy * dy;
scale = (scale) ? 1.0 / scale : 1.0;
start = dx * point0.x + dy * point0.y;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
double qx_device = x + offset_x;
double qy_device = y + offset_y;
/* transform fragment into pattern space */
double qx = a * qx_device + c * qy_device + tx;
double qy = b * qx_device + d * qy_device + ty;
factor = ((dx * qx + dy * qy) - start) * scale;
_cairo_pattern_calc_color_at_pixel (&op, _cairo_fixed_from_double (factor), pixels++);
}
}
_cairo_pattern_shader_fini (&op);
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_linear_pattern_classify (cairo_linear_pattern_t *pattern,
double offset_x,
@ -1041,10 +840,10 @@ _cairo_linear_pattern_classify (cairo_linear_pattern_t *pattern,
* pattern. We actually only need 3/4 corners, so we skip the
* fourth.
*/
point0.x = pattern->point0.x;
point0.y = pattern->point0.y;
point1.x = pattern->point1.x;
point1.y = pattern->point1.y;
point0.x = _cairo_fixed_to_double (pattern->gradient.p1.x);
point0.y = _cairo_fixed_to_double (pattern->gradient.p1.y);
point1.x = _cairo_fixed_to_double (pattern->gradient.p2.x);
point1.y = _cairo_fixed_to_double (pattern->gradient.p2.y);
_cairo_matrix_get_affine (&pattern->base.base.matrix,
&a, &b, &c, &d, &tx, &ty);
@ -1079,131 +878,6 @@ _cairo_linear_pattern_classify (cairo_linear_pattern_t *pattern,
*is_horizontal = factors[2] == factors[0];
}
static cairo_status_t
_cairo_image_data_set_radial (cairo_radial_pattern_t *pattern,
double offset_x,
double offset_y,
uint32_t *pixels,
int width,
int height)
{
int x, y, aligned_circles;
cairo_point_double_t c0, c1;
double px, py, ex, ey;
double a, b, c, d, tx, ty;
double r0, r1, c0_e_x, c0_e_y, c0_e, c1_e_x, c1_e_y, c1_e,
c0_c1_x, c0_c1_y, c0_c1, angle_c0, c1_y, y_x, c0_y, c0_x, r1_2,
denumerator, fraction, factor;
cairo_shader_op_t op;
cairo_status_t status;
status = _cairo_pattern_shader_init (&pattern->base, &op);
if (status)
return status;
c0.x = pattern->center0.x;
c0.y = pattern->center0.y;
r0 = pattern->radius0;
c1.x = pattern->center1.x;
c1.y = pattern->center1.y;
r1 = pattern->radius1;
if (c0.x != c1.x || c0.y != c1.y) {
aligned_circles = 0;
c0_c1_x = c1.x - c0.x;
c0_c1_y = c1.y - c0.y;
c0_c1 = sqrt (c0_c1_x * c0_c1_x + c0_c1_y * c0_c1_y);
r1_2 = r1 * r1;
} else {
aligned_circles = 1;
r1 = 1.0 / (r1 - r0);
r1_2 = c0_c1 = 0.0; /* shut up compiler */
}
_cairo_matrix_get_affine (&pattern->base.base.matrix,
&a, &b, &c, &d, &tx, &ty);
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
px = x + offset_x;
py = y + offset_y;
/* transform fragment */
ex = a * px + c * py + tx;
ey = b * px + d * py + ty;
if (aligned_circles) {
ex = ex - c1.x;
ey = ey - c1.y;
factor = (sqrt (ex * ex + ey * ey) - r0) * r1;
} else {
/*
y (ex, ey)
c0 -------------------+---------- x
\ | __--
\ | __--
\ | __--
\ | __-- r1
\ | __--
c1 --
We need to calulate distance c0->x; the distance from
the inner circle center c0, through fragment position
(ex, ey) to point x where it crosses the outer circle.
From points c0, c1 and (ex, ey) we get angle C0. With
angle C0 we calculate distance c1->y and c0->y and by
knowing c1->y and r1, we also know y->x. Adding y->x to
c0->y gives us c0->x. The gradient offset can then be
calculated as:
offset = (c0->e - r0) / (c0->x - r0)
*/
c0_e_x = ex - c0.x;
c0_e_y = ey - c0.y;
c0_e = sqrt (c0_e_x * c0_e_x + c0_e_y * c0_e_y);
c1_e_x = ex - c1.x;
c1_e_y = ey - c1.y;
c1_e = sqrt (c1_e_x * c1_e_x + c1_e_y * c1_e_y);
denumerator = -2.0 * c0_e * c0_c1;
if (denumerator != 0.0) {
fraction = (c1_e * c1_e - c0_e * c0_e - c0_c1 * c0_c1) /
denumerator;
if (fraction > 1.0)
fraction = 1.0;
else if (fraction < -1.0)
fraction = -1.0;
angle_c0 = acos (fraction);
c0_y = cos (angle_c0) * c0_c1;
c1_y = sin (angle_c0) * c0_c1;
y_x = sqrt (r1_2 - c1_y * c1_y);
c0_x = y_x + c0_y;
factor = (c0_e - r0) / (c0_x - r0);
} else {
factor = -r0;
}
}
_cairo_pattern_calc_color_at_pixel (&op, _cairo_fixed_from_double (factor), pixels++);
}
}
_cairo_pattern_shader_fini (&op);
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
cairo_surface_t *dst,
@ -1215,9 +889,52 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
cairo_surface_attributes_t *attr)
{
cairo_image_surface_t *image;
cairo_status_t status;
uint32_t *data;
cairo_bool_t repeat = FALSE;
pixman_image_t *pixman_image;
pixman_transform_t pixman_transform;
cairo_status_t status;
cairo_bool_t repeat = FALSE;
if (pattern->base.type == CAIRO_PATTERN_LINEAR)
{
cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) pattern;
pixman_image = pixman_image_create_linear_gradient (&linear->gradient,
pattern->stops,
pattern->n_stops);
}
else
{
cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern;
pixman_image = pixman_image_create_radial_gradient (&radial->gradient,
pattern->stops,
pattern->n_stops);
}
if (pixman_image == NULL)
return CAIRO_STATUS_NO_MEMORY;
if (_cairo_surface_is_image (dst))
{
image = (cairo_image_surface_t *)
_cairo_image_surface_create_for_pixman_image (pixman_image,
CAIRO_FORMAT_ARGB32);
if (image->base.status)
{
pixman_image_destroy (pixman_image);
return CAIRO_STATUS_NO_MEMORY;
}
attr->x_offset = attr->y_offset = 0;
attr->matrix = pattern->base.matrix;
attr->extend = pattern->base.extend;
attr->filter = CAIRO_FILTER_NEAREST;
attr->acquired = FALSE;
*out = &image->base;
return CAIRO_STATUS_SUCCESS;
}
if (pattern->base.type == CAIRO_PATTERN_LINEAR) {
cairo_bool_t is_horizontal;
@ -1242,46 +959,47 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
repeat = TRUE;
}
}
data = malloc (width * height * 4);
if (data == NULL)
return CAIRO_STATUS_NO_MEMORY;
if (pattern->base.type == CAIRO_PATTERN_LINEAR)
{
cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) pattern;
status = _cairo_image_data_set_linear (linear, x, y, data,
width, height);
}
else
{
cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern;
status = _cairo_image_data_set_radial (radial, x, y, data,
width, height);
}
if (status) {
free (data);
return status;
}
image = (cairo_image_surface_t *)
cairo_image_surface_create_for_data ((unsigned char *) data,
CAIRO_FORMAT_ARGB32,
width, height,
width * 4);
cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
if (image->base.status) {
free (data);
pixman_image_destroy (pixman_image);
return CAIRO_STATUS_NO_MEMORY;
}
_cairo_image_surface_assume_ownership_of_data (image);
pixman_image_set_filter (pixman_image, PIXMAN_FILTER_BILINEAR);
_cairo_matrix_to_pixman_matrix (&pattern->base.matrix, &pixman_transform);
pixman_image_set_transform (pixman_image, &pixman_transform);
switch (pattern->base.extend) {
case CAIRO_EXTEND_NONE:
pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_NONE);
break;
case CAIRO_EXTEND_REPEAT:
pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_NORMAL);
break;
case CAIRO_EXTEND_REFLECT:
pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_REFLECT);
break;
case CAIRO_EXTEND_PAD:
pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_PAD);
break;
}
pixman_composite (PIXMAN_OPERATOR_SRC,
pixman_image,
NULL,
image->pixman_image,
x, y,
0, 0,
0, 0,
width, height);
pixman_image_destroy (pixman_image);
status = _cairo_surface_clone_similar (dst, &image->base, out);
cairo_surface_destroy (&image->base);
attr->x_offset = -x;
@ -1290,7 +1008,7 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
attr->extend = repeat ? CAIRO_EXTEND_REPEAT : CAIRO_EXTEND_NONE;
attr->filter = CAIRO_FILTER_NEAREST;
attr->acquired = FALSE;
return status;
}
@ -1448,15 +1166,27 @@ _cairo_pattern_acquire_surface (cairo_pattern_t *pattern,
/* fast path for gradients with less than 2 color stops */
if (src->n_stops < 2)
{
const cairo_color_t *color;
cairo_solid_pattern_t solid;
if (src->n_stops)
color = &src->stops->color;
else
color = CAIRO_COLOR_TRANSPARENT;
{
cairo_color_t color;
_cairo_pattern_init_solid (&solid, color);
_cairo_color_init_rgba (&color,
src->stops->color.red / 65536.0,
src->stops->color.green / 65536.0,
src->stops->color.blue / 65536.0,
src->stops->color.alpha / 65536.0);
_cairo_pattern_init_solid (&solid, &color);
}
else
{
const cairo_color_t *color;
color = _cairo_stock_color (CAIRO_STOCK_TRANSPARENT);
_cairo_pattern_init_solid (&solid, color);
}
status = _cairo_pattern_acquire_surface_for_solid (&solid, dst,
x, y,
@ -1598,3 +1328,85 @@ _cairo_pattern_acquire_surfaces (cairo_pattern_t *src,
return status;
}
/**
* _cairo_pattern_get_extents:
*
* Return the "target-space" extents of @pattern in @extents.
*
* For unbounded patterns, the @extents will be initialized with
* "infinite" extents, (minimum and maximum fixed-point values).
*
* XXX: Currently, bounded gradient patterns will also return
* "infinite" extents, though it would be possible to optimize these
* with a little more work.
**/
cairo_status_t
_cairo_pattern_get_extents (cairo_pattern_t *pattern,
cairo_rectangle_t *extents)
{
if (pattern->extend == CAIRO_EXTEND_NONE &&
pattern->type == CAIRO_PATTERN_SURFACE)
{
cairo_status_t status;
cairo_rectangle_t surface_extents;
cairo_surface_pattern_t *surface_pattern =
(cairo_surface_pattern_t *) pattern;
cairo_surface_t *surface = surface_pattern->surface;
cairo_matrix_t imatrix;
double x, y;
/* Initialize to keep the compiler quiet. */
int left=0, right=0, top=0, bottom=0;
int lx, rx, ty, by;
int sx, sy;
cairo_bool_t set = FALSE;
status = _cairo_surface_get_extents (surface, &surface_extents);
if (status)
return status;
imatrix = pattern->matrix;
cairo_matrix_invert (&imatrix);
for (sy = 0; sy <= 1; sy++) {
for (sx = 0; sx <= 1; sx++) {
x = surface_extents.x + sx * surface_extents.width;
y = surface_extents.y + sy * surface_extents.height;
cairo_matrix_transform_point (&imatrix, &x, &y);
if (x < 0) x = 0;
if (x > CAIRO_MAXSHORT) x = CAIRO_MAXSHORT;
if (y < 0) y = 0;
if (y > CAIRO_MAXSHORT) y = CAIRO_MAXSHORT;
lx = floor (x); rx = ceil (x);
ty = floor (y); by = ceil (y);
if (!set) {
left = lx;
right = rx;
top = ty;
bottom = by;
set = TRUE;
} else {
if (lx < left) left = lx;
if (rx > right) right = rx;
if (ty < top) top = ty;
if (by > bottom) bottom = by;
}
}
}
extents->x = left; extents->width = right - left;
extents->y = top; extents->height = bottom - top;
return CAIRO_STATUS_SUCCESS;
}
/* XXX: We could optimize gradients with pattern->extend of NONE
* here in some cases, (eg. radial gradients and 1 axis of
* horizontal/vertical linear gradients).
*/
extents->x = 0;
extents->y = 0;
extents->width = CAIRO_MAXSHORT;
extents->height = CAIRO_MAXSHORT;
return CAIRO_STATUS_SUCCESS;
}

Просмотреть файл

@ -51,9 +51,6 @@
* could add generation counters to surfaces and remember the stream
* ID for a particular generation for a particular surface.
*
* - Multi stop gradients. What are the exponential interpolation
* functions, could they be used for gradients?
*
* - Clipping: must be able to reset clipping
*
* - Images of other formats than 8 bit RGBA.
@ -79,8 +76,6 @@
*
* - Add test case for RGBA gradients.
*
* - Pattern extend isn't honoured by image backend.
*
* - Coordinate space for create_similar() args?
*
* - Investigate /Matrix entry in content stream dicts for pages
@ -194,10 +189,13 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend;
static unsigned int
_cairo_pdf_document_new_object (cairo_pdf_document_t *document)
{
cairo_status_t status;
cairo_pdf_object_t object;
object.offset = _cairo_output_stream_get_position (document->output_stream);
if (_cairo_array_append (&document->objects, &object, 1) == NULL)
status = _cairo_array_append (&document->objects, &object);
if (status)
return 0;
return document->next_available_id++;
@ -217,7 +215,8 @@ static void
_cairo_pdf_surface_add_stream (cairo_pdf_surface_t *surface,
cairo_pdf_stream_t *stream)
{
_cairo_array_append (&surface->streams, &stream, 1);
/* XXX: Should be checking the return value here. */
_cairo_array_append (&surface->streams, &stream);
surface->current_stream = stream;
}
@ -227,7 +226,8 @@ _cairo_pdf_surface_add_pattern (cairo_pdf_surface_t *surface, unsigned int id)
cairo_pdf_resource_t resource;
resource.id = id;
_cairo_array_append (&surface->patterns, &resource, 1);
/* XXX: Should be checking the return value here. */
_cairo_array_append (&surface->patterns, &resource);
}
static void
@ -244,7 +244,8 @@ _cairo_pdf_surface_add_xobject (cairo_pdf_surface_t *surface, unsigned int id)
}
resource.id = id;
_cairo_array_append (&surface->xobjects, &resource, 1);
/* XXX: Should be checking the return value here. */
_cairo_array_append (&surface->xobjects, &resource);
}
static unsigned int
@ -260,7 +261,8 @@ _cairo_pdf_surface_add_alpha (cairo_pdf_surface_t *surface, double alpha)
return i;
}
_cairo_array_append (&surface->alphas, &alpha, 1);
/* XXX: Should be checking the return value here. */
_cairo_array_append (&surface->alphas, &alpha);
return _cairo_array_num_elements (&surface->alphas) - 1;
}
@ -278,7 +280,8 @@ _cairo_pdf_surface_add_font (cairo_pdf_surface_t *surface, unsigned int id)
}
resource.id = id;
_cairo_array_append (&surface->fonts, &resource, 1);
/* XXX: Should be checking the return value here. */
_cairo_array_append (&surface->fonts, &resource);
}
static cairo_surface_t *
@ -710,7 +713,7 @@ _cairo_pdf_surface_composite_pdf (cairo_pdf_surface_t *dst,
}
static cairo_int_status_t
_cairo_pdf_surface_composite (cairo_operator_t operator,
_cairo_pdf_surface_composite (cairo_operator_t op,
cairo_pattern_t *src_pattern,
cairo_pattern_t *mask_pattern,
void *abstract_dst,
@ -740,7 +743,7 @@ _cairo_pdf_surface_composite (cairo_operator_t operator,
static cairo_int_status_t
_cairo_pdf_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t operator,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects)
@ -766,7 +769,7 @@ _cairo_pdf_surface_fill_rectangles (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
}
static void
static cairo_status_t
emit_solid_pattern (cairo_pdf_surface_t *surface,
cairo_solid_pattern_t *pattern)
{
@ -782,11 +785,13 @@ emit_solid_pattern (cairo_pdf_surface_t *surface,
pattern->color.green,
pattern->color.blue,
alpha);
return CAIRO_STATUS_SUCCESS;
}
static void
static cairo_status_t
emit_surface_pattern (cairo_pdf_surface_t *dst,
cairo_surface_pattern_t *pattern)
cairo_surface_pattern_t *pattern)
{
cairo_pdf_document_t *document = dst->document;
cairo_output_stream_t *output = document->output_stream;
@ -797,13 +802,14 @@ emit_surface_pattern (cairo_pdf_surface_t *dst,
unsigned int id, alpha;
cairo_matrix_t pm;
if (pattern->surface->backend == &cairo_pdf_surface_backend) {
return;
}
/* XXX: This is broken. We need new code here to actually emit the
* PDF surface. */
if (pattern->surface->backend == &cairo_pdf_surface_backend)
return CAIRO_STATUS_SUCCESS;
status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra);
if (status)
return;
return status;
_cairo_pdf_document_close_stream (document);
@ -841,48 +847,155 @@ emit_surface_pattern (cairo_pdf_surface_t *dst,
stream->id, alpha);
_cairo_surface_release_source_image (pattern->surface, image, image_extra);
return CAIRO_STATUS_SUCCESS;
}
typedef struct _cairo_pdf_color_stop {
double offset;
unsigned int gradient_id;
unsigned char color_char[4];
} cairo_pdf_color_stop_t;
static unsigned int
emit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradient_pattern_t *pattern)
emit_linear_colorgradient (cairo_pdf_document_t *document,
cairo_pdf_color_stop_t *stop1,
cairo_pdf_color_stop_t *stop2)
{
cairo_pdf_document_t *document = surface->document;
cairo_output_stream_t *output = document->output_stream;
unsigned int function_id;
char stops[2][3];
function_id = _cairo_pdf_document_new_object (document);
unsigned int function_id = _cairo_pdf_document_new_object (document);
_cairo_output_stream_printf (output,
"%d 0 obj\r\n"
"<< /FunctionType 0\r\n"
" /Domain [ 0.0 1.0 ]\r\n"
" /Domain [ 0 1 ]\r\n"
" /Size [ 2 ]\r\n"
" /BitsPerSample 8\r\n"
" /Range [ 0.0 1.0 0.0 1.0 0.0 1.0 ]\r\n"
" /Range [ 0 1 0 1 0 1 ]\r\n"
" /Length 6\r\n"
">>\r\n"
"stream\r\n",
function_id);
stops[0][0] = pattern->stops[0].color.red * 0xff + 0.5;
stops[0][1] = pattern->stops[0].color.green * 0xff + 0.5;
stops[0][2] = pattern->stops[0].color.blue * 0xff + 0.5;
stops[1][0] = pattern->stops[1].color.red * 0xff + 0.5;
stops[1][1] = pattern->stops[1].color.green * 0xff + 0.5;
stops[1][2] = pattern->stops[1].color.blue * 0xff + 0.5;
_cairo_output_stream_write (output, stops, sizeof (stops));
_cairo_output_stream_write (output, stop1->color_char, 3);
_cairo_output_stream_write (output, stop2->color_char, 3);
_cairo_output_stream_printf (output,
"\r\n"
"endstream\r\n"
"endobj\r\n");
return function_id;
}
static unsigned int
emit_stiched_colorgradient (cairo_pdf_document_t *document,
unsigned int n_stops,
cairo_pdf_color_stop_t stops[])
{
cairo_output_stream_t *output = document->output_stream;
unsigned int function_id;
unsigned int i;
/* emit linear gradients between pairs of subsequent stops... */
for (i = 0; i < n_stops-1; i++) {
stops[i].gradient_id = emit_linear_colorgradient (document,
&stops[i],
&stops[i+1]);
}
/* ... and stich them together */
function_id = _cairo_pdf_document_new_object (document);
_cairo_output_stream_printf (output,
"%d 0 obj\r\n"
"<< /FunctionType 3\r\n"
" /Domain [ 0 1 ]\r\n"
" /Functions [ ",
function_id);
for (i = 0; i < n_stops-1; i++)
_cairo_output_stream_printf (output, "%d 0 R ", stops[i].gradient_id);
_cairo_output_stream_printf (output,
"]\r\n"
" /Bounds [ ");
for (i = 1; i < n_stops-1; i++)
_cairo_output_stream_printf (output, "%f ", stops[i].offset);
_cairo_output_stream_printf (output,
"]\r\n"
" /Encode [ ");
for (i = 1; i < n_stops; i++)
_cairo_output_stream_printf (output, "0 1 ");
_cairo_output_stream_printf (output,
"]\r\n"
">>\r\n"
"endobj\r\n");
return function_id;
}
static void
#define COLOR_STOP_EPSILLON 1e-6
static unsigned int
emit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradient_pattern_t *pattern)
{
cairo_pdf_document_t *document = surface->document;
unsigned int function_id;
cairo_pdf_color_stop_t *allstops, *stops;
unsigned int n_stops;
unsigned int i;
function_id = _cairo_pdf_document_new_object (document);
allstops = malloc ((pattern->n_stops + 2) * sizeof (cairo_pdf_color_stop_t));
if (allstops == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return 0;
}
stops = &allstops[1];
n_stops = pattern->n_stops;
for (i = 0; i < pattern->n_stops; i++) {
stops[i].color_char[0] = pattern->stops[i].color.red >> 8;
stops[i].color_char[1] = pattern->stops[i].color.green >> 8;
stops[i].color_char[2] = pattern->stops[i].color.blue >> 8;
stops[i].color_char[3] = pattern->stops[i].color.alpha >> 8;
stops[i].offset = _cairo_fixed_to_double (pattern->stops[i].x);
}
/* make sure first offset is 0.0 and last offset is 1.0. (Otherwise Acrobat
* Reader chokes.) */
if (stops[0].offset > COLOR_STOP_EPSILLON) {
memcpy (allstops, stops, sizeof (cairo_pdf_color_stop_t));
stops = allstops;
stops[0].offset = 0.0;
n_stops++;
}
if (stops[n_stops-1].offset < 1.0 - COLOR_STOP_EPSILLON) {
memcpy (&stops[n_stops],
&stops[n_stops - 1],
sizeof (cairo_pdf_color_stop_t));
stops[n_stops].offset = 1.0;
n_stops++;
}
if (n_stops == 2) {
/* no need for stiched function */
function_id = emit_linear_colorgradient (document, &stops[0], &stops[1]);
} else {
/* multiple stops: stich. XXX possible optimization: regulary spaced
* stops do not require stiching. XXX */
function_id = emit_stiched_colorgradient (document,
n_stops,
stops);
}
free (allstops);
return function_id;
}
static cairo_status_t
emit_linear_pattern (cairo_pdf_surface_t *surface, cairo_linear_pattern_t *pattern)
{
cairo_pdf_document_t *document = surface->document;
@ -894,15 +1007,17 @@ emit_linear_pattern (cairo_pdf_surface_t *surface, cairo_linear_pattern_t *patte
_cairo_pdf_document_close_stream (document);
function_id = emit_pattern_stops (surface, &pattern->base);
if (function_id == 0)
return CAIRO_STATUS_NO_MEMORY;
p2u = pattern->base.base.matrix;
cairo_matrix_invert (&p2u);
x0 = pattern->point0.x;
y0 = pattern->point0.y;
x0 = _cairo_fixed_to_double (pattern->gradient.p1.x);
y0 = _cairo_fixed_to_double (pattern->gradient.p1.y);
cairo_matrix_transform_point (&p2u, &x0, &y0);
x1 = pattern->point1.x;
y1 = pattern->point1.y;
x1 = _cairo_fixed_to_double (pattern->gradient.p2.x);
y1 = _cairo_fixed_to_double (pattern->gradient.p2.y);
cairo_matrix_transform_point (&p2u, &x1, &y1);
pattern_id = _cairo_pdf_document_new_object (document);
@ -934,9 +1049,11 @@ emit_linear_pattern (cairo_pdf_surface_t *surface, cairo_linear_pattern_t *patte
_cairo_output_stream_printf (output,
"/Pattern cs /res%d scn /a%d gs\r\n",
pattern_id, alpha);
return CAIRO_STATUS_SUCCESS;
}
static void
static cairo_status_t
emit_radial_pattern (cairo_pdf_surface_t *surface, cairo_radial_pattern_t *pattern)
{
cairo_pdf_document_t *document = surface->document;
@ -948,17 +1065,19 @@ emit_radial_pattern (cairo_pdf_surface_t *surface, cairo_radial_pattern_t *patte
_cairo_pdf_document_close_stream (document);
function_id = emit_pattern_stops (surface, &pattern->base);
if (function_id == 0)
return CAIRO_STATUS_NO_MEMORY;
p2u = pattern->base.base.matrix;
cairo_matrix_invert (&p2u);
x0 = pattern->center0.x;
y0 = pattern->center0.y;
r0 = pattern->radius0;
x0 = _cairo_fixed_to_double (pattern->gradient.inner.x);
y0 = _cairo_fixed_to_double (pattern->gradient.inner.y);
r0 = _cairo_fixed_to_double (pattern->gradient.inner.radius);
cairo_matrix_transform_point (&p2u, &x0, &y0);
x1 = pattern->center1.x;
y1 = pattern->center1.y;
r1 = pattern->radius1;
x1 = _cairo_fixed_to_double (pattern->gradient.outer.x);
y1 = _cairo_fixed_to_double (pattern->gradient.outer.y);
r1 = _cairo_fixed_to_double (pattern->gradient.outer.radius);
cairo_matrix_transform_point (&p2u, &x1, &y1);
/* FIXME: This is surely crack, but how should you scale a radius
@ -1001,28 +1120,29 @@ emit_radial_pattern (cairo_pdf_surface_t *surface, cairo_radial_pattern_t *patte
_cairo_output_stream_printf (output,
"/Pattern cs /res%d scn /a%d gs\r\n",
pattern_id, alpha);
return CAIRO_STATUS_SUCCESS;
}
static void
static cairo_status_t
emit_pattern (cairo_pdf_surface_t *surface, cairo_pattern_t *pattern)
{
switch (pattern->type) {
case CAIRO_PATTERN_SOLID:
emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
break;
return emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
case CAIRO_PATTERN_SURFACE:
emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);
break;
return emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);
case CAIRO_PATTERN_LINEAR:
emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern);
break;
return emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern);
case CAIRO_PATTERN_RADIAL:
emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern);
break;
return emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern);
}
ASSERT_NOT_REACHED;
return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
}
static double
@ -1108,20 +1228,23 @@ _cairo_pdf_path_close_path (void *closure)
}
static cairo_int_status_t
_cairo_pdf_surface_fill_path (cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_dst,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance)
_cairo_pdf_surface_fill (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *pattern,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias)
{
cairo_pdf_surface_t *surface = abstract_dst;
cairo_pdf_surface_t *surface = abstract_surface;
cairo_pdf_document_t *document = surface->document;
const char *pdf_operator;
cairo_status_t status;
pdf_path_info_t info;
emit_pattern (surface, pattern);
status = emit_pattern (surface, pattern);
if (status)
return status;
/* After the above switch the current stream should belong to this
* surface, so no need to _cairo_pdf_surface_ensure_stream() */
@ -1158,7 +1281,7 @@ _cairo_pdf_surface_fill_path (cairo_operator_t operator,
}
static cairo_int_status_t
_cairo_pdf_surface_composite_trapezoids (cairo_operator_t operator,
_cairo_pdf_surface_composite_trapezoids (cairo_operator_t op,
cairo_pattern_t *pattern,
void *abstract_dst,
cairo_antialias_t antialias,
@ -1174,9 +1297,12 @@ _cairo_pdf_surface_composite_trapezoids (cairo_operator_t operator,
cairo_pdf_surface_t *surface = abstract_dst;
cairo_pdf_document_t *document = surface->document;
cairo_output_stream_t *output = document->output_stream;
cairo_int_status_t status;
int i;
emit_pattern (surface, pattern);
status = emit_pattern (surface, pattern);
if (status)
return status;
/* After the above switch the current stream should belong to this
* surface, so no need to _cairo_pdf_surface_ensure_stream() */
@ -1253,6 +1379,7 @@ static cairo_font_subset_t *
_cairo_pdf_document_get_font (cairo_pdf_document_t *document,
cairo_scaled_font_t *scaled_font)
{
cairo_status_t status;
cairo_unscaled_font_t *unscaled_font;
cairo_font_subset_t *pdf_font;
unsigned int num_fonts, i;
@ -1279,7 +1406,8 @@ _cairo_pdf_document_get_font (cairo_pdf_document_t *document,
pdf_font->font_id = _cairo_pdf_document_new_object (document);
if (_cairo_array_append (&document->fonts, &pdf_font, 1) == NULL) {
status = _cairo_array_append (&document->fonts, &pdf_font);
if (status) {
_cairo_font_subset_destroy (pdf_font);
return NULL;
}
@ -1288,23 +1416,24 @@ _cairo_pdf_document_get_font (cairo_pdf_document_t *document,
}
static cairo_int_status_t
_cairo_pdf_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_surface,
int source_x,
int source_y,
int dest_x,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
int num_glyphs)
_cairo_pdf_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t op,
cairo_pattern_t *pattern,
void *abstract_surface,
int source_x,
int source_y,
int dest_x,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_pdf_surface_t *surface = abstract_surface;
cairo_pdf_document_t *document = surface->document;
cairo_output_stream_t *output = document->output_stream;
cairo_font_subset_t *pdf_font;
cairo_int_status_t status;
int i, index;
double det;
@ -1323,7 +1452,9 @@ _cairo_pdf_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
if (fabs (det) < 0.000001)
return CAIRO_STATUS_SUCCESS;
emit_pattern (surface, pattern);
status = emit_pattern (surface, pattern);
if (status)
return status;
_cairo_output_stream_printf (output,
"BT /res%u 1 Tf", pdf_font->font_id);
@ -1432,9 +1563,20 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = {
NULL, /* set_clip_region */
_cairo_pdf_surface_intersect_clip_path,
_cairo_pdf_surface_get_extents,
_cairo_pdf_surface_show_glyphs,
_cairo_pdf_surface_fill_path,
_cairo_pdf_surface_get_font_options
_cairo_pdf_surface_old_show_glyphs,
_cairo_pdf_surface_get_font_options,
NULL, /* flush */
NULL, /* mark_dirty_rectangle */
NULL, /* scaled_font_fini */
NULL, /* scaled_glyph_fini */
/* Here are the drawing functions */
NULL, /* paint */
NULL, /* mask */
NULL, /* stroke */
_cairo_pdf_surface_fill,
NULL /* show_glyphs */
};
static cairo_pdf_document_t *
@ -1747,6 +1889,7 @@ static cairo_status_t
_cairo_pdf_document_add_page (cairo_pdf_document_t *document,
cairo_pdf_surface_t *surface)
{
cairo_status_t status;
cairo_pdf_stream_t *stream;
cairo_pdf_resource_t *res;
cairo_output_stream_t *output = document->output_stream;
@ -1852,7 +1995,9 @@ _cairo_pdf_document_add_page (cairo_pdf_document_t *document,
">>\r\n"
"endobj\r\n");
_cairo_array_append (&document->pages, &page_id, 1);
status = _cairo_array_append (&document->pages, &page_id);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}

Просмотреть файл

@ -36,8 +36,6 @@
#include "cairoint.h"
#include "cairo-gstate-private.h"
static int
_cairo_pen_vertices_needed (double tolerance, double radius, cairo_matrix_t *matrix);
@ -59,35 +57,28 @@ _cairo_pen_init_empty (cairo_pen_t *pen)
}
cairo_status_t
_cairo_pen_init (cairo_pen_t *pen, double radius, cairo_gstate_t *gstate)
_cairo_pen_init (cairo_pen_t *pen,
double radius,
double tolerance,
cairo_matrix_t *ctm)
{
int i;
int reflect;
double det;
if (pen->num_vertices) {
/* XXX: It would be nice to notice that the pen is already properly constructed.
However, this test would also have to account for possible changes in the transformation
matrix.
if (pen->radius == radius && pen->tolerance == tolerance)
return CAIRO_STATUS_SUCCESS;
*/
_cairo_pen_fini (pen);
}
pen->radius = radius;
pen->tolerance = gstate->tolerance;
pen->tolerance = tolerance;
_cairo_matrix_compute_determinant (&gstate->ctm, &det);
_cairo_matrix_compute_determinant (ctm, &det);
if (det >= 0) {
reflect = 0;
} else {
reflect = 1;
}
pen->num_vertices = _cairo_pen_vertices_needed (gstate->tolerance,
pen->num_vertices = _cairo_pen_vertices_needed (tolerance,
radius,
&gstate->ctm);
ctm);
pen->vertices = malloc (pen->num_vertices * sizeof (cairo_pen_vertex_t));
if (pen->vertices == NULL) {
@ -105,7 +96,7 @@ _cairo_pen_init (cairo_pen_t *pen, double radius, cairo_gstate_t *gstate)
double dx = radius * cos (reflect ? -theta : theta);
double dy = radius * sin (reflect ? -theta : theta);
cairo_pen_vertex_t *v = &pen->vertices[i];
cairo_matrix_transform_distance (&gstate->ctm, &dx, &dy);
cairo_matrix_transform_distance (ctm, &dx, &dy);
v->point.x = _cairo_fixed_from_double (dx);
v->point.y = _cairo_fixed_from_double (dy);
}

Просмотреть файл

@ -34,6 +34,7 @@
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
* Kristian Høgsberg <krh@redhat.com>
* Keith Packard <keithp@keithp.com>
*/
#include "cairoint.h"
@ -105,8 +106,8 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
surface->base.device_x_scale = surface->x_dpi / 72.0;
surface->base.device_y_scale = surface->y_dpi / 72.0;
surface->current_page = _cairo_meta_surface_create (width,
height);
surface->current_page = _cairo_meta_surface_create (width * surface->x_dpi / 72,
height * surface->y_dpi / 72);
if (surface->current_page->status) {
free (surface);
_cairo_error (CAIRO_STATUS_NO_MEMORY);
@ -194,7 +195,7 @@ _cairo_ps_surface_finish (void *abstract_surface)
/* Document header */
_cairo_output_stream_printf (surface->stream,
"%%!PS-Adobe-3.0\n"
"%%%%Creator: Cairo (http://cairographics.org)\n"
"%%%%Creator: cairo (http://cairographics.org)\n"
"%%%%CreationDate: %s"
"%%%%Title: Some clever title\n"
"%%%%Pages: %d\n"
@ -247,82 +248,6 @@ _cairo_ps_surface_finish (void *abstract_surface)
return status;
}
static cairo_int_status_t
_cairo_ps_surface_composite (cairo_operator_t operator,
cairo_pattern_t *src_pattern,
cairo_pattern_t *mask_pattern,
void *abstract_dst,
int src_x,
int src_y,
int mask_x,
int mask_y,
int dst_x,
int dst_y,
unsigned int width,
unsigned int height)
{
cairo_ps_surface_t *surface = abstract_dst;
return _cairo_surface_composite (operator,
src_pattern,
mask_pattern,
surface->current_page,
src_x,
src_y,
mask_x,
mask_y,
dst_x,
dst_y,
width,
height);
}
static cairo_int_status_t
_cairo_ps_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t operator,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects)
{
cairo_ps_surface_t *surface = abstract_surface;
return _cairo_surface_fill_rectangles (surface->current_page,
operator,
color,
rects,
num_rects);
}
static cairo_int_status_t
_cairo_ps_surface_composite_trapezoids (cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_dst,
cairo_antialias_t antialias,
int x_src,
int y_src,
int x_dst,
int y_dst,
unsigned int width,
unsigned int height,
cairo_trapezoid_t *traps,
int num_traps)
{
cairo_ps_surface_t *surface = abstract_dst;
return _cairo_surface_composite_trapezoids (operator,
pattern,
surface->current_page,
antialias,
x_src,
y_src,
x_dst,
y_dst,
width,
height,
traps,
num_traps);
}
static cairo_int_status_t
_cairo_ps_surface_copy_page (void *abstract_surface)
{
@ -336,11 +261,15 @@ _cairo_ps_surface_copy_page (void *abstract_surface)
static cairo_int_status_t
_cairo_ps_surface_show_page (void *abstract_surface)
{
cairo_status_t status;
cairo_ps_surface_t *surface = abstract_surface;
_cairo_array_append (&surface->pages, &surface->current_page, 1);
surface->current_page = _cairo_meta_surface_create (surface->width,
surface->height);
status = _cairo_array_append (&surface->pages, &surface->current_page);
if (status)
return status;
surface->current_page = _cairo_meta_surface_create (surface->width * surface->x_dpi / 72,
surface->height * surface->y_dpi / 72);
if (surface->current_page->status)
return CAIRO_STATUS_NO_MEMORY;
@ -386,6 +315,7 @@ static cairo_font_subset_t *
_cairo_ps_surface_get_font (cairo_ps_surface_t *surface,
cairo_scaled_font_t *scaled_font)
{
cairo_status_t status;
cairo_unscaled_font_t *unscaled_font;
cairo_font_subset_t *subset;
unsigned int num_fonts, i;
@ -409,7 +339,9 @@ _cairo_ps_surface_get_font (cairo_ps_surface_t *surface,
return NULL;
subset->font_id = surface->fonts.num_elements;
if (_cairo_array_append (&surface->fonts, &subset, 1) == NULL) {
status = _cairo_array_append (&surface->fonts, &subset);
if (status) {
_cairo_font_subset_destroy (subset);
return NULL;
}
@ -418,65 +350,95 @@ _cairo_ps_surface_get_font (cairo_ps_surface_t *surface,
}
static cairo_int_status_t
_cairo_ps_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_surface,
int source_x,
int source_y,
int dest_x,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
int num_glyphs)
_cairo_ps_surface_paint (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source)
{
cairo_ps_surface_t *surface = abstract_surface;
cairo_font_subset_t *subset;
int i;
/* XXX: Need to fix this to work with a general cairo_scaled_font_t. */
if (! _cairo_scaled_font_is_ft (scaled_font))
return CAIRO_INT_STATUS_UNSUPPORTED;
assert (_cairo_surface_is_meta (surface->current_page));
/* Collect font subset info as we go. */
subset = _cairo_ps_surface_get_font (surface, scaled_font);
if (subset == NULL)
return CAIRO_STATUS_NO_MEMORY;
for (i = 0; i < num_glyphs; i++)
_cairo_font_subset_use_glyph (subset, glyphs[i].index);
return _cairo_surface_show_glyphs (scaled_font,
operator,
pattern,
surface->current_page,
source_x,
source_y,
dest_x,
dest_y,
width,
height,
glyphs,
num_glyphs);
return _cairo_surface_paint (surface->current_page, op, source);
}
static cairo_int_status_t
_cairo_ps_surface_fill_path (cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_dst,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance)
_cairo_ps_surface_mask (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_pattern_t *mask)
{
cairo_ps_surface_t *surface = abstract_dst;
cairo_ps_surface_t *surface = abstract_surface;
return _cairo_surface_fill_path (operator,
pattern,
surface->current_page,
path,
fill_rule,
tolerance);
assert (_cairo_surface_is_meta (surface->current_page));
return _cairo_surface_mask (surface->current_page, op, source,
mask);
}
static cairo_int_status_t
_cairo_ps_surface_stroke (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_stroke_style_t *style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias)
{
cairo_ps_surface_t *surface = abstract_surface;
assert (_cairo_surface_is_meta (surface->current_page));
return _cairo_surface_stroke (surface->current_page, op, source,
path, style,
ctm, ctm_inverse,
tolerance, antialias);
}
static cairo_int_status_t
_cairo_ps_surface_fill (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias)
{
cairo_ps_surface_t *surface = abstract_surface;
assert (_cairo_surface_is_meta (surface->current_page));
return _cairo_surface_fill (surface->current_page, op, source,
path, fill_rule,
tolerance, antialias);
}
static cairo_int_status_t
_cairo_ps_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{
cairo_ps_surface_t *surface = abstract_surface;
assert (_cairo_surface_is_meta (surface->current_page));
return _cairo_surface_show_glyphs (surface->current_page, op, source,
glyphs, num_glyphs,
scaled_font);
}
static cairo_surface_t *
_cairo_ps_surface_snapshot (void *abstract_surface)
{
cairo_ps_surface_t *surface = abstract_surface;
assert (_cairo_surface_is_meta (surface->current_page));
return _cairo_surface_snapshot (surface->current_page);
}
static const cairo_surface_backend_t cairo_ps_surface_backend = {
@ -487,16 +449,30 @@ static const cairo_surface_backend_t cairo_ps_surface_backend = {
NULL, /* acquire_dest_image */
NULL, /* release_dest_image */
NULL, /* clone_similar */
_cairo_ps_surface_composite,
_cairo_ps_surface_fill_rectangles,
_cairo_ps_surface_composite_trapezoids,
NULL, /* composite */
NULL, /* fill_rectangles */
NULL, /* composite_trapezoids */
_cairo_ps_surface_copy_page,
_cairo_ps_surface_show_page,
NULL, /* set_clip_region */
_cairo_ps_surface_intersect_clip_path,
_cairo_ps_surface_get_extents,
NULL, /* old_show_glyphs */
NULL, /* get_font_options */
NULL, /* flush */
NULL, /* mark_dirty_rectangle */
NULL, /* scaled_font_fini */
NULL, /* scaled_glyph_fini */
/* Here are the drawing functions */
_cairo_ps_surface_paint,
_cairo_ps_surface_mask,
_cairo_ps_surface_stroke,
_cairo_ps_surface_fill,
_cairo_ps_surface_show_glyphs,
_cairo_ps_surface_fill_path
_cairo_ps_surface_snapshot
};
static cairo_int_status_t
@ -572,57 +548,30 @@ _cairo_ps_surface_write_font_subsets (cairo_ps_surface_t *surface)
return CAIRO_STATUS_SUCCESS;
}
typedef struct _cairo_ps_fallback_area cairo_ps_fallback_area_t;
struct _cairo_ps_fallback_area {
int x, y;
unsigned int width, height;
cairo_ps_fallback_area_t *next;
};
typedef struct _ps_output_surface {
cairo_surface_t base;
cairo_ps_surface_t *parent;
cairo_ps_fallback_area_t *fallback_areas;
cairo_bool_t fallback;
} ps_output_surface_t;
/*
* XXX for now, just a page-wide boolean
* Doing a better job is harder as it must
* avoid rendering the same object in pieces
*/
static cairo_int_status_t
_ps_output_add_fallback_area (ps_output_surface_t *surface,
int x, int y,
unsigned int width,
unsigned int height)
{
cairo_ps_fallback_area_t *area;
/* FIXME: Do a better job here. Ideally, we would use a 32 bit
* region type, but probably just computing bounding boxes would
* also work fine. */
area = malloc (sizeof (cairo_ps_fallback_area_t));
if (area == NULL)
return CAIRO_STATUS_NO_MEMORY;
area->x = x;
area->y = y;
area->width = width;
area->height = height;
area->next = surface->fallback_areas;
surface->fallback_areas = area;
surface->fallback = TRUE;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_ps_output_finish (void *abstract_surface)
{
ps_output_surface_t *surface = abstract_surface;
cairo_ps_fallback_area_t *area, *next;
for (area = surface->fallback_areas; area != NULL; area = next) {
next = area->next;
free (area);
}
return CAIRO_STATUS_SUCCESS;
}
@ -642,24 +591,162 @@ color_is_translucent (const cairo_color_t *color)
}
static cairo_bool_t
pattern_is_translucent (cairo_pattern_t *abstract_pattern)
format_is_translucent (cairo_format_t format)
{
cairo_pattern_union_t *pattern;
switch (format) {
case CAIRO_FORMAT_ARGB32:
return TRUE;
case CAIRO_FORMAT_RGB24:
return FALSE;
case CAIRO_FORMAT_A8:
return TRUE;
case CAIRO_FORMAT_A1:
return TRUE;
}
return TRUE;
}
static cairo_bool_t
surface_is_translucent (const cairo_surface_t *surface)
{
if (_cairo_surface_is_image (surface)) {
const cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
return format_is_translucent (image_surface->format);
}
return TRUE;
}
static cairo_bool_t
gradient_is_translucent (const cairo_gradient_pattern_t *gradient)
{
return TRUE; /* XXX no gradient support */
#if 0
int i;
for (i = 0; i < gradient->n_stops; i++)
if (color_is_translucent (&gradient->stops[i].color))
return TRUE;
return FALSE;
#endif
}
static cairo_bool_t
pattern_is_translucent (const cairo_pattern_t *abstract_pattern)
{
const cairo_pattern_union_t *pattern;
pattern = (cairo_pattern_union_t *) abstract_pattern;
switch (pattern->base.type) {
case CAIRO_PATTERN_SOLID:
return color_is_translucent (&pattern->solid.color);
case CAIRO_PATTERN_SURFACE:
return surface_is_translucent (pattern->surface.surface);
case CAIRO_PATTERN_LINEAR:
case CAIRO_PATTERN_RADIAL:
return FALSE;
return gradient_is_translucent (&pattern->gradient.base);
}
ASSERT_NOT_REACHED;
return FALSE;
}
static cairo_bool_t
operator_always_opaque (cairo_operator_t op)
{
switch (op) {
case CAIRO_OPERATOR_CLEAR:
case CAIRO_OPERATOR_SOURCE:
return TRUE;
case CAIRO_OPERATOR_OVER:
case CAIRO_OPERATOR_IN:
case CAIRO_OPERATOR_OUT:
case CAIRO_OPERATOR_ATOP:
return FALSE;
case CAIRO_OPERATOR_DEST:
return TRUE;
case CAIRO_OPERATOR_DEST_OVER:
case CAIRO_OPERATOR_DEST_IN:
case CAIRO_OPERATOR_DEST_OUT:
case CAIRO_OPERATOR_DEST_ATOP:
return FALSE;
case CAIRO_OPERATOR_XOR:
case CAIRO_OPERATOR_ADD:
case CAIRO_OPERATOR_SATURATE:
return FALSE;
}
return FALSE;
}
static cairo_bool_t
operator_always_translucent (cairo_operator_t op)
{
switch (op) {
case CAIRO_OPERATOR_CLEAR:
case CAIRO_OPERATOR_SOURCE:
return FALSE;
case CAIRO_OPERATOR_OVER:
case CAIRO_OPERATOR_IN:
case CAIRO_OPERATOR_OUT:
case CAIRO_OPERATOR_ATOP:
return FALSE;
case CAIRO_OPERATOR_DEST:
return FALSE;
case CAIRO_OPERATOR_DEST_OVER:
case CAIRO_OPERATOR_DEST_IN:
case CAIRO_OPERATOR_DEST_OUT:
case CAIRO_OPERATOR_DEST_ATOP:
return FALSE;
case CAIRO_OPERATOR_XOR:
case CAIRO_OPERATOR_ADD:
case CAIRO_OPERATOR_SATURATE:
return TRUE;
}
return TRUE;
}
static cairo_bool_t
color_operation_needs_fallback (cairo_operator_t op,
const cairo_color_t *color)
{
if (operator_always_opaque (op))
return FALSE;
if (operator_always_translucent (op))
return TRUE;
return color_is_translucent (color);
}
static cairo_bool_t
pattern_type_supported (const cairo_pattern_t *pattern)
{
if (pattern->type == CAIRO_PATTERN_SOLID)
return TRUE;
return FALSE;
}
static cairo_bool_t
pattern_operation_needs_fallback (cairo_operator_t op,
const cairo_pattern_t *pattern)
{
if (! pattern_type_supported (pattern))
return TRUE;
if (operator_always_opaque (op))
return FALSE;
if (operator_always_translucent (op))
return TRUE;
return pattern_is_translucent (pattern);
}
/* PS Output - this section handles output of the parts of the meta
* surface we can render natively in PS. */
@ -711,7 +798,12 @@ emit_image (cairo_ps_surface_t *surface,
_cairo_pattern_init_for_surface (&pattern.surface, &image->base);
_cairo_surface_composite (CAIRO_OPERATOR_DEST_OVER,
_cairo_surface_fill_rectangle (opaque,
CAIRO_OPERATOR_SOURCE,
CAIRO_COLOR_WHITE,
0, 0, image->width, image->height);
_cairo_surface_composite (CAIRO_OPERATOR_OVER,
&pattern.base,
NULL,
opaque,
@ -812,18 +904,21 @@ static void
emit_surface_pattern (cairo_ps_surface_t *surface,
cairo_surface_pattern_t *pattern)
{
/* XXX: NYI */
}
static void
emit_linear_pattern (cairo_ps_surface_t *surface,
cairo_linear_pattern_t *pattern)
{
/* XXX: NYI */
}
static void
emit_radial_pattern (cairo_ps_surface_t *surface,
cairo_radial_pattern_t *pattern)
{
/* XXX: NYI */
}
static void
@ -854,7 +949,7 @@ emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pattern)
static cairo_int_status_t
_ps_output_composite (cairo_operator_t operator,
_ps_output_composite (cairo_operator_t op,
cairo_pattern_t *src_pattern,
cairo_pattern_t *mask_pattern,
void *abstract_dst,
@ -874,6 +969,9 @@ _ps_output_composite (cairo_operator_t operator,
cairo_image_surface_t *image;
void *image_extra;
if (surface->fallback)
return CAIRO_STATUS_SUCCESS;
if (mask_pattern) {
/* FIXME: Investigate how this can be done... we'll probably
* need pixmap fallbacks for this, though. */
@ -928,7 +1026,7 @@ bail:
static cairo_int_status_t
_ps_output_fill_rectangles (void *abstract_surface,
cairo_operator_t operator,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects)
@ -938,10 +1036,13 @@ _ps_output_fill_rectangles (void *abstract_surface,
cairo_solid_pattern_t solid;
int i;
if (surface->fallback)
return CAIRO_STATUS_SUCCESS;
if (!num_rects)
return CAIRO_STATUS_SUCCESS;
if (color_is_translucent (color)) {
if (color_operation_needs_fallback (op, color)) {
int min_x = rects[0].x;
int min_y = rects[0].y;
int max_x = rects[0].x + rects[0].width;
@ -986,7 +1087,7 @@ intersect (cairo_line_t *line, cairo_fixed_t y)
}
static cairo_int_status_t
_ps_output_composite_trapezoids (cairo_operator_t operator,
_ps_output_composite_trapezoids (cairo_operator_t op,
cairo_pattern_t *pattern,
void *abstract_dst,
cairo_antialias_t antialias,
@ -1003,7 +1104,10 @@ _ps_output_composite_trapezoids (cairo_operator_t operator,
cairo_output_stream_t *stream = surface->parent->stream;
int i;
if (pattern_is_translucent (pattern))
if (surface->fallback)
return CAIRO_STATUS_SUCCESS;
if (pattern_operation_needs_fallback (op, pattern))
return _ps_output_add_fallback_area (surface, x_dst, y_dst, width, height);
_cairo_output_stream_printf (stream,
@ -1123,6 +1227,9 @@ _ps_output_intersect_clip_path (void *abstract_surface,
ps_output_path_info_t info;
const char *ps_operator;
if (surface->fallback)
return CAIRO_STATUS_SUCCESS;
_cairo_output_stream_printf (stream,
"%% _ps_output_intersect_clip_path\n");
@ -1162,33 +1269,39 @@ _ps_output_intersect_clip_path (void *abstract_surface,
static cairo_int_status_t
_ps_output_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_surface,
int source_x,
int source_y,
int dest_x,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
int num_glyphs)
_ps_output_old_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t op,
cairo_pattern_t *pattern,
void *abstract_surface,
int source_x,
int source_y,
int dest_x,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
int num_glyphs)
{
ps_output_surface_t *surface = abstract_surface;
cairo_output_stream_t *stream = surface->parent->stream;
cairo_font_subset_t *subset;
int i, subset_index;
if (surface->fallback)
return CAIRO_STATUS_SUCCESS;
/* XXX: Need to fix this to work with a general cairo_scaled_font_t. */
if (! _cairo_scaled_font_is_ft (scaled_font))
return CAIRO_INT_STATUS_UNSUPPORTED;
if (pattern_is_translucent (pattern))
if (surface->fallback)
return CAIRO_STATUS_SUCCESS;
if (pattern_operation_needs_fallback (op, pattern))
return _ps_output_add_fallback_area (surface, dest_x, dest_y, width, height);
_cairo_output_stream_printf (stream,
"%% _ps_output_show_glyphs\n");
"%% _ps_output_old_show_glyphs\n");
emit_pattern (surface->parent, pattern);
@ -1223,29 +1336,103 @@ _ps_output_show_glyphs (cairo_scaled_font_t *scaled_font,
return CAIRO_STATUS_SUCCESS;
}
/* XXX: Just stubbing this out for now. Should be able to do much
* better here. */
static cairo_int_status_t
_ps_output_fill_path (cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_dst,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance)
_ps_output_paint (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source)
{
ps_output_surface_t *surface = abstract_dst;
ps_output_surface_t *surface = abstract_surface;
if (pattern_operation_needs_fallback (op, source))
return _ps_output_add_fallback_area (surface,
0, 0,
surface->parent->width,
surface->parent->height);
/* XXX: Should be able to do much better here. */
return _ps_output_add_fallback_area (surface,
0, 0,
surface->parent->width,
surface->parent->height);
}
/* XXX: Just stubbing this out for now. Should be able to do much
* better here. */
static cairo_int_status_t
_ps_output_mask (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_pattern_t *mask)
{
ps_output_surface_t *surface = abstract_surface;
if (pattern_operation_needs_fallback (op, source))
return _ps_output_add_fallback_area (surface,
0, 0,
surface->parent->width,
surface->parent->height);
/* XXX: Should be able to do much better here. */
return _ps_output_add_fallback_area (surface,
0, 0,
surface->parent->width,
surface->parent->height);
}
/* XXX: Just stubbing this out for now. Should be able to do much
* better here. */
static cairo_int_status_t
_ps_output_stroke (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_stroke_style_t *style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias)
{
ps_output_surface_t *surface = abstract_surface;
if (pattern_operation_needs_fallback (op, source))
return _ps_output_add_fallback_area (surface,
0, 0,
surface->parent->width,
surface->parent->height);
/* XXX: Should be able to do much better here. */
return _ps_output_add_fallback_area (surface,
0, 0,
surface->parent->width,
surface->parent->height);
}
static cairo_int_status_t
_ps_output_fill (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias)
{
ps_output_surface_t *surface = abstract_surface;
cairo_output_stream_t *stream = surface->parent->stream;
cairo_int_status_t status;
ps_output_path_info_t info;
const char *ps_operator;
if (pattern_is_translucent (pattern))
if (pattern_operation_needs_fallback (op, source))
return _ps_output_add_fallback_area (surface,
0, 0,
surface->parent->width,
surface->parent->height);
_cairo_output_stream_printf (stream,
"%% _ps_output_fill_path\n");
"%% _ps_output_fill\n");
emit_pattern (surface->parent, pattern);
emit_pattern (surface->parent, source);
info.output_stream = stream;
info.has_current_point = FALSE;
@ -1275,6 +1462,31 @@ _ps_output_fill_path (cairo_operator_t operator,
return status;
}
/* XXX: Just stubbing this out for now. Should be able to do much
* better here. */
static cairo_int_status_t
_ps_output_show_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{
ps_output_surface_t *surface = abstract_surface;
if (pattern_operation_needs_fallback (op, source))
return _ps_output_add_fallback_area (surface,
0, 0,
surface->parent->width,
surface->parent->height);
/* XXX: Should be able to do much better here. */
return _ps_output_add_fallback_area (surface,
0, 0,
surface->parent->width,
surface->parent->height);
}
static const cairo_surface_backend_t ps_output_backend = {
NULL, /* create_similar */
_ps_output_finish,
@ -1291,8 +1503,20 @@ static const cairo_surface_backend_t ps_output_backend = {
NULL, /* set_clip_region */
_ps_output_intersect_clip_path,
NULL, /* get_extents */
_ps_output_show_glyphs,
_ps_output_fill_path
_ps_output_old_show_glyphs,
NULL, /* get_font_options */
NULL, /* flush */
NULL, /* mark_dirty_rectangle */
NULL, /* scaled_font_fini */
NULL, /* scaled_glyph_fini */
/* Here are the drawing functions */
_ps_output_paint,
_ps_output_mask,
_ps_output_stroke,
_ps_output_fill,
_ps_output_show_glyphs
};
static cairo_int_status_t
@ -1306,7 +1530,7 @@ _ps_output_render_fallbacks (cairo_surface_t *surface,
int width, height;
ps_output = (ps_output_surface_t *) surface;
if (ps_output->fallback_areas == NULL)
if (! ps_output->fallback)
return CAIRO_STATUS_SUCCESS;
width = ps_output->parent->width * ps_output->parent->x_dpi / 72;
@ -1356,7 +1580,7 @@ _ps_output_surface_create (cairo_ps_surface_t *parent)
_cairo_surface_init (&ps_output->base, &ps_output_backend);
ps_output->parent = parent;
ps_output->fallback_areas = NULL;
ps_output->fallback = FALSE;
return &ps_output->base;
}

Просмотреть файл

@ -0,0 +1,61 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2004 Calum Robinson
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Calum Robinson
*
* Contributor(s):
* Calum Robinson <calumr@mac.com>
*/
#ifndef CAIRO_QUARTZ_PRIVATE_H
#define CAIRO_QUARTZ_PRIVATE_H
#include <cairoint.h>
#include <cairo-quartz.h>
typedef struct cairo_quartz_surface {
cairo_surface_t base;
CGContextRef context;
cairo_bool_t flipped;
int width;
int height;
cairo_image_surface_t *image;
pixman_region16_t *clip_region;
CGImageRef cgImage;
} cairo_quartz_surface_t;
cairo_bool_t
_cairo_surface_is_quartz (cairo_surface_t *surface);
#endif /* CAIRO_QUARTZ_PRIVATE_H */

Просмотреть файл

@ -35,20 +35,7 @@
#include "cairoint.h"
#include "cairo-private.h"
#include "cairo-quartz.h"
typedef struct cairo_quartz_surface {
cairo_surface_t base;
CGContextRef context;
int width;
int height;
cairo_image_surface_t *image;
CGImageRef cgImage;
} cairo_quartz_surface_t;
#include "cairo-quartz-private.h"
static void
ImageDataReleaseFunc(void *info, const void *data, size_t size)
@ -69,6 +56,9 @@ _cairo_quartz_surface_finish(void *abstract_surface)
if (surface->cgImage)
CGImageRelease(surface->cgImage);
if (surface->clip_region)
pixman_region_destroy (surface->clip_region);
return CAIRO_STATUS_SUCCESS;
}
@ -174,8 +164,17 @@ _cairo_quartz_surface_release_dest_image(void *abstract_surface,
rect = CGRectMake(0, 0, surface->width, surface->height);
if (surface->flipped) {
CGContextSaveGState (surface->context);
CGContextTranslateCTM (surface->context, 0, surface->height);
CGContextScaleCTM (surface->context, 1, -1);
}
CGContextDrawImage(surface->context, rect, surface->cgImage);
if (surface->flipped)
CGContextRestoreGState (surface->context);
memset(surface->image->data, 0, surface->width * surface->height * 4);
}
}
@ -188,6 +187,16 @@ _cairo_quartz_surface_set_clip_region(void *abstract_surface,
unsigned int serial;
serial = _cairo_surface_allocate_clip_serial (&surface->image->base);
if (surface->clip_region)
pixman_region_destroy (surface->clip_region);
if (region) {
surface->clip_region = pixman_region_create ();
pixman_region_copy (surface->clip_region, region);
} else
surface->clip_region = NULL;
return _cairo_surface_set_clip_region(&surface->image->base,
region, serial);
}
@ -222,11 +231,12 @@ static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
_cairo_quartz_surface_set_clip_region,
NULL, /* intersect_clip_path */
_cairo_quartz_surface_get_extents,
NULL /* show_glyphs */
NULL /* old_show_glyphs */
};
cairo_surface_t *cairo_quartz_surface_create(CGContextRef context,
cairo_bool_t flipped,
int width, int height)
{
cairo_quartz_surface_t *surface;
@ -244,6 +254,8 @@ cairo_surface_t *cairo_quartz_surface_create(CGContextRef context,
surface->height = height;
surface->image = NULL;
surface->cgImage = NULL;
surface->clip_region = NULL;
surface->flipped = flipped;
// Set up the image surface which Cairo draws into and we blit to & from.
void *foo;
@ -251,3 +263,9 @@ cairo_surface_t *cairo_quartz_surface_create(CGContextRef context,
return (cairo_surface_t *) surface;
}
int
_cairo_surface_is_quartz (cairo_surface_t *surface)
{
return surface->backend == &cairo_quartz_surface_backend;
}

Просмотреть файл

@ -47,6 +47,7 @@ CAIRO_BEGIN_DECLS
cairo_public cairo_surface_t *
cairo_quartz_surface_create (CGContextRef context,
cairo_bool_t flipped,
int width,
int height);

Просмотреть файл

@ -1,4 +1,4 @@
/* $Id: cairo-scaled-font.c,v 1.1 2005-10-06 04:02:06 vladimir%pobox.com Exp $
/* $Id: cairo-scaled-font.c,v 1.3 2006-01-18 22:15:25 vladimir%pobox.com Exp $
*
* Copyright © 2005 Keith Packard
*
@ -776,7 +776,7 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
cairo_status_t
_cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
cairo_operator_t op,
cairo_pattern_t *pattern,
cairo_surface_t *surface,
int source_x,
@ -785,7 +785,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
int dest_y,
unsigned int width,
unsigned int height,
cairo_glyph_t *glyphs,
const cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_status_t status;
@ -795,14 +795,14 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
/* These operators aren't interpreted the same way by the backends;
* they are implemented in terms of other operators in cairo-gstate.c
*/
assert (operator != CAIRO_OPERATOR_SOURCE && operator != CAIRO_OPERATOR_CLEAR);
assert (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_CLEAR);
if (scaled_font->status)
return scaled_font->status;
if (scaled_font->backend->show_glyphs != NULL) {
status = scaled_font->backend->show_glyphs (scaled_font,
operator, pattern,
op, pattern,
surface,
source_x, source_y,
dest_x, dest_y,
@ -887,7 +887,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
_cairo_pattern_init_for_surface (&mask_pattern, mask);
status = _cairo_surface_composite (operator, pattern, &mask_pattern.base,
status = _cairo_surface_composite (op, pattern, &mask_pattern.base,
surface,
source_x, source_y,
0, 0,

Просмотреть файл

@ -0,0 +1,87 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Carl Worth <cworth@cworth.org>
*/
#include "cairoint.h"
void
_cairo_stroke_style_init (cairo_stroke_style_t *style)
{
style->line_width = CAIRO_GSTATE_LINE_WIDTH_DEFAULT;
style->line_cap = CAIRO_GSTATE_LINE_CAP_DEFAULT;
style->line_join = CAIRO_GSTATE_LINE_JOIN_DEFAULT;
style->miter_limit = CAIRO_GSTATE_MITER_LIMIT_DEFAULT;
style->dash = NULL;
style->num_dashes = 0;
style->dash_offset = 0.0;
}
cairo_status_t
_cairo_stroke_style_init_copy (cairo_stroke_style_t *style,
cairo_stroke_style_t *other)
{
style->line_width = other->line_width;
style->line_cap = other->line_cap;
style->line_join = other->line_join;
style->miter_limit = other->miter_limit;
style->num_dashes = other->num_dashes;
if (other->dash == NULL) {
style->dash = NULL;
} else {
style->dash = malloc (style->num_dashes * sizeof (double));
if (style->dash == NULL)
return CAIRO_STATUS_NO_MEMORY;
memcpy (style->dash, other->dash,
style->num_dashes * sizeof (double));
}
style->dash_offset = other->dash_offset;
return CAIRO_STATUS_SUCCESS;
}
void
_cairo_stroke_style_fini (cairo_stroke_style_t *style)
{
if (style->dash) {
free (style->dash);
style->dash = NULL;
}
style->num_dashes = 0;
}

Просмотреть файл

@ -0,0 +1,119 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2002 University of Southern California
* Copyright © 2005 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is University of Southern
* California.
*
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
*/
#ifndef CAIRO_SURFACE_FALLBACK_PRIVATE_H
#define CAIRO_SURFACE_FALLBACK_PRIVATE_H
#include "cairoint.h"
cairo_private cairo_status_t
_cairo_surface_fallback_paint (cairo_surface_t *surface,
cairo_operator_t op,
cairo_pattern_t *source);
cairo_private cairo_status_t
_cairo_surface_fallback_mask (cairo_surface_t *surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_pattern_t *mask);
cairo_private cairo_status_t
_cairo_surface_fallback_stroke (cairo_surface_t *surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_stroke_style_t *stroke_style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias);
cairo_private cairo_status_t
_cairo_surface_fallback_fill (cairo_surface_t *surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias);
cairo_private cairo_status_t
_cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font);
cairo_private cairo_surface_t *
_cairo_surface_fallback_snapshot (cairo_surface_t *surface);
cairo_private cairo_status_t
_cairo_surface_fallback_composite (cairo_operator_t op,
cairo_pattern_t *src,
cairo_pattern_t *mask,
cairo_surface_t *dst,
int src_x,
int src_y,
int mask_x,
int mask_y,
int dst_x,
int dst_y,
unsigned int width,
unsigned int height);
cairo_private cairo_status_t
_cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects);
cairo_private cairo_status_t
_cairo_surface_fallback_composite_trapezoids (cairo_operator_t op,
cairo_pattern_t *pattern,
cairo_surface_t *dst,
cairo_antialias_t antialias,
int src_x,
int src_y,
int dst_x,
int dst_y,
unsigned int width,
unsigned int height,
cairo_trapezoid_t *traps,
int num_traps);
#endif

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,63 @@
/* cairo - a vector graphics library with display and print output
*
* cairo-svg.h
*
* Copyright © 2005 Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr>
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
*/
#ifndef CAIRO_SVG_H
#define CAIRO_SVG_H
#include <cairo.h>
#if CAIRO_HAS_SVG_SURFACE
CAIRO_BEGIN_DECLS
cairo_surface_t *
cairo_svg_surface_create (const char *filename,
double width_in_points,
double height_in_points);
cairo_surface_t *
cairo_svg_surface_create_for_stream (cairo_write_func_t write_func,
void *closure,
double width_in_points,
double height_in_points);
void
cairo_svg_surface_set_dpi (cairo_surface_t *surface,
double x_dpi,
double y_dpi);
CAIRO_END_DECLS
#else /* CAIRO_HAS_SVG_SURFACE */
# error Cairo was not compiled with support for the svg backend
#endif /* CAIRO_HAS_SVG_SURFACE */
#endif /* CAIRO_SVG_H */

Просмотреть файл

@ -258,6 +258,54 @@ _cairo_traps_translate (cairo_traps_t *traps, int x, int y)
}
}
void
_cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps,
cairo_trapezoid_t *src_traps,
int num_traps,
double tx, double ty,
double sx, double sy)
{
int i;
cairo_fixed_t xoff = _cairo_fixed_from_double (tx);
cairo_fixed_t yoff = _cairo_fixed_from_double (ty);
if (sx == 1.0 && sy == 1.0) {
for (i = 0; i < num_traps; i++) {
offset_traps[i].top = src_traps[i].top + yoff;
offset_traps[i].bottom = src_traps[i].bottom + yoff;
offset_traps[i].left.p1.x = src_traps[i].left.p1.x + xoff;
offset_traps[i].left.p1.y = src_traps[i].left.p1.y + yoff;
offset_traps[i].left.p2.x = src_traps[i].left.p2.x + xoff;
offset_traps[i].left.p2.y = src_traps[i].left.p2.y + yoff;
offset_traps[i].right.p1.x = src_traps[i].right.p1.x + xoff;
offset_traps[i].right.p1.y = src_traps[i].right.p1.y + yoff;
offset_traps[i].right.p2.x = src_traps[i].right.p2.x + xoff;
offset_traps[i].right.p2.y = src_traps[i].right.p2.y + yoff;
}
} else {
cairo_fixed_t xsc = _cairo_fixed_from_double (sx);
cairo_fixed_t ysc = _cairo_fixed_from_double (sy);
for (i = 0; i < num_traps; i++) {
#define FIXED_MUL(_a, _b) \
(_cairo_int64_to_int32(_cairo_int64_rsl(_cairo_int32x32_64_mul((_a), (_b)), 16)))
offset_traps[i].top = FIXED_MUL(src_traps[i].top + yoff, ysc);
offset_traps[i].bottom = FIXED_MUL(src_traps[i].bottom + yoff, ysc);
offset_traps[i].left.p1.x = FIXED_MUL(src_traps[i].left.p1.x + xoff, xsc);
offset_traps[i].left.p1.y = FIXED_MUL(src_traps[i].left.p1.y + yoff, ysc);
offset_traps[i].left.p2.x = FIXED_MUL(src_traps[i].left.p2.x + xoff, xsc);
offset_traps[i].left.p2.y = FIXED_MUL(src_traps[i].left.p2.y + yoff, ysc);
offset_traps[i].right.p1.x = FIXED_MUL(src_traps[i].right.p1.x + xoff, xsc);
offset_traps[i].right.p1.y = FIXED_MUL(src_traps[i].right.p1.y + yoff, ysc);
offset_traps[i].right.p2.x = FIXED_MUL(src_traps[i].right.p2.x + xoff, xsc);
offset_traps[i].right.p2.y = FIXED_MUL(src_traps[i].right.p2.y + yoff, ysc);
#undef FIXED_MUL
}
}
}
cairo_status_t
_cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3])
{
@ -859,4 +907,3 @@ _cairo_traps_extract_region (cairo_traps_t *traps,
return CAIRO_STATUS_SUCCESS;
}

Просмотреть файл

@ -891,15 +891,20 @@ _start_glyphs (cairo_glyph_state_t *state,
static cairo_status_t
_flush_glyphs (cairo_glyph_state_t *state)
{
cairo_status_t status;
int dx = 0;
if (!_cairo_array_append (&state->dx, &dx, 1))
return CAIRO_STATUS_NO_MEMORY;
WCHAR * elements;
status = _cairo_array_append (&state->dx, &dx);
if (status)
return status;
elements = _cairo_array_index (&state->glyphs, 0);
if (!ExtTextOutW (state->hdc,
state->start_x, state->last_y,
ETO_GLYPH_INDEX,
NULL,
(WCHAR *)state->glyphs.elements,
elements,
state->glyphs.num_elements,
(int *)state->dx.elements)) {
return _cairo_win32_print_gdi_error ("_flush_glyphs");
@ -917,6 +922,7 @@ _add_glyph (cairo_glyph_state_t *state,
double device_x,
double device_y)
{
cairo_status_t status;
double user_x = device_x;
double user_y = device_y;
WCHAR glyph_index = index;
@ -931,15 +937,16 @@ _add_glyph (cairo_glyph_state_t *state,
int dx;
if (logical_y != state->last_y) {
cairo_status_t status = _flush_glyphs (state);
status = _flush_glyphs (state);
if (status)
return status;
state->start_x = logical_x;
}
dx = logical_x - state->last_x;
if (!_cairo_array_append (&state->dx, &dx, 1))
return CAIRO_STATUS_NO_MEMORY;
status = _cairo_array_append (&state->dx, &dx);
if (status)
return status;
} else {
state->start_x = logical_x;
}
@ -947,7 +954,9 @@ _add_glyph (cairo_glyph_state_t *state,
state->last_x = logical_x;
state->last_y = logical_y;
_cairo_array_append (&state->glyphs, &glyph_index, 1);
status = _cairo_array_append (&state->glyphs, &glyph_index);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
@ -1096,7 +1105,7 @@ _cairo_win32_scaled_font_glyph_init (void *abstract_font,
static cairo_int_status_t
_cairo_win32_scaled_font_show_glyphs (void *abstract_font,
cairo_operator_t operator,
cairo_operator_t op,
cairo_pattern_t *pattern,
cairo_surface_t *generic_surface,
int source_x,
@ -1117,7 +1126,7 @@ _cairo_win32_scaled_font_show_glyphs (void *abstract_font,
if (_cairo_surface_is_win32 (generic_surface) &&
surface->format == CAIRO_FORMAT_RGB24 &&
operator == CAIRO_OPERATOR_OVER &&
op == CAIRO_OPERATOR_OVER &&
_cairo_pattern_is_opaque_solid (pattern)) {
cairo_solid_pattern_t *solid_pattern = (cairo_solid_pattern_t *)pattern;
@ -1186,13 +1195,13 @@ _cairo_win32_scaled_font_show_glyphs (void *abstract_font,
return CAIRO_STATUS_NO_MEMORY;
}
/* For operator == OVER, no-cleartype, a possible optimization here is to
/* For op == OVER, no-cleartype, a possible optimization here is to
* draw onto an intermediate ARGB32 surface and alpha-blend that with the
* destination
*/
_cairo_pattern_init_for_surface (&mask, mask_surface);
status = _cairo_surface_composite (operator, pattern,
status = _cairo_surface_composite (op, pattern,
&mask.base,
&surface->base,
source_x, source_y,

Просмотреть файл

@ -614,7 +614,7 @@ _composite_alpha_blend (cairo_win32_surface_t *dst,
}
static cairo_int_status_t
_cairo_win32_surface_composite (cairo_operator_t operator,
_cairo_win32_surface_composite (cairo_operator_t op,
cairo_pattern_t *pattern,
cairo_pattern_t *mask_pattern,
void *abstract_dst,
@ -662,8 +662,8 @@ _cairo_win32_surface_composite (cairo_operator_t operator,
if (alpha == 255 &&
src->format == dst->format &&
(operator == CAIRO_OPERATOR_SOURCE ||
(src->format == CAIRO_FORMAT_RGB24 && operator == CAIRO_OPERATOR_OVER))) {
(op == CAIRO_OPERATOR_SOURCE ||
(src->format == CAIRO_FORMAT_RGB24 && op == CAIRO_OPERATOR_OVER))) {
if (!BitBlt (dst->dc,
dst_x, dst_y,
@ -678,7 +678,7 @@ _cairo_win32_surface_composite (cairo_operator_t operator,
} else if (integer_transform &&
(src->format == CAIRO_FORMAT_RGB24 || src->format == CAIRO_FORMAT_ARGB32) &&
dst->format == CAIRO_FORMAT_RGB24 &&
operator == CAIRO_OPERATOR_OVER) {
op == CAIRO_OPERATOR_OVER) {
return _composite_alpha_blend (dst, src, alpha,
src_x + itx, src_y + ity,
@ -695,7 +695,7 @@ _cairo_win32_surface_composite (cairo_operator_t operator,
* super-luminescent colors (a == 0, r,g,b > 0)
*/
static enum { DO_CLEAR, DO_SOURCE, DO_NOTHING, DO_UNSUPPORTED }
categorize_solid_dest_operator (cairo_operator_t operator,
categorize_solid_dest_operator (cairo_operator_t op,
unsigned short alpha)
{
enum { SOURCE_TRANSPARENT, SOURCE_LIGHT, SOURCE_SOLID, SOURCE_OTHER } source;
@ -707,7 +707,7 @@ categorize_solid_dest_operator (cairo_operator_t operator,
else
source = SOURCE_OTHER;
switch (operator) {
switch (op) {
case CAIRO_OPERATOR_CLEAR: /* 0 0 */
case CAIRO_OPERATOR_OUT: /* 1 - Ab 0 */
return DO_CLEAR;
@ -768,7 +768,7 @@ categorize_solid_dest_operator (cairo_operator_t operator,
static cairo_int_status_t
_cairo_win32_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t operator,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects)
@ -788,7 +788,7 @@ _cairo_win32_surface_fill_rectangles (void *abstract_surface,
/* Optimize for no destination alpha (surface->pixman_image is non-NULL for all
* surfaces with alpha.)
*/
switch (categorize_solid_dest_operator (operator, color->alpha_short)) {
switch (categorize_solid_dest_operator (op, color->alpha_short)) {
case DO_CLEAR:
new_color = RGB (0, 0, 0);
break;
@ -837,10 +837,6 @@ _cairo_win32_surface_set_clip_region (void *abstract_surface,
cairo_win32_surface_t *surface = abstract_surface;
cairo_status_t status;
#if 0
return CAIRO_STATUS_SUCCESS;
#endif
/* If we are in-memory, then we set the clip on the image surface
* as well as on the underlying GDI surface.
*/
@ -1049,8 +1045,7 @@ static const cairo_surface_backend_t cairo_win32_surface_backend = {
_cairo_win32_surface_set_clip_region,
NULL, /* intersect_clip_path */
_cairo_win32_surface_get_extents,
NULL, /* show_glyphs */
NULL, /* fill_path */
NULL, /* old_show_glyphs */
NULL, /* get_font_options */
_cairo_win32_surface_flush,
NULL /* mark_dirty_rectangle */
@ -1067,7 +1062,6 @@ CRITICAL_SECTION cairo_toy_font_face_hash_table_mutex;
CRITICAL_SECTION cairo_scaled_font_map_mutex;
CRITICAL_SECTION cairo_ft_unscaled_font_map_mutex;
#if 0
BOOL WINAPI
DllMain (HINSTANCE hinstDLL,
DWORD fdwReason,
@ -1090,5 +1084,3 @@ DllMain (HINSTANCE hinstDLL,
return TRUE;
}
#endif
#endif

Просмотреть файл

@ -787,6 +787,8 @@ _cairo_xcb_surface_set_attributes (cairo_xcb_surface_t *surface,
break;
case CAIRO_EXTEND_REFLECT:
return CAIRO_INT_STATUS_UNSUPPORTED;
case CAIRO_EXTEND_PAD:
return CAIRO_INT_STATUS_UNSUPPORTED;
}
status = _cairo_xcb_surface_set_filter (surface, attributes->filter);
@ -797,9 +799,9 @@ _cairo_xcb_surface_set_attributes (cairo_xcb_surface_t *surface,
}
static int
_render_operator (cairo_operator_t operator)
_render_operator (cairo_operator_t op)
{
switch (operator) {
switch (op) {
case CAIRO_OPERATOR_CLEAR:
return XCBRenderPictOpClear;
case CAIRO_OPERATOR_SOURCE:
@ -834,7 +836,7 @@ _render_operator (cairo_operator_t operator)
}
static cairo_int_status_t
_cairo_xcb_surface_composite (cairo_operator_t operator,
_cairo_xcb_surface_composite (cairo_operator_t op,
cairo_pattern_t *src_pattern,
cairo_pattern_t *mask_pattern,
void *abstract_dst,
@ -875,7 +877,7 @@ _cairo_xcb_surface_composite (cairo_operator_t operator,
status = _cairo_xcb_surface_set_attributes (mask, &mask_attr);
if (status == CAIRO_STATUS_SUCCESS)
XCBRenderComposite (dst->dpy,
_render_operator (operator),
_render_operator (op),
src->picture,
mask->picture,
dst->picture,
@ -891,7 +893,7 @@ _cairo_xcb_surface_composite (cairo_operator_t operator,
static XCBRenderPICTURE maskpict = { 0 };
XCBRenderComposite (dst->dpy,
_render_operator (operator),
_render_operator (op),
src->picture,
maskpict,
dst->picture,
@ -913,7 +915,7 @@ _cairo_xcb_surface_composite (cairo_operator_t operator,
static cairo_int_status_t
_cairo_xcb_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t operator,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects)
@ -931,7 +933,7 @@ _cairo_xcb_surface_fill_rectangles (void *abstract_surface,
/* XXX: This XCBRECTANGLE cast is evil... it needs to go away somehow. */
XCBRenderFillRectangles (surface->dpy,
_render_operator (operator),
_render_operator (op),
surface->picture,
render_color, num_rects, (XCBRECTANGLE *) rects);
@ -939,7 +941,7 @@ _cairo_xcb_surface_fill_rectangles (void *abstract_surface,
}
static cairo_int_status_t
_cairo_xcb_surface_composite_trapezoids (cairo_operator_t operator,
_cairo_xcb_surface_composite_trapezoids (cairo_operator_t op,
cairo_pattern_t *pattern,
void *abstract_dst,
cairo_antialias_t antialias,
@ -995,7 +997,7 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t operator,
status = _cairo_xcb_surface_set_attributes (src, &attributes);
if (status == CAIRO_STATUS_SUCCESS)
XCBRenderTrapezoids (dst->dpy,
_render_operator (operator),
_render_operator (op),
src->picture, dst->picture,
render_format.id,
render_src_x + attributes.x_offset,
@ -1038,7 +1040,12 @@ static const cairo_surface_backend_t cairo_xcb_surface_backend = {
NULL, /* _cairo_xcb_surface_set_clip_region */
NULL, /* intersect_clip_path */
_cairo_xcb_surface_get_extents,
NULL /* show_glyphs */
NULL, /* old_show_glyphs */
NULL, /* get_font_options */
NULL, /* flush */
NULL, /* mark_dirty_rectangle */
NULL, /* scaled_font_fini */
NULL /* scaled_glyph_fini */
};
/**

Просмотреть файл

@ -693,6 +693,7 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
ximage.red_mask = red;
ximage.green_mask = green;
ximage.blue_mask = blue;
ximage.xoffset = 0;
XInitImage (&ximage);
@ -936,6 +937,7 @@ _cairo_xlib_surface_set_attributes (cairo_xlib_surface_t *surface,
_cairo_xlib_surface_set_repeat (surface, 1);
break;
case CAIRO_EXTEND_REFLECT:
case CAIRO_EXTEND_PAD:
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@ -993,14 +995,14 @@ _surface_has_alpha (cairo_xlib_surface_t *surface)
* requires alpha compositing to complete.
*/
static cairo_bool_t
_operator_needs_alpha_composite (cairo_operator_t operator,
_operator_needs_alpha_composite (cairo_operator_t op,
cairo_bool_t surface_has_alpha)
{
if (operator == CAIRO_OPERATOR_SOURCE ||
if (op == CAIRO_OPERATOR_SOURCE ||
(!surface_has_alpha &&
(operator == CAIRO_OPERATOR_OVER ||
operator == CAIRO_OPERATOR_ATOP ||
operator == CAIRO_OPERATOR_IN)))
(op == CAIRO_OPERATOR_OVER ||
op == CAIRO_OPERATOR_ATOP ||
op == CAIRO_OPERATOR_IN)))
return FALSE;
return TRUE;
@ -1037,7 +1039,7 @@ typedef enum {
*/
static composite_operation_t
_categorize_composite_operation (cairo_xlib_surface_t *dst,
cairo_operator_t operator,
cairo_operator_t op,
cairo_pattern_t *src_pattern,
cairo_bool_t have_mask)
@ -1058,13 +1060,13 @@ _categorize_composite_operation (cairo_xlib_surface_t *dst,
* fallback is impossible.
*/
if (have_mask ||
!(operator == CAIRO_OPERATOR_SOURCE || operator == CAIRO_OPERATOR_OVER))
!(op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_OVER))
return DO_UNSUPPORTED;
if (_cairo_surface_is_xlib (surface_pattern->surface)) {
cairo_xlib_surface_t *src = (cairo_xlib_surface_t *)surface_pattern->surface;
if (operator == CAIRO_OPERATOR_OVER && _surface_has_alpha (src))
if (op == CAIRO_OPERATOR_OVER && _surface_has_alpha (src))
return DO_UNSUPPORTED;
/* If these are on the same screen but otherwise incompatible,
@ -1097,7 +1099,7 @@ _categorize_composite_operation (cairo_xlib_surface_t *dst,
*/
static composite_operation_t
_recategorize_composite_operation (cairo_xlib_surface_t *dst,
cairo_operator_t operator,
cairo_operator_t op,
cairo_xlib_surface_t *src,
cairo_surface_attributes_t *src_attr,
cairo_bool_t have_mask)
@ -1105,7 +1107,7 @@ _recategorize_composite_operation (cairo_xlib_surface_t *dst,
cairo_bool_t is_integer_translation =
_cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL);
cairo_bool_t needs_alpha_composite =
_operator_needs_alpha_composite (operator, _surface_has_alpha (src));
_operator_needs_alpha_composite (op, _surface_has_alpha (src));
if (!have_mask &&
is_integer_translation &&
@ -1137,9 +1139,9 @@ _recategorize_composite_operation (cairo_xlib_surface_t *dst,
}
static int
_render_operator (cairo_operator_t operator)
_render_operator (cairo_operator_t op)
{
switch (operator) {
switch (op) {
case CAIRO_OPERATOR_CLEAR:
return PictOpClear;
@ -1177,7 +1179,7 @@ _render_operator (cairo_operator_t operator)
}
static cairo_int_status_t
_cairo_xlib_surface_composite (cairo_operator_t operator,
_cairo_xlib_surface_composite (cairo_operator_t op,
cairo_pattern_t *src_pattern,
cairo_pattern_t *mask_pattern,
void *abstract_dst,
@ -1201,7 +1203,7 @@ _cairo_xlib_surface_composite (cairo_operator_t operator,
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst))
return CAIRO_INT_STATUS_UNSUPPORTED;
operation = _categorize_composite_operation (dst, operator, src_pattern,
operation = _categorize_composite_operation (dst, op, src_pattern,
mask_pattern != NULL);
if (operation == DO_UNSUPPORTED)
return CAIRO_INT_STATUS_UNSUPPORTED;
@ -1217,7 +1219,7 @@ _cairo_xlib_surface_composite (cairo_operator_t operator,
if (status)
return status;
operation = _recategorize_composite_operation (dst, operator, src, &src_attr,
operation = _recategorize_composite_operation (dst, op, src, &src_attr,
mask_pattern != NULL);
if (operation == DO_UNSUPPORTED) {
status = CAIRO_INT_STATUS_UNSUPPORTED;
@ -1238,7 +1240,7 @@ _cairo_xlib_surface_composite (cairo_operator_t operator,
goto FAIL;
XRenderComposite (dst->dpy,
_render_operator (operator),
_render_operator (op),
src->src_picture,
mask->src_picture,
dst->dst_picture,
@ -1250,7 +1252,7 @@ _cairo_xlib_surface_composite (cairo_operator_t operator,
width, height);
} else {
XRenderComposite (dst->dpy,
_render_operator (operator),
_render_operator (op),
src->src_picture,
0,
dst->dst_picture,
@ -1300,9 +1302,7 @@ _cairo_xlib_surface_composite (cairo_operator_t operator,
ASSERT_NOT_REACHED;
}
if (!_cairo_operator_bounded (operator) ||
operator == CAIRO_OPERATOR_SOURCE ||
operator == CAIRO_OPERATOR_CLEAR)
if (!_cairo_operator_bounded_by_source (op))
status = _cairo_surface_composite_fixup_unbounded (&dst->base,
&src_attr, src->width, src->height,
mask ? &mask_attr : NULL,
@ -1324,7 +1324,7 @@ _cairo_xlib_surface_composite (cairo_operator_t operator,
static cairo_int_status_t
_cairo_xlib_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t operator,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects)
@ -1343,7 +1343,7 @@ _cairo_xlib_surface_fill_rectangles (void *abstract_surface,
/* XXX: This XRectangle cast is evil... it needs to go away somehow. */
_cairo_xlib_surface_ensure_dst_picture (surface);
XRenderFillRectangles (surface->dpy,
_render_operator (operator),
_render_operator (op),
surface->dst_picture,
&render_color, (XRectangle *) rects, num_rects);
@ -1442,7 +1442,7 @@ _create_trapezoid_mask (cairo_xlib_surface_t *dst,
}
static cairo_int_status_t
_cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator,
_cairo_xlib_surface_composite_trapezoids (cairo_operator_t op,
cairo_pattern_t *pattern,
void *abstract_dst,
cairo_antialias_t antialias,
@ -1467,7 +1467,7 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator,
if (!CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS (dst))
return CAIRO_INT_STATUS_UNSUPPORTED;
operation = _categorize_composite_operation (dst, operator, pattern, TRUE);
operation = _categorize_composite_operation (dst, op, pattern, TRUE);
if (operation == DO_UNSUPPORTED)
return CAIRO_INT_STATUS_UNSUPPORTED;
@ -1478,7 +1478,7 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator,
if (status)
return status;
operation = _recategorize_composite_operation (dst, operator, src, &attributes, TRUE);
operation = _recategorize_composite_operation (dst, op, src, &attributes, TRUE);
if (operation == DO_UNSUPPORTED) {
status = CAIRO_INT_STATUS_UNSUPPORTED;
goto FAIL;
@ -1509,7 +1509,7 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator,
if (status)
goto FAIL;
if (!_cairo_operator_bounded (operator)) {
if (!_cairo_operator_bounded_by_mask (op)) {
/* XRenderCompositeTrapezoids() creates a mask only large enough for the
* trapezoids themselves, but if the operator is unbounded, then we need
* to actually composite all the way out to the bounds, so we create
@ -1528,7 +1528,7 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator,
}
XRenderComposite (dst->dpy,
_render_operator (operator),
_render_operator (op),
src->src_picture,
mask_picture,
dst->dst_picture,
@ -1551,7 +1551,7 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator,
} else {
/* XXX: The XTrapezoid cast is evil and needs to go away somehow. */
XRenderCompositeTrapezoids (dst->dpy,
_render_operator (operator),
_render_operator (op),
src->src_picture, dst->dst_picture,
pict_format,
render_src_x + attributes.x_offset,
@ -1654,18 +1654,18 @@ _cairo_xlib_surface_get_font_options (void *abstract_surface,
}
static cairo_int_status_t
_cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_surface,
int source_x,
int source_y,
int dest_x,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
int num_glyphs);
_cairo_xlib_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t op,
cairo_pattern_t *pattern,
void *abstract_surface,
int source_x,
int source_y,
int dest_x,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
int num_glyphs);
static void
_cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font);
@ -1690,8 +1690,7 @@ static const cairo_surface_backend_t cairo_xlib_surface_backend = {
_cairo_xlib_surface_set_clip_region,
NULL, /* intersect_clip_path */
_cairo_xlib_surface_get_extents,
_cairo_xlib_surface_show_glyphs,
NULL, /* fill_path */
_cairo_xlib_surface_old_show_glyphs,
_cairo_xlib_surface_get_font_options,
NULL, /* flush */
NULL, /* mark_dirty_rectangle */
@ -2201,14 +2200,14 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
#define N_STACK_BUF 1024
static cairo_status_t
_cairo_xlib_surface_show_glyphs8 (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
cairo_xlib_surface_t *src,
cairo_xlib_surface_t *self,
int source_x,
int source_y,
const cairo_glyph_t *glyphs,
int num_glyphs)
_cairo_xlib_surface_old_show_glyphs8 (cairo_scaled_font_t *scaled_font,
cairo_operator_t op,
cairo_xlib_surface_t *src,
cairo_xlib_surface_t *self,
int source_x,
int source_y,
const cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
XGlyphElt8 *elts = NULL;
@ -2248,7 +2247,7 @@ _cairo_xlib_surface_show_glyphs8 (cairo_scaled_font_t *scaled_font,
}
XRenderCompositeText8 (self->dpy,
_render_operator (operator),
_render_operator (op),
src->src_picture,
self->dst_picture,
font_private->format,
@ -2263,14 +2262,14 @@ _cairo_xlib_surface_show_glyphs8 (cairo_scaled_font_t *scaled_font,
}
static cairo_status_t
_cairo_xlib_surface_show_glyphs16 (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
cairo_xlib_surface_t *src,
cairo_xlib_surface_t *self,
int source_x,
int source_y,
const cairo_glyph_t *glyphs,
int num_glyphs)
_cairo_xlib_surface_old_show_glyphs16 (cairo_scaled_font_t *scaled_font,
cairo_operator_t op,
cairo_xlib_surface_t *src,
cairo_xlib_surface_t *self,
int source_x,
int source_y,
const cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
XGlyphElt16 *elts = NULL;
@ -2310,7 +2309,7 @@ _cairo_xlib_surface_show_glyphs16 (cairo_scaled_font_t *scaled_font,
}
XRenderCompositeText16 (self->dpy,
_render_operator (operator),
_render_operator (op),
src->src_picture,
self->dst_picture,
font_private->format,
@ -2325,14 +2324,14 @@ _cairo_xlib_surface_show_glyphs16 (cairo_scaled_font_t *scaled_font,
}
static cairo_status_t
_cairo_xlib_surface_show_glyphs32 (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
cairo_xlib_surface_t *src,
cairo_xlib_surface_t *self,
int source_x,
int source_y,
const cairo_glyph_t *glyphs,
int num_glyphs)
_cairo_xlib_surface_old_show_glyphs32 (cairo_scaled_font_t *scaled_font,
cairo_operator_t op,
cairo_xlib_surface_t *src,
cairo_xlib_surface_t *self,
int source_x,
int source_y,
const cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
XGlyphElt32 *elts = NULL;
@ -2372,7 +2371,7 @@ _cairo_xlib_surface_show_glyphs32 (cairo_scaled_font_t *scaled_font,
}
XRenderCompositeText32 (self->dpy,
_render_operator (operator),
_render_operator (op),
src->src_picture,
self->dst_picture,
font_private->format,
@ -2387,18 +2386,18 @@ _cairo_xlib_surface_show_glyphs32 (cairo_scaled_font_t *scaled_font,
}
static cairo_int_status_t
_cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_surface,
int source_x,
int source_y,
int dest_x,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
int num_glyphs)
_cairo_xlib_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t op,
cairo_pattern_t *pattern,
void *abstract_surface,
int source_x,
int source_y,
int dest_x,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_surface_attributes_t attributes;
cairo_int_status_t status;
@ -2414,7 +2413,7 @@ _cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (self) || !self->format)
return CAIRO_INT_STATUS_UNSUPPORTED;
operation = _categorize_composite_operation (self, operator, pattern, TRUE);
operation = _categorize_composite_operation (self, op, pattern, TRUE);
if (operation == DO_UNSUPPORTED)
return CAIRO_INT_STATUS_UNSUPPORTED;
@ -2431,7 +2430,7 @@ _cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
if (status)
return status;
operation = _recategorize_composite_operation (self, operator, src, &attributes, TRUE);
operation = _recategorize_composite_operation (self, op, src, &attributes, TRUE);
if (operation == DO_UNSUPPORTED) {
status = CAIRO_INT_STATUS_UNSUPPORTED;
goto FAIL;
@ -2461,22 +2460,22 @@ _cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
/* Call the appropriate sub-function. */
if (max_index < 256)
status = _cairo_xlib_surface_show_glyphs8 (scaled_font, operator, src, self,
status = _cairo_xlib_surface_old_show_glyphs8 (scaled_font, op, src, self,
source_x + attributes.x_offset - dest_x,
source_y + attributes.y_offset - dest_y,
glyphs, num_glyphs);
else if (max_index < 65536)
status = _cairo_xlib_surface_show_glyphs16 (scaled_font, operator, src, self,
status = _cairo_xlib_surface_old_show_glyphs16 (scaled_font, op, src, self,
source_x + attributes.x_offset - dest_x,
source_y + attributes.y_offset - dest_y,
glyphs, num_glyphs);
else
status = _cairo_xlib_surface_show_glyphs32 (scaled_font, operator, src, self,
status = _cairo_xlib_surface_old_show_glyphs32 (scaled_font, op, src, self,
source_x + attributes.x_offset - dest_x,
source_y + attributes.y_offset - dest_y,
glyphs, num_glyphs);
if (status == CAIRO_STATUS_SUCCESS && !_cairo_operator_bounded (operator)) {
if (status == CAIRO_STATUS_SUCCESS && !_cairo_operator_bounded_by_mask (op)) {
cairo_rectangle_t extents;
status = _cairo_scaled_font_glyph_device_extents (scaled_font,
glyphs,

Просмотреть файл

@ -82,8 +82,6 @@ static const cairo_t cairo_nil = {
void
_cairo_error (cairo_status_t status)
{
fprintf (stderr, "#### Cairo Error: %d\n", status);
assert (status > CAIRO_STATUS_SUCCESS &&
status <= CAIRO_STATUS_LAST_STATUS);
}
@ -327,7 +325,7 @@ cairo_restore (cairo_t *cr)
slim_hidden_def(cairo_restore);
/**
* cairo_set_target:
* moz_cairo_set_target:
* @cr: a #cairo_t
* @target: a #cairo_surface_t
*
@ -335,7 +333,7 @@ slim_hidden_def(cairo_restore);
* @target must not be %NULL, or an error will be set on @cr.
*/
void
cairo_set_target (cairo_t *cr, cairo_surface_t *target)
moz_cairo_set_target (cairo_t *cr, cairo_surface_t *target)
{
if (cr->status)
return;
@ -345,36 +343,123 @@ cairo_set_target (cairo_t *cr, cairo_surface_t *target)
return;
}
_cairo_gstate_set_target (cr->gstate, target);
_moz_cairo_gstate_set_target (cr->gstate, target);
}
slim_hidden_def(moz_cairo_set_target);
/**
* cairo_push_group:
* @cr: a cairo context
*
* Pushes a temporary surface onto the rendering stack, redirecting
* all rendering into it. The surface dimensions are the size of
* the current clipping bounding box. Initially, this surface
* is cleared to fully transparent black (0,0,0,1).
*
* cairo_push_group() calls cairo_save() so that any changes to the
* graphics state will not be visible after cairo_pop_group() or
* cairo_pop_group_with_alpha(). See cairo_pop_group() and
* cairo_pop_group_with_alpha().
*/
/* XXX: I want to rethink this API
void
cairo_push_group (cairo_t *cr)
{
if (cr->status)
return;
cairo_status_t status;
cairo_rectangle_t extents;
cairo_surface_t *group_surface = NULL;
cr->status = cairoPush (cr);
if (cr->status)
return;
/* Get the extents that we'll use in creating our new group surface */
_cairo_surface_get_extents (_cairo_gstate_get_target (cr->gstate), &extents);
status = _cairo_clip_intersect_to_rectangle (_cairo_gstate_get_clip (cr->gstate), &extents);
if (status != CAIRO_STATUS_SUCCESS)
goto bail;
cr->status = _cairo_gstate_begin_group (cr->gstate);
group_surface = cairo_surface_create_similar (_cairo_gstate_get_target (cr->gstate),
CAIRO_CONTENT_COLOR_ALPHA,
extents.width,
extents.height);
status = cairo_surface_status (group_surface);
if (status)
goto bail;
/* XXX hrm. How best to make sure that drawing still happens in
* the right place? Is this correct? Need to double-check the
* coordinate spaces.
*/
cairo_surface_set_device_offset (group_surface, -extents.x, -extents.y);
/* create a new gstate for the redirect */
cairo_save (cr);
if (cr->status)
goto bail;
_cairo_gstate_redirect_target (cr->gstate, group_surface);
bail:
cairo_surface_destroy (group_surface);
if (status)
_cairo_set_error (cr, status);
}
slim_hidden_def(cairo_push_group);
void
cairo_pattern_t *
cairo_pop_group (cairo_t *cr)
{
if (cr->status)
return;
cairo_surface_t *group_surface, *parent_target;
cairo_pattern_t *group_pattern = NULL;
cr->status = _cairo_gstate_end_group (cr->gstate);
if (cr->status)
return;
/* Grab the active surfaces */
group_surface = _cairo_gstate_get_target (cr->gstate);
parent_target = _cairo_gstate_get_parent_target (cr->gstate);
cr->status = cairoPop (cr);
/* Verify that we are at the right nesting level */
if (parent_target == NULL) {
_cairo_set_error (cr, CAIRO_STATUS_INVALID_POP_GROUP);
return NULL;
}
/* We need to save group_surface before we restore; we don't need
* to reference parent_target and original_target, since the
* gstate will still hold refs to them once we restore. */
cairo_surface_reference (group_surface);
cairo_restore (cr);
if (cr->status)
goto done;
/* Undo the device offset we used; we're back in a normal-sized
* surface, so this pattern will be positioned at the right place.
* XXXvlad - er, this doesn't make sense, why does it work?
*/
cairo_surface_set_device_offset (group_surface, 0, 0);
group_pattern = cairo_pattern_create_for_surface (group_surface);
if (!group_pattern) {
cr->status = CAIRO_STATUS_NO_MEMORY;
goto done;
}
done:
cairo_surface_destroy (group_surface);
return group_pattern;
}
*/
slim_hidden_def(cairo_pop_group);
void
cairo_pop_group_to_source (cairo_t *cr)
{
cairo_pattern_t *group_pattern;
group_pattern = cairo_pop_group (cr);
if (!group_pattern)
return;
cairo_set_source (cr, group_pattern);
}
slim_hidden_def(cairo_pop_group_to_source);
/**
* cairo_set_operator:
@ -2422,7 +2507,7 @@ cairo_get_target (cairo_t *cr)
if (cr->status)
return (cairo_surface_t*) &_cairo_surface_nil;
return _cairo_gstate_get_target (cr->gstate);
return _cairo_gstate_get_original_target (cr->gstate);
}
/**
@ -2433,10 +2518,6 @@ cairo_get_target (cairo_t *cr)
* #cairo_path_t. See #cairo_path_data_t for hints on how to iterate
* over the returned data structure.
*
* Return value: the copy of the current path. The caller owns the
* returned object and should call cairo_path_destroy() when finished
* with it.
*
* This function will always return a valid pointer, but the result
* will have no data (<literal>data==NULL</literal> and
* <literal>num_data==0</literal>), if either of the following

Просмотреть файл

@ -253,15 +253,16 @@ cairo_public void
cairo_restore (cairo_t *cr);
cairo_public void
cairo_set_target (cairo_t *cr, cairo_surface_t *target);
moz_cairo_set_target (cairo_t *cr, cairo_surface_t *target);
/* XXX: I want to rethink this API
cairo_public void
cairo_push_group (cairo_t *cr);
cairo_public void
cairo_public cairo_pattern_t *
cairo_pop_group (cairo_t *cr);
*/
cairo_public void
cairo_pop_group_to_source (cairo_t *cr);
/* Modify state */
@ -1292,10 +1293,24 @@ cairo_public void
cairo_pattern_get_matrix (cairo_pattern_t *pattern,
cairo_matrix_t *matrix);
/**
* cairo_extend_t
* @CAIRO_EXTEND_NONE: pixels outside of the source pattern
* are fully transparent
* @CAIRO_EXTEND_REPEAT: the pattern is tiled by repeating
* @CAIRO_EXTEND_REFLECT: the pattern is tiled by reflecting
* at the edges
* @CAIRO_EXTEND_PAD: pixels outside of the pattern copy
* the closest pixel from the source (since cairo 1.2)
*
* #cairo_extend_t is used to describe how the area outside
* of a pattern will be drawn.
*/
typedef enum _cairo_extend {
CAIRO_EXTEND_NONE,
CAIRO_EXTEND_REPEAT,
CAIRO_EXTEND_REFLECT
CAIRO_EXTEND_REFLECT,
CAIRO_EXTEND_PAD
} cairo_extend_t;
cairo_public void

Просмотреть файл

@ -66,6 +66,8 @@
#include "cairo-debug.h"
#include <pixman.h>
CAIRO_BEGIN_DECLS
#if __GNUC__ >= 3 && defined(__ELF__)
# define slim_hidden_proto(name) slim_hidden_proto1(name, INT_##name)
# define slim_hidden_def(name) slim_hidden_def1(name, INT_##name)
@ -130,6 +132,7 @@
#define INLINE
#endif
#if 0
#if HAVE_PTHREAD_H
# include <pthread.h>
# define CAIRO_MUTEX_DECLARE(name) static pthread_mutex_t name = PTHREAD_MUTEX_INITIALIZER
@ -138,12 +141,7 @@
# define CAIRO_MUTEX_UNLOCK(name) pthread_mutex_unlock (&name)
#endif
/* Since we have no way currently to initialize the mutexes and
* cairo is only used from the main thread, turn off the critical
* sections.
*/
#if !defined(CAIRO_MUTEX_DECLARE) && defined CAIRO_HAS_WIN32_SURFACE
#if 0
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
/* the real initialization must take place in DllMain */
@ -152,13 +150,19 @@
# define CAIRO_MUTEX_LOCK(name) EnterCriticalSection (&name)
# define CAIRO_MUTEX_UNLOCK(name) LeaveCriticalSection (&name)
#endif
#if !defined(CAIRO_MUTEX_DECLARE) && defined CAIRO_HAS_BEOS_SURFACE
cairo_private void _cairo_beos_lock(void*);
cairo_private void _cairo_beos_unlock(void*);
/* the real initialization takes place in a global constructor */
# define CAIRO_MUTEX_DECLARE(name) extern void* name;
# define CAIRO_MUTEX_DECLARE_GLOBAL(name) extern void* name;
# define CAIRO_MUTEX_LOCK(name) _cairo_beos_lock (&name)
# define CAIRO_MUTEX_UNLOCK(name) _cairo_beos_unlock (&name)
#endif
#endif /* 0 */
#ifndef CAIRO_MUTEX_DECLARE
#if 0
# error "No mutex declarations. Cairo will not work with multiple threads." \
"(Remove this #error directive to acknowledge & accept this limitation)."
#endif
# define CAIRO_MUTEX_DECLARE(name)
# define CAIRO_MUTEX_DECLARE_GLOBAL(name)
# define CAIRO_MUTEX_LOCK(name)
@ -185,10 +189,6 @@ do { \
assert (NOT_REACHED); \
} while (0)
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#include "cairo-wideint.h"
typedef int32_t cairo_fixed_16_16_t;
@ -261,7 +261,11 @@ typedef enum cairo_direction {
} cairo_direction_t;
typedef struct _cairo_path_fixed cairo_path_fixed_t;
typedef enum _cairo_clip_mode cairo_clip_mode_t;
typedef enum _cairo_clip_mode {
CAIRO_CLIP_MODE_PATH,
CAIRO_CLIP_MODE_REGION,
CAIRO_CLIP_MODE_MASK
} cairo_clip_mode_t;
typedef struct _cairo_clip_path cairo_clip_path_t;
typedef struct _cairo_clip cairo_clip_t;
@ -329,12 +333,18 @@ struct _cairo_array {
int size;
int num_elements;
int element_size;
char *elements;
char **elements;
cairo_bool_t is_snapshot;
};
cairo_private void
_cairo_array_init (cairo_array_t *array, int element_size);
void
_cairo_array_init_snapshot (cairo_array_t *array,
const cairo_array_t *other);
cairo_private void
_cairo_array_fini (cairo_array_t *array);
@ -344,9 +354,18 @@ _cairo_array_grow_by (cairo_array_t *array, int additional);
cairo_private void
_cairo_array_truncate (cairo_array_t *array, int length);
cairo_private void *
_cairo_array_append (cairo_array_t *array,
const void *elements, int num_elements);
cairo_private cairo_status_t
_cairo_array_append (cairo_array_t *array, const void *element);
cairo_private cairo_status_t
_cairo_array_append_multiple (cairo_array_t *array,
const void *elements,
int num_elements);
cairo_status_t
_cairo_array_allocate (cairo_array_t *array,
int num_elements,
void **elements);
cairo_private void *
_cairo_array_index (cairo_array_t *array, int index);
@ -520,7 +539,7 @@ struct _cairo_scaled_font_backend {
uint32_t ucs4);
cairo_int_status_t
(*show_glyphs) (void *scaled_font,
cairo_operator_t operator,
cairo_operator_t op,
cairo_pattern_t *pattern,
cairo_surface_t *surface,
int source_x,
@ -568,6 +587,16 @@ extern const cairo_private struct _cairo_scaled_font_backend cairo_atsui_scaled_
#endif
typedef struct _cairo_stroke_style {
double line_width;
cairo_line_cap_t line_cap;
cairo_line_join_t line_join;
double miter_limit;
double *dash;
int num_dashes;
double dash_offset;
} cairo_stroke_style_t;
struct _cairo_surface_backend {
cairo_surface_t *
(*create_similar) (void *surface,
@ -609,7 +638,7 @@ struct _cairo_surface_backend {
/* XXX: dst should be the first argument for consistency */
cairo_int_status_t
(*composite) (cairo_operator_t operator,
(*composite) (cairo_operator_t op,
cairo_pattern_t *src,
cairo_pattern_t *mask,
void *dst,
@ -624,14 +653,14 @@ struct _cairo_surface_backend {
cairo_int_status_t
(*fill_rectangles) (void *surface,
cairo_operator_t operator,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects);
/* XXX: dst should be the first argument for consistency */
cairo_int_status_t
(*composite_trapezoids) (cairo_operator_t operator,
(*composite_trapezoids) (cairo_operator_t op,
cairo_pattern_t *pattern,
void *dst,
cairo_antialias_t antialias,
@ -708,8 +737,8 @@ struct _cairo_surface_backend {
* surfaces as glyphs.
*/
cairo_int_status_t
(*show_glyphs) (cairo_scaled_font_t *font,
cairo_operator_t operator,
(*old_show_glyphs) (cairo_scaled_font_t *font,
cairo_operator_t op,
cairo_pattern_t *pattern,
void *surface,
int source_x,
@ -721,14 +750,6 @@ struct _cairo_surface_backend {
const cairo_glyph_t *glyphs,
int num_glyphs);
cairo_int_status_t
(*fill_path) (cairo_operator_t operator,
cairo_pattern_t *pattern,
void *dst,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance);
void
(*get_font_options) (void *surface,
cairo_font_options_t *options);
@ -749,6 +770,51 @@ struct _cairo_surface_backend {
void
(*scaled_glyph_fini) (cairo_scaled_glyph_t *scaled_glyph,
cairo_scaled_font_t *scaled_font);
/* OK, I'm starting over somewhat by defining the 5 top-level
* drawing operators for the surface backend here with consistent
* naming and argument-order convensions. */
cairo_int_status_t
(*paint) (void *surface,
cairo_operator_t op,
cairo_pattern_t *source);
cairo_int_status_t
(*mask) (void *surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_pattern_t *mask);
cairo_int_status_t
(*stroke) (void *surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_stroke_style_t *style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias);
cairo_int_status_t
(*fill) (void *surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias);
cairo_int_status_t
(*show_glyphs) (void *surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font);
cairo_surface_t *
(*snapshot) (void *surface);
};
typedef struct _cairo_format_masks {
@ -772,10 +838,12 @@ struct _cairo_surface {
double device_x_scale;
double device_y_scale;
cairo_clip_t *clip;
/*
* Each time a clip region is modified, it gets the next value in this
* sequence. This means that clip regions for this surface are uniquely
* identified andupdates to the clip can be readily identified
* identified and updates to the clip can be readily identified
*/
unsigned int next_clip_serial;
/*
@ -787,6 +855,9 @@ struct _cairo_surface {
* The special value '0' is reserved for the unclipped case.
*/
unsigned int current_clip_serial;
/* A "snapshot" surface is immutable. See _cairo_surface_snapshot. */
cairo_bool_t is_snapshot;
};
struct _cairo_image_surface {
@ -833,7 +904,8 @@ typedef enum {
CAIRO_STOCK_TRANSPARENT
} cairo_stock_t;
#define CAIRO_EXTEND_DEFAULT CAIRO_EXTEND_NONE
#define CAIRO_EXTEND_SURFACE_DEFAULT CAIRO_EXTEND_NONE
#define CAIRO_EXTEND_GRADIENT_DEFAULT CAIRO_EXTEND_PAD
#define CAIRO_FILTER_DEFAULT CAIRO_FILTER_BEST
typedef enum {
@ -843,11 +915,6 @@ typedef enum {
CAIRO_PATTERN_RADIAL
} cairo_pattern_type_t;
typedef struct _cairo_color_stop {
cairo_fixed_t offset;
cairo_color_t color;
} cairo_color_stop_t;
struct _cairo_pattern {
cairo_pattern_type_t type;
unsigned int ref_count;
@ -873,24 +940,20 @@ typedef struct _cairo_surface_pattern {
typedef struct _cairo_gradient_pattern {
cairo_pattern_t base;
cairo_color_stop_t *stops;
int n_stops;
pixman_gradient_stop_t *stops;
int n_stops;
} cairo_gradient_pattern_t;
typedef struct _cairo_linear_pattern {
cairo_gradient_pattern_t base;
cairo_point_double_t point0;
cairo_point_double_t point1;
pixman_linear_gradient_t gradient;
} cairo_linear_pattern_t;
typedef struct _cairo_radial_pattern {
cairo_gradient_pattern_t base;
cairo_point_double_t center0;
cairo_point_double_t center1;
double radius0;
double radius1;
pixman_radial_gradient_t gradient;
} cairo_radial_pattern_t;
typedef union {
@ -1008,17 +1071,26 @@ cairo_private cairo_gstate_t *
_cairo_gstate_clone (cairo_gstate_t *gstate);
cairo_private void
_cairo_gstate_set_target (cairo_gstate_t *gstate, cairo_surface_t *target);
_moz_cairo_gstate_set_target (cairo_gstate_t *gstate, cairo_surface_t *target);
cairo_private cairo_status_t
_cairo_gstate_begin_group (cairo_gstate_t *gstate);
cairo_private cairo_bool_t
_cairo_gstate_is_redirected (cairo_gstate_t *gstate);
cairo_private cairo_status_t
_cairo_gstate_end_group (cairo_gstate_t *gstate);
cairo_private void
_cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child);
cairo_private cairo_surface_t *
_cairo_gstate_get_target (cairo_gstate_t *gstate);
cairo_private cairo_surface_t *
_cairo_gstate_get_parent_target (cairo_gstate_t *gstate);
cairo_private cairo_surface_t *
_cairo_gstate_get_original_target (cairo_gstate_t *gstate);
cairo_private cairo_clip_t *
_cairo_gstate_get_clip (cairo_gstate_t *gstate);
cairo_private cairo_status_t
_cairo_gstate_set_source (cairo_gstate_t *gstate, cairo_pattern_t *source);
@ -1026,7 +1098,7 @@ cairo_private cairo_pattern_t *
_cairo_gstate_get_source (cairo_gstate_t *gstate);
cairo_private cairo_status_t
_cairo_gstate_set_operator (cairo_gstate_t *gstate, cairo_operator_t operator);
_cairo_gstate_set_operator (cairo_gstate_t *gstate, cairo_operator_t op);
cairo_private cairo_operator_t
_cairo_gstate_get_operator (cairo_gstate_t *gstate);
@ -1234,7 +1306,10 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
cairo_path_fixed_t *path);
cairo_private cairo_bool_t
_cairo_operator_bounded (cairo_operator_t operator);
_cairo_operator_bounded_by_mask (cairo_operator_t op);
cairo_private cairo_bool_t
_cairo_operator_bounded_by_source (cairo_operator_t op);
/* cairo_color.c */
cairo_private const cairo_color_t *
@ -1306,6 +1381,10 @@ _cairo_unscaled_font_destroy (cairo_unscaled_font_t *font);
cairo_private void
_cairo_font_options_init_default (cairo_font_options_t *options);
cairo_private void
_cairo_font_options_init_copy (cairo_font_options_t *options,
const cairo_font_options_t *other);
/* cairo_hull.c */
cairo_private cairo_status_t
_cairo_hull_compute (cairo_pen_vertex_t *vertices, int *num_vertices);
@ -1398,6 +1477,13 @@ _cairo_path_fixed_bounds (cairo_path_fixed_t *path,
double *x1, double *y1,
double *x2, double *y2);
cairo_private void
_cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path,
cairo_fixed_t offx,
cairo_fixed_t offy,
cairo_fixed_t scalex,
cairo_fixed_t scaley);
/* cairo_path_fill.c */
cairo_private cairo_status_t
_cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path,
@ -1407,9 +1493,12 @@ _cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path,
/* cairo_path_stroke.c */
cairo_private cairo_status_t
_cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
cairo_gstate_t *gstate,
cairo_traps_t *traps);
_cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
cairo_stroke_style_t *stroke_style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_traps_t *traps);
/* cairo-scaled-font.c */
@ -1454,7 +1543,7 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
cairo_private cairo_status_t
_cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_surface_t *surface,
int source_x,
@ -1463,7 +1552,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
int dest_y,
unsigned int width,
unsigned int height,
cairo_glyph_t *glyphs,
const cairo_glyph_t *glyphs,
int num_glyphs);
cairo_private cairo_status_t
@ -1496,6 +1585,18 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
cairo_private void
_cairo_scaled_font_map_destroy (void);
/* cairo-stroke-style.c */
cairo_private void
_cairo_stroke_style_init (cairo_stroke_style_t *style);
cairo_private cairo_status_t
_cairo_stroke_style_init_copy (cairo_stroke_style_t *style,
cairo_stroke_style_t *other);
cairo_private void
_cairo_stroke_style_fini (cairo_stroke_style_t *style);
/* cairo-surface.c */
extern const cairo_private cairo_surface_t _cairo_surface_nil;
@ -1523,7 +1624,7 @@ cairo_private cairo_clip_mode_t
_cairo_surface_get_clip_mode (cairo_surface_t *surface);
cairo_private cairo_status_t
_cairo_surface_composite (cairo_operator_t operator,
_cairo_surface_composite (cairo_operator_t op,
cairo_pattern_t *src,
cairo_pattern_t *mask,
cairo_surface_t *dst,
@ -1538,7 +1639,7 @@ _cairo_surface_composite (cairo_operator_t operator,
cairo_private cairo_status_t
_cairo_surface_fill_rectangle (cairo_surface_t *surface,
cairo_operator_t operator,
cairo_operator_t op,
const cairo_color_t *color,
int x,
int y,
@ -1547,27 +1648,58 @@ _cairo_surface_fill_rectangle (cairo_surface_t *surface,
cairo_private cairo_status_t
_cairo_surface_fill_region (cairo_surface_t *surface,
cairo_operator_t operator,
cairo_operator_t op,
const cairo_color_t *color,
pixman_region16_t *region);
cairo_private cairo_status_t
_cairo_surface_fill_rectangles (cairo_surface_t *surface,
cairo_operator_t operator,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects);
cairo_private cairo_int_status_t
_cairo_surface_fill_path (cairo_operator_t operator,
cairo_pattern_t *pattern,
cairo_surface_t *dst,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance);
cairo_private cairo_status_t
_cairo_surface_paint (cairo_surface_t *surface,
cairo_operator_t op,
cairo_pattern_t *source);
cairo_private cairo_status_t
_cairo_surface_mask (cairo_surface_t *surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_pattern_t *mask);
cairo_private cairo_status_t
_cairo_surface_stroke (cairo_surface_t *surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_stroke_style_t *style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias);
cairo_private cairo_status_t
_cairo_surface_fill (cairo_surface_t *surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias);
cairo_private cairo_status_t
_cairo_surface_show_glyphs (cairo_surface_t *surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font);
cairo_private cairo_status_t
_cairo_surface_composite_trapezoids (cairo_operator_t operator,
_cairo_surface_composite_trapezoids (cairo_operator_t op,
cairo_pattern_t *pattern,
cairo_surface_t *dst,
cairo_antialias_t antialias,
@ -1580,18 +1712,10 @@ _cairo_surface_composite_trapezoids (cairo_operator_t operator,
cairo_trapezoid_t *traps,
int ntraps);
cairo_private cairo_status_t
_cairo_surface_clip_and_composite_trapezoids (cairo_pattern_t *src,
cairo_operator_t operator,
cairo_surface_t *dst,
cairo_traps_t *traps,
cairo_clip_t *clip,
cairo_antialias_t antialias);
cairo_private cairo_status_t
cairo_private cairo_int_status_t
_cairo_surface_copy_page (cairo_surface_t *surface);
cairo_private cairo_status_t
cairo_private cairo_int_status_t
_cairo_surface_show_page (cairo_surface_t *surface);
cairo_private cairo_status_t
@ -1623,6 +1747,9 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
cairo_surface_t *src,
cairo_surface_t **clone_out);
cairo_private cairo_surface_t *
_cairo_surface_snapshot (cairo_surface_t *surface);
cairo_private unsigned int
_cairo_surface_get_current_clip_serial (cairo_surface_t *surface);
@ -1652,18 +1779,18 @@ _cairo_surface_get_extents (cairo_surface_t *surface,
cairo_rectangle_t *rectangle);
cairo_private cairo_status_t
_cairo_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
cairo_pattern_t *pattern,
cairo_surface_t *surface,
int source_x,
int source_y,
int dest_x,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
int num_glyphs);
_cairo_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t op,
cairo_pattern_t *pattern,
cairo_surface_t *surface,
int source_x,
int source_y,
int dest_x,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
int num_glyphs);
cairo_private cairo_status_t
_cairo_surface_composite_fixup_unbounded (cairo_surface_t *dst,
@ -1715,6 +1842,10 @@ _cairo_format_from_content (cairo_content_t content);
cairo_private cairo_content_t
_cairo_content_from_format (cairo_format_t format);
cairo_surface_t *
_cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
cairo_format_t format);
cairo_private cairo_surface_t *
_cairo_image_surface_create_with_masks (unsigned char *data,
cairo_format_masks_t *format,
@ -1725,16 +1856,18 @@ _cairo_image_surface_create_with_masks (unsigned char *data,
cairo_private void
_cairo_image_surface_assume_ownership_of_data (cairo_image_surface_t *surface);
cairo_private cairo_int_status_t
_cairo_image_surface_set_clip_region (cairo_image_surface_t *surface,
pixman_region16_t *region);
cairo_private cairo_bool_t
_cairo_surface_is_image (const cairo_surface_t *surface);
cairo_private cairo_bool_t
_cairo_surface_is_image (cairo_surface_t *surface);
_cairo_surface_is_meta (const cairo_surface_t *surface);
/* cairo_pen.c */
cairo_private cairo_status_t
_cairo_pen_init (cairo_pen_t *pen, double radius, cairo_gstate_t *gstate);
_cairo_pen_init (cairo_pen_t *pen,
double radius,
double tolerance,
cairo_matrix_t *ctm);
cairo_private cairo_status_t
_cairo_pen_init_empty (cairo_pen_t *pen);
@ -1830,6 +1963,10 @@ _cairo_matrix_is_integer_translation(const cairo_matrix_t *matrix,
cairo_private double
_cairo_matrix_transformed_circle_major_axis(cairo_matrix_t *matrix, double radius);
cairo_private void
_cairo_matrix_to_pixman_matrix (const cairo_matrix_t *matrix,
pixman_transform_t *pixman_transform);
/* cairo_traps.c */
cairo_private void
_cairo_traps_init (cairo_traps_t *traps);
@ -1865,6 +2002,13 @@ cairo_private cairo_status_t
_cairo_traps_extract_region (cairo_traps_t *tr,
pixman_region16_t **region);
cairo_private void
_cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps,
cairo_trapezoid_t *src_traps,
int num_traps,
double tx, double ty,
double sx, double sy);
/* cairo_slope.c */
cairo_private void
_cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b);
@ -1944,6 +2088,10 @@ _cairo_pattern_acquire_surfaces (cairo_pattern_t *src,
cairo_surface_attributes_t *src_attributes,
cairo_surface_attributes_t *mask_attributes);
cairo_status_t
_cairo_pattern_get_extents (cairo_pattern_t *pattern,
cairo_rectangle_t *extents);
cairo_private cairo_status_t
_cairo_gstate_set_antialias (cairo_gstate_t *gstate,
cairo_antialias_t antialias);
@ -2014,6 +2162,9 @@ _cairo_output_stream_create_for_file (const char *filename);
cairo_private void
_cairo_error (cairo_status_t status);
cairo_private int
_cairo_dtostr (char *buffer, size_t size, double d);
/* Avoid unnecessary PLT entries. */
slim_hidden_proto(cairo_get_current_point)
@ -2037,5 +2188,11 @@ slim_hidden_proto(cairo_restore)
slim_hidden_proto(cairo_save)
slim_hidden_proto(cairo_stroke_preserve)
slim_hidden_proto(cairo_surface_destroy)
slim_hidden_proto(cairo_push_group)
slim_hidden_proto(cairo_pop_group)
slim_hidden_proto(cairo_pop_group_to_source)
slim_hidden_proto(moz_cairo_set_target)
CAIRO_END_DECLS
#endif

Просмотреть файл

@ -0,0 +1,205 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Carl Worth <cworth@cworth.org>
*/
/* This isn't a "real" surface, but just something to be used by the
* test suite to test a mythical backend that uses nothing but
* fallbacks.
*
* The defining feature of this backend is that it has as many NULL
* backend function entries as possible. The ones that aren't NULL are
* simply those that must be implemented to have working fallbacks.
* (Except for create_similar---fallbacks would work fine without
* that---I implemented it here in order to create as many surfaces as
* possible of type test_fallback_surface_t during the test suite
* run).
*
* It's possible that this code might serve as a good starting point
* for someone working on bringing up a new backend, starting with the
* minimal all-fallbacks approach and working up gradually from
* there.
*/
#include "test-fallback-surface.h"
#include "cairoint.h"
typedef struct _test_fallback_surface {
cairo_surface_t base;
/* This is a cairo_image_surface to hold the actual contents. */
cairo_surface_t *backing;
} test_fallback_surface_t;
const cairo_private cairo_surface_backend_t test_fallback_surface_backend;
cairo_surface_t *
_test_fallback_surface_create (cairo_format_t format,
int width,
int height)
{
test_fallback_surface_t *surface;
cairo_surface_t *backing;
backing = cairo_image_surface_create (format, width, height);
if (cairo_surface_status (backing))
return (cairo_surface_t*) &_cairo_surface_nil;
surface = malloc (sizeof (test_fallback_surface_t));
if (surface == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t*) &_cairo_surface_nil;
}
_cairo_surface_init (&surface->base, &test_fallback_surface_backend);
surface->backing = backing;
return &surface->base;
}
static cairo_surface_t *
_test_fallback_surface_create_similar (void *abstract_surface,
cairo_content_t content,
int width,
int height)
{
assert (CAIRO_CONTENT_VALID (content));
return _test_fallback_surface_create (_cairo_format_from_content (content),
width, height);
}
static cairo_status_t
_test_fallback_surface_finish (void *abstract_surface)
{
test_fallback_surface_t *surface = abstract_surface;
cairo_surface_destroy (surface->backing);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_test_fallback_surface_acquire_source_image (void *abstract_surface,
cairo_image_surface_t **image_out,
void **image_extra)
{
test_fallback_surface_t *surface = abstract_surface;
return _cairo_surface_acquire_source_image (surface->backing,
image_out, image_extra);
}
static void
_test_fallback_surface_release_source_image (void *abstract_surface,
cairo_image_surface_t *image,
void *image_extra)
{
test_fallback_surface_t *surface = abstract_surface;
_cairo_surface_release_source_image (surface->backing,
image, image_extra);
}
static cairo_status_t
_test_fallback_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_t *interest_rect,
cairo_image_surface_t**image_out,
cairo_rectangle_t *image_rect_out,
void **image_extra)
{
test_fallback_surface_t *surface = abstract_surface;
return _cairo_surface_acquire_dest_image (surface->backing,
interest_rect,
image_out,
image_rect_out,
image_extra);
}
static void
_test_fallback_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_t *interest_rect,
cairo_image_surface_t*image,
cairo_rectangle_t *image_rect,
void *image_extra)
{
test_fallback_surface_t *surface = abstract_surface;
_cairo_surface_release_dest_image (surface->backing,
interest_rect,
image,
image_rect,
image_extra);
}
static cairo_int_status_t
_test_fallback_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
{
test_fallback_surface_t *surface = abstract_surface;
return _cairo_surface_get_extents (surface->backing, rectangle);
}
const cairo_surface_backend_t test_fallback_surface_backend = {
_test_fallback_surface_create_similar,
_test_fallback_surface_finish,
_test_fallback_surface_acquire_source_image,
_test_fallback_surface_release_source_image,
_test_fallback_surface_acquire_dest_image,
_test_fallback_surface_release_dest_image,
NULL, /* clone_similar */
NULL, /* composite */
NULL, /* fill_rectangles */
NULL, /* composite_trapezoids */
NULL, /* copy_page */
NULL, /* show_page */
NULL, /* set_clip_region */
NULL, /* intersect_clip_path */
_test_fallback_surface_get_extents,
NULL, /* old_show_glyphs */
NULL, /* get_font_options */
NULL, /* flush */
NULL, /* mark_dirty_rectangle */
NULL, /* scaled_font_fini */
NULL, /* scaled_glyph_fini */
NULL, /* paint */
NULL, /* mask */
NULL, /* stroke */
NULL, /* fill */
NULL, /* show_glyphs */
NULL /* snapshot */
};

Просмотреть файл

@ -0,0 +1,50 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Carl Worth <cworth@cworth.org>
*/
#ifndef TEST_FALLBACK_SURFACE_H
#define TEST_FALLBACK_SURFACE_H
#include "cairo.h"
CAIRO_BEGIN_DECLS
cairo_surface_t *
_test_fallback_surface_create (cairo_format_t format,
int width,
int height);
CAIRO_END_DECLS
#endif /* TEST_FALLBACK_SURFACE_H */

Просмотреть файл

@ -0,0 +1,325 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Carl Worth <cworth@cworth.org>
*/
/* This isn't a "real" surface, but just something to be used by the
* test suite to help exercise the meta-surface paths in cairo.
*
* The defining feature of this backend is that it uses a meta surface
* to record all operations, and then replays everything to an image
* surface.
*
* It's possible that this code might serve as a good starting point
* for someone working on bringing up a new meta-surface-based
* backend.
*/
#include "test-meta-surface.h"
#include "cairoint.h"
#include "cairo-meta-surface-private.h"
typedef struct _test_meta_surface {
cairo_surface_t base;
/* This is a cairo_meta_surface to record all operations. */
cairo_surface_t *meta;
/* And this is a cairo_image_surface to hold the final result. */
cairo_surface_t *image;
cairo_bool_t image_reflects_meta;
} test_meta_surface_t;
const cairo_private cairo_surface_backend_t test_meta_surface_backend;
static cairo_int_status_t
_test_meta_surface_show_page (void *abstract_surface);
cairo_surface_t *
_test_meta_surface_create (cairo_format_t format,
int width,
int height)
{
test_meta_surface_t *surface;
surface = malloc (sizeof (test_meta_surface_t));
if (surface == NULL)
goto FAIL;
_cairo_surface_init (&surface->base, &test_meta_surface_backend);
surface->meta = _cairo_meta_surface_create (width, height);
if (cairo_surface_status (surface->meta))
goto FAIL_CLEANUP_SURFACE;
surface->image = cairo_image_surface_create (format, width, height);
if (cairo_surface_status (surface->image))
goto FAIL_CLEANUP_META;
surface->image_reflects_meta = FALSE;
return &surface->base;
FAIL_CLEANUP_META:
cairo_surface_destroy (surface->meta);
FAIL_CLEANUP_SURFACE:
free (surface);
FAIL:
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t*) &_cairo_surface_nil;
}
static cairo_status_t
_test_meta_surface_finish (void *abstract_surface)
{
test_meta_surface_t *surface = abstract_surface;
cairo_surface_destroy (surface->meta);
cairo_surface_destroy (surface->image);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_test_meta_surface_acquire_source_image (void *abstract_surface,
cairo_image_surface_t **image_out,
void **image_extra)
{
test_meta_surface_t *surface = abstract_surface;
if (! surface->image_reflects_meta)
_test_meta_surface_show_page (abstract_surface);
return _cairo_surface_acquire_source_image (surface->image,
image_out, image_extra);
}
static void
_test_meta_surface_release_source_image (void *abstract_surface,
cairo_image_surface_t *image,
void *image_extra)
{
test_meta_surface_t *surface = abstract_surface;
_cairo_surface_release_source_image (surface->image,
image, image_extra);
}
static cairo_int_status_t
_test_meta_surface_show_page (void *abstract_surface)
{
test_meta_surface_t *surface = abstract_surface;
if (surface->image_reflects_meta)
return CAIRO_STATUS_SUCCESS;
_cairo_meta_surface_replay (surface->meta, surface->image);
surface->image_reflects_meta = TRUE;
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_test_meta_surface_intersect_clip_path (void *abstract_surface,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias)
{
test_meta_surface_t *surface = abstract_surface;
return _cairo_surface_intersect_clip_path (surface->meta,
path, fill_rule,
tolerance, antialias);
}
static cairo_int_status_t
_test_meta_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
{
test_meta_surface_t *surface = abstract_surface;
surface->image_reflects_meta = FALSE;
return _cairo_surface_get_extents (surface->image, rectangle);
}
static cairo_int_status_t
_test_meta_surface_paint (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source)
{
test_meta_surface_t *surface = abstract_surface;
surface->image_reflects_meta = FALSE;
return _cairo_surface_paint (surface->meta, op, source);
}
static cairo_int_status_t
_test_meta_surface_mask (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_pattern_t *mask)
{
test_meta_surface_t *surface = abstract_surface;
surface->image_reflects_meta = FALSE;
return _cairo_surface_mask (surface->meta, op, source, mask);
}
static cairo_int_status_t
_test_meta_surface_stroke (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_stroke_style_t *style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias)
{
test_meta_surface_t *surface = abstract_surface;
surface->image_reflects_meta = FALSE;
return _cairo_surface_stroke (surface->meta, op, source,
path, style,
ctm, ctm_inverse,
tolerance, antialias);
}
static cairo_int_status_t
_test_meta_surface_fill (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias)
{
test_meta_surface_t *surface = abstract_surface;
surface->image_reflects_meta = FALSE;
return _cairo_surface_fill (surface->meta, op, source,
path, fill_rule,
tolerance, antialias);
}
static cairo_int_status_t
_test_meta_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{
test_meta_surface_t *surface = abstract_surface;
surface->image_reflects_meta = FALSE;
return _cairo_surface_show_glyphs (surface->meta, op, source,
glyphs, num_glyphs,
scaled_font);
}
static cairo_surface_t *
_test_meta_surface_snapshot (void *abstract_other)
{
test_meta_surface_t *other = abstract_other;
/* XXX: Just making a snapshot of other->meta is what we really
* want. But this currently triggers a bug somewhere (the "mask"
* test from the test suite segfaults).
*
* For now, we'll create a new image surface and replay onto
* that. It would be tempting to replay into other->image and then
* return a snapshot of that, but that will cause the self-copy
* test to fail, (since our replay will be affected by a clip that
* should not have any effect on the use of the resulting snapshot
* as a source).
*/
#if 0
return _cairo_surface_snapshot (other->meta);
#else
cairo_rectangle_t extents;
cairo_surface_t *surface;
_cairo_surface_get_extents (other->image, &extents);
surface = cairo_surface_create_similar (other->image,
CAIRO_CONTENT_COLOR_ALPHA,
extents.width,
extents.height);
_cairo_meta_surface_replay (other->meta, surface);
return surface;
#endif
}
const cairo_surface_backend_t test_meta_surface_backend = {
NULL, /* create_similar */
_test_meta_surface_finish,
_test_meta_surface_acquire_source_image,
_test_meta_surface_release_source_image,
NULL, /* acquire_dest_image */
NULL, /* release_dest_image */
NULL, /* clone_similar */
NULL, /* composite */
NULL, /* fill_rectangles */
NULL, /* composite_trapezoids */
NULL, /* copy_page */
_test_meta_surface_show_page,
NULL, /* set_clip_region */
_test_meta_surface_intersect_clip_path,
_test_meta_surface_get_extents,
NULL, /* old_show_glyphs */
NULL, /* get_font_options */
NULL, /* flush */
NULL, /* mark_dirty_rectangle */
NULL, /* scaled_font_fini */
NULL, /* scaled_glyph_fini */
_test_meta_surface_paint,
_test_meta_surface_mask,
_test_meta_surface_stroke,
_test_meta_surface_fill,
_test_meta_surface_show_glyphs,
_test_meta_surface_snapshot
};

Просмотреть файл

@ -0,0 +1,50 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Carl Worth <cworth@cworth.org>
*/
#ifndef TEST_META_SURFACE_H
#define TEST_META_SURFACE_H
#include "cairo.h"
CAIRO_BEGIN_DECLS
cairo_surface_t *
_test_meta_surface_create (cairo_format_t format,
int width,
int height);
CAIRO_END_DECLS
#endif /* TEST_META_SURFACE_H */

Просмотреть файл

@ -0,0 +1,67 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Carl Worth <cworth@cworth.org>
*/
/* This isn't a "real" surface, but just something to be used by the
* test suite to help exercise the paginated-surface paths in cairo.
*
* The defining feature of this backend is that it uses a paginated
* surface to record all operations, and then replays everything to an
* image surface.
*
* It's possible that this code might serve as a good starting point
* for someone working on bringing up a new paginated-surface-based
* backend.
*/
#include "test-paginated-surface.h"
#include "cairoint.h"
#include "cairo-paginated-surface-private.h"
cairo_surface_t *
_test_paginated_surface_create_for_data (unsigned char *data,
cairo_format_t format,
int width,
int height,
int stride)
{
cairo_surface_t *target;
target = cairo_image_surface_create_for_data (data, format,
width, height, stride);
return _cairo_paginated_surface_create (target, width, height);
}

Просмотреть файл

@ -0,0 +1,52 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Carl Worth <cworth@cworth.org>
*/
#ifndef TEST_PAGINATED_SURFACE_H
#define TEST_PAGINATED_SURFACE_H
#include "cairo.h"
CAIRO_BEGIN_DECLS
cairo_surface_t *
_test_paginated_surface_create_for_data (unsigned char *data,
cairo_format_t format,
int width,
int height,
int stride);
CAIRO_END_DECLS
#endif /* TEST_PAGINATED_SURFACE_H */

Просмотреть файл

Просмотреть файл

@ -47,10 +47,14 @@ glitz_agl_fini (void);
/* glitz_agl_format.c */
glitz_drawable_format_t *
glitz_agl_find_drawable_format (unsigned long mask,
const glitz_drawable_format_t *templ,
int count);
glitz_agl_find_window_format (unsigned long mask,
const glitz_drawable_format_t *templ,
int count);
glitz_drawable_format_t *
glitz_agl_find_pbuffer_format (unsigned long mask,
const glitz_drawable_format_t *templ,
int count);
/* glitz_agl_drawable.c */

Просмотреть файл

@ -36,7 +36,7 @@ _glitz_agl_get_bundle (const char *name)
{
CFBundleRef bundle = 0;
FSRefParam ref_param;
unsigned char framework_name[256];
char framework_name[256];
framework_name[0] = strlen (name);
strcpy (&framework_name[1], name);
@ -52,7 +52,7 @@ _glitz_agl_get_bundle (const char *name)
memset (&ref, 0, sizeof (ref));
ref_param.ioNamePtr = framework_name;
ref_param.ioNamePtr = (unsigned char *) framework_name;
ref_param.newRef = &ref;
if (PBMakeFSRefSync (&ref_param) == noErr) {
@ -173,9 +173,9 @@ _glitz_agl_make_current (void *abstract_drawable,
if (drawable->base.width != drawable->width ||
drawable->base.height != drawable->height)
_glitz_agl_drawable_update_size (drawable,
drawable->base.width,
drawable->base.height);
glitz_agl_drawable_update_size (drawable,
drawable->base.width,
drawable->base.height);
if (aglGetCurrentContext () != context->context)
{
@ -186,7 +186,7 @@ _glitz_agl_make_current (void *abstract_drawable,
if (drawable->pbuffer)
{
AGLPbuffer pbuffer;
GLuint unused;
GLint unused;
aglGetPBuffer (context->context, &pbuffer,
&unused, &unused, &unused);
@ -242,7 +242,7 @@ _glitz_agl_context_get_proc_address (void *abstract_context,
glitz_function_pointer_t func;
CFBundleRef bundle;
_glitz_agl_make_current (drawable, context, NULL);
_glitz_agl_make_current (drawable, context);
bundle = _glitz_agl_get_bundle ("OpenGL.framework");
@ -309,20 +309,23 @@ glitz_agl_context_get (glitz_agl_thread_info_t *thread_info,
context->backend.make_current = _glitz_agl_make_current;
context->backend.get_proc_address = _glitz_agl_context_get_proc_address;
context->backend.draw_buffer = _glitz_drawable_draw_buffer;
context->backend.read_buffer = _glitz_drawable_read_buffer;
context->backend.drawable_formats = NULL;
context->backend.n_drawable_formats = 0;
if (screen_info->n_formats)
if (thread_info->n_formats)
{
int size;
size = sizeof (glitz_int_drawable_format_t) * screen_info->n_formats;
size = sizeof (glitz_int_drawable_format_t) * thread_info->n_formats;
context->backend.drawable_formats = malloc (size);
if (context->backend.drawable_formats)
{
memcpy (context->backend.drawable_formats, screen_info->formats,
memcpy (context->backend.drawable_formats, thread_info->formats,
size);
context->backend.n_drawable_formats = screen_info->n_formats;
context->backend.n_drawable_formats = thread_info->n_formats;
}
}
@ -436,9 +439,9 @@ _glitz_agl_context_update (glitz_agl_drawable_t *drawable,
case GLITZ_DRAWABLE_CURRENT:
if (drawable->base.width != drawable->width ||
drawable->base.height != drawable->height)
_glitz_agl_drawable_update_size (drawable,
drawable->base.width,
drawable->base.height);
glitz_agl_drawable_update_size (drawable,
drawable->base.width,
drawable->base.height);
context = aglGetCurrentContext ();
if (context != drawable->context->context) {
@ -446,7 +449,7 @@ _glitz_agl_context_update (glitz_agl_drawable_t *drawable,
} else {
if (drawable->pbuffer) {
AGLPbuffer pbuffer;
GLuint unused;
GLint unused;
aglGetPBuffer (drawable->context->context, &pbuffer,
&unused, &unused, &unused);

Просмотреть файл

@ -52,7 +52,7 @@ _glitz_agl_create_drawable (glitz_agl_thread_info_t *thread_info,
drawable->height = height;
_glitz_drawable_init (&drawable->base,
format,
&thread_info->formats[format->id],
&context->backend,
width, height);
@ -73,16 +73,15 @@ _glitz_agl_create_drawable (glitz_agl_thread_info_t *thread_info,
}
glitz_bool_t
_glitz_agl_drawable_update_size (glitz_agl_drawable_t *drawable,
int width,
int height)
glitz_agl_drawable_update_size (glitz_agl_drawable_t *drawable,
int width,
int height)
{
if (drawable->pbuffer)
{
glitz_agl_pbuffer_destroy (drawable->thread_info, drawable->pbuffer);
glitz_agl_pbuffer_destroy (drawable->pbuffer);
drawable->pbuffer =
glitz_agl_pbuffer_create (drawable->thread_info,
drawable->context->fbconfig,
(int) width, (int) height);
if (!drawable->pbuffer)
return 0;
@ -104,9 +103,6 @@ _glitz_agl_create_pbuffer_drawable (glitz_agl_thread_info_t *thread_info,
glitz_agl_context_t *context;
AGLPbuffer pbuffer;
if (!format->types.pbuffer)
return NULL;
context = glitz_agl_context_get (thread_info, format);
if (!context)
return NULL;
@ -158,7 +154,7 @@ glitz_agl_create_drawable_for_window (glitz_drawable_format_t *format,
if (!thread_info)
return NULL;
if (format->id >= screen_info->n_formats)
if (format->id >= thread_info->n_formats)
return NULL;
context = glitz_agl_context_get (thread_info, format);
@ -186,7 +182,7 @@ glitz_agl_create_pbuffer_drawable (glitz_drawable_format_t *format,
if (!thread_info)
return NULL;
if (format->id >= screen_info->n_formats)
if (format->id >= thread_info->n_formats)
return NULL;
return _glitz_agl_create_pbuffer_drawable (thread_info, format,
@ -208,8 +204,9 @@ glitz_agl_destroy (void *abstract_drawable)
*/
glitz_agl_push_current (abstract_drawable, NULL,
GLITZ_CONTEXT_CURRENT);
glitz_program_map_fini (&drawable->base.backend->gl,
glitz_program_map_fini (drawable->base.backend->gl,
&drawable->thread_info->program_map);
glitz_program_map_init (&drawable->thread_info->program_map);
glitz_agl_pop_current (abstract_drawable);
}
@ -219,7 +216,7 @@ glitz_agl_destroy (void *abstract_drawable)
if (context == drawable->context->context) {
if (drawable->pbuffer) {
AGLPbuffer pbuffer;
GLuint unused;
GLint unused;
aglGetPBuffer (context, &pbuffer, &unused, &unused, &unused);

Просмотреть файл

@ -145,58 +145,60 @@ static int
_glitz_agl_format_compare (const void *elem1,
const void *elem2)
{
int i, score[2];
glitz_drawable_format_t *format[2];
glitz_int_drawable_format_t *format[2];
int i, score[2];
format[0] = (glitz_drawable_format_t *) elem1;
format[1] = (glitz_drawable_format_t *) elem2;
format[0] = (glitz_int_drawable_format_t *) elem1;
format[1] = (glitz_int_drawable_format_t *) elem2;
i = score[0] = score[1] = 0;
for (; i < 2; i++) {
if (format[i]->color.red_size) {
if (format[i]->color.red_size == 8)
for (; i < 2; i++)
{
if (format[i]->d.color.red_size)
{
if (format[i]->d.color.red_size >= 8)
score[i] += 5;
score[i] += 10;
}
if (format[i]->color.green_size) {
if (format[i]->color.green_size == 8)
if (format[i]->d.color.alpha_size)
{
if (format[i]->d.color.alpha_size >= 8)
score[i] += 5;
score[i] += 10;
}
if (format[i]->color.alpha_size) {
if (format[i]->color.alpha_size == 8)
score[i] += 5;
score[i] += 10;
}
if (format[i]->stencil_size)
if (format[i]->d.stencil_size)
score[i] += 5;
if (format[i]->depth_size)
if (format[i]->d.depth_size)
score[i] += 5;
if (format[i]->doublebuffer)
if (format[i]->d.doublebuffer)
score[i] += 10;
if (format[i]->types.window)
if (format[i]->d.samples > 1)
score[i] -= (20 - format[i]->d.samples);
if (format[i]->types & GLITZ_DRAWABLE_TYPE_WINDOW_MASK)
score[i] += 10;
if (format[i]->types.pbuffer)
if (format[i]->types & GLITZ_DRAWABLE_TYPE_PBUFFER_MASK)
score[i] += 10;
if (format[i]->samples > 1)
score[i] -= (20 - format[i]->samples);
if (format[i]->caveat)
score[i] -= 1000;
}
return score[1] - score[0];
}
static void
_glitz_add_format (glitz_agl_thread_info_t *thread_info,
glitz_drawable_format_t *format,
AGLPixelFormat pixel_format)
_glitz_agl_add_format (glitz_agl_thread_info_t *thread_info,
glitz_int_drawable_format_t *format,
AGLPixelFormat pixel_format)
{
if (!glitz_drawable_format_find (thread_info->formats,
thread_info->n_formats,
@ -206,14 +208,14 @@ _glitz_add_format (glitz_agl_thread_info_t *thread_info,
thread_info->formats =
realloc (thread_info->formats,
sizeof (glitz_drawable_format_t) * (n + 1));
sizeof (glitz_int_drawable_format_t) * (n + 1));
thread_info->pixel_formats =
realloc (thread_info->pixel_formats,
sizeof (AGLPixelFormat) * (n + 1));
if (thread_info->formats && thread_info->pixel_formats) {
thread_info->formats[n] = *format;
thread_info->formats[n].id = n;
thread_info->formats[n] = *(glitz_int_drawable_format_t*)format;
thread_info->formats[n].d.id = n;
thread_info->pixel_formats[n] = pixel_format;
thread_info->n_formats++;
}
@ -223,12 +225,13 @@ _glitz_add_format (glitz_agl_thread_info_t *thread_info,
void
glitz_agl_query_formats (glitz_agl_thread_info_t *thread_info)
{
glitz_drawable_format_t format;
glitz_int_drawable_format_t format;
AGLPixelFormat pixel_format, *new_pfs;
int n_attribs_list, i;
format.types.window = 1;
format.id = 0;
format.types = GLITZ_DRAWABLE_TYPE_WINDOW_MASK;
format.d.id = 0;
format.color.fourcc = GLITZ_FOURCC_RGB;
n_attribs_list = sizeof (_attribs_list) / sizeof (GLint *);
@ -245,20 +248,20 @@ glitz_agl_query_formats (glitz_agl_thread_info_t *thread_info)
}
aglDescribePixelFormat (pixel_format, AGL_DOUBLEBUFFER, &value);
format.doublebuffer = (value)? 1: 0;
format.d.doublebuffer = (value)? 1: 0;
aglDescribePixelFormat (pixel_format, AGL_RED_SIZE, &value);
format.color.red_size = (unsigned short) value;
format.d.color.red_size = (unsigned short) value;
aglDescribePixelFormat (pixel_format, AGL_GREEN_SIZE, &value);
format.color.green_size = (unsigned short) value;
format.d.color.green_size = (unsigned short) value;
aglDescribePixelFormat (pixel_format, AGL_BLUE_SIZE, &value);
format.color.blue_size = (unsigned short) value;
format.d.color.blue_size = (unsigned short) value;
aglDescribePixelFormat (pixel_format, AGL_ALPHA_SIZE, &value);
format.color.alpha_size = (unsigned short) value;
format.d.color.alpha_size = (unsigned short) value;
aglDescribePixelFormat (pixel_format, AGL_DEPTH_SIZE, &value);
format.depth_size = (unsigned short) value;
format.d.depth_size = (unsigned short) value;
aglDescribePixelFormat (pixel_format, AGL_STENCIL_SIZE, &value);
format.stencil_size = (unsigned short) value;
format.d.stencil_size = (unsigned short) value;
if (thread_info->agl_feature_mask & GLITZ_AGL_FEATURE_MULTISAMPLE_MASK)
{
@ -266,42 +269,42 @@ glitz_agl_query_formats (glitz_agl_thread_info_t *thread_info)
&value);
if (value) {
aglDescribePixelFormat (pixel_format, AGL_SAMPLES_ARB, &value);
format.samples = (unsigned short) (value > 1)? value: 1;
format.d.samples = (unsigned short) (value > 1)? value: 1;
} else
format.samples = 1;
format.d.samples = 1;
} else
format.samples = 1;
format.d.samples = 1;
if (thread_info->agl_feature_mask & GLITZ_AGL_FEATURE_PBUFFER_MASK) {
if (format.color.red_size && format.color.green_size &&
format.color.blue_size && format.color.alpha_size &&
format.doublebuffer == 0 && format.stencil_size == 0 &&
format.depth_size == 0) {
if (format.d.color.red_size && format.d.color.green_size &&
format.d.color.blue_size && format.d.color.alpha_size &&
format.d.doublebuffer == 0 && format.d.stencil_size == 0 &&
format.d.depth_size == 0) {
if (thread_info->agl_feature_mask &
GLITZ_AGL_FEATURE_PBUFFER_MULTISAMPLE_MASK)
format.types.pbuffer = 1;
else if (format.samples == 1)
format.types.pbuffer = 1;
format.types |= GLITZ_DRAWABLE_TYPE_PBUFFER_MASK;
else if (format.d.samples == 1)
format.types |= GLITZ_DRAWABLE_TYPE_PBUFFER_MASK;
else
format.types.pbuffer = 0;
format.types &= ~GLITZ_DRAWABLE_TYPE_PBUFFER_MASK;
} else
format.types.pbuffer = 0;
format.types &= ~GLITZ_DRAWABLE_TYPE_PBUFFER_MASK;
} else
format.types.pbuffer = 0;
format.types &= ~GLITZ_DRAWABLE_TYPE_PBUFFER_MASK;
if (format.color.red_size ||
format.color.green_size ||
format.color.blue_size ||
format.color.alpha_size)
_glitz_add_format (thread_info, &format, pixel_format);
if (format.d.color.red_size ||
format.d.color.green_size ||
format.d.color.blue_size ||
format.d.color.alpha_size)
_glitz_agl_add_format (thread_info, &format, pixel_format);
}
if (!thread_info->n_formats)
return;
qsort (thread_info->formats, thread_info->n_formats,
sizeof (glitz_drawable_format_t), _glitz_agl_format_compare);
sizeof (glitz_int_drawable_format_t), _glitz_agl_format_compare);
/*
* Update AGLPixelFormat list so that it matches the sorted format list.
@ -313,8 +316,8 @@ glitz_agl_query_formats (glitz_agl_thread_info_t *thread_info)
}
for (i = 0; i < thread_info->n_formats; i++) {
new_pfs[i] = thread_info->pixel_formats[thread_info->formats[i].id];
thread_info->formats[i].id = i;
new_pfs[i] = thread_info->pixel_formats[thread_info->formats[i].d.id];
thread_info->formats[i].d.id = i;
}
free (thread_info->pixel_formats);
@ -322,14 +325,43 @@ glitz_agl_query_formats (glitz_agl_thread_info_t *thread_info)
}
glitz_drawable_format_t *
glitz_agl_find_drawable_format (unsigned long mask,
const glitz_drawable_format_t *templ,
int count)
glitz_agl_find_window_format (unsigned long mask,
const glitz_drawable_format_t *templ,
int count)
{
glitz_agl_thread_info_t *thread_info = glitz_agl_thread_info_get ();
glitz_int_drawable_format_t itempl;
glitz_agl_thread_info_t *thread_info =
glitz_agl_thread_info_get ();
glitz_drawable_format_copy (templ, &itempl.d, mask);
itempl.types = GLITZ_DRAWABLE_TYPE_WINDOW_MASK;
mask |= GLITZ_INT_FORMAT_WINDOW_MASK;
return glitz_drawable_format_find (thread_info->formats,
thread_info->n_formats,
mask, templ, count);
mask, &itempl, count);
}
slim_hidden_def(glitz_agl_find_drawable_format);
slim_hidden_def(glitz_agl_find_window_format);
glitz_drawable_format_t *
glitz_agl_find_pbuffer_format (unsigned long mask,
const glitz_drawable_format_t *templ,
int count)
{
glitz_int_drawable_format_t itempl;
glitz_agl_thread_info_t *thread_info =
glitz_agl_thread_info_get ();
glitz_drawable_format_copy (templ, &itempl.d, mask);
itempl.types = GLITZ_DRAWABLE_TYPE_PBUFFER_MASK;
mask |= GLITZ_INT_FORMAT_PBUFFER_MASK;
return glitz_drawable_format_find (thread_info->formats,
thread_info->n_formats,
mask, &itempl, count);
}
slim_hidden_def(glitz_agl_find_pbuffer_format);

Просмотреть файл

@ -130,6 +130,11 @@ glitz_agl_destroy (void *abstract_drawable);
extern glitz_bool_t __internal_linkage
glitz_agl_swap_buffers (void *abstract_drawable);
extern glitz_bool_t __internal_linkage
glitz_agl_drawable_update_size (glitz_agl_drawable_t *drawable,
int width,
int height);
/* Avoid unnecessary PLT entries. */
slim_hidden_proto(glitz_agl_init)
@ -137,5 +142,6 @@ slim_hidden_proto(glitz_agl_fini)
slim_hidden_proto(glitz_agl_find_drawable_format)
slim_hidden_proto(glitz_agl_create_drawable_for_window)
slim_hidden_proto(glitz_agl_create_pbuffer_drawable)
slim_hidden_proto(glitz_agl_drawable_update_size)
#endif /* GLITZ_GLXINT_H_INCLUDED */

Просмотреть файл

@ -45,6 +45,9 @@ _glitz_egl_format_compare (const void *elem1,
for (; i < 2; i++)
{
if (format[i]->d.color.fourcc != GLITZ_FOURCC_RGB)
score[i] -= 1000;
if (format[i]->d.color.red_size)
{
if (format[i]->d.color.red_size >= 8)
@ -118,7 +121,8 @@ _glitz_egl_query_configs (glitz_egl_screen_info_t *screen_info)
if (!egl_configs)
return;
format.d.id = 0;
format.d.id = 0;
format.d.color.fourcc = GLITZ_FOURCC_RGB;
format.d.doublebuffer = 1;
eglGetConfigs (egl_display, egl_configs, num_configs, &num_configs);

Просмотреть файл

@ -122,7 +122,7 @@ _glitz_egl_make_current (void *abstract_drawable,
drawable->base.height);
if ((eglGetCurrentContext () != context->egl_context) ||
(eglGetCurrentSurface ( 0 ) != drawable->egl_surface))
(eglGetCurrentSurface ( EGL_READ ) != drawable->egl_surface))
{
if (display_info->thread_info->cctx)
{
@ -206,6 +206,9 @@ glitz_egl_context_get (glitz_egl_screen_info_t *screen_info,
context->backend.make_current = _glitz_egl_make_current;
context->backend.get_proc_address = _glitz_egl_context_get_proc_address;
context->backend.draw_buffer = _glitz_drawable_draw_buffer;
context->backend.read_buffer = _glitz_drawable_read_buffer;
context->backend.drawable_formats = NULL;
context->backend.n_drawable_formats = 0;

Просмотреть файл

@ -215,6 +215,7 @@ glitz_egl_destroy (void *abstract_drawable)
GLITZ_CONTEXT_CURRENT);
glitz_program_map_fini (surface->base.backend->gl,
&surface->screen_info->program_map);
glitz_program_map_init (&surface->screen_info->program_map);
glitz_egl_pop_current (abstract_drawable);
}

Просмотреть файл

@ -422,8 +422,10 @@ glitz_copy_area (glitz_surface_t *src,
glitz_surface_pop_current (src);
}
gl->read_buffer (src->buffer);
gl->draw_buffer (dst->buffer);
src->drawable->backend->read_buffer (src->drawable,
src->buffer);
dst->drawable->backend->draw_buffer (dst->drawable,
dst->buffer);
glitz_set_operator (gl, GLITZ_OPERATOR_SRC);
@ -496,8 +498,8 @@ glitz_copy_area (glitz_surface_t *src,
gl->color_4us (0x0, 0x0, 0x0, 0xffff);
param.filter[0] = param.filter[1] = GLITZ_GL_CLAMP_TO_EDGE;
param.wrap[0] = param.wrap[1] = GLITZ_GL_NEAREST;
param.filter[0] = param.filter[1] = GLITZ_GL_NEAREST;
param.wrap[0] = param.wrap[1] = GLITZ_GL_CLAMP_TO_EDGE;
glitz_texture_ensure_parameters (gl, texture, &param);
@ -596,7 +598,7 @@ glitz_copy_area (glitz_surface_t *src,
{
glitz_texture_t *texture;
gl->read_buffer (src->buffer);
src->drawable->backend->read_buffer (src->drawable, src->buffer);
texture = glitz_surface_get_texture (dst, 1);
if (texture)

Просмотреть файл

@ -26,19 +26,9 @@
#ifndef GLITZ_H_INCLUDED
#define GLITZ_H_INCLUDED
#if defined(__SVR4) && defined(__sun)
# include <sys/int_types.h>
#else
# if defined(__OpenBSD__)
# include <inttypes.h>
# else
# include <stdint.h>
# endif
#endif
#define GLITZ_MAJOR 0
#define GLITZ_MINOR 5
#define GLITZ_REVISION 0
#define GLITZ_REVISION 2
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
@ -158,17 +148,29 @@ typedef enum {
typedef unsigned long glitz_format_id_t;
typedef unsigned int glitz_fourcc_t;
#define GLITZ_FORMAT_FOURCC_MASK (1L << 5)
#define GLITZ_FOURCC(a, b, c, d) \
((a) | (b) << 8 | (c) << 16 | ((glitz_fourcc_t) (d)) << 24)
#define GLITZ_FOURCC_RGB ((glitz_fourcc_t) 0x0)
#define GLITZ_FOURCC_YV12 GLITZ_FOURCC ('Y', 'V', '1', '2')
#define GLITZ_FOURCC_YUY2 GLITZ_FOURCC ('Y', 'U', 'Y', '2')
typedef struct _glitz_color_format_t {
glitz_fourcc_t fourcc;
unsigned short red_size;
unsigned short green_size;
unsigned short blue_size;
unsigned short alpha_size;
} glitz_color_format_t;
#define GLITZ_FORMAT_DEPTH_SIZE_MASK (1L << 5)
#define GLITZ_FORMAT_STENCIL_SIZE_MASK (1L << 6)
#define GLITZ_FORMAT_DOUBLEBUFFER_MASK (1L << 7)
#define GLITZ_FORMAT_SAMPLES_MASK (1L << 8)
#define GLITZ_FORMAT_DEPTH_SIZE_MASK (1L << 6)
#define GLITZ_FORMAT_STENCIL_SIZE_MASK (1L << 7)
#define GLITZ_FORMAT_DOUBLEBUFFER_MASK (1L << 8)
#define GLITZ_FORMAT_SAMPLES_MASK (1L << 9)
typedef struct _glitz_drawable_format_t {
glitz_format_id_t id;
@ -179,15 +181,8 @@ typedef struct _glitz_drawable_format_t {
glitz_bool_t doublebuffer;
} glitz_drawable_format_t;
#define GLITZ_FORMAT_TYPE_MASK (1L << 5)
typedef enum {
GLITZ_FORMAT_TYPE_COLOR
} glitz_format_type_t;
typedef struct _glitz_format_t {
glitz_format_id_t id;
glitz_format_type_t type;
glitz_color_format_t color;
} glitz_format_t;
@ -482,6 +477,15 @@ void
glitz_context_bind_texture (glitz_context_t *context,
glitz_texture_object_t *texture);
void
glitz_context_draw_buffers (glitz_context_t *context,
const glitz_drawable_buffer_t *buffers,
int n);
void
glitz_context_read_buffer (glitz_context_t *context,
const glitz_drawable_buffer_t buffer);
/* glitz_rect.c */
@ -579,6 +583,7 @@ typedef struct _glitz_pixel_masks {
} glitz_pixel_masks_t;
typedef struct _glitz_pixel_format {
glitz_fourcc_t fourcc;
glitz_pixel_masks_t masks;
int xoffset;
int skip_lines;

Просмотреть файл

@ -347,7 +347,7 @@ _glitz_combine_solid_solidc (glitz_composite_op_t *op)
if (op->solid->alpha > 0)
op->gl->blend_color ((glitz_gl_clampf_t)
op->solid->red / op->solid->alpha,
op->solid->red / op->solid->alpha,
(glitz_gl_clampf_t)
op->solid->green / op->solid->alpha,
(glitz_gl_clampf_t)
@ -421,9 +421,10 @@ _glitz_combine_map[GLITZ_SURFACE_TYPES][GLITZ_SURFACE_TYPES] = {
((SURFACE_PAD (surface))? \
(TEXTURE_PADABLE (&(surface)->texture)) \
: \
( \
(!SURFACE_PROJECTIVE_TRANSFORM (surface)) || \
((feature_mask) & GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK) \
(TEXTURE_CLAMPABLE (&(surface)->texture) && \
((!SURFACE_PROJECTIVE_TRANSFORM (surface)) || \
((feature_mask) & GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK) \
) \
) \
) \
)

Просмотреть файл

@ -110,6 +110,11 @@ void
glitz_context_make_current (glitz_context_t *context,
glitz_drawable_t *drawable)
{
glitz_lose_current_function_t lose_current;
lose_current = context->lose_current;
context->lose_current = 0;
if (drawable != context->drawable)
{
glitz_drawable_reference (drawable);
@ -145,6 +150,8 @@ glitz_context_make_current (glitz_context_t *context,
GLITZ_DAMAGE_SOLID_MASK);
}
context->lose_current = lose_current;
drawable->backend->make_current (drawable, context);
}
slim_hidden_def(glitz_context_make_current);
@ -179,3 +186,63 @@ glitz_context_bind_texture (glitz_context_t *context,
&texture->param);
}
slim_hidden_def(glitz_context_bind_texture);
void
glitz_context_draw_buffers (glitz_context_t *context,
const glitz_drawable_buffer_t *buffers,
int n)
{
unsigned int mask = 0;
#define FRONT_BIT (1 << 0)
#define BACK_BIT (1 << 1)
while (n--)
{
switch (*buffers++) {
case GLITZ_DRAWABLE_BUFFER_FRONT_COLOR:
mask |= FRONT_BIT;
break;
case GLITZ_DRAWABLE_BUFFER_BACK_COLOR:
mask |= BACK_BIT;
default:
break;
}
}
if (mask)
{
if (mask == (FRONT_BIT | BACK_BIT))
context->drawable->backend->draw_buffer (context->drawable,
GLITZ_GL_FRONT_AND_BACK);
else if (mask == FRONT_BIT)
context->drawable->backend->draw_buffer (context->drawable,
GLITZ_GL_FRONT);
else
context->drawable->backend->draw_buffer (context->drawable,
GLITZ_GL_BACK);
}
#undef FRONT_BIT
#undef BACK_BIT
}
slim_hidden_def(glitz_context_draw_buffers);
void
glitz_context_read_buffer (glitz_context_t *context,
const glitz_drawable_buffer_t buffer)
{
switch (buffer) {
case GLITZ_DRAWABLE_BUFFER_FRONT_COLOR:
context->drawable->backend->read_buffer (context->drawable,
GLITZ_GL_FRONT);
break;
case GLITZ_DRAWABLE_BUFFER_BACK_COLOR:
context->drawable->backend->read_buffer (context->drawable,
GLITZ_GL_BACK);
default:
break;
}
}
slim_hidden_def(glitz_context_read_buffer);

Просмотреть файл

@ -55,6 +55,28 @@ _glitz_drawable_init (glitz_drawable_t *drawable,
drawable->update_all = 1;
}
void
_glitz_drawable_draw_buffer (void *abstract_drawable,
const glitz_gl_enum_t buffer)
{
glitz_drawable_t *drawable = abstract_drawable;
GLITZ_GL_DRAWABLE (drawable);
gl->draw_buffer (buffer);
}
void
_glitz_drawable_read_buffer (void *abstract_drawable,
const glitz_gl_enum_t buffer)
{
glitz_drawable_t *drawable = abstract_drawable;
GLITZ_GL_DRAWABLE (drawable);
gl->read_buffer (buffer);
}
static glitz_bool_t
_glitz_drawable_size_check (glitz_drawable_t *other,
unsigned int width,
@ -241,8 +263,8 @@ glitz_drawable_swap_buffer_region (glitz_drawable_t *drawable,
gl->disable (GLITZ_GL_DITHER);
gl->read_buffer (GLITZ_GL_BACK);
gl->draw_buffer (GLITZ_GL_FRONT);
drawable->backend->read_buffer (drawable, GLITZ_GL_BACK);
drawable->backend->draw_buffer (drawable, GLITZ_GL_FRONT);
glitz_set_operator (gl, GLITZ_OPERATOR_SRC);

Просмотреть файл

@ -107,6 +107,10 @@ glitz_filter_set_params (glitz_surface_t *surface,
_glitz_filter_params_set (&dm, 3.0f, &params, &n_params);
_glitz_filter_params_set (&dn, 3.0f, &params, &n_params);
glitz_clamp_value (&dm, 1.0f, 1024.0f);
glitz_clamp_value (&dn, 1.0f, 1024.0f);
m = dm;
n = dn;
@ -130,8 +134,10 @@ glitz_filter_set_params (glitz_surface_t *surface,
_glitz_filter_params_set (&weight, 0.0f, &params, &n_params);
if (weight != 0.0f) {
vec = &vecs[surface->filter_params->id++];
vec->v[0] = (i - cx) * surface->texture.texcoord_width_unit;
vec->v[1] = (cy - j) * surface->texture.texcoord_height_unit;
vec->v[0] = (i - cx) *
surface->texture.texcoord_width_unit;
vec->v[1] = (cy - j) *
surface->texture.texcoord_height_unit;
vec->v[2] = weight;
vec->v[3] = 0.0f;
}
@ -211,15 +217,16 @@ glitz_filter_set_params (glitz_surface_t *surface,
if (size < 2)
size = 2;
if (_glitz_filter_params_ensure (surface, size + 1))
return GLITZ_STATUS_NO_MEMORY;
vecs = surface->filter_params->vectors;
if (filter == GLITZ_FILTER_LINEAR_GRADIENT) {
glitz_float_t length, angle, dh, dv;
if (filter == GLITZ_FILTER_LINEAR_GRADIENT)
{
glitz_float_t length, dh, dv;
glitz_float_t start_x, start_y, stop_x, stop_y;
if (_glitz_filter_params_ensure (surface, size + 1))
return GLITZ_STATUS_NO_MEMORY;
vecs = surface->filter_params->vectors;
_glitz_filter_params_set (&start_x, 0.0f, &params, &n_params);
_glitz_filter_params_set (&start_y, 0.0f, &params, &n_params);
_glitz_filter_params_set (&stop_x, 1.0f, &params, &n_params);
@ -228,32 +235,48 @@ glitz_filter_set_params (glitz_surface_t *surface,
dh = stop_x - start_x;
dv = stop_y - start_y;
length = sqrtf (dh * dh + dv * dv);
length = dh * dh + dv * dv;
angle = -atan2f (dv, dh);
vecs->v[0] = dh / length;
vecs->v[1] = dv / length;
vecs->v[2] = -vecs->v[0] * start_x - vecs->v[1] * start_y;
vecs->v[3] = 0.0f;
}
else
{
glitz_float_t r0, r1, r, x0, y0, x1, y1, dx, dy;
vecs->v[2] = cosf (angle);
vecs->v[3] = -sinf (angle);
if (_glitz_filter_params_ensure (surface, size + 2))
return GLITZ_STATUS_NO_MEMORY;
vecs->v[0] = vecs->v[2] * start_x;
vecs->v[0] += vecs->v[3] * start_y;
vecs = surface->filter_params->vectors;
vecs->v[1] = (length)? 1.0f / length: 2147483647.0f;
} else {
glitz_float_t r0, r1;
_glitz_filter_params_set (&vecs->v[0], 0.5f, &params, &n_params);
_glitz_filter_params_set (&vecs->v[1], 0.5f, &params, &n_params);
_glitz_filter_params_set (&x0, 0.5f, &params, &n_params);
_glitz_filter_params_set (&y0, 0.5f, &params, &n_params);
_glitz_filter_params_set (&r0, 0.0f, &params, &n_params);
_glitz_filter_params_set (&r1, 0.5f, &params, &n_params);
_glitz_filter_params_set (&x1, x0, &params, &n_params);
_glitz_filter_params_set (&y1, y0, &params, &n_params);
_glitz_filter_params_set (&r1, r0 + 0.5f, &params, &n_params);
glitz_clamp_value (&r0, 0.0f, r1);
vecs->v[2] = r0;
if (r1 != r0)
vecs->v[3] = 1.0f / (r1 - r0);
else
vecs->v[3] = 2147483647.0f;
r = r0 / r1;
dx = x1 - x0;
dy = y1 - y0;
vecs->v[0] = x0 - r * dx;
vecs->v[1] = y0 - r * dy;
vecs->v[2] = dx * 2.0f;
vecs->v[3] = dy * 2.0f;
vecs++;
vecs->v[0] = 1.0f / (1.0f + r);
vecs->v[1] = -r * vecs->v[0];
vecs->v[2] = (r1 * r1 - dx * dx - dy * dy) * 4.0f;
vecs->v[3] = 2.0f / vecs->v[2];
}
vecs++;
@ -309,10 +332,35 @@ glitz_filter_set_params (glitz_surface_t *surface,
break;
case GLITZ_FILTER_BILINEAR:
case GLITZ_FILTER_NEAREST:
if (surface->filter_params)
free (surface->filter_params);
switch (surface->format->color.fourcc) {
case GLITZ_FOURCC_YV12:
if (_glitz_filter_params_ensure (surface, 2))
return GLITZ_STATUS_NO_MEMORY;
surface->filter_params = NULL;
vecs = surface->filter_params->vectors;
vecs->v[0] = 0.0f;
vecs->v[1] = surface->texture.texcoord_height_unit *
((surface->texture.box.y2 + 1) & ~1);
vecs->v[2] = surface->texture.texcoord_width_unit *
(surface->texture.width >> 1);
vecs->v[3] = 0.0f;
vecs++;
vecs->v[0] = surface->texture.texcoord_width_unit;
vecs->v[1] = surface->texture.texcoord_height_unit;
vecs->v[2] = surface->texture.texcoord_width_unit *
surface->texture.box.x2 - vecs->v[0];
vecs->v[3] = surface->texture.texcoord_height_unit *
surface->texture.box.y2 - vecs->v[1];
surface->filter_params->id = 1;
break;
default:
free (surface->filter_params);
surface->filter_params = NULL;
}
break;
}
@ -325,6 +373,9 @@ glitz_gl_uint_t
glitz_filter_get_fragment_program (glitz_surface_t *surface,
glitz_composite_op_t *op)
{
if (surface->filter_params->fp_type == GLITZ_FP_UNSUPPORTED)
return 0;
return glitz_get_fragment_program (op,
surface->filter_params->fp_type,
surface->filter_params->id);
@ -334,43 +385,56 @@ void
glitz_filter_set_type (glitz_surface_t *surface,
glitz_filter_t filter)
{
switch (filter) {
case GLITZ_FILTER_CONVOLUTION:
case GLITZ_FILTER_GAUSSIAN:
surface->filter_params->fp_type = GLITZ_FP_CONVOLUTION;
switch (surface->format->color.fourcc) {
case GLITZ_FOURCC_YV12:
switch (filter) {
case GLITZ_FILTER_BILINEAR:
case GLITZ_FILTER_NEAREST:
surface->filter_params->fp_type = GLITZ_FP_COLORSPACE_YV12;
break;
default:
surface->filter_params->fp_type = GLITZ_FP_UNSUPPORTED;
break;
}
break;
case GLITZ_FILTER_LINEAR_GRADIENT:
if (surface->flags & GLITZ_SURFACE_FLAG_REPEAT_MASK) {
if (SURFACE_MIRRORED (surface))
default:
switch (filter) {
case GLITZ_FILTER_CONVOLUTION:
case GLITZ_FILTER_GAUSSIAN:
surface->filter_params->fp_type = GLITZ_FP_CONVOLUTION;
break;
case GLITZ_FILTER_LINEAR_GRADIENT:
if (surface->flags & GLITZ_SURFACE_FLAG_REPEAT_MASK) {
if (SURFACE_MIRRORED (surface))
surface->filter_params->fp_type =
GLITZ_FP_LINEAR_GRADIENT_REFLECT;
else
surface->filter_params->fp_type =
GLITZ_FP_LINEAR_GRADIENT_REPEAT;
} else if (surface->flags & GLITZ_SURFACE_FLAG_PAD_MASK) {
surface->filter_params->fp_type =
GLITZ_FP_LINEAR_GRADIENT_REFLECT;
else
GLITZ_FP_LINEAR_GRADIENT_NEAREST;
} else
surface->filter_params->fp_type =
GLITZ_FP_LINEAR_GRADIENT_REPEAT;
} else if (surface->flags & GLITZ_SURFACE_FLAG_PAD_MASK) {
surface->filter_params->fp_type =
GLITZ_FP_LINEAR_GRADIENT_NEAREST;
} else
surface->filter_params->fp_type =
GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT;
break;
case GLITZ_FILTER_RADIAL_GRADIENT:
if (surface->flags & GLITZ_SURFACE_FLAG_REPEAT_MASK) {
if (SURFACE_MIRRORED (surface))
GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT;
break;
case GLITZ_FILTER_RADIAL_GRADIENT:
if (surface->flags & GLITZ_SURFACE_FLAG_REPEAT_MASK) {
if (SURFACE_MIRRORED (surface))
surface->filter_params->fp_type =
GLITZ_FP_RADIAL_GRADIENT_REFLECT;
else
surface->filter_params->fp_type =
GLITZ_FP_RADIAL_GRADIENT_REPEAT;
} else if (surface->flags & GLITZ_SURFACE_FLAG_PAD_MASK) {
surface->filter_params->fp_type =
GLITZ_FP_RADIAL_GRADIENT_REFLECT;
else
GLITZ_FP_RADIAL_GRADIENT_NEAREST;
} else
surface->filter_params->fp_type =
GLITZ_FP_RADIAL_GRADIENT_REPEAT;
} else if (surface->flags & GLITZ_SURFACE_FLAG_PAD_MASK) {
surface->filter_params->fp_type = GLITZ_FP_RADIAL_GRADIENT_NEAREST;
} else
surface->filter_params->fp_type =
GLITZ_FP_RADIAL_GRADIENT_TRANSPARENT;
break;
case GLITZ_FILTER_BILINEAR:
case GLITZ_FILTER_NEAREST:
break;
GLITZ_FP_RADIAL_GRADIENT_TRANSPARENT;
default:
break;
}
}
}
@ -402,6 +466,15 @@ glitz_filter_enable (glitz_surface_t *surface,
vec++;
j = 1;
if (surface->filter == GLITZ_FILTER_RADIAL_GRADIENT)
{
gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, j++,
vec->v);
vec++;
}
if (fp_type == GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT ||
fp_type == GLITZ_FP_RADIAL_GRADIENT_TRANSPARENT) {
glitz_vec4_t v;
@ -410,10 +483,8 @@ glitz_filter_enable (glitz_surface_t *surface,
v.v[2] = 0.0f;
v.v[3] = (vec->v[3])? 1.0f / vec->v[3]: 1.0f;
gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, 1, v.v);
j = 2;
} else
j = 1;
gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, j++, v.v);
}
for (i = 0; i < surface->filter_params->id; i++, vec++)
gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM,
@ -432,6 +503,18 @@ glitz_filter_enable (glitz_surface_t *surface,
} break;
case GLITZ_FILTER_BILINEAR:
case GLITZ_FILTER_NEAREST:
switch (surface->format->color.fourcc) {
case GLITZ_FOURCC_YV12: {
glitz_vec4_t *vec;
vec = surface->filter_params->vectors;
gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, 0,
vec[0].v);
gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, 1,
vec[1].v);
} break;
}
break;
}
}

Просмотреть файл

@ -31,28 +31,32 @@
#include <stdlib.h>
struct _texture_format {
static struct _texture_format {
glitz_gl_int_t texture_format;
glitz_format_t format;
} _texture_formats[] = {
{ GLITZ_GL_ALPHA4, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 4 } } },
{ GLITZ_GL_ALPHA8, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 8 } } },
{ GLITZ_GL_ALPHA12, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 12 } } },
{ GLITZ_GL_ALPHA16, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 16 } } },
{ GLITZ_GL_R3_G3_B2, { 0, GLITZ_FORMAT_TYPE_COLOR, { 3, 3, 2, 0 } } },
{ GLITZ_GL_RGB4, { 0, GLITZ_FORMAT_TYPE_COLOR, { 4, 4, 4, 0 } } },
{ GLITZ_GL_RGB5, { 0, GLITZ_FORMAT_TYPE_COLOR, { 5, 6, 5, 0 } } },
{ GLITZ_GL_RGB8, { 0, GLITZ_FORMAT_TYPE_COLOR, { 8, 8, 8, 0 } } },
{ GLITZ_GL_RGB10, { 0, GLITZ_FORMAT_TYPE_COLOR, { 10, 10, 10, 0 } } },
{ GLITZ_GL_RGB12, { 0, GLITZ_FORMAT_TYPE_COLOR, { 12, 12, 12, 0 } } },
{ GLITZ_GL_RGB16, { 0, GLITZ_FORMAT_TYPE_COLOR, { 16, 16, 16, 0 } } },
{ GLITZ_GL_RGBA2, { 0, GLITZ_FORMAT_TYPE_COLOR, { 2, 2, 2, 2 } } },
{ GLITZ_GL_RGB5_A1, { 0, GLITZ_FORMAT_TYPE_COLOR, { 5, 5, 5, 1 } } },
{ GLITZ_GL_RGBA4, { 0, GLITZ_FORMAT_TYPE_COLOR, { 4, 4, 4, 4 } } },
{ GLITZ_GL_RGBA8, { 0, GLITZ_FORMAT_TYPE_COLOR, { 8, 8, 8, 8 } } },
{ GLITZ_GL_RGB10_A2, { 0, GLITZ_FORMAT_TYPE_COLOR, { 10, 10, 10, 2 } } },
{ GLITZ_GL_RGBA12, { 0, GLITZ_FORMAT_TYPE_COLOR, { 12, 12, 12, 12 } } },
{ GLITZ_GL_RGBA16, { 0, GLITZ_FORMAT_TYPE_COLOR, { 16, 16, 16, 16 } } }
{ GLITZ_GL_ALPHA4, { 0, { GLITZ_FOURCC_RGB, 0, 0, 0, 4 } } },
{ GLITZ_GL_ALPHA8, { 0, { GLITZ_FOURCC_RGB, 0, 0, 0, 8 } } },
{ GLITZ_GL_ALPHA12, { 0, { GLITZ_FOURCC_RGB, 0, 0, 0, 12 } } },
{ GLITZ_GL_ALPHA16, { 0, { GLITZ_FOURCC_RGB, 0, 0, 0, 16 } } },
{ GLITZ_GL_R3_G3_B2, { 0, { GLITZ_FOURCC_RGB, 3, 3, 2, 0 } } },
{ GLITZ_GL_RGB4, { 0, { GLITZ_FOURCC_RGB, 4, 4, 4, 0 } } },
{ GLITZ_GL_RGB5, { 0, { GLITZ_FOURCC_RGB, 5, 6, 5, 0 } } },
{ GLITZ_GL_RGB8, { 0, { GLITZ_FOURCC_RGB, 8, 8, 8, 0 } } },
{ GLITZ_GL_RGB10, { 0, { GLITZ_FOURCC_RGB, 10, 10, 10, 0 } } },
{ GLITZ_GL_RGB12, { 0, { GLITZ_FOURCC_RGB, 12, 12, 12, 0 } } },
{ GLITZ_GL_RGB16, { 0, { GLITZ_FOURCC_RGB, 16, 16, 16, 0 } } },
{ GLITZ_GL_RGBA2, { 0, { GLITZ_FOURCC_RGB, 2, 2, 2, 2 } } },
{ GLITZ_GL_RGB5_A1, { 0, { GLITZ_FOURCC_RGB, 5, 5, 5, 1 } } },
{ GLITZ_GL_RGBA4, { 0, { GLITZ_FOURCC_RGB, 4, 4, 4, 4 } } },
{ GLITZ_GL_RGBA8, { 0, { GLITZ_FOURCC_RGB, 8, 8, 8, 8 } } },
{ GLITZ_GL_RGB10_A2, { 0, { GLITZ_FOURCC_RGB, 10, 10, 10, 2 } } },
{ GLITZ_GL_RGBA12, { 0, { GLITZ_FOURCC_RGB, 12, 12, 12, 12 } } },
{ GLITZ_GL_RGBA16, { 0, { GLITZ_FOURCC_RGB, 16, 16, 16, 16 } } }
};
static glitz_format_t _texture_format_yv12 = {
0, { GLITZ_FOURCC_YV12, 0, 0, 0, 0 }
};
static void
@ -79,7 +83,8 @@ void
glitz_create_surface_formats (glitz_gl_proc_address_list_t *gl,
glitz_format_t **formats,
glitz_gl_int_t **texture_formats,
int *n_formats)
int *n_formats,
unsigned long features)
{
glitz_gl_int_t value;
int i, n_texture_formats;
@ -88,12 +93,12 @@ glitz_create_surface_formats (glitz_gl_proc_address_list_t *gl,
sizeof (_texture_formats) / sizeof (struct _texture_format);
for (i = 0; i < n_texture_formats; i++) {
gl->tex_image_2d (GLITZ_GL_PROXY_TEXTURE_2D, 0,
_texture_formats[i].texture_format, 1, 1, 0,
GLITZ_GL_RGBA, GLITZ_GL_UNSIGNED_BYTE, NULL);
switch (_texture_formats[i].format.color.fourcc) {
case GLITZ_FOURCC_RGB:
gl->tex_image_2d (GLITZ_GL_PROXY_TEXTURE_2D, 0,
_texture_formats[i].texture_format, 1, 1, 0,
GLITZ_GL_RGBA, GLITZ_GL_UNSIGNED_BYTE, NULL);
switch (_texture_formats[i].format.type) {
case GLITZ_FORMAT_TYPE_COLOR:
if (_texture_formats[i].format.color.red_size) {
gl->get_tex_level_parameter_iv (GLITZ_GL_PROXY_TEXTURE_2D, 0,
GLITZ_GL_TEXTURE_RED_SIZE,
@ -136,6 +141,13 @@ glitz_create_surface_formats (glitz_gl_proc_address_list_t *gl,
_texture_formats[i].texture_format,
&_texture_formats[i].format);
}
/* formats used for YUV surfaces */
if (features & GLITZ_FEATURE_FRAGMENT_PROGRAM_MASK)
{
_glitz_add_texture_format (formats, texture_formats, n_formats,
GLITZ_GL_LUMINANCE8, &_texture_format_yv12);
}
}
static void
@ -155,7 +167,7 @@ _glitz_add_drawable_format (glitz_int_drawable_format_t *format,
}
}
/* TODO: Available drawable formats needs to be validated is a similar way
/* TODO: Available drawable formats needs to be validated in a similar way
as surface formats. */
void
_glitz_add_drawable_formats (glitz_gl_proc_address_list_t *gl,
@ -167,10 +179,10 @@ _glitz_add_drawable_formats (glitz_gl_proc_address_list_t *gl,
{
glitz_int_drawable_format_t format;
glitz_drawable_format_t d[] = {
{ 0, { 8, 8, 8, 0 }, 0, 0, 1, 0 },
{ 0, { 8, 8, 8, 8 }, 0, 0, 1, 0 },
{ 0, { 8, 8, 8, 0 }, 24, 8, 1, 1 },
{ 0, { 8, 8, 8, 8 }, 24, 8, 1, 1 }
{ 0, { GLITZ_FOURCC_RGB, 8, 8, 8, 0 }, 0, 0, 1, 0 },
{ 0, { GLITZ_FOURCC_RGB, 8, 8, 8, 8 }, 0, 0, 1, 0 },
{ 0, { GLITZ_FOURCC_RGB, 8, 8, 8, 0 }, 24, 8, 1, 1 },
{ 0, { GLITZ_FOURCC_RGB, 8, 8, 8, 8 }, 24, 8, 1, 1 }
};
int i;
@ -196,6 +208,9 @@ glitz_drawable_format_copy (const glitz_drawable_format_t *src,
if (mask & GLITZ_FORMAT_ID_MASK)
dst->id = src->id;
if (mask & GLITZ_FORMAT_FOURCC_MASK)
dst->color.fourcc = src->color.fourcc;
if (mask & GLITZ_FORMAT_RED_SIZE_MASK)
dst->color.red_size = src->color.red_size;
@ -234,6 +249,10 @@ glitz_drawable_format_find (glitz_int_drawable_format_t *formats,
if (templ->d.id != formats->d.id)
continue;
if (mask & GLITZ_FORMAT_FOURCC_MASK)
if (templ->d.color.fourcc != formats->d.color.fourcc)
continue;
if (mask & GLITZ_FORMAT_RED_SIZE_MASK)
if (templ->d.color.red_size != formats->d.color.red_size)
continue;
@ -300,8 +319,8 @@ _glitz_format_find (glitz_format_t *formats,
if (templ->id != formats->id)
continue;
if (mask & GLITZ_FORMAT_TYPE_MASK)
if (templ->type != formats->type)
if (mask & GLITZ_FORMAT_FOURCC_MASK)
if (templ->color.fourcc != formats->color.fourcc)
continue;
if (mask & GLITZ_FORMAT_RED_SIZE_MASK)
@ -345,9 +364,13 @@ glitz_find_standard_format (glitz_drawable_t *drawable,
glitz_format_t templ;
unsigned long mask = GLITZ_FORMAT_RED_SIZE_MASK |
GLITZ_FORMAT_GREEN_SIZE_MASK | GLITZ_FORMAT_BLUE_SIZE_MASK |
GLITZ_FORMAT_ALPHA_SIZE_MASK | GLITZ_FORMAT_TYPE_MASK;
GLITZ_FORMAT_ALPHA_SIZE_MASK | GLITZ_FORMAT_FOURCC_MASK;
templ.type = GLITZ_FORMAT_TYPE_COLOR;
templ.color.fourcc = GLITZ_FOURCC_RGB;
templ.color.red_size = 0;
templ.color.green_size = 0;
templ.color.blue_size = 0;
templ.color.alpha_size = 0;
switch (format_name) {
case GLITZ_STANDARD_ARGB32:
@ -360,18 +383,11 @@ glitz_find_standard_format (glitz_drawable_t *drawable,
templ.color.red_size = 8;
templ.color.green_size = 8;
templ.color.blue_size = 8;
templ.color.alpha_size = 0;
break;
case GLITZ_STANDARD_A8:
templ.color.red_size = 0;
templ.color.green_size = 0;
templ.color.blue_size = 0;
templ.color.alpha_size = 8;
break;
case GLITZ_STANDARD_A1:
templ.color.red_size = 0;
templ.color.green_size = 0;
templ.color.blue_size = 0;
templ.color.alpha_size = 1;
break;
}

Просмотреть файл

@ -313,6 +313,19 @@ _glitz_fbo_swap_buffers (void *abstract_drawable)
if (!drawable->fb)
return 1;
/* flip */
if (drawable->base.back && drawable->base.front)
{
glitz_texture_t tmp;
tmp = drawable->base.front->texture;
drawable->base.front->texture = drawable->base.back->texture;
drawable->base.back->texture = tmp;
return 1;
}
return 0;
}
@ -351,6 +364,50 @@ _glitz_fbo_destroy (void *abstract_drawable)
free (drawable);
}
static void
_glitz_fbo_draw_buffer (void *abstract_drawable,
const glitz_gl_enum_t buffer)
{
glitz_fbo_drawable_t *drawable = (glitz_fbo_drawable_t *)
abstract_drawable;
GLITZ_GL_DRAWABLE (drawable->other);
switch (buffer) {
case GLITZ_GL_FRONT:
gl->draw_buffer (GLITZ_GL_COLOR_ATTACHMENT0);
break;
case GLITZ_GL_BACK:
gl->draw_buffer (GLITZ_GL_COLOR_ATTACHMENT1);
break;
/* TODO: use GL_ARB_draw_buffers
case GLITZ_GL_FRONT_AND_BACK:
*/
default:
break;
}
}
static void
_glitz_fbo_read_buffer (void *abstract_drawable,
const glitz_gl_enum_t buffer)
{
glitz_fbo_drawable_t *drawable = (glitz_fbo_drawable_t *)
abstract_drawable;
GLITZ_GL_DRAWABLE (drawable->other);
switch (buffer) {
case GLITZ_GL_FRONT:
gl->read_buffer (GLITZ_GL_COLOR_ATTACHMENT0);
break;
case GLITZ_GL_BACK:
gl->read_buffer (GLITZ_GL_COLOR_ATTACHMENT1);
default:
break;
}
}
glitz_drawable_t *
_glitz_fbo_drawable_create (glitz_drawable_t *other,
glitz_int_drawable_format_t *format,
@ -377,6 +434,8 @@ _glitz_fbo_drawable_create (glitz_drawable_t *other,
backend->detach_notify = _glitz_fbo_detach_notify;
backend->swap_buffers = _glitz_fbo_swap_buffers;
backend->make_current = _glitz_fbo_make_current;
backend->draw_buffer = _glitz_fbo_draw_buffer;
backend->read_buffer = _glitz_fbo_read_buffer;
drawable->fb = 0;

Просмотреть файл

@ -202,24 +202,25 @@ typedef ptrdiff_t glitz_gl_sizeiptr_t;
#define GLITZ_GL_BGR 0x80E0
#define GLITZ_GL_BGRA 0x80E1
#define GLITZ_GL_ALPHA4 0x803B
#define GLITZ_GL_ALPHA8 0x803C
#define GLITZ_GL_ALPHA12 0x803D
#define GLITZ_GL_ALPHA16 0x803E
#define GLITZ_GL_R3_G3_B2 0x2A10
#define GLITZ_GL_RGB4 0x804F
#define GLITZ_GL_RGB5 0x8050
#define GLITZ_GL_RGB8 0x8051
#define GLITZ_GL_RGB10 0x8052
#define GLITZ_GL_RGB12 0x8053
#define GLITZ_GL_RGB16 0x8054
#define GLITZ_GL_RGBA2 0x8055
#define GLITZ_GL_RGBA4 0x8056
#define GLITZ_GL_RGB5_A1 0x8057
#define GLITZ_GL_RGBA8 0x8058
#define GLITZ_GL_RGB10_A2 0x8059
#define GLITZ_GL_RGBA12 0x805A
#define GLITZ_GL_RGBA16 0x805B
#define GLITZ_GL_ALPHA4 0x803B
#define GLITZ_GL_ALPHA8 0x803C
#define GLITZ_GL_ALPHA12 0x803D
#define GLITZ_GL_ALPHA16 0x803E
#define GLITZ_GL_LUMINANCE8 0x8040
#define GLITZ_GL_R3_G3_B2 0x2A10
#define GLITZ_GL_RGB4 0x804F
#define GLITZ_GL_RGB5 0x8050
#define GLITZ_GL_RGB8 0x8051
#define GLITZ_GL_RGB10 0x8052
#define GLITZ_GL_RGB12 0x8053
#define GLITZ_GL_RGB16 0x8054
#define GLITZ_GL_RGBA2 0x8055
#define GLITZ_GL_RGBA4 0x8056
#define GLITZ_GL_RGB5_A1 0x8057
#define GLITZ_GL_RGBA8 0x8058
#define GLITZ_GL_RGB10_A2 0x8059
#define GLITZ_GL_RGBA12 0x805A
#define GLITZ_GL_RGBA16 0x805B
#define GLITZ_GL_FRONT_AND_BACK 0x0408
#define GLITZ_GL_FLAT 0x1D00

Просмотреть файл

@ -37,23 +37,10 @@ typedef struct _glitz_gl_pixel_format {
glitz_gl_enum_t type;
} glitz_gl_pixel_format_t;
static glitz_gl_pixel_format_t _gl_pixel_formats[] = {
static glitz_gl_pixel_format_t _gl_rgb_pixel_formats[] = {
{
{
{
8,
0x000000ff,
0x00000000,
0x00000000,
0x00000000
},
0, 0, 0,
GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP
},
GLITZ_GL_ALPHA,
GLITZ_GL_UNSIGNED_BYTE
}, {
{
GLITZ_FOURCC_RGB,
{
32,
0xff000000,
@ -72,12 +59,31 @@ static glitz_gl_pixel_format_t _gl_pixel_formats[] = {
GLITZ_GL_UNSIGNED_BYTE
#endif
}, {
{
GLITZ_FOURCC_RGB,
{
8,
0x000000ff,
0x00000000,
0x00000000,
0x00000000
},
0, 0, 0,
GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP
},
GLITZ_GL_ALPHA,
GLITZ_GL_UNSIGNED_BYTE
}
};
static glitz_gl_pixel_format_t _gl_packed_pixel_formats[] = {
#define N_RGB_FORMATS \
(sizeof (_gl_rgb_pixel_formats) / sizeof (glitz_gl_pixel_format_t))
static glitz_gl_pixel_format_t _gl_packed_rgb_pixel_formats[] = {
{
{
GLITZ_FOURCC_RGB,
{
16,
0x00000000,
@ -99,6 +105,31 @@ static glitz_gl_pixel_format_t _gl_packed_pixel_formats[] = {
}
};
#define N_PACKED_RGB_FORMATS \
(sizeof (_gl_packed_rgb_pixel_formats) / sizeof (glitz_gl_pixel_format_t))
static glitz_gl_pixel_format_t _gl_yuv_pixel_formats[] = {
{
{
GLITZ_FOURCC_YV12,
{
12,
0x00000000,
0x00000000,
0x00000000,
0x00000000
},
0, 0, 0,
GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP
},
GLITZ_GL_LUMINANCE,
GLITZ_GL_UNSIGNED_BYTE
}
};
#define N_YUV_FORMATS \
(sizeof (_gl_yuv_pixel_formats) / sizeof (glitz_gl_pixel_format_t))
#define SOLID_ALPHA 0
#define SOLID_RED 1
#define SOLID_GREEN 2
@ -106,6 +137,7 @@ static glitz_gl_pixel_format_t _gl_packed_pixel_formats[] = {
static glitz_pixel_format_t _solid_format[] = {
{
GLITZ_FOURCC_RGB,
{
16,
0x0000ffff,
@ -116,6 +148,7 @@ static glitz_pixel_format_t _solid_format[] = {
0, 0, 0,
GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP
}, {
GLITZ_FOURCC_RGB,
{
16,
0x00000000,
@ -126,6 +159,7 @@ static glitz_pixel_format_t _solid_format[] = {
0, 0, 0,
GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP
}, {
GLITZ_FOURCC_RGB,
{
16,
0x00000000,
@ -136,6 +170,7 @@ static glitz_pixel_format_t _solid_format[] = {
0, 0, 0,
GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP
}, {
GLITZ_FOURCC_RGB,
{
16,
0x00000000,
@ -153,19 +188,19 @@ typedef struct _glitz_pixel_color {
} glitz_pixel_color_t;
typedef struct _glitz_pixel_transform_op {
char *line;
int offset;
char *line, *line2, *line3;
int offset;
glitz_pixel_format_t *format;
glitz_pixel_color_t *color;
glitz_pixel_color_t *color;
} glitz_pixel_transform_op_t;
#define FETCH(p, mask) \
((mask) ? ((uint32_t) ((((uint64_t) (((uint32_t) (p)) & (mask))) * \
#define FETCH(p, mask) \
((mask) ? ((uint32_t) ((((uint64_t) (((uint32_t) (p)) & (mask))) * \
0xffffffff) / ((uint64_t) (mask)))): 0x0)
#define FETCH_A(p, mask) \
((mask) ? ((uint32_t) ((((uint64_t) (((uint32_t) (p)) & (mask))) * \
0xffffffff) /((uint64_t) (mask)))): 0xffffffff)
#define FETCH_A(p, mask) \
((mask) ? ((uint32_t) ((((uint64_t) (((uint32_t) (p)) & (mask))) * \
0xffffffff) / ((uint64_t) (mask)))): 0xffffffff)
typedef void (*glitz_pixel_fetch_function_t) (glitz_pixel_transform_op_t *op);
@ -237,9 +272,59 @@ _fetch_32 (glitz_pixel_transform_op_t *op)
op->color->b = FETCH (p, op->format->masks.blue_mask);
}
static void
_fetch_yv12 (glitz_pixel_transform_op_t *op)
{
int16_t y = ((uint8_t *) op->line)[op->offset] - 16;
int16_t v = ((uint8_t *) op->line2)[op->offset >> 1] - 128;
int16_t u = ((uint8_t *) op->line3)[op->offset >> 1] - 128;
int32_t r, g, b;
/* TODO: use tables, in a tight loop */
op->color->a = 0xffffffff;
/* all colors multiplied by 0x010101, cropped, shifted */
/* R = 1.164(Y - 16) + 1.596(V - 128) */
r = 0x012b27 * y + 0x019a2e * v;
op->color->r = r >= 0 ? r < 0x1000000 ? (((unsigned) r) << 8) :
0xffffffff : 0;
/* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
op->color->g = g >= 0 ? g < 0x1000000 ? (((unsigned) g) << 8) :
0xffffffff : 0;
/* B = 1.164(Y - 16) + 2.018(U - 128) */
b = 0x012b27 * y + 0x0206a2 * u;
op->color->b = b >= 0 ? b < 0x1000000 ? (((unsigned) b) << 8) :
0xffffffff : 0;
}
static void
_fetch_yuy2 (glitz_pixel_transform_op_t *op)
{
int16_t y = ((uint8_t *) op->line)[op->offset << 1] - 16;
int16_t u = ((uint8_t *) op->line)[((op->offset << 1) & -4) + 1] - 128;
int16_t v = ((uint8_t *) op->line)[((op->offset << 1) & -4) + 3] - 128;
int32_t r, g, b;
/* TODO: use tables, in a tight loop */
op->color->a = 0xffffffff;
/* all colors multiplied by 0x010101, cropped, shifted */
/* R = 1.164(Y - 16) + 1.596(V - 128) */
r = 0x012b27 * y + 0x019a2e * v;
op->color->r = r >= 0 ? r < 0x1000000 ? (((unsigned) r) << 8) :
0xffffffff : 0;
/* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
op->color->g = g >= 0 ? g < 0x1000000 ? (((unsigned) g) << 8) :
0xffffffff : 0;
/* B = 1.164(Y - 16) + 2.018(U - 128) */
b = 0x012b27 * y + 0x0206a2 * u;
op->color->b = b >= 0 ? b < 0x1000000 ? (((unsigned) b) << 8) :
0xffffffff : 0;
}
typedef void (*glitz_pixel_store_function_t) (glitz_pixel_transform_op_t *op);
#define STORE(v, mask) \
#define STORE(v, mask) \
(((uint32_t) (((v) * (uint64_t) (mask)) / 0xffffffff)) & (mask))
static void
@ -320,15 +405,76 @@ _store_32 (glitz_pixel_transform_op_t *op)
STORE (op->color->b, op->format->masks.blue_mask);
}
static void
_store_yv12 (glitz_pixel_transform_op_t *op)
{
uint8_t *yp = &((uint8_t *) op->line)[op->offset];
int16_t y;
/* Y = (0.257 * R) + (0.504 * G) + (0.098 * B) + 16 */
y = op->color->r / 0x03e41be4 + op->color->g / 0x01fbefbf +
op->color->b / 0x0a343eb2 + 16;
*yp = y > 0 ? y < 255 ? y : 255 : 0;
if (op->line2 && (op->offset & 1) == 0)
{
uint8_t *vp = &((uint8_t *) op->line2)[op->offset >> 1];
uint8_t *up = &((uint8_t *) op->line3)[op->offset >> 1];
int16_t v, u;
/* V = (0.439 * R) - (0.368 * G) - (0.071 * B) + 128 */
v = op->color->r / 0x024724bd - op->color->g / 0x02b7a6f5 -
op->color->b / 0x0e15a241 + 128;
*vp = v > 0 ? v < 255 ? v : 255 : 0;
/* U = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128 */
u = op->color->b / 0x024724bd - op->color->r / 0x06c1bad0 -
op->color->g / 0x36fb99f + 128;
*up = u > 0 ? u < 255 ? u : 255 : 0;
}
}
static void
_store_yuy2 (glitz_pixel_transform_op_t *op)
{
uint8_t *p = (uint8_t *) &op->line[op->offset << 1];
int16_t y, v, u;
/* Y = (0.257 * R) + (0.504 * G) + (0.098 * B) + 16 */
y = op->color->r / 0x03e41be4 + op->color->g / 0x01fbefbf +
op->color->b / 0x0a343eb2 + 16;
p[0] = y >= 0 ? y < 255 ? y : 255 : 0;
if ((op->offset & 1) == 0)
{
/* U = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128 */
u = op->color->b / 0x024724bd - op->color->r / 0x06c1bad0 -
op->color->g / 0x36fb99f + 128;
p[1] = u >= 0 ? u < 255 ? u : 255 : 0;
}
else
{
/* V = (0.439 * R) - (0.368 * G) - (0.071 * B) + 128 */
v = op->color->r / 0x024724bd - op->color->g / 0x02b7a6f5 -
op->color->b / 0x0e15a241 + 128;
p[1] = v >= 0 ? v < 255 ? v : 255 : 0;
}
}
#define GLITZ_TRANSFORM_PIXELS_MASK (1L << 0)
#define GLITZ_TRANSFORM_SCANLINE_ORDER_MASK (1L << 1)
#define GLITZ_TRANSFORM_COPY_BOX_MASK (1L << 2)
typedef struct _glitz_image {
char *data;
char *data;
glitz_pixel_format_t *format;
int width;
int height;
int width;
int height;
} glitz_image_t;
static void
@ -342,62 +488,111 @@ _glitz_pixel_transform (unsigned long transform,
int width,
int height)
{
int src_stride, dst_stride;
int x, y, bytes_per_pixel = 0;
int src_stride, dst_stride;
int src_planeoffset = 0, dst_planeoffset = 0;
int x, y, bytes_per_pixel = 0;
glitz_pixel_fetch_function_t fetch;
glitz_pixel_store_function_t store;
glitz_pixel_color_t color;
glitz_pixel_transform_op_t src_op, dst_op;
glitz_pixel_color_t color;
glitz_pixel_transform_op_t src_op, dst_op;
switch (src->format->masks.bpp) {
case 1:
fetch = _fetch_1;
switch (src->format->fourcc) {
case GLITZ_FOURCC_RGB:
switch (src->format->masks.bpp) {
case 1:
fetch = _fetch_1;
break;
case 8:
fetch = _fetch_8;
break;
case 16:
fetch = _fetch_16;
break;
case 24:
fetch = _fetch_24;
break;
case 32:
default:
fetch = _fetch_32;
}
break;
case 8:
fetch = _fetch_8;
case GLITZ_FOURCC_YV12:
fetch = _fetch_yv12;
break;
case 16:
fetch = _fetch_16;
case GLITZ_FOURCC_YUY2:
fetch = _fetch_yuy2;
break;
case 24:
fetch = _fetch_24;
break;
case 32:
default:
fetch = _fetch_32;
break;
}
switch (dst->format->masks.bpp) {
case 1:
store = _store_1;
switch (dst->format->fourcc) {
case GLITZ_FOURCC_RGB:
switch (dst->format->masks.bpp) {
case 1:
store = _store_1;
break;
case 8:
store = _store_8;
break;
case 16:
store = _store_16;
break;
case 24:
store = _store_24;
break;
case 32:
default:
store = _store_32;
}
break;
case 8:
store = _store_8;
case GLITZ_FOURCC_YV12:
store = _store_yv12;
break;
case 16:
store = _store_16;
case GLITZ_FOURCC_YUY2:
store = _store_yuy2;
break;
case 24:
store = _store_24;
break;
case 32:
default:
store = _store_32;
break;
}
src_stride = (src->format->bytes_per_line)? src->format->bytes_per_line:
(((src->width * src->format->masks.bpp) / 8) + 3) & -4;
switch (src->format->fourcc) {
case GLITZ_FOURCC_YV12:
src_stride = (src->format->bytes_per_line) ?
src->format->bytes_per_line: (src->width + 3) & -4;
src_planeoffset = src_stride * src->height;
bytes_per_pixel = 1;
break;
default:
src_stride = (src->format->bytes_per_line) ?
src->format->bytes_per_line:
(((src->width * src->format->masks.bpp) / 8) + 3) & -4;
/* This only works for bpp % 8 = 0, but it shouldn't be a problem as
* it will never be used for bitmaps */
bytes_per_pixel = src->format->masks.bpp / 8;
}
if (src_stride == 0)
src_stride = 1;
src_op.format = src->format;
src_op.color = &color;
dst_stride = (dst->format->bytes_per_line)? dst->format->bytes_per_line:
(((dst->width * dst->format->masks.bpp) / 8) + 3) & -4;
switch (dst->format->fourcc) {
case GLITZ_FOURCC_YV12:
dst_stride = (dst->format->bytes_per_line) ?
dst->format->bytes_per_line: (dst->width + 3) & -4;
dst_planeoffset = dst_stride * dst->height;
break;
default:
dst_stride = (dst->format->bytes_per_line) ?
dst->format->bytes_per_line:
(((dst->width * dst->format->masks.bpp) / 8) + 3) & -4;
}
if (dst_stride == 0)
dst_stride = 1;
dst_op.format = dst->format;
dst_op.color = &color;
@ -408,7 +603,49 @@ _glitz_pixel_transform (unsigned long transform,
else
src_op.line = &src->data[(y + y_src) * src_stride];
dst_op.line = &dst->data[(y + y_dst) * dst_stride];
switch (src->format->fourcc) {
case GLITZ_FOURCC_YV12:
if (src->format->scanline_order != dst->format->scanline_order)
{
src_op.line2 =
&src->data[src_planeoffset +
(((src->height - (y + y_src) - 1) >> 1))
* (src_stride >> 1)];
src_op.line3 =
&src->data[src_planeoffset +
(src_planeoffset >> 2) +
(((src->height - (y + y_src) - 1) >> 1))
* (src_stride >> 1)];
}
else
{
src_op.line2 =
&src->data[src_planeoffset +
((y + y_src) >> 1) * (src_stride >> 1)];
src_op.line3 =
&src->data[src_planeoffset +
(src_planeoffset >> 2) +
((y + y_src) >> 1) * (src_stride >> 1)];
}
break;
}
dst_op.line = &dst->data[(y + y_dst) * dst_stride];
dst_op.line2 = dst_op.line3 = NULL;
switch (dst->format->fourcc) {
case GLITZ_FOURCC_YV12:
if ((y & 1) == 0)
{
dst_op.line2 =
&dst->data[dst_planeoffset +
((y + y_dst) >> 1) * (dst_stride >> 1)];
dst_op.line3 =
&dst->data[dst_planeoffset + (dst_planeoffset >> 2) +
((y + y_dst) >> 1) * (dst_stride >> 1)];
}
break;
}
if (transform & GLITZ_TRANSFORM_PIXELS_MASK)
{
@ -423,41 +660,62 @@ _glitz_pixel_transform (unsigned long transform,
}
else
{
/* This only works for bpp >= 8, but it shouldn't be a problem as
it will never be used for bitmaps */
if (bytes_per_pixel == 0)
bytes_per_pixel = src->format->masks.bpp / 8;
memcpy (&dst_op.line[x_dst * bytes_per_pixel],
&src_op.line[x_src * bytes_per_pixel],
width * bytes_per_pixel);
switch (dst->format->fourcc) {
case GLITZ_FOURCC_YV12:
/* Will overwrite color components of adjacent pixels for odd
* image sizes or not update color on odd start lines -
* who cares? */
if ((y & 1) == 0)
{
memcpy (&dst_op.line2[x_dst >> 1],
&src_op.line2[x_src >> 1],
width >> 1);
memcpy (&dst_op.line3[x_dst >> 1],
&src_op.line3[x_src >> 1],
width >> 1);
}
break;
}
}
}
}
static glitz_bool_t
_glitz_format_match (glitz_pixel_masks_t *masks1,
glitz_pixel_masks_t *masks2,
unsigned long mask)
_glitz_format_match (glitz_pixel_format_t *format1,
glitz_pixel_format_t *format2,
unsigned long mask)
{
if (masks1->bpp != masks2->bpp)
if (format1->fourcc != format2->fourcc)
return 0;
if (mask & GLITZ_FORMAT_RED_SIZE_MASK)
if (masks1->red_mask != masks2->red_mask)
switch (format1->fourcc) {
case GLITZ_FOURCC_RGB:
if (format1->masks.bpp != format2->masks.bpp)
return 0;
if (mask & GLITZ_FORMAT_GREEN_SIZE_MASK)
if (masks1->green_mask != masks2->green_mask)
return 0;
if (mask & GLITZ_FORMAT_RED_SIZE_MASK)
if (format1->masks.red_mask != format2->masks.red_mask)
return 0;
if (mask & GLITZ_FORMAT_BLUE_SIZE_MASK)
if (masks1->blue_mask != masks2->blue_mask)
return 0;
if (mask & GLITZ_FORMAT_GREEN_SIZE_MASK)
if (format1->masks.green_mask != format2->masks.green_mask)
return 0;
if (mask & GLITZ_FORMAT_ALPHA_SIZE_MASK)
if (masks1->alpha_mask != masks2->alpha_mask)
return 0;
if (mask & GLITZ_FORMAT_BLUE_SIZE_MASK)
if (format1->masks.blue_mask != format2->masks.blue_mask)
return 0;
if (mask & GLITZ_FORMAT_ALPHA_SIZE_MASK)
if (format1->masks.alpha_mask != format2->masks.alpha_mask)
return 0;
break;
default:
return 1;
}
return 1;
}
@ -467,29 +725,32 @@ _glitz_find_gl_pixel_format (glitz_pixel_format_t *format,
unsigned long color_mask,
unsigned long feature_mask)
{
int i, n_formats;
int i;
n_formats = sizeof (_gl_pixel_formats) / sizeof (glitz_gl_pixel_format_t);
for (i = 0; i < n_formats; i++)
for (i = 0; i < N_RGB_FORMATS; i++)
{
if (_glitz_format_match (&_gl_pixel_formats[i].pixel.masks,
&format->masks, color_mask))
return &_gl_pixel_formats[i];
if (_glitz_format_match (&_gl_rgb_pixel_formats[i].pixel,
format, color_mask))
return &_gl_rgb_pixel_formats[i];
}
if (feature_mask & GLITZ_FEATURE_PACKED_PIXELS_MASK)
{
n_formats = sizeof (_gl_packed_pixel_formats) /
sizeof (glitz_gl_pixel_format_t);
for (i = 0; i < n_formats; i++)
for (i = 0; i < N_PACKED_RGB_FORMATS; i++)
{
if (_glitz_format_match (&_gl_packed_pixel_formats[i].pixel.masks,
&format->masks, color_mask))
return &_gl_packed_pixel_formats[i];
if (_glitz_format_match (&_gl_packed_rgb_pixel_formats[i].pixel,
format, color_mask))
return &_gl_packed_rgb_pixel_formats[i];
}
}
for (i = 0; i < N_YUV_FORMATS; i++)
{
if (_glitz_format_match (&_gl_yuv_pixel_formats[i].pixel,
format, color_mask))
return &_gl_yuv_pixel_formats[i];
}
return NULL;
}
@ -505,10 +766,10 @@ _component_size (unsigned long mask)
}
static glitz_bool_t
_glitz_format_diff (glitz_pixel_masks_t *masks,
glitz_color_format_t *pixel_color,
glitz_color_format_t *internal_color,
int *diff)
_glitz_rgb_format_diff (glitz_pixel_masks_t *masks,
glitz_color_format_t *pixel_color,
glitz_color_format_t *internal_color,
int *diff)
{
int size;
@ -546,48 +807,69 @@ _glitz_find_best_gl_pixel_format (glitz_pixel_format_t *format,
glitz_color_format_t *internal_color,
unsigned long feature_mask)
{
glitz_gl_pixel_format_t *best = NULL;
glitz_color_format_t color;
int i, n_formats, diff, best_diff = MAXSHORT;
glitz_gl_pixel_format_t *best = _gl_rgb_pixel_formats;
glitz_color_format_t color;
int i, diff, best_diff = MAXSHORT;
glitz_pixel_masks_t *masks;
color.red_size = _component_size (format->masks.red_mask);
color.green_size = _component_size (format->masks.green_mask);
color.blue_size = _component_size (format->masks.blue_mask);
color.alpha_size = _component_size (format->masks.alpha_mask);
switch (internal_color->fourcc) {
case GLITZ_FOURCC_YV12:
case GLITZ_FOURCC_YUY2:
for (i = 0; i < N_YUV_FORMATS; i++)
{
glitz_fourcc_t fourcc;
n_formats = sizeof (_gl_pixel_formats) / sizeof (glitz_gl_pixel_format_t);
for (i = 0; best_diff > 0 && i < n_formats; i++)
fourcc = internal_color->fourcc;
if (_gl_yuv_pixel_formats[i].pixel.fourcc == fourcc)
return &_gl_yuv_pixel_formats[i];
}
default:
break;
}
switch (format->fourcc) {
case GLITZ_FOURCC_RGB:
color.red_size = _component_size (format->masks.red_mask);
color.green_size = _component_size (format->masks.green_mask);
color.blue_size = _component_size (format->masks.blue_mask);
color.alpha_size = _component_size (format->masks.alpha_mask);
break;
case GLITZ_FOURCC_YV12:
case GLITZ_FOURCC_YUY2:
color.red_size = color.green_size = color.blue_size = 8;
color.alpha_size = 0;
break;
default:
color.red_size = color.green_size = color.blue_size =
color.alpha_size = 8;
break;
}
for (i = 0; best_diff > 0 && i < N_RGB_FORMATS; i++)
{
if (_glitz_format_diff (&_gl_pixel_formats[i].pixel.masks,
&color,
internal_color,
&diff))
masks = &_gl_rgb_pixel_formats[i].pixel.masks;
if (_glitz_rgb_format_diff (masks, &color, internal_color, &diff))
{
if (diff < best_diff)
{
best = &_gl_pixel_formats[i];
best = &_gl_rgb_pixel_formats[i];
best_diff = diff;
}
}
}
if (feature_mask & GLITZ_FEATURE_PACKED_PIXELS_MASK)
{
n_formats = sizeof (_gl_packed_pixel_formats) /
sizeof (glitz_gl_pixel_format_t);
if (!(feature_mask & GLITZ_FEATURE_PACKED_PIXELS_MASK))
return best;
for (i = 0; best_diff > 0 && i < n_formats; i++)
for (i = 0; best_diff > 0 && i < N_PACKED_RGB_FORMATS; i++)
{
masks = &_gl_packed_rgb_pixel_formats[i].pixel.masks;
if (_glitz_rgb_format_diff (masks, &color, internal_color, &diff))
{
if (_glitz_format_diff (&_gl_packed_pixel_formats[i].pixel.masks,
&color,
internal_color,
&diff))
if (diff < best_diff)
{
if (diff < best_diff)
{
best = &_gl_packed_pixel_formats[i];
best_diff = diff;
}
best = &_gl_packed_rgb_pixel_formats[i];
best_diff = diff;
}
}
}
@ -652,7 +934,6 @@ glitz_set_pixels (glitz_surface_t *dst,
src_image.data =
glitz_buffer_map (buffer, GLITZ_BUFFER_ACCESS_READ_ONLY);
src_image.data += format->skip_lines * format->bytes_per_line;
src_image.format = format;
src_image.width = src_image.height = 1;
@ -663,7 +944,8 @@ glitz_set_pixels (glitz_surface_t *dst,
_glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK,
&src_image, &dst_image,
format->xoffset, 0, 0, 0, 1, 1);
format->xoffset,format->skip_lines,
0, 0, 1, 1);
} else
dst->solid.alpha = 0xffff;
@ -674,7 +956,8 @@ glitz_set_pixels (glitz_surface_t *dst,
_glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK,
&src_image, &dst_image,
format->xoffset, 0, 0, 0, 1, 1);
format->xoffset,format->skip_lines,
0, 0, 1, 1);
} else
dst->solid.red = 0;
@ -685,7 +968,8 @@ glitz_set_pixels (glitz_surface_t *dst,
_glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK,
&src_image, &dst_image,
format->xoffset, 0, 0, 0, 1, 1);
format->xoffset,format->skip_lines,
0, 0, 1, 1);
} else
dst->solid.green = 0;
@ -696,7 +980,8 @@ glitz_set_pixels (glitz_surface_t *dst,
_glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK,
&src_image, &dst_image,
format->xoffset, 0, 0, 0, 1, 1);
format->xoffset,format->skip_lines,
0, 0, 1, 1);
} else
dst->solid.blue = 0;
@ -738,9 +1023,11 @@ glitz_set_pixels (glitz_surface_t *dst,
/* find direct format */
gl_format =
_glitz_find_gl_pixel_format (format,
color_mask,
_glitz_find_gl_pixel_format (format, color_mask,
dst->drawable->backend->feature_mask);
if (gl_format && gl_format->pixel.fourcc != dst->format->color.fourcc)
gl_format = NULL;
if (gl_format == NULL)
{
unsigned long feature_mask;
@ -748,8 +1035,7 @@ glitz_set_pixels (glitz_surface_t *dst,
feature_mask = dst->drawable->backend->feature_mask;
transform |= GLITZ_TRANSFORM_PIXELS_MASK;
gl_format =
_glitz_find_best_gl_pixel_format (format,
&dst->format->color,
_glitz_find_best_gl_pixel_format (format, &dst->format->color,
feature_mask);
}
@ -762,7 +1048,7 @@ glitz_set_pixels (glitz_surface_t *dst,
}
if (height > 1) {
if (format->scanline_order == GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN)
if (format->scanline_order != gl_format->pixel.scanline_order)
transform |= GLITZ_TRANSFORM_SCANLINE_ORDER_MASK;
}
@ -792,11 +1078,25 @@ glitz_set_pixels (glitz_surface_t *dst,
{
if (!data)
{
int stride, bpp;
int size;
bpp = gl_format->pixel.masks.bpp;
stride = (((width * bpp) / 8) + 3) & -4;
data = malloc (stride * height);
switch (gl_format->pixel.fourcc) {
case GLITZ_FOURCC_YV12:
bytes_per_line = (width + 3) & -4;
bytes_per_pixel = 1;
size = bytes_per_line * height +
bytes_per_line * ((height + 1) >> 1);
break;
default:
bytes_per_line =
(((width * gl_format->pixel.masks.bpp) / 8) + 3) &
-4;
bytes_per_pixel = gl_format->pixel.masks.bpp / 8;
size = bytes_per_line * height;
break;
}
data = malloc (size);
if (!data)
{
glitz_surface_status_add (dst,
@ -807,13 +1107,13 @@ glitz_set_pixels (glitz_surface_t *dst,
dst_image.data = pixels = data;
dst_image.format = &gl_format->pixel;
ptr =
glitz_buffer_map (buffer,
GLITZ_BUFFER_ACCESS_READ_ONLY);
ptr = glitz_buffer_map (buffer,
GLITZ_BUFFER_ACCESS_READ_ONLY);
src_image.format = format;
gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 4);
gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, 0);
gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH,
bytes_per_line / bytes_per_pixel);
}
dst_image.width = box.x2 - box.x1;
@ -822,13 +1122,13 @@ glitz_set_pixels (glitz_surface_t *dst,
src_image.width = box.x2 - box.x1;
src_image.height = box.y2 - box.y1;
src_image.data = ptr + (format->skip_lines + box.y1 - y_dst) *
format->bytes_per_line;
src_image.data = ptr;
_glitz_pixel_transform (transform,
&src_image,
&dst_image,
format->xoffset + box.x1 - x_dst, 0,
format->xoffset + box.x1 - x_dst,
format->skip_lines + box.y1 - y_dst,
0, 0,
box.x2 - box.x1, box.y2 - box.y1);
}
@ -840,7 +1140,14 @@ glitz_set_pixels (glitz_surface_t *dst,
GLITZ_GL_PIXEL_UNPACK_BUFFER);
bytes_per_line = format->bytes_per_line;
bytes_per_pixel = format->masks.bpp / 8;
switch (format->fourcc) {
case GLITZ_FOURCC_YV12:
bytes_per_pixel = 1;
break;
default:
bytes_per_pixel = format->masks.bpp / 8;
}
if (bytes_per_line)
{
if ((bytes_per_line % 4) == 0)
@ -868,12 +1175,59 @@ glitz_set_pixels (glitz_surface_t *dst,
(format->xoffset + box.x1 - x_dst) * bytes_per_pixel;
}
gl->tex_sub_image_2d (texture->target, 0,
texture->box.x1 + box.x1,
texture->box.y2 - box.y2,
box.x2 - box.x1, box.y2 - box.y1,
gl_format->format, gl_format->type,
pixels);
switch (gl_format->pixel.fourcc) {
case GLITZ_FOURCC_YV12:
gl->tex_sub_image_2d (texture->target, 0,
box.x1,
texture->box.y2 - box.y2,
box.x2 - box.x1, box.y2 - box.y1,
gl_format->format, gl_format->type,
pixels);
if ((bytes_per_line % 8) == 0)
gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 4);
else if ((bytes_per_line % 4) == 0)
gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 2);
else
gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 1);
gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH,
(bytes_per_line / bytes_per_pixel) >> 1);
gl->tex_sub_image_2d (texture->target, 0,
(box.x1 >> 1),
texture->height - ((box.y2 + 1) >> 1),
(box.x2 - box.x1 + 1) >> 1,
(box.y2 - box.y1 + 1) >> 1,
gl_format->format, gl_format->type,
pixels + bytes_per_line * height);
gl->tex_sub_image_2d (texture->target, 0,
(texture->width >> 1) + (box.x1 >> 1),
texture->height - ((box.y2 + 1) >> 1),
(box.x2 - box.x1 + 1) >> 1,
(box.y2 - box.y1 + 1) >> 1,
gl_format->format, gl_format->type,
pixels + bytes_per_line * height +
((bytes_per_line * height) >> 2));
break;
case GLITZ_FOURCC_YUY2:
gl->tex_sub_image_2d (texture->target, 0,
texture->box.x1 + (box.x1 >> 1),
texture->box.y2 - box.y2,
(box.x2 - box.x1 + 1) >> 1,
box.y2 - box.y1,
gl_format->format, gl_format->type,
pixels);
break;
default:
gl->tex_sub_image_2d (texture->target, 0,
texture->box.x1 + box.x1,
texture->box.y2 - box.y2,
box.x2 - box.x1, box.y2 - box.y1,
gl_format->format, gl_format->type,
pixels);
}
glitz_surface_damage (dst, &box,
GLITZ_DAMAGE_DRAWABLE_MASK |
@ -1155,7 +1509,7 @@ glitz_get_pixels (glitz_surface_t *src,
if (from_drawable)
{
gl->read_buffer (src->buffer);
src->drawable->backend->read_buffer (src->drawable, src->buffer);
gl->disable (GLITZ_GL_SCISSOR_TEST);

Просмотреть файл

@ -45,24 +45,24 @@
#define EXPAND_SRC_DECL "TEMP src;"
#define EXPAND_SRC_2D_IN_OP \
{ "TXP src, fragment.texcoord[1], texture[1], 2D;", \
"DP4 color.a, color, fragment.color;", \
"MUL result.color, src, color.a;" }
"DP4 color.a, color, fragment.color;", \
"MUL result.color, src, color.a;" }
#define EXPAND_SRC_RECT_IN_OP \
{ "TXP src, fragment.texcoord[1], texture[1], RECT;", \
"DP4 color.a, color, fragment.color;", \
"MUL result.color, src, color.a;" }
"DP4 color.a, color, fragment.color;", \
"MUL result.color, src, color.a;" }
#define EXPAND_MASK_DECL "TEMP mask;"
#define EXPAND_MASK_2D_IN_OP \
{ "TXP mask, fragment.texcoord[0], texture[0], 2D;", \
"DP4 mask.a, mask, fragment.color;", \
"MUL result.color, color, mask.a;" }
#define EXPAND_MASK_2D_IN_OP \
{ "TXP mask, fragment.texcoord[0], texture[0], 2D;", \
"DP4 mask.a, mask, fragment.color;", \
"MUL result.color, color, mask.a;" }
#define EXPAND_MASK_RECT_IN_OP \
{ "TXP mask, fragment.texcoord[0], texture[0], RECT;", \
"DP4 mask.a, mask, fragment.color;", \
"MUL result.color, color, mask.a;" }
"DP4 mask.a, mask, fragment.color;", \
"MUL result.color, color, mask.a;" }
#define EXPAND_IN_NA \
{ "NA", "NA", "NA" }
@ -139,6 +139,18 @@ static const struct _glitz_program_expand_t {
}
};
/*
* perspective divide.
*/
static const char *_perspective_divide[] = {
"RCP position.w, pos.w;",
"MUL position, pos, position.w;", NULL
};
static const char *_no_perspective_divide[] = {
"MOV position, pos;", NULL
};
/*
* general convolution filter.
*/
@ -148,79 +160,73 @@ static const char *_convolution_header[] = {
"TEMP color, in, coord, position;",
/* extra declarations */
"%s"
/* perspective divide */
"RCP position.w, pos.w;",
"MUL position, pos, position.w;", NULL
"%s", NULL
};
static const char *_convolution_sample_first[] = {
"MOV coord, 0.0;",
"ADD coord.x, position.x, p[0].x;",
"ADD coord.y, position.y, p[0].y;",
"ADD coord.xy, position.xyxx, p[0].xyxx;",
"TEX in, coord, texture[%s], %s;",
"MUL color, in, p[0].z;", NULL
};
static const char *_convolution_sample[] = {
"ADD coord.x, position.x, p[%d].x;",
"ADD coord.y, position.y, p[%d].y;",
"ADD coord.xy, position.xyxx, p[%d].xyxx;",
"TEX in, coord, texture[%s], %s;",
"MAD color, in, p[%d].z, color;", NULL
};
/*
* gradient filters.
*/
static const char *_gradient_header[] = {
"PARAM gradient = program.local[0];",
"PARAM stops[%d] = { program.local[1..%d] };",
"PARAM gradient[%d] = { program.local[0..%d] };",
"PARAM stops[%d] = { program.local[%d..%d] };",
"ATTRIB pos = fragment.texcoord[%s];",
"TEMP color, second_color, stop0, stop1, position;",
/* extra declarations */
"%s",
/* perspective divide */
"RCP position.w, pos.w;",
"MUL position, pos, position.w;", NULL
"%s", NULL
};
/*
* linear gradient filter.
*
* gradient.x = start offset
* gradient.y = 1 / length
* gradient.z = cos (angle)
* gradient.w = -sin (angle)
* gradient.x = a
* gradient.y = b
* gradient.z = offset
*/
static const char *_linear_gradient_calculations[] = {
"MUL position.x, gradient.z, position.x;",
"MAD position.x, gradient.w, position.y, position.x;",
"SUB position.z, position.x, gradient.x;",
"MUL position.z, position.z, gradient.y;", NULL
"MUL position.xy, gradient[0], position;",
"ADD position.x, position.x, position.y;",
"ADD position.z, position.x, gradient[0].z;", NULL
};
/*
* radial gradient filter.
*
* gradient.x = center point X coordinate
* gradient.y = center point Y coordinate
* gradient.z = radius0
* gradient.w = 1 / (radius1 - radius0)
* gradient[0].x = fx
* gradient[0].y = fy
* gradient[0].z = dx
* gradient[0].w = dy
*
* gradient[1].x = m
* gradient[1].y = b
* gradient[1].z = 4a
* gradient[1].w = 1 / 2a
*/
static const char *_radial_gradient_calculations[] = {
"SUB position, position, gradient;",
"MUL position.x, position.x, position.x;",
"MAD position.x, position.y, position.y, position.x;",
"RSQ position.y, position.x;",
"RCP position.x, position.y;",
"MUL position.x, position.x, position.x;",
"MUL position.x, position.x, position.y;",
"SUB position.x, position.x, gradient.z;",
"MUL position.z, position.x, gradient.w;", NULL
"SUB position, position.xyxx, gradient[0].xyxx;",
"MUL position.zw, position.xxxy, gradient[0];",
"ADD position.w, position.w, position.z;",
"MUL position.xyz, position.xyww, position.xyww;",
"ADD position.x, position.x, position.y;",
"MAD position.z, position.x, gradient[1].z, position.z;",
"RSQ position.z, position.z;",
"RCP position.z, position.z;",
"SUB position.x, position.z, position.w;",
"MUL position.x, position.x, gradient[1].w;",
"MAD position.z, position.x, gradient[1].x, gradient[1].y;", NULL
};
static const char *_gradient_fill_repeat[] = {
@ -228,15 +234,12 @@ static const char *_gradient_fill_repeat[] = {
};
static const char *_gradient_fill_reflect[] = {
"FLR position.w, position.z;",
"MUL position.w, position.w, 0.5;",
"FLR position.w, position.w;",
"MUL position.y, position.w, 2.0;",
"FLR position.x, position.z;",
"SUB position.y, position.x, position.y;",
"FRC position.x, position.z;",
"SUB position.x, position.x, position.y;",
"ABS position.z, position.x;", NULL
"MUL position.z, position.z, 0.5;"
"FRC position.z, position.z;"
"MUL position.z, position.z, 2.0;"
"SUB position.z, 1.0, position.z;"
"ABS position.z, position.z;"
"SUB position.z, 1.0, position.z;", NULL
};
static const char *_gradient_init_stops[] = {
@ -263,7 +266,37 @@ static const char *_gradient_fetch_and_interpolate[] = {
"MUL_SAT position.z, position.z, stop0.w;",
/* linear interpolation */
"LRP color, position.z, second_color, color;", NULL
"LRP color, position.z, second_color, color;",
/* multiply alpha */
"MUL color.rgb, color.rgba, color.a;", NULL
};
/*
* color conversion filters
*/
static const char *_colorspace_yv12_header[] = {
"PARAM offset = program.local[0];",
"PARAM minmax = program.local[1];",
"ATTRIB pos = fragment.texcoord[%s];",
"TEMP color, tmp, position;",
/* extra declarations */
"%s", NULL
};
static const char *_colorspace_yv12[] = {
"MAX position, position, minmax;",
"MIN position, position, minmax.zwww;",
"TEX color, position, texture[%s], %s;",
"MAD position, position, .5, offset.xyww;",
"TEX tmp.x, position, texture[%s], %s;",
"MAD color, color, 1.164, -0.073;", /* -1.164 * 16 / 255 */
"ADD position.x, position.x, offset.z;",
"TEX tmp.y, position, texture[%s], %s;",
"SUB tmp, tmp, { .5, .5 };",
"MAD color.xyz, { 1.596, -.813, 0 }, tmp.xxxw, color;",
"MAD color.xyz, { 0, -.391, 2.018 }, tmp.yyyw, color;", NULL
};
static struct _glitz_program_query {
@ -276,9 +309,9 @@ static struct _glitz_program_query {
{ GLITZ_GL_PROGRAM_NATIVE_INSTRUCTIONS,
GLITZ_GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS, 1 },
{ GLITZ_GL_PROGRAM_PARAMETERS,
GLITZ_GL_MAX_PROGRAM_PARAMETERS, 1 },
GLITZ_GL_MAX_PROGRAM_PARAMETERS, 0 },
{ GLITZ_GL_PROGRAM_NATIVE_PARAMETERS,
GLITZ_GL_MAX_PROGRAM_NATIVE_PARAMETERS, 1 },
GLITZ_GL_MAX_PROGRAM_NATIVE_PARAMETERS, 0 },
{ GLITZ_GL_PROGRAM_ALU_INSTRUCTIONS,
GLITZ_GL_MAX_PROGRAM_ALU_INSTRUCTIONS, 0 },
{ GLITZ_GL_PROGRAM_TEX_INSTRUCTIONS,
@ -321,10 +354,10 @@ _glitz_program_under_limits (glitz_gl_proc_address_list_t *gl)
static glitz_gl_int_t
_glitz_compile_arb_fragment_program (glitz_gl_proc_address_list_t *gl,
char *program_string,
int n_parameters)
char *string,
int n_parameters)
{
glitz_gl_int_t error, pid = -1;
glitz_gl_int_t error = 0, pid = -1;
glitz_gl_uint_t program;
/* clear error flags */
@ -334,11 +367,9 @@ _glitz_compile_arb_fragment_program (glitz_gl_proc_address_list_t *gl,
gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, program);
gl->program_string (GLITZ_GL_FRAGMENT_PROGRAM,
GLITZ_GL_PROGRAM_FORMAT_ASCII,
strlen (program_string),
program_string);
strlen (string), string);
if (gl->get_error () == GLITZ_GL_NO_ERROR) {
gl->get_integer_v (GLITZ_GL_PROGRAM_ERROR_POSITION, &error);
if (error == -1) {
glitz_gl_int_t value;
@ -358,6 +389,14 @@ _glitz_compile_arb_fragment_program (glitz_gl_proc_address_list_t *gl,
}
}
}
#ifdef DEBUG
else {
gl->get_integer_v (GLITZ_GL_PROGRAM_ERROR_POSITION, &error);
}
if (error != -1)
fprintf (stderr, "fp error at pos %d beginning with '%.40s'\n",
error, string+error);
#endif
if (pid == -1) {
gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, 0);
@ -368,7 +407,8 @@ _glitz_compile_arb_fragment_program (glitz_gl_proc_address_list_t *gl,
}
static void
_string_array_to_char_array (char *dst, const char *src[])
_string_array_to_char_array (char *dst,
const char *src[])
{
int i, n;
@ -387,17 +427,26 @@ _string_array_to_char_array (char *dst, const char *src[])
#define GRADIENT_BASE_SIZE 2048
#define GRADIENT_STOP_SIZE 256
#define COLORSPACE_BASE_SIZE 2048
static glitz_gl_uint_t
_glitz_create_fragment_program (glitz_composite_op_t *op,
int fp_type,
int id,
int p_divide,
const glitz_program_expand_t *expand)
{
char buffer[1024], *program = NULL, *tex, *p = NULL;
char *texture_type, *extra_declarations;
char buffer[1024], *program = NULL, *tex, *p = NULL;
char *texture_type, *extra_declarations;
const char **pos_to_position;
const glitz_in_op_t *in;
glitz_gl_uint_t fp;
int i;
glitz_gl_uint_t fp;
int i;
if (p_divide)
pos_to_position = _perspective_divide;
else
pos_to_position = _no_perspective_divide;
switch (op->type) {
case GLITZ_COMBINE_TYPE_ARGBF:
@ -438,12 +487,15 @@ _glitz_create_fragment_program (glitz_composite_op_t *op,
_string_array_to_char_array (buffer, _convolution_header);
p += sprintf (p, buffer, id, id - 1, tex, extra_declarations);
_string_array_to_char_array (buffer, pos_to_position);
p += sprintf (p, buffer);
_string_array_to_char_array (buffer, _convolution_sample_first);
p += sprintf (p, buffer, tex, texture_type);
_string_array_to_char_array (buffer, _convolution_sample);
for (i = 1; i < id; i++)
p += sprintf (p, buffer, i, i, tex, texture_type, i);
p += sprintf (p, buffer, i, tex, texture_type, i);
break;
case GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT:
@ -465,17 +517,27 @@ _glitz_create_fragment_program (glitz_composite_op_t *op,
p += sprintf (p, "!!ARBfp1.0");
_string_array_to_char_array (buffer, _gradient_header);
p += sprintf (p, buffer, id, id, tex, extra_declarations);
switch (fp_type) {
case GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT:
case GLITZ_FP_LINEAR_GRADIENT_NEAREST:
case GLITZ_FP_LINEAR_GRADIENT_REPEAT:
case GLITZ_FP_LINEAR_GRADIENT_REFLECT:
p += sprintf (p, buffer, 1, 0, id, 1, id, tex, extra_declarations);
_string_array_to_char_array (buffer, pos_to_position);
p += sprintf (p, buffer);
_string_array_to_char_array (buffer,
_linear_gradient_calculations);
break;
default:
p += sprintf (p, buffer, 2, 1, id, 2, id + 1, tex,
extra_declarations);
_string_array_to_char_array (buffer, pos_to_position);
p += sprintf (p, buffer);
_string_array_to_char_array (buffer,
_radial_gradient_calculations);
break;
@ -514,6 +576,25 @@ _glitz_create_fragment_program (glitz_composite_op_t *op,
id++;
break;
case GLITZ_FP_COLORSPACE_YV12:
program = malloc (COLORSPACE_BASE_SIZE);
if (program == NULL)
return 0;
p = program;
p += sprintf (p, "!!ARBfp1.0");
_string_array_to_char_array (buffer, _colorspace_yv12_header);
p += sprintf (p, buffer, tex, extra_declarations);
_string_array_to_char_array (buffer, pos_to_position);
p += sprintf (p, buffer);
_string_array_to_char_array (buffer, _colorspace_yv12);
p += sprintf (p, buffer, tex, texture_type, tex, texture_type,
tex, texture_type);
break;
default:
return 0;
}
@ -525,8 +606,12 @@ _glitz_create_fragment_program (glitz_composite_op_t *op,
if (op->per_component)
p += sprintf (p, "%s", in->dot_product);
p += sprintf (p, "%s", in->mult);
sprintf (p, "END");
#ifdef DEBUG
fprintf (stderr, "***** fp %d:\n%s\n\n", id, program);
#endif
fp = _glitz_compile_arb_fragment_program (op->gl, program, id);
free (program);
@ -545,22 +630,24 @@ glitz_program_map_fini (glitz_gl_proc_address_list_t *gl,
glitz_program_map_t *map)
{
glitz_gl_uint_t program;
int i, j, k, x, y;
int i, j, k, x, y, z;
for (i = 0; i < GLITZ_COMBINE_TYPES; i++) {
for (j = 0; j < GLITZ_FP_TYPES; j++) {
for (x = 0; x < GLITZ_TEXTURE_LAST; x++) {
for (y = 0; y < GLITZ_TEXTURE_LAST; y++) {
glitz_program_t *p = &map->filters[i][j].fp[x][y];
for (z = 0; z < 2; z++) {
glitz_program_t *p = &map->filters[i][j].fp[x][y][z];
if (p->name) {
for (k = 0; k < p->size; k++)
if (p->name[k] > 0) {
program = p->name[k];
gl->delete_programs (1, &program);
}
if (p->name) {
for (k = 0; k < p->size; k++)
if (p->name[k] > 0) {
program = p->name[k];
gl->delete_programs (1, &program);
}
free (p->name);
free (p->name);
}
}
}
}
@ -583,12 +670,30 @@ glitz_get_fragment_program (glitz_composite_op_t *op,
int id)
{
glitz_program_map_t *map;
glitz_program_t *program;
int t0 = TEXTURE_INDEX (op->src);
int t1 = TEXTURE_INDEX (op->mask);
glitz_program_t *program;
int t0 = TEXTURE_INDEX (op->src);
int t1 = TEXTURE_INDEX (op->mask);
int p_divide = 1;
switch (op->type) {
case GLITZ_COMBINE_TYPE_ARGBF:
case GLITZ_COMBINE_TYPE_ARGBF_SOLID:
case GLITZ_COMBINE_TYPE_ARGBF_SOLIDC:
case GLITZ_COMBINE_TYPE_ARGBF_ARGB:
case GLITZ_COMBINE_TYPE_ARGBF_ARGBC:
if (!SURFACE_PROJECTIVE_TRANSFORM (op->src))
p_divide = 0;
break;
case GLITZ_COMBINE_TYPE_ARGB_ARGBF:
case GLITZ_COMBINE_TYPE_SOLID_ARGBF:
if (!SURFACE_PROJECTIVE_TRANSFORM (op->mask))
p_divide = 0;
default:
break;
}
map = op->dst->drawable->backend->program_map;
program = &map->filters[op->type][fp_type].fp[t0][t1];
program = &map->filters[op->type][fp_type].fp[t0][t1][p_divide];
if (program->size < id) {
int old_size;
@ -609,7 +714,7 @@ glitz_get_fragment_program (glitz_composite_op_t *op,
glitz_surface_push_current (op->dst, GLITZ_CONTEXT_CURRENT);
program->name[id - 1] =
_glitz_create_fragment_program (op, fp_type, id,
_glitz_create_fragment_program (op, fp_type, id, p_divide,
_program_expand_map[t0][t1]);
glitz_surface_pop_current (op->dst);

Просмотреть файл

@ -144,6 +144,7 @@ glitz_set_rectangles (glitz_surface_t *dst,
else
{
static glitz_pixel_format_t pf = {
GLITZ_FOURCC_RGB,
{
32,
0xff000000,

Просмотреть файл

@ -90,8 +90,11 @@ glitz_surface_create (glitz_drawable_t *drawable,
glitz_texture_init (&surface->texture, width, height,
drawable->backend->texture_formats[format->id],
surface->format->color.fourcc,
feature_mask, unnormalized);
glitz_surface_set_filter (surface, GLITZ_FILTER_NEAREST, NULL, 0);
if (width > 64 || height > 64)
{
glitz_surface_push_current (surface, GLITZ_CONTEXT_CURRENT);
@ -205,7 +208,8 @@ _glitz_surface_sync_texture (glitz_surface_t *surface)
glitz_surface_push_current (surface, GLITZ_DRAWABLE_CURRENT);
gl->read_buffer (surface->buffer);
surface->drawable->backend->read_buffer (surface->drawable,
surface->buffer);
gl->disable (GLITZ_GL_SCISSOR_TEST);
@ -270,8 +274,8 @@ glitz_surface_sync_drawable (glitz_surface_t *surface)
GLITZ_GL_REPLACE);
gl->color_4us (0x0, 0x0, 0x0, 0xffff);
param.filter[0] = param.filter[1] = GLITZ_GL_CLAMP_TO_EDGE;
param.wrap[0] = param.wrap[1] = GLITZ_GL_NEAREST;
param.filter[0] = param.filter[1] = GLITZ_GL_NEAREST;
param.wrap[0] = param.wrap[1] = GLITZ_GL_CLAMP_TO_EDGE;
glitz_texture_ensure_parameters (gl, texture, &param);
@ -470,7 +474,7 @@ _glitz_surface_update_state (glitz_surface_t *surface)
drawable->update_all = 0;
}
gl->draw_buffer (surface->buffer);
drawable->backend->draw_buffer (drawable, surface->buffer);
if (SURFACE_DITHER (surface))
gl->enable (GLITZ_GL_DITHER);
@ -490,7 +494,7 @@ glitz_surface_attach (glitz_surface_t *surface,
if (surface == drawable->front)
return;
if (surface->format->type != GLITZ_FORMAT_TYPE_COLOR)
if (surface->format->color.fourcc != GLITZ_FOURCC_RGB)
drawable = NULL;
if (drawable)
@ -510,7 +514,7 @@ glitz_surface_attach (glitz_surface_t *surface,
if (surface == drawable->back)
return;
if (surface->format->type != GLITZ_FORMAT_TYPE_COLOR)
if (surface->format->color.fourcc != GLITZ_FOURCC_RGB)
drawable = NULL;
if (drawable)
@ -847,13 +851,25 @@ glitz_surface_set_filter (glitz_surface_t *surface,
} else {
switch (filter) {
case GLITZ_FILTER_NEAREST:
surface->flags &= ~GLITZ_SURFACE_FLAG_FRAGMENT_FILTER_MASK;
switch (surface->format->color.fourcc) {
case GLITZ_FOURCC_YV12:
surface->flags |= GLITZ_SURFACE_FLAG_FRAGMENT_FILTER_MASK;
break;
default:
surface->flags &= ~GLITZ_SURFACE_FLAG_FRAGMENT_FILTER_MASK;
}
surface->flags &= ~GLITZ_SURFACE_FLAG_LINEAR_TRANSFORM_FILTER_MASK;
surface->flags &= ~GLITZ_SURFACE_FLAG_IGNORE_WRAP_MASK;
surface->flags &= ~GLITZ_SURFACE_FLAG_EYE_COORDS_MASK;
break;
case GLITZ_FILTER_BILINEAR:
surface->flags &= ~GLITZ_SURFACE_FLAG_FRAGMENT_FILTER_MASK;
switch (surface->format->color.fourcc) {
case GLITZ_FOURCC_YV12:
surface->flags |= GLITZ_SURFACE_FLAG_FRAGMENT_FILTER_MASK;
break;
default:
surface->flags &= ~GLITZ_SURFACE_FLAG_FRAGMENT_FILTER_MASK;
}
surface->flags |= GLITZ_SURFACE_FLAG_LINEAR_TRANSFORM_FILTER_MASK;
surface->flags &= ~GLITZ_SURFACE_FLAG_IGNORE_WRAP_MASK;
surface->flags &= ~GLITZ_SURFACE_FLAG_EYE_COORDS_MASK;

Просмотреть файл

@ -34,6 +34,7 @@ glitz_texture_init (glitz_texture_t *texture,
int width,
int height,
glitz_gl_int_t texture_format,
glitz_fourcc_t fourcc,
unsigned long feature_mask,
glitz_bool_t unnormalized)
{
@ -44,24 +45,48 @@ glitz_texture_init (glitz_texture_t *texture,
texture->param.border_color.alpha = 0;
texture->format = texture_format;
texture->name = 0;
texture->fourcc = fourcc;
texture->name = 0;
if (feature_mask & GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK)
{
switch (fourcc) {
case GLITZ_FOURCC_YV12:
/* U and V plane added below */
texture->box.x1 = texture->box.y1 = 0;
texture->box.x2 = texture->width = width;
texture->box.x2 = width;
texture->box.y2 = height;
texture->width = (width + 1) & ~1;
texture->height = (height + 1) & ~1;
texture->height += texture->height >> 1;
texture->flags = GLITZ_TEXTURE_FLAG_PADABLE_MASK;
break;
case GLITZ_FOURCC_YUY2:
/* 1 RGBA texel for 2 YUY2 pixels */
texture->box.x1 = texture->box.y1 = 0;
texture->box.x2 = texture->width = width >> 1;
texture->box.y2 = texture->height = height;
texture->flags = GLITZ_TEXTURE_FLAG_REPEATABLE_MASK |
texture->flags = GLITZ_TEXTURE_FLAG_CLAMPABLE_MASK |
GLITZ_TEXTURE_FLAG_REPEATABLE_MASK |
GLITZ_TEXTURE_FLAG_PADABLE_MASK;
}
else
{
texture->box.x1 = texture->box.y1 = 1;
texture->box.x2 = width + 1;
texture->box.y2 = height + 1;
texture->width = width + 2;
texture->height = height + 2;
texture->flags = 0;
break;
default:
if (feature_mask & GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK)
{
texture->box.x1 = texture->box.y1 = 0;
texture->box.x2 = texture->width = width;
texture->box.y2 = texture->height = height;
texture->flags = GLITZ_TEXTURE_FLAG_CLAMPABLE_MASK |
GLITZ_TEXTURE_FLAG_REPEATABLE_MASK |
GLITZ_TEXTURE_FLAG_PADABLE_MASK;
}
else
{
texture->box.x1 = texture->box.y1 = 1;
texture->box.x2 = width + 1;
texture->box.y2 = height + 1;
texture->width = width + 2;
texture->height = height + 2;
texture->flags = GLITZ_TEXTURE_FLAG_CLAMPABLE_MASK;
}
}
if (!unnormalized &&
@ -154,8 +179,10 @@ glitz_texture_allocate (glitz_gl_proc_address_list_t *gl,
glitz_texture_bind (gl, texture);
if (texture->box.x2 != texture->width ||
texture->box.y2 != texture->height) {
if (TEXTURE_CLAMPABLE (texture) &&
(texture->box.x2 != texture->width ||
texture->box.y2 != texture->height))
{
data = malloc (texture->width * texture->height);
if (data)
memset (data, 0, texture->width * texture->height);
@ -276,6 +303,7 @@ glitz_texture_set_tex_gen (glitz_gl_proc_address_list_t *gl,
if (flags & GLITZ_SURFACE_FLAG_GEN_T_COORDS_MASK)
{
plane.v[0] = plane.v[2] = 0.0f;
if (flags & GLITZ_SURFACE_FLAG_EYE_COORDS_MASK)
{
plane.v[1] = 1.0f;
@ -284,7 +312,6 @@ glitz_texture_set_tex_gen (glitz_gl_proc_address_list_t *gl,
else
{
plane.v[1] = -texture->texcoord_height_unit;
if (flags & GLITZ_SURFACE_FLAG_TRANSFORM_MASK)
plane.v[3] = (y_src + texture->box.y2 - texture->box.y1) *
texture->texcoord_height_unit;

Просмотреть файл

@ -31,6 +31,7 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
static glitz_extension_map gl_extensions[] = {
{ 0.0, "GL_ARB_texture_rectangle", GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK },
@ -108,14 +109,36 @@ glitz_extensions_query (glitz_gl_float_t version,
return mask;
}
static glitz_gl_float_t
_glitz_gl_version_string_to_float (const char *gl_version_string)
{
glitz_gl_float_t version = 0.0f;
int i;
for (i = 0; isdigit (gl_version_string[i]); i++)
version = version * 10.0f + (gl_version_string[i] - 48);
if (gl_version_string[i++] != '.')
return 0.0f;
version = version * 10.0f + (gl_version_string[i] - 48);
return (version + 0.1f) / 10.0f;
}
static glitz_status_t
_glitz_query_gl_extensions (glitz_gl_proc_address_list_t *gl,
glitz_gl_float_t *gl_version,
unsigned long *feature_mask)
{
const char *gl_extensions_string;
const char *gl_version_string;
*gl_version = atof ((const char *) gl->get_string (GLITZ_GL_VERSION));
gl_version_string = (const char *) gl->get_string (GLITZ_GL_VERSION);
if (!gl_version_string)
return GLITZ_STATUS_NOT_SUPPORTED;
*gl_version = _glitz_gl_version_string_to_float (gl_version_string);
if (*gl_version < 1.2f)
return GLITZ_STATUS_NOT_SUPPORTED;
@ -315,7 +338,8 @@ glitz_backend_init (glitz_backend_t *backend,
glitz_create_surface_formats (backend->gl,
&backend->formats,
&backend->texture_formats,
&backend->n_formats);
&backend->n_formats,
backend->feature_mask);
_glitz_add_drawable_formats (backend->gl,
backend->feature_mask,
&backend->drawable_formats,

Просмотреть файл

@ -26,6 +26,10 @@
#ifndef GLITZINT_H_INCLUDED
#define GLITZINT_H_INCLUDED
#ifdef _MSC_VER
#define _USE_MATH_DEFINES
#endif
#include <stdlib.h>
#include <string.h>
#include <limits.h>
@ -33,6 +37,25 @@
#include "glitz.h"
#if defined(__SVR4) && defined(__sun)
# include <sys/int_types.h>
#elif defined(_MSC_VER)
typedef __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
# if defined(__OpenBSD__)
# include <inttypes.h>
# else
# include <stdint.h>
# endif
#endif
#if defined(__APPLE__) || defined(__sun__)
# define floorf(a) floor (a)
# define ceilf(a) ceil (a)
@ -230,7 +253,9 @@ typedef int glitz_combine_type_t;
#define GLITZ_FP_RADIAL_GRADIENT_NEAREST 6
#define GLITZ_FP_RADIAL_GRADIENT_REPEAT 7
#define GLITZ_FP_RADIAL_GRADIENT_REFLECT 8
#define GLITZ_FP_TYPES 9
#define GLITZ_FP_COLORSPACE_YV12 9
#define GLITZ_FP_UNSUPPORTED 10
#define GLITZ_FP_TYPES 11
typedef struct _glitz_program_t {
glitz_gl_int_t *name;
@ -238,7 +263,7 @@ typedef struct _glitz_program_t {
} glitz_program_t;
typedef struct _glitz_filter_map_t {
glitz_program_t fp[GLITZ_TEXTURE_LAST][GLITZ_TEXTURE_LAST];
glitz_program_t fp[GLITZ_TEXTURE_LAST][GLITZ_TEXTURE_LAST][2];
} glitz_filter_map_t;
typedef struct _glitz_program_map_t {
@ -382,6 +407,14 @@ typedef struct glitz_backend {
(*make_current) (void *drawable,
void *context);
void
(*draw_buffer) (void *drawable,
const glitz_gl_enum_t buffer);
void
(*read_buffer) (void *drawable,
const glitz_gl_enum_t buffer);
glitz_function_pointer_t
(*get_proc_address) (void *context,
const char *name);
@ -430,13 +463,17 @@ typedef struct _glitz_vec4_t {
} glitz_vec4_t;
#define GLITZ_TEXTURE_FLAG_ALLOCATED_MASK (1L << 0)
#define GLITZ_TEXTURE_FLAG_REPEATABLE_MASK (1L << 1)
#define GLITZ_TEXTURE_FLAG_PADABLE_MASK (1L << 2)
#define GLITZ_TEXTURE_FLAG_INVALID_SIZE_MASK (1L << 3)
#define GLITZ_TEXTURE_FLAG_CLAMPABLE_MASK (1L << 1)
#define GLITZ_TEXTURE_FLAG_REPEATABLE_MASK (1L << 2)
#define GLITZ_TEXTURE_FLAG_PADABLE_MASK (1L << 3)
#define GLITZ_TEXTURE_FLAG_INVALID_SIZE_MASK (1L << 4)
#define TEXTURE_ALLOCATED(texture) \
((texture)->flags & GLITZ_TEXTURE_FLAG_ALLOCATED_MASK)
#define TEXTURE_CLAMPABLE(texture) \
((texture)->flags & GLITZ_TEXTURE_FLAG_CLAMPABLE_MASK)
#define TEXTURE_REPEATABLE(texture) \
((texture)->flags & GLITZ_TEXTURE_FLAG_REPEATABLE_MASK)
@ -456,17 +493,18 @@ typedef struct _glitz_texture {
glitz_gl_uint_t name;
glitz_gl_enum_t target;
glitz_gl_int_t format;
glitz_fourcc_t fourcc;
unsigned long flags;
glitz_texture_parameters_t param;
int width;
int height;
int width;
int height;
glitz_box_t box;
glitz_box_t box;
glitz_float_t texcoord_width_unit;
glitz_float_t texcoord_height_unit;
glitz_float_t texcoord_width_unit;
glitz_float_t texcoord_height_unit;
} glitz_texture_t;
struct _glitz_texture_object {
@ -716,7 +754,8 @@ void
glitz_create_surface_formats (glitz_gl_proc_address_list_t *gl,
glitz_format_t **formats,
glitz_gl_int_t **texture_formats,
int *n_formats);
int *n_formats,
unsigned long features);
extern void __internal_linkage
_glitz_add_drawable_formats (glitz_gl_proc_address_list_t *gl,
@ -741,6 +780,7 @@ glitz_texture_init (glitz_texture_t *texture,
int width,
int height,
glitz_gl_int_t texture_format,
glitz_fourcc_t fourcc,
unsigned long feature_mask,
glitz_bool_t unnormalized);
@ -907,6 +947,14 @@ _glitz_drawable_init (glitz_drawable_t *drawable,
int width,
int height);
void
_glitz_drawable_draw_buffer (void *abstract_drawable,
const glitz_gl_enum_t buffer);
void
_glitz_drawable_read_buffer (void *abstract_drawable,
const glitz_gl_enum_t buffer);
extern glitz_drawable_t __internal_linkage *
_glitz_fbo_drawable_create (glitz_drawable_t *other,
glitz_int_drawable_format_t *format,
@ -1052,5 +1100,7 @@ slim_hidden_proto(glitz_context_set_user_data)
slim_hidden_proto(glitz_context_get_proc_address)
slim_hidden_proto(glitz_context_make_current)
slim_hidden_proto(glitz_context_bind_texture)
slim_hidden_proto(glitz_context_draw_buffers)
slim_hidden_proto(glitz_context_read_buffer)
#endif /* GLITZINT_H_INCLUDED */

Просмотреть файл

@ -286,6 +286,9 @@ glitz_glx_context_get (glitz_glx_screen_info_t *screen_info,
context->backend.make_current = _glitz_glx_make_current;
context->backend.get_proc_address = _glitz_glx_context_get_proc_address;
context->backend.draw_buffer = _glitz_drawable_draw_buffer;
context->backend.read_buffer = _glitz_drawable_read_buffer;
context->backend.drawable_formats = NULL;
context->backend.n_drawable_formats = 0;

Просмотреть файл

@ -216,6 +216,7 @@ glitz_glx_destroy (void *abstract_drawable)
GLITZ_CONTEXT_CURRENT);
glitz_program_map_fini (drawable->base.backend->gl,
&drawable->screen_info->program_map);
glitz_program_map_init (&drawable->screen_info->program_map);
glitz_glx_pop_current (abstract_drawable);
}

Просмотреть файл

@ -45,6 +45,9 @@ _glitz_glx_format_compare (const void *elem1,
for (; i < 2; i++)
{
if (format[i]->d.color.fourcc != GLITZ_FOURCC_RGB)
score[i] -= 1000;
if (format[i]->d.color.red_size)
{
if (format[i]->d.color.red_size >= 8)
@ -119,8 +122,9 @@ _glitz_glx_query_formats (glitz_glx_screen_info_t *screen_info)
&visual_templ, &num_visuals);
/* No pbuffers without fbconfigs */
format.types = GLITZ_DRAWABLE_TYPE_WINDOW_MASK;
format.d.id = 0;
format.types = GLITZ_DRAWABLE_TYPE_WINDOW_MASK;
format.d.id = 0;
format.d.color.fourcc = GLITZ_FOURCC_RGB;
for (i = 0; i < num_visuals; i++)
{
@ -243,7 +247,8 @@ _glitz_glx_query_formats_using_fbconfigs (glitz_glx_screen_info_t *screen_info)
if (value & GLX_PBUFFER_BIT)
format.types |= GLITZ_DRAWABLE_TYPE_PBUFFER_MASK;
format.d.id = 0;
format.d.id = 0;
format.d.color.fourcc = GLITZ_FOURCC_RGB;
glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_FBCONFIG_ID,
&value);

Просмотреть файл

@ -43,8 +43,8 @@ extern "C" {
/* glitz_wgl_info.c */
typedef struct _glitz_wgl_thread_starter_arg_t {
int (*user_thread_function) (void *);
void *user_thread_function_arg;
int (*user_thread_function) (void *);
void *user_thread_function_arg;
} glitz_wgl_thread_starter_arg_t;
int
@ -55,27 +55,32 @@ glitz_wgl_init (const char *gl_library);
void
glitz_wgl_fini (void);
/* glitz_wgl_format.c */
glitz_drawable_format_t *
glitz_wgl_find_drawable_format (unsigned long mask,
const glitz_drawable_format_t *templ,
int count);
glitz_wgl_find_window_format (unsigned long mask,
const glitz_drawable_format_t *templ,
int count);
glitz_drawable_format_t *
glitz_wgl_find_pbuffer_format (unsigned long mask,
const glitz_drawable_format_t *templ,
int count);
/* glitz_wgl_drawable.c */
glitz_drawable_t *
glitz_wgl_create_drawable_for_window (glitz_drawable_format_t *format,
HWND window,
unsigned int width,
unsigned int height);
HWND window,
unsigned int width,
unsigned int height);
glitz_drawable_t *
glitz_wgl_create_pbuffer_drawable (glitz_drawable_format_t *format,
unsigned int width,
unsigned int height);
unsigned int width,
unsigned int height);
#if defined(__cplusplus) || defined(c_plusplus)
}

Просмотреть файл

@ -1,6 +1,6 @@
/*
* Copyright © 2004 David Reveman
*
*
* 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
@ -12,11 +12,11 @@
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
* NO EVENT SHALL DAVID REVEMAN 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,
* 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.
*
@ -45,263 +45,287 @@ _glitz_wgl_context_create (glitz_wgl_screen_info_t *screen_info,
int format_id,
glitz_wgl_context_t *context)
{
PIXELFORMATDESCRIPTOR dummy_pfd;
PIXELFORMATDESCRIPTOR dummy_pfd;
dummy_pfd.nSize = sizeof (PIXELFORMATDESCRIPTOR);
dummy_pfd.nVersion = 1;
dummy_pfd.nSize = sizeof (PIXELFORMATDESCRIPTOR);
dummy_pfd.nVersion = 1;
SetPixelFormat (dc, format_id, &dummy_pfd);
SetPixelFormat (dc, format_id, &dummy_pfd);
context->context = wglCreateContext (dc);
context->context = wglCreateContext (dc);
context->pixel_format = format_id;
context->pixel_format = format_id;
}
static glitz_context_t *
_glitz_wgl_create_context (void *abstract_drawable,
glitz_drawable_format_t *format)
glitz_drawable_format_t *format)
{
glitz_wgl_drawable_t *drawable = (glitz_wgl_drawable_t *) abstract_drawable;
glitz_wgl_screen_info_t *screen_info = drawable->screen_info;
int format_id = screen_info->format_ids[format->id];
glitz_wgl_context_t *context;
glitz_wgl_drawable_t *drawable = (glitz_wgl_drawable_t *) abstract_drawable;
glitz_wgl_screen_info_t *screen_info = drawable->screen_info;
int format_id = screen_info->format_ids[format->id];
glitz_wgl_context_t *context;
context = malloc (sizeof (glitz_wgl_context_t));
if (!context)
return NULL;
context = malloc (sizeof (glitz_wgl_context_t));
if (!context)
return NULL;
_glitz_context_init (&context->base, &drawable->base);
_glitz_context_init (&context->base, &drawable->base);
_glitz_wgl_context_create (screen_info,
drawable->dc,
format_id,
context);
_glitz_wgl_context_create (screen_info,
drawable->dc,
format_id,
context);
wglShareLists (screen_info->root_context, context->context);
wglShareLists (screen_info->root_context, context->context);
return (glitz_context_t *) context;
return (glitz_context_t *) context;
}
static void
_glitz_wgl_destroy_context (void *abstract_context)
{
glitz_wgl_context_t *context = (glitz_wgl_context_t *) abstract_context;
glitz_wgl_context_t *context = (glitz_wgl_context_t *) abstract_context;
wglDeleteContext (context->context);
wglDeleteContext (context->context);
_glitz_context_fini (&context->base);
_glitz_context_fini (&context->base);
free (context);
free (context);
}
static void
_glitz_wgl_copy_context (void *abstract_src,
void *abstract_dst,
unsigned long mask)
void *abstract_dst,
unsigned long mask)
{
glitz_wgl_context_t *src = (glitz_wgl_context_t *) abstract_src;
glitz_wgl_context_t *dst = (glitz_wgl_context_t *) abstract_dst;
glitz_wgl_context_t *src = (glitz_wgl_context_t *) abstract_src;
glitz_wgl_context_t *dst = (glitz_wgl_context_t *) abstract_dst;
wglCopyContext (src->context, dst->context, mask);
wglCopyContext (src->context, dst->context, mask);
}
static void
_glitz_wgl_make_current (void *abstract_context,
void *abstract_drawable)
void *abstract_drawable)
{
glitz_wgl_context_t *context = (glitz_wgl_context_t *) abstract_context;
glitz_wgl_drawable_t *drawable = (glitz_wgl_drawable_t *) abstract_drawable;
glitz_wgl_context_t *context = (glitz_wgl_context_t *) abstract_context;
glitz_wgl_drawable_t *drawable = (glitz_wgl_drawable_t *) abstract_drawable;
if (wglGetCurrentContext() != context->context ||
wglGetCurrentDC() != drawable->dc)
{
wglMakeCurrent (drawable->dc, context->context);
}
if (wglGetCurrentContext() != context->context ||
wglGetCurrentDC() != drawable->dc)
{
wglMakeCurrent (drawable->dc, context->context);
}
}
static void
_glitz_wgl_notify_dummy (void *abstract_drawable,
glitz_surface_t *surface) {}
static glitz_function_pointer_t
_glitz_wgl_context_get_proc_address (void *abstract_context,
const char *name)
{
glitz_wgl_context_t *context = (glitz_wgl_context_t *) abstract_context;
glitz_wgl_drawable_t *drawable = (glitz_wgl_drawable_t *)
context->base.drawable;
/* _glitz_wgl_make_current (drawable, context, NULL); */
return glitz_wgl_get_proc_address (name, drawable->screen_info);
}
glitz_wgl_context_t *
glitz_wgl_context_get (glitz_wgl_screen_info_t *screen_info,
HDC dc,
glitz_drawable_format_t *format)
HDC dc,
glitz_drawable_format_t *format)
{
glitz_wgl_context_t *context;
glitz_wgl_context_t **contexts = screen_info->contexts;
int index, n_contexts = screen_info->n_contexts;
int format_id;
glitz_wgl_context_t *context;
glitz_wgl_context_t **contexts = screen_info->contexts;
int index, n_contexts = screen_info->n_contexts;
int format_id;
for (; n_contexts; n_contexts--, contexts++)
if ((*contexts)->pixel_format == screen_info->format_ids[format->id]) {
return *contexts;
}
for (; n_contexts; n_contexts--, contexts++)
if ((*contexts)->pixel_format == screen_info->format_ids[format->id])
return *contexts;
index = screen_info->n_contexts++;
index = screen_info->n_contexts++;
screen_info->contexts =
realloc (screen_info->contexts,
sizeof (glitz_wgl_context_t *) * screen_info->n_contexts);
screen_info->contexts =
realloc (screen_info->contexts,
sizeof (glitz_wgl_context_t *) * screen_info->n_contexts);
context = malloc (sizeof (glitz_wgl_context_t));
context = malloc (sizeof (glitz_wgl_context_t));
screen_info->contexts[index] = context;
screen_info->contexts[index] = context;
format_id = screen_info->format_ids[format->id];
format_id = screen_info->format_ids[format->id];
_glitz_wgl_context_create (screen_info,
dc,
format_id,
context);
_glitz_wgl_context_create (screen_info,
dc,
format_id,
context);
wglShareLists (screen_info->root_context, context->context);
wglShareLists (screen_info->root_context, context->context);
#if 0
/* Not needed as the root_context is created already when the
* singleton screen_info is set up.
*/
if (!screen_info->root_context)
screen_info->root_context = context->context;
/* Not needed as the root_context is created already when the
* singleton screen_info is set up.
*/
if (!screen_info->root_context)
screen_info->root_context = context->context;
#endif
memcpy (&context->backend.gl,
&_glitz_wgl_gl_proc_address,
sizeof (glitz_gl_proc_address_list_t));
context->backend.gl = &_glitz_wgl_gl_proc_address;
context->backend.create_pbuffer = glitz_wgl_create_pbuffer;
context->backend.destroy = glitz_wgl_destroy;
context->backend.push_current = glitz_wgl_push_current;
context->backend.pop_current = glitz_wgl_pop_current;
context->backend.swap_buffers = glitz_wgl_swap_buffers;
context->backend.create_pbuffer = glitz_wgl_create_pbuffer;
context->backend.destroy = glitz_wgl_destroy;
context->backend.push_current = glitz_wgl_push_current;
context->backend.pop_current = glitz_wgl_pop_current;
context->backend.attach_notify = _glitz_wgl_notify_dummy;
context->backend.detach_notify = _glitz_wgl_notify_dummy;
context->backend.swap_buffers = glitz_wgl_swap_buffers;
context->backend.create_context = _glitz_wgl_create_context;
context->backend.destroy_context = _glitz_wgl_destroy_context;
context->backend.copy_context = _glitz_wgl_copy_context;
context->backend.make_current = _glitz_wgl_make_current;
context->backend.create_context = _glitz_wgl_create_context;
context->backend.destroy_context = _glitz_wgl_destroy_context;
context->backend.copy_context = _glitz_wgl_copy_context;
context->backend.make_current = _glitz_wgl_make_current;
context->backend.get_proc_address = _glitz_wgl_context_get_proc_address;
context->backend.drawable_formats = screen_info->formats;
context->backend.n_drawable_formats = screen_info->n_formats;
context->backend.draw_buffer = _glitz_drawable_draw_buffer;
context->backend.read_buffer = _glitz_drawable_read_buffer;
context->backend.texture_formats = NULL;
context->backend.formats = NULL;
context->backend.n_formats = 0;
context->backend.program_map = &screen_info->program_map;
context->backend.feature_mask = 0;
context->initialized = 0;
return context;
context->backend.drawable_formats = screen_info->formats;
context->backend.n_drawable_formats = screen_info->n_formats;
context->backend.texture_formats = NULL;
context->backend.formats = NULL;
context->backend.n_formats = 0;
context->backend.program_map = &screen_info->program_map;
context->backend.feature_mask = 0;
context->initialized = 0;
return context;
}
void
glitz_wgl_context_destroy (glitz_wgl_screen_info_t *screen_info,
glitz_wgl_context_t *context)
glitz_wgl_context_t *context)
{
if (context->backend.formats)
free (context->backend.formats);
if (context->backend.formats)
free (context->backend.formats);
if (context->backend.texture_formats)
free (context->backend.texture_formats);
if (context->backend.texture_formats)
free (context->backend.texture_formats);
wglDeleteContext (context->context);
wglDeleteContext (context->context);
free (context);
free (context);
}
static void
_glitz_wgl_context_initialize (glitz_wgl_screen_info_t *screen_info,
glitz_wgl_context_t *context)
glitz_wgl_context_t *context)
{
glitz_backend_init (&context->backend,
glitz_wgl_get_proc_address,
(void *) screen_info);
glitz_backend_init (&context->backend,
glitz_wgl_get_proc_address,
(void *) screen_info);
context->backend.gl.get_integer_v (GLITZ_GL_MAX_VIEWPORT_DIMS,
context->max_viewport_dims);
context->backend.gl->get_integer_v (GLITZ_GL_MAX_VIEWPORT_DIMS,
context->max_viewport_dims);
glitz_initiate_state (&_glitz_wgl_gl_proc_address);
context->initialized = 1;
glitz_initiate_state (&_glitz_wgl_gl_proc_address);
context->initialized = 1;
}
static void
_glitz_wgl_context_make_current (glitz_wgl_drawable_t *drawable,
glitz_bool_t flush)
{
if (flush)
if (flush)
{
glFlush ();
glFlush ();
}
wglMakeCurrent (drawable->dc, drawable->context->context);
if (!drawable->context->initialized)
_glitz_wgl_context_initialize (drawable->screen_info, drawable->context);
wglMakeCurrent (drawable->dc, drawable->context->context);
drawable->base.update_all = 1;
if (!drawable->context->initialized)
_glitz_wgl_context_initialize (drawable->screen_info, drawable->context);
}
static void
_glitz_wgl_context_update (glitz_wgl_drawable_t *drawable,
glitz_constraint_t constraint)
{
HGLRC context;
HGLRC context;
switch (constraint) {
case GLITZ_NONE:
break;
case GLITZ_ANY_CONTEXT_CURRENT:
context = wglGetCurrentContext ();
if (context == NULL)
_glitz_wgl_context_make_current (drawable, 0);
break;
case GLITZ_CONTEXT_CURRENT:
context = wglGetCurrentContext ();
if (context != drawable->context->context)
_glitz_wgl_context_make_current (drawable, (context)? 1: 0);
break;
case GLITZ_DRAWABLE_CURRENT:
context = wglGetCurrentContext ();
if ((context != drawable->context->context) ||
(wglGetCurrentDC () != drawable->dc))
_glitz_wgl_context_make_current (drawable, (context)? 1: 0);
break;
}
switch (constraint) {
case GLITZ_NONE:
break;
case GLITZ_ANY_CONTEXT_CURRENT:
context = wglGetCurrentContext ();
if (context == NULL)
_glitz_wgl_context_make_current (drawable, 0);
break;
case GLITZ_CONTEXT_CURRENT:
context = wglGetCurrentContext ();
if (context != drawable->context->context)
_glitz_wgl_context_make_current (drawable, (context)? 1: 0);
break;
case GLITZ_DRAWABLE_CURRENT:
context = wglGetCurrentContext ();
if ((context != drawable->context->context) ||
(wglGetCurrentDC () != drawable->dc))
_glitz_wgl_context_make_current (drawable, (context)? 1: 0);
break;
}
}
void
glitz_bool_t
glitz_wgl_push_current (void *abstract_drawable,
glitz_surface_t *surface,
glitz_constraint_t constraint)
glitz_surface_t *surface,
glitz_constraint_t constraint)
{
glitz_wgl_drawable_t *drawable = (glitz_wgl_drawable_t *) abstract_drawable;
glitz_wgl_context_info_t *context_info;
int index;
glitz_wgl_drawable_t *drawable = (glitz_wgl_drawable_t *) abstract_drawable;
glitz_wgl_context_info_t *context_info;
int index;
index = drawable->screen_info->context_stack_size++;
index = drawable->screen_info->context_stack_size++;
context_info = &drawable->screen_info->context_stack[index];
context_info->drawable = drawable;
context_info->surface = surface;
context_info->constraint = constraint;
_glitz_wgl_context_update (context_info->drawable, constraint);
context_info = &drawable->screen_info->context_stack[index];
context_info->drawable = drawable;
context_info->surface = surface;
context_info->constraint = constraint;
_glitz_wgl_context_update (context_info->drawable, constraint);
return 1;
}
glitz_surface_t *
glitz_wgl_pop_current (void *abstract_drawable)
{
glitz_wgl_drawable_t *drawable = (glitz_wgl_drawable_t *) abstract_drawable;
glitz_wgl_context_info_t *context_info = NULL;
int index;
glitz_wgl_drawable_t *drawable = (glitz_wgl_drawable_t *) abstract_drawable;
glitz_wgl_context_info_t *context_info = NULL;
int index;
drawable->screen_info->context_stack_size--;
index = drawable->screen_info->context_stack_size - 1;
drawable->screen_info->context_stack_size--;
index = drawable->screen_info->context_stack_size - 1;
context_info = &drawable->screen_info->context_stack[index];
context_info = &drawable->screen_info->context_stack[index];
if (context_info->drawable)
_glitz_wgl_context_update (context_info->drawable,
context_info->constraint);
if (context_info->constraint == GLITZ_DRAWABLE_CURRENT)
return context_info->surface;
return NULL;
if (context_info->drawable)
_glitz_wgl_context_update (context_info->drawable,
context_info->constraint);
if (context_info->constraint == GLITZ_DRAWABLE_CURRENT)
return context_info->surface;
return NULL;
}

Просмотреть файл

@ -1,6 +1,6 @@
/*
* Copyright © 2004 David Reveman
*
*
* 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
@ -12,11 +12,11 @@
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
* NO EVENT SHALL DAVID REVEMAN 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,
* 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.
*
@ -39,184 +39,190 @@
glitz_status_t
glitz_wgl_make_current_read (void *abstract_surface)
{
return GLITZ_STATUS_NOT_SUPPORTED;
return GLITZ_STATUS_NOT_SUPPORTED;
}
static glitz_wgl_drawable_t *
_glitz_wgl_create_drawable (glitz_wgl_screen_info_t *screen_info,
glitz_wgl_context_t *context,
glitz_drawable_format_t *format,
glitz_wgl_context_t *context,
glitz_drawable_format_t *format,
HWND window,
HDC dc,
HPBUFFERARB pbuffer,
int width,
int height)
HDC dc,
HPBUFFERARB pbuffer,
int width,
int height)
{
glitz_wgl_drawable_t *drawable;
if (width <= 0 || height <= 0)
return NULL;
glitz_wgl_drawable_t *drawable;
drawable = (glitz_wgl_drawable_t *) malloc (sizeof (glitz_wgl_drawable_t));
if (drawable == NULL)
return NULL;
if (width <= 0 || height <= 0)
return NULL;
drawable->base.ref_count = 1;
drawable->screen_info = screen_info;
drawable->context = context;
drawable->window = window;
drawable->dc = dc;
drawable->pbuffer = pbuffer;
drawable->base.format = format;
drawable->base.backend = &context->backend;
drawable = (glitz_wgl_drawable_t *) malloc (sizeof (glitz_wgl_drawable_t));
if (drawable == NULL)
return NULL;
glitz_drawable_update_size (&drawable->base, width, height);
drawable->base.ref_count = 1;
drawable->screen_info = screen_info;
drawable->context = context;
drawable->window = window;
drawable->dc = dc;
drawable->pbuffer = pbuffer;
if (!context->initialized) {
glitz_wgl_push_current (drawable, NULL, GLITZ_CONTEXT_CURRENT);
glitz_wgl_pop_current (drawable);
}
if (width > context->max_viewport_dims[0] ||
height > context->max_viewport_dims[1]) {
free (drawable);
return NULL;
}
_glitz_drawable_init (&drawable->base,
&screen_info->formats[format->id],
&context->backend,
width,
height);
screen_info->drawables++;
return drawable;
if (!context->initialized) {
glitz_wgl_push_current (drawable, NULL, GLITZ_CONTEXT_CURRENT);
glitz_wgl_pop_current (drawable);
}
if (width > context->max_viewport_dims[0] ||
height > context->max_viewport_dims[1]) {
free (drawable);
return NULL;
}
screen_info->drawables++;
return drawable;
}
static glitz_drawable_t *
_glitz_wgl_create_pbuffer_drawable (glitz_wgl_screen_info_t *screen_info,
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height)
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height)
{
glitz_wgl_drawable_t *drawable;
glitz_wgl_context_t *context;
HPBUFFERARB pbuffer;
HDC dc;
glitz_wgl_drawable_t *drawable;
glitz_wgl_context_t *context;
glitz_int_drawable_format_t *iformat = &screen_info->formats[format->id];
HPBUFFERARB pbuffer;
HDC dc;
if (!format->types.pbuffer)
return NULL;
if (!(iformat->types & GLITZ_DRAWABLE_TYPE_PBUFFER_MASK))
return NULL;
pbuffer = glitz_wgl_pbuffer_create (screen_info, screen_info->format_ids[format->id],
width, height,
&dc);
if (!pbuffer)
return NULL;
context = glitz_wgl_context_get (screen_info, dc, format);
if (!context) {
glitz_wgl_pbuffer_destroy (screen_info, pbuffer, dc);
return NULL;
}
pbuffer = glitz_wgl_pbuffer_create (screen_info, screen_info->format_ids[format->id],
width, height,
&dc);
if (!pbuffer)
return NULL;
drawable = _glitz_wgl_create_drawable (screen_info, context, format,
NULL, dc, pbuffer,
width, height);
if (!drawable) {
glitz_wgl_pbuffer_destroy (screen_info, pbuffer, dc);
glitz_wgl_context_destroy (screen_info, context);
return NULL;
}
return &drawable->base;
context = glitz_wgl_context_get (screen_info, dc, format);
if (!context) {
glitz_wgl_pbuffer_destroy (screen_info, pbuffer, dc);
return NULL;
}
drawable = _glitz_wgl_create_drawable (screen_info, context, format,
NULL, dc, pbuffer,
width, height);
if (!drawable) {
glitz_wgl_pbuffer_destroy (screen_info, pbuffer, dc);
glitz_wgl_context_destroy (screen_info, context);
return NULL;
}
return &drawable->base;
}
glitz_drawable_t *
glitz_wgl_create_pbuffer (void *abstract_templ,
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height)
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height)
{
glitz_wgl_drawable_t *templ = (glitz_wgl_drawable_t *) abstract_templ;
glitz_wgl_drawable_t *templ = (glitz_wgl_drawable_t *) abstract_templ;
return _glitz_wgl_create_pbuffer_drawable (templ->screen_info, format,
width, height);
return _glitz_wgl_create_pbuffer_drawable (templ->screen_info, format,
width, height);
}
glitz_drawable_t *
glitz_wgl_create_drawable_for_window (glitz_drawable_format_t *format,
HWND window,
unsigned int width,
unsigned int height)
HWND window,
unsigned int width,
unsigned int height)
{
glitz_wgl_drawable_t *drawable;
glitz_wgl_screen_info_t *screen_info;
glitz_wgl_context_t *context;
HDC dc;
glitz_wgl_drawable_t *drawable;
glitz_wgl_screen_info_t *screen_info;
glitz_wgl_context_t *context;
HDC dc;
screen_info = glitz_wgl_screen_info_get ();
if (!screen_info)
return NULL;
dc = GetDC (window);
screen_info = glitz_wgl_screen_info_get ();
if (!screen_info)
return NULL;
context = glitz_wgl_context_get (screen_info, dc, format);
if (!context) {
ReleaseDC (window, dc);
return NULL;
}
drawable = _glitz_wgl_create_drawable (screen_info, context, format,
window, dc, NULL,
width, height);
if (!drawable)
return NULL;
dc = GetDC (window);
return &drawable->base;
context = glitz_wgl_context_get (screen_info, dc, format);
if (!context) {
ReleaseDC (window, dc);
return NULL;
}
drawable = _glitz_wgl_create_drawable (screen_info, context, format,
window, dc, NULL,
width, height);
if (!drawable)
return NULL;
return &drawable->base;
}
glitz_drawable_t *
glitz_wgl_create_pbuffer_drawable (glitz_drawable_format_t *format,
unsigned int width,
unsigned int height)
unsigned int width,
unsigned int height)
{
glitz_wgl_screen_info_t *screen_info;
glitz_wgl_screen_info_t *screen_info;
screen_info = glitz_wgl_screen_info_get ();
if (!screen_info)
return NULL;
screen_info = glitz_wgl_screen_info_get ();
if (!screen_info)
return NULL;
return _glitz_wgl_create_pbuffer_drawable (screen_info, format,
width, height);
return _glitz_wgl_create_pbuffer_drawable (screen_info, format,
width, height);
}
void
glitz_wgl_destroy (void *abstract_drawable)
{
glitz_wgl_drawable_t *drawable = (glitz_wgl_drawable_t *) abstract_drawable;
glitz_wgl_drawable_t *drawable = (glitz_wgl_drawable_t *) abstract_drawable;
drawable->screen_info->drawables--;
if (drawable->screen_info->drawables == 0) {
/*
* Last drawable? We have to destroy all fragment programs as this may
* be our last chance to have a context current.
*/
glitz_wgl_push_current (abstract_drawable, NULL, GLITZ_CONTEXT_CURRENT);
glitz_program_map_fini (&drawable->base.backend->gl,
&drawable->screen_info->program_map);
glitz_wgl_pop_current (abstract_drawable);
}
if (wglGetCurrentDC () == drawable->dc)
{
wglMakeCurrent (NULL, NULL);
drawable->screen_info->drawables--;
if (drawable->screen_info->drawables == 0) {
/*
* Last drawable? We have to destroy all fragment programs as this may
* be our last chance to have a context current.
*/
glitz_wgl_push_current (abstract_drawable, NULL, GLITZ_CONTEXT_CURRENT);
glitz_program_map_fini (drawable->base.backend->gl,
&drawable->screen_info->program_map);
glitz_program_map_init (&drawable->screen_info->program_map);
glitz_wgl_pop_current (abstract_drawable);
}
if (drawable->pbuffer)
glitz_wgl_pbuffer_destroy (drawable->screen_info, drawable->pbuffer, drawable->dc);
free (drawable);
if (wglGetCurrentDC () == drawable->dc)
{
wglMakeCurrent (NULL, NULL);
}
if (drawable->pbuffer)
glitz_wgl_pbuffer_destroy (drawable->screen_info, drawable->pbuffer, drawable->dc);
free (drawable);
}
void
glitz_bool_t
glitz_wgl_swap_buffers (void *abstract_drawable)
{
glitz_wgl_drawable_t *drawable = (glitz_wgl_drawable_t *) abstract_drawable;
glitz_wgl_drawable_t *drawable = (glitz_wgl_drawable_t *) abstract_drawable;
SwapBuffers (drawable->dc);
SwapBuffers (drawable->dc);
return 1;
}

Просмотреть файл

@ -1,6 +1,6 @@
/*
* Copyright © 2004 David Reveman
*
*
* 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
@ -12,11 +12,11 @@
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
* NO EVENT SHALL DAVID REVEMAN 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,
* 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.
*
@ -38,45 +38,46 @@
#include <ctype.h>
static glitz_extension_map wgl_extensions[] = {
{ 0.0, "WGL_ARB_pixel_format", GLITZ_WGL_FEATURE_PIXEL_FORMAT_MASK },
{ 0.0, "WGL_ARB_pbuffer", GLITZ_WGL_FEATURE_PBUFFER_MASK },
{ 0.0, "WGL_ARB_make_current_read",
GLITZ_WGL_FEATURE_MAKE_CURRENT_READ_MASK },
{ 0.0, "WGL_ARB_multisample", GLITZ_WGL_FEATURE_MULTISAMPLE_MASK },
{ 0.0, NULL, 0 }
{ 0.0, "WGL_ARB_pixel_format", GLITZ_WGL_FEATURE_PIXEL_FORMAT_MASK },
{ 0.0, "WGL_ARB_pbuffer", GLITZ_WGL_FEATURE_PBUFFER_MASK },
{ 0.0, "WGL_ARB_make_current_read",
GLITZ_WGL_FEATURE_MAKE_CURRENT_READ_MASK },
{ 0.0, "WGL_ARB_multisample", GLITZ_WGL_FEATURE_MULTISAMPLE_MASK },
{ 0.0, NULL, 0 }
};
void
glitz_wgl_query_extensions (glitz_wgl_screen_info_t *screen_info,
glitz_gl_float_t wgl_version)
{
typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc);
PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB;
const char *wgl_extensions_string;
typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc);
PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB;
const char *wgl_extensions_string;
wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress ("wglGetExtensionsStringARB");
wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
wglGetProcAddress ("wglGetExtensionsStringARB");
if (wglGetExtensionsStringARB == NULL)
return;
if (wglGetExtensionsStringARB == NULL)
return;
wgl_extensions_string = (*wglGetExtensionsStringARB) (screen_info->root_dc);
screen_info->wgl_feature_mask =
glitz_extensions_query (wgl_version,
wgl_extensions_string,
wgl_extensions);
if (screen_info->wgl_feature_mask & GLITZ_WGL_FEATURE_MULTISAMPLE_MASK) {
const char *renderer;
wgl_extensions_string = (*wglGetExtensionsStringARB) (screen_info->root_dc);
renderer = glGetString (GL_RENDERER);
if (renderer) {
/* nVIDIA's driver seem to support multisample with pbuffers (?) */
if (!strncmp ("GeForce", renderer, 7) ||
!strncmp ("Quadro", renderer, 6))
screen_info->wgl_feature_mask |=
GLITZ_WGL_FEATURE_PBUFFER_MULTISAMPLE_MASK;
screen_info->wgl_feature_mask =
glitz_extensions_query (wgl_version,
wgl_extensions_string,
wgl_extensions);
if (screen_info->wgl_feature_mask & GLITZ_WGL_FEATURE_MULTISAMPLE_MASK) {
const char *renderer;
renderer = glGetString (GL_RENDERER);
if (renderer) {
/* nVIDIA's driver seem to support multisample with pbuffers (?) */
if (!strncmp ("GeForce", renderer, 7) ||
!strncmp ("Quadro", renderer, 6))
screen_info->wgl_feature_mask |=
GLITZ_WGL_FEATURE_PBUFFER_MULTISAMPLE_MASK;
}
}
}
}

Просмотреть файл

@ -1,6 +1,6 @@
/*
* Copyright © 2004 David Reveman
*
*
* 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
@ -12,11 +12,11 @@
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
* NO EVENT SHALL DAVID REVEMAN 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,
* 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.
*
@ -40,308 +40,324 @@
static int
_glitz_wgl_format_compare (const void *elem1,
const void *elem2)
const void *elem2)
{
int i, score[2];
glitz_drawable_format_t *format[2];
format[0] = (glitz_drawable_format_t *) elem1;
format[1] = (glitz_drawable_format_t *) elem2;
i = score[0] = score[1] = 0;
glitz_int_drawable_format_t *format[2];
int i, score[2];
for (; i < 2; i++) {
if (format[i]->color.red_size) {
if (format[i]->color.red_size == 8)
score[i] += 5;
score[i] += 10;
format[0] = (glitz_int_drawable_format_t *) elem1;
format[1] = (glitz_int_drawable_format_t *) elem2;
i = score[0] = score[1] = 0;
for (; i < 2; i++)
{
if (format[i]->d.color.fourcc != GLITZ_FOURCC_RGB)
score[i] -= 1000;
if (format[i]->d.color.red_size)
{
if (format[i]->d.color.red_size >= 8)
score[i] += 5;
score[i] += 10;
}
if (format[i]->d.color.alpha_size)
{
if (format[i]->d.color.alpha_size >= 8)
score[i] += 5;
score[i] += 10;
}
if (format[i]->d.stencil_size)
score[i] += 5;
if (format[i]->d.depth_size)
score[i] += 5;
if (format[i]->d.doublebuffer)
score[i] += 10;
if (format[i]->d.samples > 1)
score[i] -= (20 - format[i]->d.samples);
if (format[i]->types & GLITZ_DRAWABLE_TYPE_WINDOW_MASK)
score[i] += 10;
if (format[i]->types & GLITZ_DRAWABLE_TYPE_PBUFFER_MASK)
score[i] += 10;
if (format[i]->caveat)
score[i] -= format[i]->caveat * 500;
}
if (format[i]->color.green_size) {
if (format[i]->color.green_size == 8)
score[i] += 5;
score[i] += 10;
}
if (format[i]->color.alpha_size) {
if (format[i]->color.alpha_size == 8)
score[i] += 5;
score[i] += 10;
}
if (format[i]->stencil_size)
score[i] += 5;
if (format[i]->depth_size)
score[i] += 5;
if (format[i]->doublebuffer)
score[i] += 10;
if (format[i]->types.window)
score[i] += 10;
if (format[i]->types.pbuffer)
score[i] += 10;
if (format[i]->samples > 1)
score[i] -= (20 - format[i]->samples);
}
return score[1] - score[0];
return score[1] - score[0];
}
static void
_glitz_add_format (glitz_wgl_screen_info_t *screen_info,
glitz_drawable_format_t *format,
int id)
_glitz_add_format (glitz_wgl_screen_info_t *screen_info,
glitz_int_drawable_format_t *format,
int id)
{
if (!glitz_drawable_format_find (screen_info->formats,
screen_info->n_formats,
GLITZ_DRAWABLE_FORMAT_ALL_EXCEPT_ID_MASK,
format, 0)) {
int n = screen_info->n_formats;
screen_info->formats =
realloc (screen_info->formats,
sizeof (glitz_drawable_format_t) * (n + 1));
screen_info->format_ids =
realloc (screen_info->format_ids, sizeof (int) * (n + 1));
if (screen_info->formats && screen_info->format_ids) {
screen_info->formats[n] = *format;
screen_info->formats[n].id = n;
screen_info->format_ids[n] = id;
screen_info->n_formats++;
screen_info->format_ids =
realloc (screen_info->format_ids,
sizeof (int) * (n + 1));
screen_info->formats =
realloc (screen_info->formats,
sizeof (glitz_int_drawable_format_t) * (n + 1));
if (screen_info->format_ids && screen_info->formats)
{
screen_info->formats[n] = *format;
screen_info->formats[n].d.id = n;
screen_info->format_ids[n] = id;
screen_info->n_formats++;
}
}
}
static glitz_bool_t
_glitz_wgl_query_formats (glitz_wgl_screen_info_t *screen_info)
{
glitz_drawable_format_t format;
int i, num_pixel_formats;
PIXELFORMATDESCRIPTOR pfd;
pfd.nSize = sizeof (PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
glitz_int_drawable_format_t format;
int i, num_pixel_formats;
PIXELFORMATDESCRIPTOR pfd;
num_pixel_formats =
DescribePixelFormat (screen_info->root_dc, 1,
sizeof (PIXELFORMATDESCRIPTOR), &pfd);
pfd.nSize = sizeof (PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
if (!num_pixel_formats)
return 0;
num_pixel_formats =
DescribePixelFormat (screen_info->root_dc, 1,
sizeof (PIXELFORMATDESCRIPTOR), &pfd);
for (i = 1; i <= num_pixel_formats; i++) {
format.id = 0;
if (!num_pixel_formats)
return 0;
if (!DescribePixelFormat (screen_info->root_dc, i,
sizeof (PIXELFORMATDESCRIPTOR), &pfd))
{
continue;
}
for (i = 1; i <= num_pixel_formats; i++) {
format.d.id = 0;
format.caveat = 0;
format.types = 0;
if (!((pfd.dwFlags & PFD_DRAW_TO_WINDOW) &&
(pfd.dwFlags & PFD_SUPPORT_OPENGL)))
continue;
if (!DescribePixelFormat (screen_info->root_dc, i,
sizeof (PIXELFORMATDESCRIPTOR), &pfd))
{
continue;
}
if (pfd.iPixelType != PFD_TYPE_RGBA)
continue;
if (pfd.dwFlags & (PFD_NEED_PALETTE |
PFD_NEED_SYSTEM_PALETTE |
PFD_STEREO))
continue;
#ifndef USE_MESA
/* Can't use the Windows software implementation as glitz
* unconditionally requires OpenGL 1.2, and it's only 1.1.
*/
if (pfd.dwFlags & PFD_GENERIC_FORMAT)
continue;
#ifdef DEBUG
printf ("Pixel format %d Flags: 0x%08x\n", i, pfd.dwFlags);
#endif
format.types.window = 1;
format.types.pbuffer = 0;
if (!((pfd.dwFlags & PFD_DRAW_TO_WINDOW) &&
(pfd.dwFlags & PFD_SUPPORT_OPENGL)))
continue;
format.color.red_size = pfd.cRedBits;
format.color.green_size = pfd.cGreenBits;
format.color.blue_size = pfd.cBlueBits;
format.color.alpha_size = pfd.cAlphaBits;
if (pfd.iPixelType != PFD_TYPE_RGBA)
continue;
format.depth_size = pfd.cDepthBits;
format.stencil_size = pfd.cStencilBits;
if (pfd.dwFlags & (PFD_NEED_PALETTE |
PFD_NEED_SYSTEM_PALETTE |
PFD_STEREO))
continue;
format.doublebuffer = (pfd.dwFlags & PFD_DOUBLEBUFFER) != 0;
format.samples = 1;
#ifndef USE_MESA
/* Can't use the Windows software implementation as glitz
* unconditionally requires OpenGL 1.2, and it's only 1.1.
*/
if (pfd.dwFlags & PFD_GENERIC_FORMAT)
continue;
#endif
_glitz_add_format (screen_info, &format, i);
}
format.types = GLITZ_DRAWABLE_TYPE_WINDOW_MASK;
return 0;
format.d.color.red_size = pfd.cRedBits;
format.d.color.green_size = pfd.cGreenBits;
format.d.color.blue_size = pfd.cBlueBits;
format.d.color.alpha_size = pfd.cAlphaBits;
format.d.color.fourcc = GLITZ_FOURCC_RGB;
format.d.depth_size = pfd.cDepthBits;
format.d.stencil_size = pfd.cStencilBits;
format.d.doublebuffer = (pfd.dwFlags & PFD_DOUBLEBUFFER) != 0;
format.d.samples = 1;
_glitz_add_format (screen_info, &format, i);
}
return 0;
}
static glitz_status_t
_glitz_wgl_query_formats_using_pixel_format (glitz_wgl_screen_info_t *screen_info)
{
glitz_drawable_format_t format;
int i, num_pixel_formats;
int question, answer;
glitz_wgl_static_proc_address_list_t *wgl = &screen_info->wgl;
question = WGL_NUMBER_PIXEL_FORMATS_ARB;
if (!wgl->get_pixel_format_attrib_iv (screen_info->root_dc, 0, 0, 1,
&question, &num_pixel_formats)) {
/* wglGetPixelFormatAttribivARB didn't work, fall back to
* DescribePixelFormat.
*/
screen_info->wgl_feature_mask &= ~GLITZ_WGL_FEATURE_PIXEL_FORMAT_MASK;
return GLITZ_STATUS_NOT_SUPPORTED;
}
glitz_int_drawable_format_t format;
int i, num_pixel_formats;
int question, answer;
glitz_wgl_static_proc_address_list_t *wgl = &screen_info->wgl;
for (i = 1; i <= num_pixel_formats; i++) {
format.id = 0;
question = WGL_SUPPORT_OPENGL_ARB;
if (!wgl->get_pixel_format_attrib_iv (screen_info->root_dc, i, 0, 1,
&question, &answer) ||
!answer)
continue;
question = WGL_PIXEL_TYPE_ARB;
if (!wgl->get_pixel_format_attrib_iv (screen_info->root_dc, i, 0, 1,
&question, &answer) ||
answer != WGL_TYPE_RGBA_ARB)
continue;
/* Stereo is not supported yet */
question = WGL_STEREO_ARB;
if (!wgl->get_pixel_format_attrib_iv (screen_info->root_dc, i, 0, 1,
&question, &answer) ||
answer != 0)
continue;
question = WGL_DRAW_TO_WINDOW_ARB;
if (!wgl->get_pixel_format_attrib_iv (screen_info->root_dc, i, 0, 1,
&question, &answer))
continue;
format.types.window = (answer) ? 1 : 0;
question = WGL_DRAW_TO_PBUFFER_ARB;
if (!wgl->get_pixel_format_attrib_iv (screen_info->root_dc, i, 0, 1,
&question, &answer))
continue;
format.types.pbuffer = (answer) ? 1 : 0;
if (!(format.types.window || format.types.pbuffer))
continue;
question = WGL_RED_BITS_ARB;
if (!wgl->get_pixel_format_attrib_iv (screen_info->root_dc, i, 0, 1,
&question, &answer))
continue;
format.color.red_size = (unsigned short) answer;
question = WGL_GREEN_BITS_ARB;
if (!wgl->get_pixel_format_attrib_iv (screen_info->root_dc, i, 0, 1,
&question, &answer))
continue;
format.color.green_size = (unsigned short) answer;
question = WGL_BLUE_BITS_ARB;
if (!wgl->get_pixel_format_attrib_iv (screen_info->root_dc, i, 0, 1,
&question, &answer))
continue;
format.color.blue_size = (unsigned short) answer;
question = WGL_ALPHA_BITS_ARB;
if (!wgl->get_pixel_format_attrib_iv (screen_info->root_dc, i, 0, 1,
&question, &answer))
continue;
format.color.alpha_size = (unsigned short) answer;
question = WGL_DEPTH_BITS_ARB;
if (!wgl->get_pixel_format_attrib_iv (screen_info->root_dc, i, 0, 1,
&question, &answer))
continue;
format.depth_size = (unsigned short) answer;
question = WGL_STENCIL_BITS_ARB;
if (!wgl->get_pixel_format_attrib_iv (screen_info->root_dc, i, 0, 1,
&question, &answer))
continue;
format.stencil_size = (unsigned short) answer;
question = WGL_DOUBLE_BUFFER_ARB;
if (!wgl->get_pixel_format_attrib_iv (screen_info->root_dc, i, 0, 1,
&question, &answer))
continue;
format.doublebuffer = (answer) ? 1: 0;
if (screen_info->wgl_feature_mask & GLITZ_WGL_FEATURE_MULTISAMPLE_MASK) {
question = WGL_SAMPLE_BUFFERS_ARB;
if (!wgl->get_pixel_format_attrib_iv (screen_info->root_dc, i, 0, 1,
&question, &answer))
continue;
if (answer) {
question = WGL_SAMPLES_ARB;
if (!wgl->get_pixel_format_attrib_iv (screen_info->root_dc, i, 0, 1,
&question, &answer))
continue;
format.samples = (unsigned short) answer;
} else {
format.samples = 1;
}
} else {
format.samples = 1;
question = WGL_NUMBER_PIXEL_FORMATS_ARB;
if (!wgl->get_pixel_format_attrib_iv (screen_info->root_dc, 0, 0, 1,
&question, &num_pixel_formats)) {
/* wglGetPixelFormatAttribivARB didn't work, fall back to
* DescribePixelFormat.
*/
screen_info->wgl_feature_mask &= ~GLITZ_WGL_FEATURE_PIXEL_FORMAT_MASK;
return GLITZ_STATUS_NOT_SUPPORTED;
}
_glitz_add_format (screen_info, &format, i);
}
return GLITZ_STATUS_SUCCESS;
for (i = 1; i <= num_pixel_formats; i++) {
format.d.id = 0;
format.types = 0;
format.d.color.fourcc = GLITZ_FOURCC_RGB;
#define ASK_QUESTION(q,a) (question=(q),wgl->get_pixel_format_attrib_iv (screen_info->root_dc, i, 0, 1, &question,(a)))
if (!ASK_QUESTION(WGL_SUPPORT_OPENGL_ARB, &answer)
|| !answer)
continue;
if (!ASK_QUESTION(WGL_PIXEL_TYPE_ARB, &answer)
|| answer != WGL_TYPE_RGBA_ARB)
continue;
if (!ASK_QUESTION(WGL_ACCELERATION_ARB, &answer))
continue;
if (answer == WGL_NO_ACCELERATION_ARB)
format.caveat = 2;
else if (answer == WGL_GENERIC_ACCELERATION_ARB)
format.caveat = 1;
else
format.caveat = 0;
/* Stereo is not supported yet */
if (!ASK_QUESTION(WGL_STEREO_ARB, &answer)
|| answer != 0)
continue;
if (!ASK_QUESTION(WGL_DRAW_TO_WINDOW_ARB, &answer))
continue;
format.types |= answer ? GLITZ_DRAWABLE_TYPE_WINDOW_MASK : 0;
if (!ASK_QUESTION(WGL_DRAW_TO_PBUFFER_ARB, &answer))
continue;
format.types |= answer ? GLITZ_DRAWABLE_TYPE_PBUFFER_MASK : 0;
if (!(format.types & (GLITZ_DRAWABLE_TYPE_WINDOW_MASK |
GLITZ_DRAWABLE_TYPE_PBUFFER_MASK)))
continue;
if (!ASK_QUESTION(WGL_RED_BITS_ARB, &answer))
continue;
format.d.color.red_size = (unsigned short) answer;
if (!ASK_QUESTION(WGL_GREEN_BITS_ARB, &answer))
continue;
format.d.color.green_size = (unsigned short) answer;
if (!ASK_QUESTION(WGL_BLUE_BITS_ARB, &answer))
continue;
format.d.color.blue_size = (unsigned short) answer;
if (!ASK_QUESTION(WGL_ALPHA_BITS_ARB, &answer))
continue;
format.d.color.alpha_size = (unsigned short) answer;
if (!ASK_QUESTION(WGL_DEPTH_BITS_ARB, &answer))
continue;
format.d.depth_size = (unsigned short) answer;
if (!ASK_QUESTION(WGL_STENCIL_BITS_ARB, &answer))
continue;
format.d.stencil_size = (unsigned short) answer;
if (!ASK_QUESTION(WGL_DOUBLE_BUFFER_ARB, &answer))
continue;
format.d.doublebuffer = (answer) ? 1: 0;
format.d.samples = 1;
if (screen_info->wgl_feature_mask & GLITZ_WGL_FEATURE_MULTISAMPLE_MASK) {
if (!ASK_QUESTION(WGL_SAMPLE_BUFFERS_ARB, &answer))
continue;
if (answer) {
if (!ASK_QUESTION(WGL_SAMPLES_ARB, &answer))
continue;
format.d.samples = (unsigned short) answer;
}
}
_glitz_add_format (screen_info, &format, i);
}
return GLITZ_STATUS_SUCCESS;
}
void
glitz_wgl_query_formats (glitz_wgl_screen_info_t *screen_info)
{
glitz_status_t status = GLITZ_STATUS_NOT_SUPPORTED;
int *new_ids, i;
glitz_status_t status = GLITZ_STATUS_NOT_SUPPORTED;
int *new_ids, i;
if (screen_info->wgl_feature_mask & GLITZ_WGL_FEATURE_PIXEL_FORMAT_MASK)
status = _glitz_wgl_query_formats_using_pixel_format (screen_info);
if (screen_info->wgl_feature_mask & GLITZ_WGL_FEATURE_PIXEL_FORMAT_MASK)
status = _glitz_wgl_query_formats_using_pixel_format (screen_info);
if (status)
_glitz_wgl_query_formats (screen_info);
if (status)
_glitz_wgl_query_formats (screen_info);
if (!screen_info->n_formats)
return;
if (!screen_info->n_formats)
return;
qsort (screen_info->formats, screen_info->n_formats,
sizeof (glitz_drawable_format_t), _glitz_wgl_format_compare);
qsort (screen_info->formats, screen_info->n_formats,
sizeof (glitz_int_drawable_format_t), _glitz_wgl_format_compare);
new_ids = malloc (sizeof (*new_ids) * screen_info->n_formats);
new_ids = malloc (sizeof (*new_ids) * screen_info->n_formats);
for (i = 0; i < screen_info->n_formats; i++) {
new_ids[i] = screen_info->format_ids[screen_info->formats[i].id];
screen_info->formats[i].id = i;
}
free (screen_info->format_ids);
screen_info->format_ids = new_ids;
for (i = 0; i < screen_info->n_formats; i++) {
new_ids[i] = screen_info->format_ids[screen_info->formats[i].d.id];
screen_info->formats[i].d.id = i;
}
free (screen_info->format_ids);
screen_info->format_ids = new_ids;
}
glitz_drawable_format_t *
glitz_wgl_find_drawable_format (unsigned long mask,
const glitz_drawable_format_t *templ,
int count)
glitz_wgl_find_window_format (unsigned long mask,
const glitz_drawable_format_t *templ,
int count)
{
glitz_wgl_screen_info_t *screen_info =
glitz_wgl_screen_info_get ();
glitz_int_drawable_format_t itempl;
glitz_wgl_screen_info_t *screen_info =
glitz_wgl_screen_info_get ();
return glitz_drawable_format_find (screen_info->formats,
screen_info->n_formats,
mask, templ, count);
glitz_drawable_format_copy (templ, &itempl.d, mask);
itempl.types = GLITZ_DRAWABLE_TYPE_WINDOW_MASK;
mask |= GLITZ_INT_FORMAT_WINDOW_MASK;
return glitz_drawable_format_find (screen_info->formats,
screen_info->n_formats,
mask, &itempl, count);
}
glitz_drawable_format_t *
glitz_wgl_find_pbuffer_format (unsigned long mask,
const glitz_drawable_format_t *templ,
int count)
{
glitz_int_drawable_format_t itempl;
glitz_wgl_screen_info_t *screen_info =
glitz_wgl_screen_info_get ();
glitz_drawable_format_copy (templ, &itempl.d, mask);
itempl.types = GLITZ_DRAWABLE_TYPE_PBUFFER_MASK;
mask |= GLITZ_INT_FORMAT_PBUFFER_MASK;
return glitz_drawable_format_find (screen_info->formats,
screen_info->n_formats,
mask, &itempl, count);
}

Просмотреть файл

@ -1,6 +1,6 @@
/*
* Copyright © 2004 David Reveman
*
*
* 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
@ -12,11 +12,11 @@
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
* NO EVENT SHALL DAVID REVEMAN 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,
* 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.
*
@ -44,164 +44,178 @@
void
glitz_wgl_print_win32_error_string (int error_code)
{
char *msg = NULL;
char *msg = NULL;
FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL, error_code, 0,
(LPTSTR) &msg, 0, NULL);
FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL, error_code, 0,
(LPTSTR) &msg, 0, NULL);
if (msg != NULL)
fprintf (stderr, "%s", msg);
else
fprintf (stderr, "Unknown error code %d", error_code);
if (msg != NULL)
fprintf (stderr, "%s", msg);
else
fprintf (stderr, "Unknown error code %d", error_code);
LocalFree (msg);
LocalFree (msg);
}
void
glitz_wgl_win32_api_failed (const char *api)
{
fprintf (stderr, "%s failed: ", api);
glitz_wgl_print_win32_error_string (GetLastError ());
fprintf (stderr, "\n");
fprintf (stderr, "%s failed: ", api);
glitz_wgl_print_win32_error_string (GetLastError ());
fprintf (stderr, "\n");
}
glitz_gl_proc_address_list_t _glitz_wgl_gl_proc_address = {
/* core */
(glitz_gl_enable_t) glEnable,
(glitz_gl_disable_t) glDisable,
(glitz_gl_get_error_t) glGetError,
(glitz_gl_get_string_t) glGetString,
(glitz_gl_enable_client_state_t) glEnableClientState,
(glitz_gl_disable_client_state_t) glDisableClientState,
(glitz_gl_vertex_pointer_t) glVertexPointer,
(glitz_gl_tex_coord_pointer_t) glTexCoordPointer,
(glitz_gl_draw_arrays_t) glDrawArrays,
(glitz_gl_tex_env_f_t) glTexEnvf,
(glitz_gl_tex_env_fv_t) glTexEnvfv,
(glitz_gl_tex_gen_i_t) glTexGeni,
(glitz_gl_tex_gen_fv_t) glTexGenfv,
(glitz_gl_color_4us_t) glColor4us,
(glitz_gl_color_4f_t) glColor4f,
(glitz_gl_scissor_t) glScissor,
(glitz_gl_blend_func_t) glBlendFunc,
(glitz_gl_clear_t) glClear,
(glitz_gl_clear_color_t) glClearColor,
(glitz_gl_clear_stencil_t) glClearStencil,
(glitz_gl_stencil_func_t) glStencilFunc,
(glitz_gl_stencil_op_t) glStencilOp,
(glitz_gl_push_attrib_t) glPushAttrib,
(glitz_gl_pop_attrib_t) glPopAttrib,
(glitz_gl_matrix_mode_t) glMatrixMode,
(glitz_gl_push_matrix_t) glPushMatrix,
(glitz_gl_pop_matrix_t) glPopMatrix,
(glitz_gl_load_identity_t) glLoadIdentity,
(glitz_gl_load_matrix_f_t) glLoadMatrixf,
(glitz_gl_depth_range_t) glDepthRange,
(glitz_gl_viewport_t) glViewport,
(glitz_gl_raster_pos_2f_t) glRasterPos2f,
(glitz_gl_bitmap_t) glBitmap,
(glitz_gl_read_buffer_t) glReadBuffer,
(glitz_gl_draw_buffer_t) glDrawBuffer,
(glitz_gl_copy_pixels_t) glCopyPixels,
(glitz_gl_flush_t) glFlush,
(glitz_gl_finish_t) glFinish,
(glitz_gl_pixel_store_i_t) glPixelStorei,
(glitz_gl_ortho_t) glOrtho,
(glitz_gl_scale_f_t) glScalef,
(glitz_gl_translate_f_t) glTranslatef,
(glitz_gl_hint_t) glHint,
(glitz_gl_depth_mask_t) glDepthMask,
(glitz_gl_polygon_mode_t) glPolygonMode,
(glitz_gl_shade_model_t) glShadeModel,
(glitz_gl_color_mask_t) glColorMask,
(glitz_gl_read_pixels_t) glReadPixels,
(glitz_gl_get_tex_image_t) glGetTexImage,
(glitz_gl_tex_sub_image_2d_t) glTexSubImage2D,
(glitz_gl_gen_textures_t) glGenTextures,
(glitz_gl_delete_textures_t) glDeleteTextures,
(glitz_gl_bind_texture_t) glBindTexture,
(glitz_gl_tex_image_2d_t) glTexImage2D,
(glitz_gl_tex_parameter_i_t) glTexParameteri,
(glitz_gl_get_tex_level_parameter_iv_t) glGetTexLevelParameteriv,
(glitz_gl_copy_tex_sub_image_2d_t) glCopyTexSubImage2D,
(glitz_gl_get_integer_v_t) glGetIntegerv,
/* core */
(glitz_gl_enable_t) glEnable,
(glitz_gl_disable_t) glDisable,
(glitz_gl_get_error_t) glGetError,
(glitz_gl_get_string_t) glGetString,
(glitz_gl_enable_client_state_t) glEnableClientState,
(glitz_gl_disable_client_state_t) glDisableClientState,
(glitz_gl_vertex_pointer_t) glVertexPointer,
(glitz_gl_tex_coord_pointer_t) glTexCoordPointer,
(glitz_gl_draw_arrays_t) glDrawArrays,
(glitz_gl_tex_env_f_t) glTexEnvf,
(glitz_gl_tex_env_fv_t) glTexEnvfv,
(glitz_gl_tex_gen_i_t) glTexGeni,
(glitz_gl_tex_gen_fv_t) glTexGenfv,
(glitz_gl_color_4us_t) glColor4us,
(glitz_gl_color_4f_t) glColor4f,
(glitz_gl_scissor_t) glScissor,
(glitz_gl_blend_func_t) glBlendFunc,
(glitz_gl_clear_t) glClear,
(glitz_gl_clear_color_t) glClearColor,
(glitz_gl_clear_stencil_t) glClearStencil,
(glitz_gl_stencil_func_t) glStencilFunc,
(glitz_gl_stencil_op_t) glStencilOp,
(glitz_gl_push_attrib_t) glPushAttrib,
(glitz_gl_pop_attrib_t) glPopAttrib,
(glitz_gl_matrix_mode_t) glMatrixMode,
(glitz_gl_push_matrix_t) glPushMatrix,
(glitz_gl_pop_matrix_t) glPopMatrix,
(glitz_gl_load_identity_t) glLoadIdentity,
(glitz_gl_load_matrix_f_t) glLoadMatrixf,
(glitz_gl_depth_range_t) glDepthRange,
(glitz_gl_viewport_t) glViewport,
(glitz_gl_raster_pos_2f_t) glRasterPos2f,
(glitz_gl_bitmap_t) glBitmap,
(glitz_gl_read_buffer_t) glReadBuffer,
(glitz_gl_draw_buffer_t) glDrawBuffer,
(glitz_gl_copy_pixels_t) glCopyPixels,
(glitz_gl_flush_t) glFlush,
(glitz_gl_finish_t) glFinish,
(glitz_gl_pixel_store_i_t) glPixelStorei,
(glitz_gl_ortho_t) glOrtho,
(glitz_gl_scale_f_t) glScalef,
(glitz_gl_translate_f_t) glTranslatef,
(glitz_gl_hint_t) glHint,
(glitz_gl_depth_mask_t) glDepthMask,
(glitz_gl_polygon_mode_t) glPolygonMode,
(glitz_gl_shade_model_t) glShadeModel,
(glitz_gl_color_mask_t) glColorMask,
(glitz_gl_read_pixels_t) glReadPixels,
(glitz_gl_get_tex_image_t) glGetTexImage,
(glitz_gl_tex_sub_image_2d_t) glTexSubImage2D,
(glitz_gl_gen_textures_t) glGenTextures,
(glitz_gl_delete_textures_t) glDeleteTextures,
(glitz_gl_bind_texture_t) glBindTexture,
(glitz_gl_tex_image_2d_t) glTexImage2D,
(glitz_gl_tex_parameter_i_t) glTexParameteri,
(glitz_gl_tex_parameter_fv_t) glTexParameterfv,
(glitz_gl_get_tex_level_parameter_iv_t) glGetTexLevelParameteriv,
(glitz_gl_copy_tex_sub_image_2d_t) glCopyTexSubImage2D,
(glitz_gl_get_integer_v_t) glGetIntegerv,
/* extensions */
(glitz_gl_blend_color_t) 0,
(glitz_gl_active_texture_t) 0,
(glitz_gl_client_active_texture_t) 0,
(glitz_gl_multi_draw_arrays_t) 0,
(glitz_gl_gen_programs_t) 0,
(glitz_gl_delete_programs_t) 0,
(glitz_gl_program_string_t) 0,
(glitz_gl_bind_program_t) 0,
(glitz_gl_program_local_param_4fv_t) 0,
(glitz_gl_get_program_iv_t) 0,
(glitz_gl_gen_buffers_t) 0,
(glitz_gl_delete_buffers_t) 0,
(glitz_gl_bind_buffer_t) 0,
(glitz_gl_buffer_data_t) 0,
(glitz_gl_buffer_sub_data_t) 0,
(glitz_gl_get_buffer_sub_data_t) 0,
(glitz_gl_map_buffer_t) 0,
(glitz_gl_unmap_buffer_t) 0
/* extensions */
(glitz_gl_blend_color_t) 0,
(glitz_gl_active_texture_t) 0,
(glitz_gl_client_active_texture_t) 0,
(glitz_gl_multi_draw_arrays_t) 0,
(glitz_gl_gen_programs_t) 0,
(glitz_gl_delete_programs_t) 0,
(glitz_gl_program_string_t) 0,
(glitz_gl_bind_program_t) 0,
(glitz_gl_program_local_param_4fv_t) 0,
(glitz_gl_get_program_iv_t) 0,
(glitz_gl_gen_buffers_t) 0,
(glitz_gl_delete_buffers_t) 0,
(glitz_gl_bind_buffer_t) 0,
(glitz_gl_buffer_data_t) 0,
(glitz_gl_buffer_sub_data_t) 0,
(glitz_gl_get_buffer_sub_data_t) 0,
(glitz_gl_map_buffer_t) 0,
(glitz_gl_unmap_buffer_t) 0,
(glitz_gl_gen_framebuffers_t) 0,
(glitz_gl_delete_framebuffers_t) 0,
(glitz_gl_bind_framebuffer_t) 0,
(glitz_gl_framebuffer_renderbuffer_t) 0,
(glitz_gl_framebuffer_texture_2d_t) 0,
(glitz_gl_check_framebuffer_status_t) 0,
(glitz_gl_gen_renderbuffers_t) 0,
(glitz_gl_delete_renderbuffers_t) 0,
(glitz_gl_bind_renderbuffer_t) 0,
(glitz_gl_renderbuffer_storage_t) 0,
(glitz_gl_get_renderbuffer_parameter_iv_t) 0
};
glitz_function_pointer_t
glitz_wgl_get_proc_address (const char *name,
void *closure)
{
glitz_wgl_screen_info_t *screen_info = (glitz_wgl_screen_info_t *) closure;
glitz_wgl_thread_info_t *info = screen_info->thread_info;
glitz_function_pointer_t address = (glitz_function_pointer_t) wglGetProcAddress (name);
glitz_wgl_screen_info_t *screen_info = (glitz_wgl_screen_info_t *) closure;
glitz_wgl_thread_info_t *info = screen_info->thread_info;
glitz_function_pointer_t address = (glitz_function_pointer_t)
wglGetProcAddress (name);
if (!address && info->gl_library) {
/* Not sure whether this has any use at all... */
if (!address && info->gl_library) {
/* Not sure whether this has any use at all... */
if (!info->dlhand)
info->dlhand = LoadLibrary (info->gl_library);
if (!info->dlhand)
info->dlhand = LoadLibrary (info->gl_library);
if (info->dlhand) {
address = (glitz_function_pointer_t) GetProcAddress (info->dlhand, name);
if (info->dlhand) {
address = (glitz_function_pointer_t)
GetProcAddress (info->dlhand, name);
}
}
}
return address;
return address;
}
static void
_glitz_wgl_proc_address_lookup (glitz_wgl_screen_info_t *screen_info)
{
screen_info->wgl.get_pixel_format_attrib_iv =
(glitz_wgl_get_pixel_format_attrib_iv_t)
glitz_wgl_get_proc_address ("wglGetPixelFormatAttribivARB", screen_info);
screen_info->wgl.choose_pixel_format = (glitz_wgl_choose_pixel_format_t)
glitz_wgl_get_proc_address ("wglChoosePixelFormatARB", screen_info);
screen_info->wgl.get_pixel_format_attrib_iv =
(glitz_wgl_get_pixel_format_attrib_iv_t)
glitz_wgl_get_proc_address ("wglGetPixelFormatAttribivARB", screen_info);
screen_info->wgl.choose_pixel_format = (glitz_wgl_choose_pixel_format_t)
glitz_wgl_get_proc_address ("wglChoosePixelFormatARB", screen_info);
screen_info->wgl.create_pbuffer = (glitz_wgl_create_pbuffer_t)
glitz_wgl_get_proc_address ("wglCreatePbufferARB", screen_info);
screen_info->wgl.get_pbuffer_dc = (glitz_wgl_get_pbuffer_dc_t)
glitz_wgl_get_proc_address ("wglGetPbufferDCARB", screen_info);
screen_info->wgl.release_pbuffer_dc = (glitz_wgl_release_pbuffer_dc_t)
glitz_wgl_get_proc_address ("wglReleasePbufferDCARB", screen_info);
screen_info->wgl.destroy_pbuffer = (glitz_wgl_destroy_pbuffer_t)
glitz_wgl_get_proc_address ("wglDestroyPbufferARB", screen_info);
screen_info->wgl.query_pbuffer = (glitz_wgl_query_pbuffer_t)
glitz_wgl_get_proc_address ("wglQueryPbufferARB", screen_info);
screen_info->wgl.create_pbuffer = (glitz_wgl_create_pbuffer_t)
glitz_wgl_get_proc_address ("wglCreatePbufferARB", screen_info);
screen_info->wgl.get_pbuffer_dc = (glitz_wgl_get_pbuffer_dc_t)
glitz_wgl_get_proc_address ("wglGetPbufferDCARB", screen_info);
screen_info->wgl.release_pbuffer_dc = (glitz_wgl_release_pbuffer_dc_t)
glitz_wgl_get_proc_address ("wglReleasePbufferDCARB", screen_info);
screen_info->wgl.destroy_pbuffer = (glitz_wgl_destroy_pbuffer_t)
glitz_wgl_get_proc_address ("wglDestroyPbufferARB", screen_info);
screen_info->wgl.query_pbuffer = (glitz_wgl_query_pbuffer_t)
glitz_wgl_get_proc_address ("wglQueryPbufferARB", screen_info);
screen_info->wgl.make_context_current = (glitz_wgl_make_context_current_t)
glitz_wgl_get_proc_address ("wglMakeContextCurrentARB", screen_info);
screen_info->wgl.make_context_current = (glitz_wgl_make_context_current_t)
glitz_wgl_get_proc_address ("wglMakeContextCurrentARB", screen_info);
if ((!screen_info->wgl.create_pbuffer) ||
(!screen_info->wgl.destroy_pbuffer) ||
(!screen_info->wgl.query_pbuffer))
screen_info->wgl_feature_mask &= ~GLITZ_WGL_FEATURE_PBUFFER_MASK;
if ((!screen_info->wgl.create_pbuffer) ||
(!screen_info->wgl.destroy_pbuffer) ||
(!screen_info->wgl.query_pbuffer))
screen_info->wgl_feature_mask &= ~GLITZ_WGL_FEATURE_PBUFFER_MASK;
}
static void
@ -210,27 +224,27 @@ _glitz_wgl_screen_destroy (glitz_wgl_screen_info_t *screen_info);
static void
_glitz_wgl_thread_info_init (glitz_wgl_thread_info_t *thread_info)
{
thread_info->screen = NULL;
thread_info->gl_library = NULL;
thread_info->dlhand = NULL;
thread_info->screen = NULL;
thread_info->gl_library = NULL;
thread_info->dlhand = NULL;
}
static void
_glitz_wgl_thread_info_fini (glitz_wgl_thread_info_t *thread_info)
{
_glitz_wgl_screen_destroy (thread_info->screen);
_glitz_wgl_screen_destroy (thread_info->screen);
thread_info->screen = NULL;
thread_info->screen = NULL;
if (thread_info->gl_library) {
free (thread_info->gl_library);
thread_info->gl_library = NULL;
}
if (thread_info->gl_library) {
free (thread_info->gl_library);
thread_info->gl_library = NULL;
}
if (thread_info->dlhand) {
FreeLibrary (thread_info->dlhand);
thread_info->dlhand = NULL;
}
if (thread_info->dlhand) {
FreeLibrary (thread_info->dlhand);
thread_info->dlhand = NULL;
}
}
static int tsd_initialized = 0;
@ -239,261 +253,261 @@ static DWORD info_tsd;
static void
_glitz_wgl_thread_info_destroy (glitz_wgl_thread_info_t *thread_info)
{
TlsSetValue (info_tsd, NULL);
if (thread_info) {
_glitz_wgl_thread_info_fini (thread_info);
free (thread_info);
}
TlsSetValue (info_tsd, NULL);
if (thread_info) {
_glitz_wgl_thread_info_fini (thread_info);
free (thread_info);
}
}
static glitz_wgl_thread_info_t *
_glitz_wgl_thread_info_get_inner (void)
{
glitz_wgl_thread_info_t *thread_info;
void *p;
if (!tsd_initialized) {
info_tsd = TlsAlloc ();
tsd_initialized = 1;
}
glitz_wgl_thread_info_t *thread_info;
void *p;
p = TlsGetValue (info_tsd);
if (p == NULL) {
thread_info = malloc (sizeof (glitz_wgl_thread_info_t));
_glitz_wgl_thread_info_init (thread_info);
TlsSetValue (info_tsd, thread_info);
} else
thread_info = (glitz_wgl_thread_info_t *) p;
return thread_info;
if (!tsd_initialized) {
info_tsd = TlsAlloc ();
tsd_initialized = 1;
}
p = TlsGetValue (info_tsd);
if (p == NULL) {
thread_info = malloc (sizeof (glitz_wgl_thread_info_t));
_glitz_wgl_thread_info_init (thread_info);
TlsSetValue (info_tsd, thread_info);
} else
thread_info = (glitz_wgl_thread_info_t *) p;
return thread_info;
}
static glitz_wgl_thread_info_t *
_glitz_wgl_thread_info_get (const char *gl_library)
{
glitz_wgl_thread_info_t *thread_info = _glitz_wgl_thread_info_get_inner ();
glitz_wgl_thread_info_t *thread_info = _glitz_wgl_thread_info_get_inner ();
if (gl_library) {
int len = strlen (gl_library);
if (thread_info->gl_library) {
free (thread_info->gl_library);
thread_info->gl_library = NULL;
}
thread_info->gl_library = malloc (len + 1);
if (thread_info->gl_library) {
memcpy (thread_info->gl_library, gl_library, len);
thread_info->gl_library[len] = '\0';
}
}
if (gl_library) {
int len = strlen (gl_library);
return thread_info;
if (thread_info->gl_library) {
free (thread_info->gl_library);
thread_info->gl_library = NULL;
}
thread_info->gl_library = malloc (len + 1);
if (thread_info->gl_library) {
memcpy (thread_info->gl_library, gl_library, len);
thread_info->gl_library[len] = '\0';
}
}
return thread_info;
}
int
glitz_wgl_thread_starter (const glitz_wgl_thread_starter_arg_t *arg)
{
glitz_wgl_thread_info_t *thread_info;
int retval;
glitz_wgl_thread_info_t *thread_info;
int retval;
retval = (*arg->user_thread_function) (arg->user_thread_function_arg);
retval = (*arg->user_thread_function) (arg->user_thread_function_arg);
if (tsd_initialized) {
thread_info = (glitz_wgl_thread_info_t *) TlsGetValue (info_tsd);
_glitz_wgl_thread_info_fini (thread_info);
free (thread_info);
}
if (tsd_initialized) {
thread_info = (glitz_wgl_thread_info_t *) TlsGetValue (info_tsd);
_glitz_wgl_thread_info_fini (thread_info);
free (thread_info);
}
return retval;
return retval;
}
static void
_glitz_wgl_create_root_context (glitz_wgl_screen_info_t *screen_info)
{
WNDCLASSEX wcl;
ATOM klass;
WNDCLASSEX wcl;
ATOM klass;
static PIXELFORMATDESCRIPTOR pfd = {
sizeof (PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL,
PFD_TYPE_RGBA,
32,
0, 0, 0,
0, 0, 0,
0, 0,
0, 0, 0, 0, 0,
0,
0,
0,
PFD_MAIN_PLANE,
0,
0,
0,
0
};
static PIXELFORMATDESCRIPTOR pfd = {
sizeof (PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL,
PFD_TYPE_RGBA,
32,
0, 0, 0,
0, 0, 0,
0, 0,
0, 0, 0, 0, 0,
0,
0,
0,
PFD_MAIN_PLANE,
0,
0,
0,
0
};
int pixel_format;
int pixel_format;
wcl.cbSize = sizeof (wcl);
wcl.style = 0;
wcl.lpfnWndProc = DefWindowProc;
wcl.cbClsExtra = 0;
wcl.cbWndExtra = 0;
wcl.hInstance = GetModuleHandle (NULL);
wcl.hIcon = NULL;
wcl.hCursor = LoadCursor (NULL, IDC_ARROW);
wcl.hbrBackground = NULL;
wcl.lpszMenuName = NULL;
wcl.lpszClassName = "glitz-wgl-root-window-class";
wcl.hIconSm = NULL;
wcl.cbSize = sizeof (wcl);
wcl.style = 0;
wcl.lpfnWndProc = DefWindowProc;
wcl.cbClsExtra = 0;
wcl.cbWndExtra = 0;
wcl.hInstance = GetModuleHandle (NULL);
wcl.hIcon = NULL;
wcl.hCursor = LoadCursor (NULL, IDC_ARROW);
wcl.hbrBackground = NULL;
wcl.lpszMenuName = NULL;
wcl.lpszClassName = "glitz-wgl-root-window-class";
wcl.hIconSm = NULL;
klass = RegisterClassEx (&wcl);
klass = RegisterClassEx (&wcl);
if (!klass) {
exit (1);
}
if (!klass) {
exit (1);
}
screen_info->root_window =
CreateWindowEx (0, (LPCTSTR) (DWORD) klass, "glitz-wgl-root-window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
100, 100,
GetDesktopWindow (),
NULL, GetModuleHandle (NULL), NULL);
screen_info->root_window =
CreateWindowEx (0, (LPCTSTR) (DWORD) klass, "glitz-wgl-root-window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
100, 100,
GetDesktopWindow (),
NULL, GetModuleHandle (NULL), NULL);
screen_info->root_dc = GetDC (screen_info->root_window);
screen_info->root_dc = GetDC (screen_info->root_window);
pixel_format = ChoosePixelFormat (screen_info->root_dc, &pfd);
pixel_format = ChoosePixelFormat (screen_info->root_dc, &pfd);
if (pixel_format != 0) {
SetPixelFormat (screen_info->root_dc, pixel_format, &pfd);
if (pixel_format != 0) {
SetPixelFormat (screen_info->root_dc, pixel_format, &pfd);
screen_info->root_context = wglCreateContext (screen_info->root_dc);
screen_info->root_context = wglCreateContext (screen_info->root_dc);
wglMakeCurrent (screen_info->root_dc, screen_info->root_context);
} else {
screen_info->root_context = NULL;
}
wglMakeCurrent (screen_info->root_dc, screen_info->root_context);
} else {
screen_info->root_context = NULL;
}
}
glitz_wgl_screen_info_t *
glitz_wgl_screen_info_get (void)
{
static glitz_wgl_screen_info_t *screen_info = NULL;
const char *gl_version;
static glitz_wgl_screen_info_t *screen_info = NULL;
const char *gl_version;
if (screen_info != NULL)
return screen_info;
if (screen_info != NULL)
return screen_info;
screen_info = malloc (sizeof (glitz_wgl_screen_info_t));
screen_info = malloc (sizeof (glitz_wgl_screen_info_t));
screen_info->drawables = 0;
screen_info->formats = NULL;
screen_info->format_ids = NULL;
screen_info->n_formats = 0;
screen_info->drawables = 0;
screen_info->formats = NULL;
screen_info->format_ids = NULL;
screen_info->n_formats = 0;
screen_info->contexts = NULL;
screen_info->n_contexts = 0;
screen_info->contexts = NULL;
screen_info->n_contexts = 0;
memset (&screen_info->wgl, 0, sizeof (glitz_wgl_static_proc_address_list_t));
memset (&screen_info->wgl, 0, sizeof (glitz_wgl_static_proc_address_list_t));
glitz_program_map_init (&screen_info->program_map);
glitz_program_map_init (&screen_info->program_map);
_glitz_wgl_create_root_context (screen_info);
_glitz_wgl_create_root_context (screen_info);
gl_version = glGetString (GL_VERSION);
gl_version = glGetString (GL_VERSION);
screen_info->wgl_version = 1;
screen_info->wgl_version = 1;
/* Can't use atof(), as GL_VERSION might always use a decimal period,
* but atof() looks for the locale-specific decimal separator.
*/
if (gl_version != NULL && gl_version[0]) {
int whole_part;
int n;
if (sscanf (gl_version, "%d%n", &whole_part, &n) == 1 &&
(gl_version[n] == '.' ||
gl_version[n] == ',')) {
double fraction = 0.1;
/* Can't use atof(), as GL_VERSION might always use a decimal period,
* but atof() looks for the locale-specific decimal separator.
*/
if (gl_version != NULL && gl_version[0]) {
int whole_part;
int n;
if (sscanf (gl_version, "%d%n", &whole_part, &n) == 1 &&
(gl_version[n] == '.' ||
gl_version[n] == ',')) {
double fraction = 0.1;
screen_info->wgl_version = whole_part;
while (isdigit (gl_version[n+1])) {
screen_info->wgl_version += (gl_version[n+1] - '0') * fraction;
fraction /= 10;
n++;
}
screen_info->wgl_version = whole_part;
while (isdigit (gl_version[n+1])) {
screen_info->wgl_version += (gl_version[n+1] - '0') * fraction;
fraction /= 10;
n++;
}
}
}
}
screen_info->wgl_feature_mask = 0;
screen_info->wgl_feature_mask = 0;
screen_info->thread_info = _glitz_wgl_thread_info_get_inner ();
screen_info->thread_info->screen = screen_info;
_glitz_wgl_thread_info_get (NULL);
screen_info->thread_info = _glitz_wgl_thread_info_get_inner ();
screen_info->thread_info->screen = screen_info;
_glitz_wgl_thread_info_get (NULL);
glitz_wgl_query_extensions (screen_info, screen_info->wgl_version);
_glitz_wgl_proc_address_lookup (screen_info);
glitz_wgl_query_formats (screen_info);
screen_info->context_stack_size = 1;
screen_info->context_stack->drawable = NULL;
screen_info->context_stack->surface = NULL;
screen_info->context_stack->constraint = GLITZ_NONE;
return screen_info;
glitz_wgl_query_extensions (screen_info, screen_info->wgl_version);
_glitz_wgl_proc_address_lookup (screen_info);
glitz_wgl_query_formats (screen_info);
screen_info->context_stack_size = 1;
screen_info->context_stack->drawable = NULL;
screen_info->context_stack->surface = NULL;
screen_info->context_stack->constraint = GLITZ_NONE;
return screen_info;
}
static void
_glitz_wgl_screen_destroy (glitz_wgl_screen_info_t *screen_info)
{
int i;
int i;
if (screen_info->root_context) {
wglMakeCurrent (NULL, NULL);
}
if (screen_info->root_context) {
wglMakeCurrent (NULL, NULL);
}
for (i = 0; i < screen_info->n_contexts; i++)
glitz_wgl_context_destroy (screen_info, screen_info->contexts[i]);
for (i = 0; i < screen_info->n_contexts; i++)
glitz_wgl_context_destroy (screen_info, screen_info->contexts[i]);
if (screen_info->contexts)
free (screen_info->contexts);
if (screen_info->formats)
free (screen_info->formats);
if (screen_info->contexts)
free (screen_info->contexts);
if (screen_info->format_ids)
free (screen_info->format_ids);
if (screen_info->root_context) {
wglDeleteContext (screen_info->root_context);
}
if (screen_info->root_dc) {
DeleteDC (screen_info->root_dc);
}
if (screen_info->formats)
free (screen_info->formats);
if (screen_info->root_window) {
DestroyWindow (screen_info->root_window);
}
if (screen_info->format_ids)
free (screen_info->format_ids);
free (screen_info);
if (screen_info->root_context) {
wglDeleteContext (screen_info->root_context);
}
if (screen_info->root_dc) {
DeleteDC (screen_info->root_dc);
}
if (screen_info->root_window) {
DestroyWindow (screen_info->root_window);
}
free (screen_info);
}
void
glitz_wgl_init (const char *gl_library)
{
_glitz_wgl_thread_info_get (gl_library);
_glitz_wgl_thread_info_get (gl_library);
}
void
glitz_wgl_fini (void)
{
glitz_wgl_thread_info_t *info = _glitz_wgl_thread_info_get (NULL);
glitz_wgl_thread_info_t *info = _glitz_wgl_thread_info_get (NULL);
_glitz_wgl_thread_info_destroy (info);
_glitz_wgl_thread_info_destroy (info);
}

Просмотреть файл

@ -1,6 +1,6 @@
/*
* Copyright © 2004 David Reveman
*
*
* 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
@ -12,11 +12,11 @@
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
* NO EVENT SHALL DAVID REVEMAN 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,
* 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.
*
@ -37,35 +37,35 @@
HPBUFFERARB
glitz_wgl_pbuffer_create (glitz_wgl_screen_info_t *screen_info,
int pixel_format,
unsigned int width,
unsigned int height,
unsigned int width,
unsigned int height,
HDC *dcp)
{
if (pixel_format) {
HPBUFFERARB retval;
int pbuffer_attr[3], i = 0;
if (pixel_format) {
HPBUFFERARB retval;
int pbuffer_attr[3], i = 0;
pbuffer_attr[i++] = WGL_PBUFFER_LARGEST_ARB;
pbuffer_attr[i++] = 0;
pbuffer_attr[i++] = 0;
pbuffer_attr[i++] = WGL_PBUFFER_LARGEST_ARB;
pbuffer_attr[i++] = 0;
pbuffer_attr[i++] = 0;
retval =
screen_info->wgl.create_pbuffer (screen_info->root_dc, pixel_format,
width, height, pbuffer_attr);
if (retval != NULL) {
*dcp = screen_info->wgl.get_pbuffer_dc (retval);
return retval;
retval =
screen_info->wgl.create_pbuffer (screen_info->root_dc, pixel_format,
width, height, pbuffer_attr);
if (retval != NULL) {
*dcp = screen_info->wgl.get_pbuffer_dc (retval);
return retval;
}
}
}
*dcp = NULL;
return NULL;
*dcp = NULL;
return NULL;
}
void
void
glitz_wgl_pbuffer_destroy (glitz_wgl_screen_info_t *screen_info,
HPBUFFERARB pbuffer,
HPBUFFERARB pbuffer,
HDC dc)
{
screen_info->wgl.release_pbuffer_dc (pbuffer, dc);
screen_info->wgl.destroy_pbuffer (pbuffer);
screen_info->wgl.release_pbuffer_dc (pbuffer, dc);
screen_info->wgl.destroy_pbuffer (pbuffer);
}

Просмотреть файл

@ -1,6 +1,6 @@
/*
* Copyright © 2004 David Reveman
*
*
* 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
@ -12,11 +12,11 @@
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
* NO EVENT SHALL DAVID REVEMAN 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,
* 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.
*
@ -98,7 +98,7 @@ typedef struct _glitz_wgl_context_t {
struct _glitz_wgl_screen_info_t {
glitz_wgl_thread_info_t *thread_info;
int drawables;
glitz_drawable_format_t *formats;
glitz_int_drawable_format_t *formats;
int *format_ids;
int n_formats;
glitz_wgl_context_t **contexts;
@ -143,34 +143,34 @@ glitz_wgl_get_proc_address (const char *name,
extern glitz_wgl_context_t *__internal_linkage
glitz_wgl_context_get (glitz_wgl_screen_info_t *screen_info,
HDC dc,
glitz_drawable_format_t *format);
glitz_drawable_format_t *format);
extern void __internal_linkage
glitz_wgl_context_destroy (glitz_wgl_screen_info_t *screen_info,
glitz_wgl_context_t *context);
glitz_wgl_context_t *context);
extern void __internal_linkage
glitz_wgl_query_formats (glitz_wgl_screen_info_t *screen_info);
extern HPBUFFERARB __internal_linkage
glitz_wgl_pbuffer_create (glitz_wgl_screen_info_t *screen_info,
int pixel_format,
unsigned int width,
unsigned int height,
int pixel_format,
unsigned int width,
unsigned int height,
HDC *dcp);
extern void __internal_linkage
glitz_wgl_pbuffer_destroy (glitz_wgl_screen_info_t *screen_info,
HPBUFFERARB pbuffer,
HPBUFFERARB pbuffer,
HDC dc);
extern glitz_drawable_t *__internal_linkage
glitz_wgl_create_pbuffer (void *abstract_templ,
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height);
glitz_drawable_format_t *format,
unsigned int width,
unsigned int height);
extern void __internal_linkage
extern glitz_bool_t __internal_linkage
glitz_wgl_push_current (void *abstract_drawable,
glitz_surface_t *surface,
glitz_constraint_t constraint);
@ -184,7 +184,7 @@ glitz_wgl_make_current_read (void *abstract_surface);
extern void __internal_linkage
glitz_wgl_destroy (void *abstract_drawable);
extern void __internal_linkage
extern glitz_bool_t __internal_linkage
glitz_wgl_swap_buffers (void *abstract_drawable);
extern void __internal_linkage

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -101,11 +101,271 @@ pixman_image_createForPixels (FbPixels *pixels,
return image;
}
static CARD32 xRenderColorToCard32(pixman_color_t c)
{
return
(c.alpha >> 8 << 24) |
(c.red >> 8 << 16) |
(c.green & 0xff00) |
(c.blue >> 8);
}
static uint32_t premultiply(uint32_t x)
{
uint32_t a = x >> 24;
uint32_t t = (x & 0xff00ff) * a + 0x800080;
t = (t + ((t >> 8) & 0xff00ff)) >> 8;
t &= 0xff00ff;
x = ((x >> 8) & 0xff) * a + 0x80;
x = (x + ((x >> 8) & 0xff));
x &= 0xff00;
x |= t | (a << 24);
return x;
}
static uint32_t INTERPOLATE_PIXEL_256(uint32_t x, uint32_t a, uint32_t y, uint32_t b)
{
CARD32 t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
t >>= 8;
t &= 0xff00ff;
x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
x &= 0xff00ff00;
x |= t;
return x;
}
uint32_t
pixman_gradient_color (pixman_gradient_stop_t *stop1,
pixman_gradient_stop_t *stop2,
uint32_t x)
{
uint32_t current_color, next_color;
int dist, idist;
current_color = xRenderColorToCard32 (stop1->color);
next_color = xRenderColorToCard32 (stop2->color);
dist = (int) (256 * (x - stop1->x) / (stop2->x - stop1->x));
idist = 256 - dist;
return premultiply (INTERPOLATE_PIXEL_256 (current_color, idist,
next_color, dist));
}
static int
pixman_init_gradient_color_table (pixman_gradient_image_t *gradient,
int tableSize)
{
int begin_pos, end_pos;
xFixed incr, dpos;
int pos, current_stop;
pixman_gradient_stop_t *stops = gradient->stops;
int nstops = gradient->nstops;
if (gradient->colorTableSize < tableSize)
{
uint32_t *newColorTable;
newColorTable = realloc (gradient->colorTable,
tableSize * sizeof (uint32_t));
if (!newColorTable)
return 1;
gradient->colorTable = newColorTable;
gradient->colorTableSize = tableSize;
}
gradient->stopRange = tableSize;
/* The position where the gradient begins and ends */
begin_pos = (stops[0].x * gradient->colorTableSize) >> 16;
end_pos = (stops[nstops - 1].x * gradient->colorTableSize) >> 16;
pos = 0; /* The position in the color table. */
/* Up to first point */
while (pos <= begin_pos) {
gradient->colorTable[pos] = xRenderColorToCard32(stops[0].color);
++pos;
}
incr = (1<<16)/ gradient->colorTableSize; /* the double increment. */
dpos = incr * pos; /* The position in terms of 0-1. */
current_stop = 0; /* We always interpolate between current and current + 1. */
/* Gradient area */
while (pos < end_pos) {
gradient->colorTable[pos] =
pixman_gradient_color (&stops[current_stop],
&stops[current_stop + 1],
dpos);
++pos;
dpos += incr;
if (dpos > stops[current_stop + 1].x)
++current_stop;
}
/* After last point */
while (pos < gradient->colorTableSize) {
gradient->colorTable[pos] =
xRenderColorToCard32 (stops[nstops - 1].color);
++pos;
}
return 0;
}
static int
_pixman_init_gradient (pixman_gradient_image_t *gradient,
const pixman_gradient_stop_t *stops,
int n_stops)
{
pixman_fixed16_16_t dpos;
int i;
if (n_stops <= 0)
return 1;
dpos = -1;
for (i = 0; i < n_stops; i++)
{
if (stops[i].x < dpos || stops[i].x > (1 << 16))
return 1;
dpos = stops[i].x;
}
gradient->class = SourcePictClassUnknown;
gradient->stopRange = 0xffff;
gradient->colorTable = NULL;
gradient->colorTableSize = 0;
return 0;
}
static pixman_image_t *
_pixman_create_source_image (void)
{
pixman_image_t *image;
image = (pixman_image_t *) malloc (sizeof (pixman_image_t));
image->pDrawable = 0;
image->pixels = 0;
image->format_code = PICT_a8r8g8b8;
pixman_image_init (image);
return image;
}
pixman_image_t *
pixman_image_create_linear_gradient (const pixman_linear_gradient_t *gradient,
const pixman_gradient_stop_t *stops,
int n_stops)
{
pixman_linear_gradient_image_t *linear;
pixman_image_t *image;
if (n_stops < 2)
return 0;
image = _pixman_create_source_image ();
if (!image)
return 0;
linear = malloc (sizeof (pixman_linear_gradient_image_t) +
sizeof (pixman_gradient_stop_t) * n_stops);
if (!linear)
{
free (image);
return 0;
}
linear->stops = (pixman_gradient_stop_t *) (linear + 1);
linear->nstops = n_stops;
memcpy (linear->stops, stops, sizeof (pixman_gradient_stop_t) * n_stops);
linear->type = SourcePictTypeLinear;
linear->p1 = gradient->p1;
linear->p2 = gradient->p2;
image->pSourcePict = (pixman_source_image_t *) linear;
if (_pixman_init_gradient (&image->pSourcePict->gradient, stops, n_stops))
{
free (image);
return 0;
}
return image;
}
pixman_image_t *
pixman_image_create_radial_gradient (const pixman_radial_gradient_t *gradient,
const pixman_gradient_stop_t *stops,
int n_stops)
{
pixman_radial_gradient_image_t *radial;
pixman_image_t *image;
double x;
if (n_stops < 2)
return 0;
image = _pixman_create_source_image ();
if (!image)
return 0;
radial = malloc (sizeof (pixman_radial_gradient_image_t) +
sizeof (pixman_gradient_stop_t) * n_stops);
if (!radial)
{
free (image);
return 0;
}
radial->stops = (pixman_gradient_stop_t *) (radial + 1);
radial->nstops = n_stops;
memcpy (radial->stops, stops, sizeof (pixman_gradient_stop_t) * n_stops);
radial->type = SourcePictTypeRadial;
x = (double) gradient->inner.radius / (double) gradient->outer.radius;
radial->dx = (gradient->outer.x - gradient->inner.x);
radial->dy = (gradient->outer.y - gradient->inner.y);
radial->fx = (gradient->inner.x) - x * radial->dx;
radial->fy = (gradient->inner.y) - x * radial->dy;
radial->m = 1. / (1 + x);
radial->b = -x * radial->m;
radial->dx /= 65536.;
radial->dy /= 65536.;
radial->fx /= 65536.;
radial->fy /= 65536.;
x = gradient->outer.radius / 65536.;
radial->a = x * x - radial->dx * radial->dx - radial->dy * radial->dy;
image->pSourcePict = (pixman_source_image_t *) radial;
if (_pixman_init_gradient (&image->pSourcePict->gradient, stops, n_stops))
{
free (image);
return 0;
}
return image;
}
void
pixman_image_init (pixman_image_t *image)
{
image->refcnt = 1;
image->repeat = 0;
image->repeat = PIXMAN_REPEAT_NONE;
image->graphicsExposures = 0;
image->subWindowMode = ClipByChildren;
image->polyEdge = PolyEdgeSharp;
@ -135,16 +395,26 @@ pixman_image_init (pixman_image_t *image)
image->serialNumber = GC_CHANGE_SERIAL_BIT;
*/
image->pCompositeClip = pixman_region_create();
pixman_region_union_rect (image->pCompositeClip, image->pCompositeClip,
0, 0, image->pixels->width, image->pixels->height);
image->freeCompClip = 1;
if (image->pixels)
{
image->pCompositeClip = pixman_region_create();
pixman_region_union_rect (image->pCompositeClip, image->pCompositeClip,
0, 0, image->pixels->width,
image->pixels->height);
image->freeCompClip = 1;
image->pSourceClip = pixman_region_create ();
pixman_region_union_rect (image->pSourceClip, image->pSourceClip,
0, 0, image->pixels->width,
image->pixels->height);
image->freeSourceClip = 1;
}
else
{
image->pCompositeClip = NULL;
image->pSourceClip = NULL;
}
image->pSourceClip = pixman_region_create ();
pixman_region_union_rect (image->pSourceClip, image->pSourceClip,
0, 0, image->pixels->width, image->pixels->height);
image->freeSourceClip = 1;
image->transform = NULL;
image->filter = PIXMAN_FILTER_NEAREST;
@ -153,6 +423,8 @@ pixman_image_init (pixman_image_t *image)
image->owns_pixels = 0;
image->pSourcePict = NULL;
}
void
@ -199,8 +471,8 @@ pixman_image_set_transform (pixman_image_t *image,
}
void
pixman_image_set_repeat (pixman_image_t *image,
int repeat)
pixman_image_set_repeat (pixman_image_t *image,
pixman_repeat_t repeat)
{
if (image)
image->repeat = repeat;
@ -218,25 +490,37 @@ pixman_image_set_filter (pixman_image_t *image,
int
pixman_image_get_width (pixman_image_t *image)
{
return image->pixels->width;
if (image->pixels)
return image->pixels->width;
return 0;
}
int
pixman_image_get_height (pixman_image_t *image)
{
return image->pixels->height;
if (image->pixels)
return image->pixels->height;
return 0;
}
int
pixman_image_get_depth (pixman_image_t *image)
{
return image->pixels->depth;
if (image->pixels)
return image->pixels->depth;
return 0;
}
int
pixman_image_get_stride (pixman_image_t *image)
{
return image->pixels->stride;
if (image->pixels)
return image->pixels->stride;
return 0;
}
pixman_format_t *
@ -248,7 +532,10 @@ pixman_image_get_format (pixman_image_t *image)
FbBits *
pixman_image_get_data (pixman_image_t *image)
{
return image->pixels->data;
if (image->pixels)
return image->pixels->data;
return 0;
}
void
@ -276,6 +563,11 @@ pixman_image_destroy (pixman_image_t *image)
image->transform = NULL;
}
if (image->pSourcePict) {
free (image->pSourcePict);
image->pSourcePict = NULL;
}
free (image);
}
slim_hidden_def(pixman_image_destroy);
@ -307,6 +599,10 @@ pixman_image_set_clip_region (pixman_image_t *image,
pixman_region_copy (image->clientClip, region);
image->clientClipType = CT_REGION;
}
image->stateChanges |= CPClipMask;
if (image->pSourcePict)
return 0;
if (image->freeCompClip)
pixman_region_destroy (image->pCompositeClip);
@ -326,7 +622,6 @@ pixman_image_set_clip_region (pixman_image_t *image,
image->clipOrigin.y);
}
image->stateChanges |= CPClipMask;
return 0;
}
@ -377,7 +672,8 @@ FbClipImageSrc (pixman_region16_t *region,
/* XXX what to do with clipping from transformed pictures? */
if (image->transform)
return 1;
if (image->repeat)
/* XXX davidr hates this, wants to never use source-based clipping */
if (image->repeat != PIXMAN_REPEAT_NONE || image->pSourcePict)
{
/* XXX no source clipping */
if (image->compositeClipSource &&

Просмотреть файл

@ -54,13 +54,92 @@ typedef struct pixman_format {
} pixman_format_t;
*/
#define PICT_GRADIENT_STOPTABLE_SIZE 1024
#define SourcePictTypeSolidFill 0
#define SourcePictTypeLinear 1
#define SourcePictTypeRadial 2
#define SourcePictTypeConical 3
#define SourcePictClassUnknown 0
#define SourcePictClassHorizontal 1
#define SourcePictClassVertical 2
typedef struct _pixman_solid_fill_image {
unsigned int type;
unsigned int class;
uint32_t color;
} pixman_solid_fill_image_t;
typedef struct _pixman_gradient_image {
unsigned int type;
unsigned int class;
pixman_gradient_stop_t *stops;
int nstops;
int stopRange;
uint32_t *colorTable;
int colorTableSize;
} pixman_gradient_image_t;
typedef struct _pixman_linear_gradient_image {
unsigned int type;
unsigned int class;
pixman_gradient_stop_t *stops;
int nstops;
int stopRange;
uint32_t *colorTable;
int colorTableSize;
pixman_point_fixed_t p1;
pixman_point_fixed_t p2;
} pixman_linear_gradient_image_t;
typedef struct _pixman_radial_gradient_image {
unsigned int type;
unsigned int class;
pixman_gradient_stop_t *stops;
int nstops;
int stopRange;
uint32_t *colorTable;
int colorTableSize;
double fx;
double fy;
double dx;
double dy;
double a;
double m;
double b;
} pixman_radial_gradient_image_t;
typedef struct _pixman_conical_gradient_image {
unsigned int type;
unsigned int class;
pixman_gradient_stop_t *stops;
int nstops;
int stopRange;
uint32_t *colorTable;
int colorTableSize;
pixman_point_fixed_t center;
pixman_fixed16_16_t angle;
} pixman_conical_gradient_image_t;
typedef union _pixman_source_image {
unsigned int type;
pixman_solid_fill_image_t solidFill;
pixman_gradient_image_t gradient;
pixman_linear_gradient_image_t linear;
pixman_radial_gradient_image_t radial;
pixman_conical_gradient_image_t conical;
} pixman_source_image_t;
typedef pixman_source_image_t *SourcePictPtr;
struct pixman_image {
FbPixels *pixels;
pixman_format_t image_format;
int format_code;
int refcnt;
unsigned int repeat : 1;
unsigned int repeat : 2;
unsigned int graphicsExposures : 1;
unsigned int subWindowMode : 1;
unsigned int polyEdge : 1;
@ -70,7 +149,7 @@ struct pixman_image {
unsigned int clientClipType : 2;
unsigned int componentAlpha : 1;
unsigned int compositeClipSource : 1;
unsigned int unused : 21;
unsigned int unused : 20;
struct pixman_image *alphaMap;
FbPoint alphaOrigin;
@ -93,6 +172,8 @@ struct pixman_image {
int filter_nparams;
int owns_pixels;
pixman_source_image_t *pSourcePict;
};
#endif /* _ICIMAGE_H_ */

Просмотреть файл

@ -835,6 +835,13 @@ pixman_private pixman_image_t *
pixman_image_createForPixels (FbPixels *pixels,
pixman_format_t *format);
pixman_private uint32_t
pixman_gradient_color (pixman_gradient_stop_t *stop1,
pixman_gradient_stop_t *stop2,
uint32_t x);
#define PictureGradientColor pixman_gradient_color
/* icpixels.c */
pixman_private FbPixels *

Просмотреть файл

@ -346,7 +346,7 @@ pixman_fill_rectangles (pixman_operator_t op,
if (!src)
goto bail2;
pixman_image_set_repeat (src, 1);
pixman_image_set_repeat (src, PIXMAN_REPEAT_NORMAL);
while (nRects--)
{

Просмотреть файл

@ -54,7 +54,7 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
******************************************************************/
/* $Id: pixman.h,v 1.8 2005-10-06 04:02:08 vladimir%pobox.com Exp $ */
/* $Id: pixman.h,v 1.11 2006-02-03 04:49:30 vladimir%pobox.com Exp $ */
/* libic.h */
@ -332,6 +332,34 @@ typedef struct pixman_transform {
pixman_fixed16_16_t matrix[3][3];
} pixman_transform_t;
typedef struct pixman_color {
unsigned short red;
unsigned short green;
unsigned short blue;
unsigned short alpha;
} pixman_color_t;
typedef struct _pixman_gradient_stop {
pixman_fixed16_16_t x;
pixman_color_t color;
} pixman_gradient_stop_t;
typedef struct _pixman_circle {
pixman_fixed16_16_t x;
pixman_fixed16_16_t y;
pixman_fixed16_16_t radius;
} pixman_circle_t;
typedef struct pixman_linear_gradient {
pixman_point_fixed_t p1;
pixman_point_fixed_t p2;
} pixman_linear_gradient_t;
typedef struct pixman_radial_gradient {
pixman_circle_t inner;
pixman_circle_t outer;
} pixman_radial_gradient_t;
typedef enum {
PIXMAN_FILTER_FAST,
PIXMAN_FILTER_GOOD,
@ -348,9 +376,17 @@ int
pixman_image_set_transform (pixman_image_t *image,
pixman_transform_t *transform);
/* Don't blame me, blame XRender */
typedef enum {
PIXMAN_REPEAT_NONE,
PIXMAN_REPEAT_NORMAL,
PIXMAN_REPEAT_PAD,
PIXMAN_REPEAT_REFLECT
} pixman_repeat_t;
void
pixman_image_set_repeat (pixman_image_t *image,
int repeat);
pixman_image_set_repeat (pixman_image_t *image,
pixman_repeat_t repeat);
void
pixman_image_set_filter (pixman_image_t *image,
@ -374,15 +410,17 @@ pixman_image_get_format (pixman_image_t *image);
pixman_bits_t *
pixman_image_get_data (pixman_image_t *image);
/* iccolor.c */
pixman_image_t *
pixman_image_create_linear_gradient (const pixman_linear_gradient_t *gradient,
const pixman_gradient_stop_t *stops,
int n_stops);
/* XXX: Do we really need a struct here? Only pixman_rectangle_t uses this. */
typedef struct pixman_color {
unsigned short red;
unsigned short green;
unsigned short blue;
unsigned short alpha;
} pixman_color_t;
pixman_image_t *
pixman_image_create_radial_gradient (const pixman_radial_gradient_t *gradient,
const pixman_gradient_stop_t *stops,
int n_stops);
/* iccolor.c */
void
pixman_color_to_pixel (const pixman_format_t *format,

Просмотреть файл

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше