b=419715, upgrade cairo to 1.6 or as-close-as-possible -- imported patch cairo-upgrade-more.patch ; r=me

This commit is contained in:
vladimir@pobox.com 2008-04-06 15:14:31 -07:00
Родитель ebd87cd7e8
Коммит 7ffac589e5
20 изменённых файлов: 458 добавлений и 208 удалений

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

@ -7,8 +7,8 @@ http://www.cairographics.org/.
VERSIONS: VERSIONS:
cairo (1.6.x - 1.5.16-23-gbb76eb5) cairo (1.6.x - 1.5.18-3-g3d22902)
pixman (0.10.x - pixman-0.10.0-5-g4cde088) pixman (0.10.x - pixman-0.10.0-8-g0b207ae)
glitz 0.5.2 (cvs - 2006-01-10) glitz 0.5.2 (cvs - 2006-01-10)
***** NOTE FOR VISUAL C++ 6.0 ***** ***** NOTE FOR VISUAL C++ 6.0 *****

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

@ -34,6 +34,11 @@
* Eugeniy Meshcheryakov <eugen@debian.org> * Eugeniy Meshcheryakov <eugen@debian.org>
*/ */
/*
* Useful links:
* http://www.adobe.com/devnet/font/pdfs/5176.CFF.pdf
*/
#define _BSD_SOURCE /* for snprintf(), strdup() */ #define _BSD_SOURCE /* for snprintf(), strdup() */
#include "cairoint.h" #include "cairoint.h"
#include "cairo-scaled-font-subsets-private.h" #include "cairo-scaled-font-subsets-private.h"

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

@ -1084,6 +1084,9 @@ cairo_pattern_get_filter (cairo_pattern_t *pattern)
* Sets the mode to be used for drawing outside the area of a pattern. * 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 * See #cairo_extend_t for details on the semantics of each extend
* strategy. * strategy.
*
* The default extend mode is %CAIRO_EXTEND_NONE for surface patterns
* and %CAIRO_EXTEND_PAD for gradient patterns.
**/ **/
void void
cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend) cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend)
@ -1980,50 +1983,65 @@ _cairo_pattern_get_extents (cairo_pattern_t *pattern,
(cairo_surface_pattern_t *) pattern; (cairo_surface_pattern_t *) pattern;
cairo_surface_t *surface = surface_pattern->surface; cairo_surface_t *surface = surface_pattern->surface;
cairo_matrix_t imatrix; cairo_matrix_t imatrix;
double x, y; double x1, y1, x2, y2;
/* 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); status = _cairo_surface_get_extents (surface, &surface_extents);
if (status) if (status)
return status; return status;
x1 = surface_extents.x;
y1 = surface_extents.y;
x2 = x1 + surface_extents.width;
y2 = y1 + surface_extents.height;
/* The filter can effectively enlarge the extents of the
* pattern, so extend as necessary. Note: We aren't doing any
* backend-specific querying of filter box sizes at this time,
* (since currently no specific backends that could do custom
* filters are calling _cairo_pattern_get_extents). */
switch (pattern->filter) {
case CAIRO_FILTER_GOOD:
case CAIRO_FILTER_BEST:
case CAIRO_FILTER_BILINEAR:
x1 -= 0.5;
y1 -= 0.5;
x2 += 0.5;
y2 += 0.5;
break;
case CAIRO_FILTER_FAST:
case CAIRO_FILTER_NEAREST:
case CAIRO_FILTER_GAUSSIAN:
default:
/* Nothing to do */
break;
}
imatrix = pattern->matrix; imatrix = pattern->matrix;
status = cairo_matrix_invert (&imatrix); status = cairo_matrix_invert (&imatrix);
/* cairo_pattern_set_matrix ensures the matrix is invertible */ /* cairo_pattern_set_matrix ensures the matrix is invertible */
assert (status == CAIRO_STATUS_SUCCESS); assert (status == CAIRO_STATUS_SUCCESS);
/* XXX Use _cairo_matrix_transform_bounding_box here */ _cairo_matrix_transform_bounding_box (&imatrix,
for (sy = 0; sy <= 1; sy++) { &x1, &y1, &x2, &y2,
for (sx = 0; sx <= 1; sx++) { NULL);
x = surface_extents.x + sx * surface_extents.width;
y = surface_extents.y + sy * surface_extents.height; x1 = floor (x1);
cairo_matrix_transform_point (&imatrix, &x, &y); if (x1 < 0)
if (x < 0) x = 0; x1 = 0;
if (x > CAIRO_RECT_INT_MAX) x = CAIRO_RECT_INT_MAX; y1 = floor (y1);
if (y < 0) y = 0; if (y1 < 0)
if (y > CAIRO_RECT_INT_MAX) y = CAIRO_RECT_INT_MAX; y1 = 0;
lx = floor (x); rx = ceil (x);
ty = floor (y); by = ceil (y); x2 = ceil (x2);
if (!set) { if (x2 > CAIRO_RECT_INT_MAX)
left = lx; x2 = CAIRO_RECT_INT_MAX;
right = rx; y2 = ceil (y2);
top = ty; if (y2 > CAIRO_RECT_INT_MAX)
bottom = by; y2 = CAIRO_RECT_INT_MAX;
set = TRUE;
} else { extents->x = x1; extents->width = x2 - x1;
if (lx < left) left = lx; extents->y = y1; extents->height = y2 - y1;
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; return CAIRO_STATUS_SUCCESS;
} }

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

@ -946,7 +946,7 @@ _cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t *pdf_operators,
_cairo_output_stream_printf (word_wrap_stream, _cairo_output_stream_printf (word_wrap_stream,
"%f %f Td ", "%f %f Td ",
(glyphs[i].x - Tlm_x)/scaled_font->scale.xx, (glyphs[i].x - Tlm_x)/scaled_font->scale.xx,
(glyphs[i].y - Tlm_y)/-scaled_font->scale.yy); (glyphs[i].y - Tlm_y)/scaled_font->scale.yy);
Tlm_x = glyphs[i].x; Tlm_x = glyphs[i].x;
Tlm_y = glyphs[i].y; Tlm_y = glyphs[i].y;
Tm_x = Tlm_x; Tm_x = Tlm_x;

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

@ -211,6 +211,18 @@ _cairo_pdf_surface_update_object (cairo_pdf_surface_t *surface,
object->offset = _cairo_output_stream_get_position (surface->output); object->offset = _cairo_output_stream_get_position (surface->output);
} }
static void
cairo_pdf_surface_set_size_internal (cairo_pdf_surface_t *surface,
double width,
double height)
{
surface->width = width;
surface->height = height;
cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, height);
_cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
&surface->cairo_to_pdf);
}
static cairo_surface_t * static cairo_surface_t *
_cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
double width, double width,
@ -442,11 +454,9 @@ cairo_pdf_surface_set_size (cairo_surface_t *surface,
return; return;
} }
pdf_surface->width = width_in_points; cairo_pdf_surface_set_size_internal (pdf_surface,
pdf_surface->height = height_in_points; width_in_points,
cairo_matrix_init (&pdf_surface->cairo_to_pdf, 1, 0, 0, -1, 0, height_in_points); height_in_points);
_cairo_pdf_operators_set_cairo_to_pdf_matrix (&pdf_surface->pdf_operators,
&pdf_surface->cairo_to_pdf);
status = _cairo_paginated_surface_set_size (pdf_surface->paginated_surface, status = _cairo_paginated_surface_set_size (pdf_surface->paginated_surface,
width_in_points, width_in_points,
height_in_points); height_in_points);
@ -731,6 +741,8 @@ _cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group)
cairo_pattern_destroy (group->source); cairo_pattern_destroy (group->source);
if (group->mask) if (group->mask)
cairo_pattern_destroy (group->mask); cairo_pattern_destroy (group->mask);
if (group->glyphs)
free (group->glyphs);
if (group->scaled_font) if (group->scaled_font)
cairo_scaled_font_destroy (group->scaled_font); cairo_scaled_font_destroy (group->scaled_font);
free (group); free (group);
@ -1481,7 +1493,6 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t *resource) cairo_pdf_resource_t *resource)
{ {
double old_width, old_height; double old_width, old_height;
cairo_matrix_t old_cairo_to_pdf;
cairo_paginated_mode_t old_paginated_mode; cairo_paginated_mode_t old_paginated_mode;
cairo_clip_t *old_clip; cairo_clip_t *old_clip;
cairo_rectangle_int_t meta_extents; cairo_rectangle_int_t meta_extents;
@ -1494,20 +1505,16 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
old_width = surface->width; old_width = surface->width;
old_height = surface->height; old_height = surface->height;
old_cairo_to_pdf = surface->cairo_to_pdf;
old_paginated_mode = surface->paginated_mode; old_paginated_mode = surface->paginated_mode;
old_clip = _cairo_surface_get_clip (&surface->base); old_clip = _cairo_surface_get_clip (&surface->base);
surface->width = meta_extents.width; cairo_pdf_surface_set_size_internal (surface,
surface->height = meta_extents.height; meta_extents.width,
meta_extents.height);
/* Patterns are emitted after fallback images. The paginated mode /* Patterns are emitted after fallback images. The paginated mode
* needs to be set to _RENDER while the meta surface is replayed * needs to be set to _RENDER while the meta surface is replayed
* back to this surface. * back to this surface.
*/ */
surface->paginated_mode = CAIRO_PAGINATED_MODE_RENDER; surface->paginated_mode = CAIRO_PAGINATED_MODE_RENDER;
cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, surface->height);
_cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
&surface->cairo_to_pdf);
_cairo_pdf_group_resources_clear (&surface->resources); _cairo_pdf_group_resources_clear (&surface->resources);
status = _cairo_pdf_surface_open_content_stream (surface, TRUE); status = _cairo_pdf_surface_open_content_stream (surface, TRUE);
if (status) if (status)
@ -1535,17 +1542,14 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
status = _cairo_pdf_surface_close_content_stream (surface); status = _cairo_pdf_surface_close_content_stream (surface);
CLEANUP_GROUP: CLEANUP_GROUP:
surface->width = old_width; cairo_pdf_surface_set_size_internal (surface,
surface->height = old_height; old_width,
old_height);
surface->paginated_mode = old_paginated_mode; surface->paginated_mode = old_paginated_mode;
surface->cairo_to_pdf = old_cairo_to_pdf;
status2 = _cairo_surface_set_clip (&surface->base, old_clip); status2 = _cairo_surface_set_clip (&surface->base, old_clip);
if (status == CAIRO_STATUS_SUCCESS) if (status == CAIRO_STATUS_SUCCESS)
status = status2; status = status2;
_cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
&surface->cairo_to_pdf);
return status; return status;
} }
@ -2515,8 +2519,9 @@ _cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern
old_width = surface->width; old_width = surface->width;
old_height = surface->height; old_height = surface->height;
surface->width = pdf_pattern->width; cairo_pdf_surface_set_size_internal (surface,
surface->height = pdf_pattern->height; pdf_pattern->width,
pdf_pattern->height);
switch (pdf_pattern->pattern->type) { switch (pdf_pattern->pattern->type) {
case CAIRO_PATTERN_TYPE_SOLID: case CAIRO_PATTERN_TYPE_SOLID:
@ -2542,8 +2547,9 @@ _cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern
break; break;
} }
surface->width = old_width; cairo_pdf_surface_set_size_internal (surface,
surface->height = old_height; old_width,
old_height);
return status; return status;
} }
@ -3821,18 +3827,13 @@ _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface,
cairo_pdf_smask_group_t *group) cairo_pdf_smask_group_t *group)
{ {
double old_width, old_height; double old_width, old_height;
cairo_matrix_t old_cairo_to_pdf;
cairo_status_t status; cairo_status_t status;
old_width = surface->width; old_width = surface->width;
old_height = surface->height; old_height = surface->height;
old_cairo_to_pdf = surface->cairo_to_pdf; cairo_pdf_surface_set_size_internal (surface,
surface->width = group->width; group->width,
surface->height = group->height; group->height);
cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, surface->height);
_cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
&surface->cairo_to_pdf);
/* _mask is a special case that requires two groups - source /* _mask is a special case that requires two groups - source
* and mask as well as a smask and gstate dictionary */ * and mask as well as a smask and gstate dictionary */
if (group->operation == PDF_MASK) if (group->operation == PDF_MASK)
@ -3883,11 +3884,9 @@ _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface,
_cairo_pdf_surface_unselect_pattern (surface); _cairo_pdf_surface_unselect_pattern (surface);
status = _cairo_pdf_surface_close_group (surface, NULL); status = _cairo_pdf_surface_close_group (surface, NULL);
surface->width = old_width; cairo_pdf_surface_set_size_internal (surface,
surface->height = old_height; old_width,
surface->cairo_to_pdf = old_cairo_to_pdf; old_height);
_cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
&surface->cairo_to_pdf);
return status; return status;
} }
@ -4627,7 +4626,12 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface,
group->operation = PDF_SHOW_GLYPHS; group->operation = PDF_SHOW_GLYPHS;
group->source = cairo_pattern_reference (source); group->source = cairo_pattern_reference (source);
group->source_res = pattern_res; group->source_res = pattern_res;
group->glyphs = glyphs; group->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
if (group->glyphs == NULL) {
_cairo_pdf_smask_group_destroy (group);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
memcpy (group->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
group->num_glyphs = num_glyphs; group->num_glyphs = num_glyphs;
group->scaled_font = cairo_scaled_font_reference (scaled_font); group->scaled_font = cairo_scaled_font_reference (scaled_font);
status = _cairo_pdf_surface_add_smask_group (surface, group); status = _cairo_pdf_surface_add_smask_group (surface, group);

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

@ -183,7 +183,8 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
" { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse\n" " { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse\n"
" } forall\n" " } forall\n"
"} bind def\n" "} bind def\n"
"/Td { moveto } bind def\n" "/Td { matrix translate cairo_font_matrix matrix concatmatrix dup\n"
" /cairo_font_matrix exch def cairo_font exch selectfont 0 0 moveto } bind def\n"
"/Tm { 6 array astore dup /cairo_font_matrix exch def\n" "/Tm { 6 array astore dup /cairo_font_matrix exch def\n"
" cairo_font exch selectfont 0 0 moveto } bind def\n" " cairo_font exch selectfont 0 0 moveto } bind def\n"
"/g { setgray } bind def\n" "/g { setgray } bind def\n"

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

@ -339,6 +339,7 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
scaled_font_glyph_index, scaled_font_glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS, CAIRO_SCALED_GLYPH_INFO_METRICS,
&scaled_glyph); &scaled_glyph);
assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
if (status) if (status)
return status; return status;
@ -544,11 +545,21 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
} }
/* Glyph not found. Determine whether the glyph is outline or /* Glyph not found. Determine whether the glyph is outline or
* bitmap and add to the appropriate subset */ * bitmap and add to the appropriate subset.
*
* glyph_index 0 (the .notdef glyph) is a special case. Some fonts
* will return CAIRO_INT_STATUS_UNSUPPORTED when doing a
* _scaled_glyph_lookup(_GLYPH_INFO_PATH). Type1-fallback creates
* empty glyphs in this case so we can put the glyph in a unscaled
* subset. */
if (scaled_font_glyph_index == 0) {
status = CAIRO_STATUS_SUCCESS;
} else {
status = _cairo_scaled_glyph_lookup (scaled_font, status = _cairo_scaled_glyph_lookup (scaled_font,
scaled_font_glyph_index, scaled_font_glyph_index,
CAIRO_SCALED_GLYPH_INFO_PATH, CAIRO_SCALED_GLYPH_INFO_PATH,
&scaled_glyph); &scaled_glyph);
}
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
return status; return status;

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

@ -887,6 +887,9 @@ slim_hidden_def (cairo_surface_get_device_offset);
* there is currently no way to have more than one fallback resolution * there is currently no way to have more than one fallback resolution
* in effect on a single page. * in effect on a single page.
* *
* The default fallback resoultion is 300 pixels per inch in both
* dimensions.
*
* Since: 1.2 * Since: 1.2
**/ **/
void void

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

@ -34,6 +34,12 @@
* Adrian Johnson <ajohnson@redneon.com> * Adrian Johnson <ajohnson@redneon.com>
*/ */
/*
* Useful links:
* http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6.html
* http://www.microsoft.com/typography/specs/default.htm
*/
#define _BSD_SOURCE /* for snprintf(), strdup() */ #define _BSD_SOURCE /* for snprintf(), strdup() */
#include "cairoint.h" #include "cairoint.h"
@ -499,26 +505,29 @@ cairo_truetype_font_remap_composite_glyph (cairo_truetype_font_t *font,
unsigned long size) unsigned long size)
{ {
tt_glyph_data_t *glyph_data; tt_glyph_data_t *glyph_data;
tt_composite_glyph_t *composite_glyph, *last_glyph; tt_composite_glyph_t *composite_glyph;
int num_args; int num_args;
int has_more_components; int has_more_components;
unsigned short flags; unsigned short flags;
unsigned short index; unsigned short index;
cairo_status_t status; cairo_status_t status;
unsigned char *end = buffer + size;
if (font->status) if (font->status)
return font->status; return font->status;
if (size < sizeof (tt_glyph_data_t)) glyph_data = (tt_glyph_data_t *) buffer;
if ((unsigned char *)(&glyph_data->data) >= end)
return CAIRO_INT_STATUS_UNSUPPORTED; return CAIRO_INT_STATUS_UNSUPPORTED;
glyph_data = (tt_glyph_data_t *) buffer;
if ((int16_t)be16_to_cpu (glyph_data->num_contours) >= 0) if ((int16_t)be16_to_cpu (glyph_data->num_contours) >= 0)
return CAIRO_STATUS_SUCCESS; return CAIRO_STATUS_SUCCESS;
composite_glyph = &glyph_data->glyph; composite_glyph = &glyph_data->glyph;
last_glyph = (tt_composite_glyph_t *) (buffer + size);
do { do {
if ((unsigned char *)(&composite_glyph->args[1]) >= end)
return CAIRO_INT_STATUS_UNSUPPORTED;
flags = be16_to_cpu (composite_glyph->flags); flags = be16_to_cpu (composite_glyph->flags);
has_more_components = flags & TT_MORE_COMPONENTS; has_more_components = flags & TT_MORE_COMPONENTS;
status = cairo_truetype_font_use_glyph (font, be16_to_cpu (composite_glyph->index), &index); status = cairo_truetype_font_use_glyph (font, be16_to_cpu (composite_glyph->index), &index);
@ -536,9 +545,6 @@ cairo_truetype_font_remap_composite_glyph (cairo_truetype_font_t *font,
else if (flags & TT_WE_HAVE_A_TWO_BY_TWO) else if (flags & TT_WE_HAVE_A_TWO_BY_TWO)
num_args += 3; num_args += 3;
composite_glyph = (tt_composite_glyph_t *) &(composite_glyph->args[num_args]); composite_glyph = (tt_composite_glyph_t *) &(composite_glyph->args[num_args]);
if (has_more_components && composite_glyph >= last_glyph)
return CAIRO_INT_STATUS_UNSUPPORTED;
} while (has_more_components); } while (has_more_components);
return CAIRO_STATUS_SUCCESS; return CAIRO_STATUS_SUCCESS;
@ -1079,7 +1085,8 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
unsigned short parent_glyph = font->scaled_font_subset->glyphs[i]; unsigned short parent_glyph = font->scaled_font_subset->glyphs[i];
status = cairo_truetype_font_use_glyph (font, parent_glyph, &parent_glyph); status = cairo_truetype_font_use_glyph (font, parent_glyph, &parent_glyph);
assert (status == CAIRO_STATUS_SUCCESS); if (status)
goto fail1;
} }
cairo_truetype_font_create_truetype_table_list (font); cairo_truetype_font_create_truetype_table_list (font);

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

@ -331,33 +331,6 @@ charstring_encrypt (cairo_array_t *data)
} }
} }
static cairo_int_status_t
create_notdef_charstring (cairo_array_t *data, cairo_charstring_type_t type)
{
cairo_status_t status;
/* We're passing constants below, so we know the 0 values will
* only use 1 byte each, and the 500 values will use 2 bytes
* each. Then 2 more for each of the commands is 10 total. */
status = _cairo_array_grow_by (data, 10);
if (status)
return status;
if (type == CAIRO_CHARSTRING_TYPE1) {
charstring_encode_integer (data, 0, type);
charstring_encode_integer (data, 0, type);
/* The width is arbitrary. */
charstring_encode_integer (data, 500, type);
charstring_encode_integer (data, 0, type);
charstring_encode_command (data, CHARSTRING_sbw);
}
charstring_encode_command (data, CHARSTRING_endchar);
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t static cairo_int_status_t
cairo_type1_font_create_charstring (cairo_type1_font_t *font, cairo_type1_font_create_charstring (cairo_type1_font_t *font,
int subset_index, int subset_index,
@ -369,6 +342,7 @@ cairo_type1_font_create_charstring (cairo_type1_font_t *font,
cairo_scaled_glyph_t *scaled_glyph; cairo_scaled_glyph_t *scaled_glyph;
t1_path_info_t path_info; t1_path_info_t path_info;
cairo_text_extents_t *metrics; cairo_text_extents_t *metrics;
cairo_bool_t emit_path = TRUE;
/* This call may return CAIRO_INT_STATUS_UNSUPPORTED for bitmap fonts. */ /* This call may return CAIRO_INT_STATUS_UNSUPPORTED for bitmap fonts. */
status = _cairo_scaled_glyph_lookup (font->type1_scaled_font, status = _cairo_scaled_glyph_lookup (font->type1_scaled_font,
@ -376,6 +350,16 @@ cairo_type1_font_create_charstring (cairo_type1_font_t *font,
CAIRO_SCALED_GLYPH_INFO_METRICS| CAIRO_SCALED_GLYPH_INFO_METRICS|
CAIRO_SCALED_GLYPH_INFO_PATH, CAIRO_SCALED_GLYPH_INFO_PATH,
&scaled_glyph); &scaled_glyph);
/* It is ok for the .notdef glyph to not have a path available. We
* just need the metrics to emit an empty glyph. */
if (glyph_index == 0 && status == CAIRO_INT_STATUS_UNSUPPORTED) {
emit_path = FALSE;
status = _cairo_scaled_glyph_lookup (font->type1_scaled_font,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
&scaled_glyph);
}
if (status) if (status)
return status; return status;
@ -411,13 +395,14 @@ cairo_type1_font_create_charstring (cairo_type1_font_t *font,
path_info.current_x = (int) scaled_glyph->metrics.x_bearing; path_info.current_x = (int) scaled_glyph->metrics.x_bearing;
path_info.current_y = (int) scaled_glyph->metrics.y_bearing; path_info.current_y = (int) scaled_glyph->metrics.y_bearing;
} else { } else {
charstring_encode_integer (data, (int) scaled_glyph->metrics.width, type); charstring_encode_integer (data, (int) scaled_glyph->metrics.x_advance, type);
path_info.current_x = 0; path_info.current_x = 0;
path_info.current_y = 0; path_info.current_y = 0;
} }
path_info.data = data; path_info.data = data;
path_info.type = type; path_info.type = type;
if (emit_path) {
status = _cairo_path_fixed_interpret (scaled_glyph->path, status = _cairo_path_fixed_interpret (scaled_glyph->path,
CAIRO_DIRECTION_FORWARD, CAIRO_DIRECTION_FORWARD,
_charstring_move_to, _charstring_move_to,
@ -427,6 +412,7 @@ cairo_type1_font_create_charstring (cairo_type1_font_t *font,
&path_info); &path_info);
if (status) if (status)
return status; return status;
}
status = _cairo_array_grow_by (data, 1); status = _cairo_array_grow_by (data, 1);
if (status) if (status)
@ -455,7 +441,7 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
"2 index /CharStrings %d dict dup begin\n", "2 index /CharStrings %d dict dup begin\n",
font->scaled_font_subset->num_glyphs + 1); font->scaled_font_subset->num_glyphs + 1);
for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) { for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
_cairo_array_truncate (&data, 0); _cairo_array_truncate (&data, 0);
/* four "random" bytes required by encryption algorithm */ /* four "random" bytes required by encryption algorithm */
status = _cairo_array_append_multiple (&data, zeros, 4); status = _cairo_array_append_multiple (&data, zeros, 4);
@ -473,6 +459,8 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
_cairo_output_stream_printf (encrypted_output, "/%s %d RD ", _cairo_output_stream_printf (encrypted_output, "/%s %d RD ",
font->scaled_font_subset->glyph_names[i], font->scaled_font_subset->glyph_names[i],
length); length);
} else if (i == 0) {
_cairo_output_stream_printf (encrypted_output, "/.notdef %d RD ", length);
} else { } else {
_cairo_output_stream_printf (encrypted_output, "/g%d %d RD ", i, length); _cairo_output_stream_printf (encrypted_output, "/g%d %d RD ", i, length);
} }
@ -482,24 +470,6 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
_cairo_output_stream_printf (encrypted_output, " ND\n"); _cairo_output_stream_printf (encrypted_output, " ND\n");
} }
/* All type 1 fonts must have a /.notdef charstring */
_cairo_array_truncate (&data, 0);
/* four "random" bytes required by encryption algorithm */
status = _cairo_array_append_multiple (&data, zeros, 4);
if (status)
goto fail;
status = create_notdef_charstring (&data, CAIRO_CHARSTRING_TYPE1);
if (status)
goto fail;
charstring_encrypt (&data);
length = _cairo_array_num_elements (&data);
_cairo_output_stream_printf (encrypted_output, "/.notdef %d RD ", length);
_cairo_output_stream_write (encrypted_output,
_cairo_array_index (&data, 0),
length);
_cairo_output_stream_printf (encrypted_output, " ND\n");
fail: fail:
_cairo_array_fini (&data); _cairo_array_fini (&data);
return status; return status;
@ -856,14 +826,10 @@ _cairo_type2_charstrings_init (cairo_type2_charstrings_t *type2_subset,
if (status) if (status)
goto fail2; goto fail2;
if (i == 0) {
status = create_notdef_charstring (&charstring, CAIRO_CHARSTRING_TYPE2);
} else {
status = cairo_type1_font_create_charstring (font, i, status = cairo_type1_font_create_charstring (font, i,
font->scaled_font_subset->glyphs[i], font->scaled_font_subset->glyphs[i],
CAIRO_CHARSTRING_TYPE2, CAIRO_CHARSTRING_TYPE2,
&charstring); &charstring);
}
if (status) if (status)
goto fail2; goto fail2;

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

@ -33,6 +33,11 @@
* Kristian Høgsberg <krh@redhat.com> * Kristian Høgsberg <krh@redhat.com>
*/ */
/*
* Useful links:
* http://partners.adobe.com/public/developer/en/font/T1_SPEC.PDF
*/
#define _BSD_SOURCE /* for snprintf(), strdup() */ #define _BSD_SOURCE /* for snprintf(), strdup() */
#include "cairoint.h" #include "cairoint.h"
#include "cairo-type1-private.h" #include "cairo-type1-private.h"

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

@ -300,6 +300,17 @@ _cairo_xlib_display_get (Display *dpy)
* back up to 6.7 or 6.8. */ * back up to 6.7 or 6.8. */
if (VendorRelease (dpy) >= 60700000 && VendorRelease (dpy) <= 60802000) if (VendorRelease (dpy) >= 60700000 && VendorRelease (dpy) <= 60802000)
display->buggy_repeat = TRUE; display->buggy_repeat = TRUE;
/* But even the new modular server has bugs, (bad enough to
* crash the X server), that it so happens we can avoid with
* the exact same buggy_repeat workaround. We've verified that
* this bug exists as least as late as version 1.3.0.0, (which
* is in Fedora 8), and is gone again in version 1.4.99.901
* (from a Fedora 9 Beta). Versions between those are still
* unknown, but until we learn more, we'll assume that any 1.3
* version is buggy. */
if (VendorRelease (dpy) < 10400000)
display->buggy_repeat = TRUE;
} else if (strstr (ServerVendor (dpy), "XFree86") != NULL) { } else if (strstr (ServerVendor (dpy), "XFree86") != NULL) {
if (VendorRelease (dpy) <= 40500000) if (VendorRelease (dpy) <= 40500000)
display->buggy_repeat = TRUE; display->buggy_repeat = TRUE;

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

@ -2925,6 +2925,20 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
already_had_glyph_surface = TRUE; already_had_glyph_surface = TRUE;
} }
/* XXX XRenderAddGlyph does not handle a glyph surface larger than the
* maximum XRequest size.
*/
{
/* pessimistic length estimation in case we need to change formats */
int len = 4 * glyph_surface->width * glyph_surface->height;
int max_request_size = XMaxRequestSize (dpy) -
sz_xRenderAddGlyphsReq -
sz_xGlyphInfo -
4;
if (len >= max_request_size)
return CAIRO_INT_STATUS_UNSUPPORTED;
}
if (scaled_font->surface_private == NULL) { if (scaled_font->surface_private == NULL) {
status = _cairo_xlib_surface_font_init (dpy, scaled_font); status = _cairo_xlib_surface_font_init (dpy, scaled_font);
if (status) if (status)

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

@ -634,9 +634,7 @@ slim_hidden_def(cairo_pop_group_to_source);
* operations. See #cairo_operator_t for details on the semantics of * operations. See #cairo_operator_t for details on the semantics of
* each available compositing operator. * each available compositing operator.
* *
* XXX: I'd also like to direct the reader's attention to some * The default operator is %CAIRO_OPERATOR_OVER.
* (not-yet-written) section on cairo's imaging model. How would I do
* that if such a section existed? (cworth).
**/ **/
void void
cairo_set_operator (cairo_t *cr, cairo_operator_t op) cairo_set_operator (cairo_t *cr, cairo_operator_t op)
@ -666,6 +664,9 @@ slim_hidden_def (cairo_set_operator);
* The color components are floating point numbers in the range 0 to * The color components are floating point numbers in the range 0 to
* 1. If the values passed in are outside that range, they will be * 1. If the values passed in are outside that range, they will be
* clamped. * clamped.
*
* The default source pattern is opaque black, (that is, it is
* equivalent to cairo_set_source_rgb (cr, 0.0, 0.0, 0.0)).
**/ **/
void void
cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue) cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue)
@ -698,6 +699,9 @@ cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue)
* The color and alpha components are floating point numbers in the * The color and alpha components are floating point numbers in the
* range 0 to 1. If the values passed in are outside that range, they * range 0 to 1. If the values passed in are outside that range, they
* will be clamped. * will be clamped.
*
* The default source pattern is opaque black, (that is, it is
* equivalent to cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0)).
**/ **/
void void
cairo_set_source_rgba (cairo_t *cr, cairo_set_source_rgba (cairo_t *cr,
@ -780,9 +784,9 @@ slim_hidden_def (cairo_set_source_surface);
* that further modifications of the current transformation matrix * that further modifications of the current transformation matrix
* will not affect the source pattern. See cairo_pattern_set_matrix(). * will not affect the source pattern. See cairo_pattern_set_matrix().
* *
* XXX: I'd also like to direct the reader's attention to some * The default source pattern is a solid pattern that is opaque black,
* (not-yet-written) section on cairo's imaging model. How would I do * (that is, it is equivalent to cairo_set_source_rgb (cr, 0.0, 0.0,
* that if such a section existed? (cworth). * 0.0)).
**/ **/
void void
cairo_set_source (cairo_t *cr, cairo_pattern_t *source) cairo_set_source (cairo_t *cr, cairo_pattern_t *source)
@ -891,6 +895,8 @@ cairo_set_antialias (cairo_t *cr, cairo_antialias_t antialias)
* (potentially self-intersecting) path. The current fill rule affects * (potentially self-intersecting) path. The current fill rule affects
* both cairo_fill() and cairo_clip(). See #cairo_fill_rule_t for details * both cairo_fill() and cairo_clip(). See #cairo_fill_rule_t for details
* on the semantics of each available fill rule. * on the semantics of each available fill rule.
*
* The default fill rule is %CAIRO_FILL_RULE_WINDING.
**/ **/
void void
cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule) cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule)
@ -959,6 +965,8 @@ cairo_set_line_width (cairo_t *cr, double width)
* examined by cairo_stroke(), cairo_stroke_extents(), and * examined by cairo_stroke(), cairo_stroke_extents(), and
* cairo_stroke_to_path(), but does not have any effect during path * cairo_stroke_to_path(), but does not have any effect during path
* construction. * construction.
*
* The default line cap style is %CAIRO_LINE_CAP_BUTT.
**/ **/
void void
cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap) cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap)
@ -976,7 +984,7 @@ cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap)
/** /**
* cairo_set_line_join: * cairo_set_line_join:
* @cr: a cairo context * @cr: a cairo context
* @line_join: a line joint style * @line_join: a line join style
* *
* Sets the current line join style within the cairo context. See * Sets the current line join style within the cairo context. See
* #cairo_line_join_t for details about how the available line join * #cairo_line_join_t for details about how the available line join
@ -986,6 +994,8 @@ cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap)
* examined by cairo_stroke(), cairo_stroke_extents(), and * examined by cairo_stroke(), cairo_stroke_extents(), and
* cairo_stroke_to_path(), but does not have any effect during path * cairo_stroke_to_path(), but does not have any effect during path
* construction. * construction.
*
* The default line join style is %CAIRO_LINE_JOIN_MITER.
**/ **/
void void
cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join) cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join)
@ -1116,6 +1126,15 @@ cairo_get_dash (cairo_t *cr,
* examined by cairo_stroke(), cairo_stroke_extents(), and * examined by cairo_stroke(), cairo_stroke_extents(), and
* cairo_stroke_to_path(), but does not have any effect during path * cairo_stroke_to_path(), but does not have any effect during path
* construction. * construction.
*
* The default miter limit value is 10.0, which will convert joins
* with interior angles less than 11 degrees to bevels instead of
* miters. For reference, a miter limit of 2.0 makes the miter cutoff
* at 60 degrees, and a miter limit of 1.414 makes the cutoff at 90
* degrees.
*
* A miter limit for a desired angle can be computed as: miter limit =
* 1/sin(angle/2)
**/ **/
void void
cairo_set_miter_limit (cairo_t *cr, double limit) cairo_set_miter_limit (cairo_t *cr, double limit)
@ -2571,13 +2590,38 @@ cairo_copy_clip_rectangle_list (cairo_t *cr)
* @slant: the slant for the font * @slant: the slant for the font
* @weight: the weight for the font * @weight: the weight for the font
* *
* Note: The cairo_select_font_face() function call is part of what
* the cairo designers call the "toy" text API. It is convenient for
* short demos and simple programs, but it is not expected to be
* adequate for serious text-using applications.
*
* Selects a family and style of font from a simplified description as * Selects a family and style of font from a simplified description as
* a family name, slant and weight. This function is meant to be used * a family name, slant and weight. Cairo provides no operation to
* only for applications with simple font needs: Cairo doesn't provide * list available family names on the system (this is a "toy",
* for operations such as listing all available fonts on the system, * remember"), but the standard CSS2 generic family names, ("serif",
* and it is expected that most applications will need to use a more * "sans-serif", "cursive", "fantasy", "monospace"), are likely to
* comprehensive font handling and text layout library in addition to * work as expected.
* cairo. *
* For "real" font selection, see the font-backend-specific
* font_face_create functions for the font backend you are using. (For
* example, if you are using the freetype-based cairo-ft font backend,
* see cairo_ft_font_face_create_for_ft_face() or
* cairo_ft_font_face_create_for_pattern().) The resulting font face
* could then be used with cairo_scaled_font_create() and
* cairo_set_scaled_font().
*
* Similarly, when using the "real" font support, you can call
* directly into the underlying font system, (such as fontconfig or
* freetype), for operations such as listing available fonts, etc.
*
* It is expected that most applications will need to use a more
* comprehensive font handling and text layout library, (for example,
* pango), in conjunction with cairo.
*
* If text is drawn without a call to cairo_select_font_face(), (nor
* cairo_set_font_face() nor cairo_set_scaled_font()), the default
* family is "sans", slant is %CAIRO_FONT_SLANT_NORMAL, and weight is
* %CAIRO_FONT_WEIGHT_NORMAL.
**/ **/
void void
cairo_select_font_face (cairo_t *cr, cairo_select_font_face (cairo_t *cr,
@ -2692,6 +2736,10 @@ cairo_get_font_face (cairo_t *cr)
* cairo_set_font_matrix(). This results in a font size of @size user space * cairo_set_font_matrix(). This results in a font size of @size user space
* units. (More precisely, this matrix will result in the font's * units. (More precisely, this matrix will result in the font's
* em-square being a @size by @size square in user space.) * em-square being a @size by @size square in user space.)
*
* If text is drawn without a call to cairo_set_font_size(), (nor
* cairo_set_font_matrix() nor cairo_set_scaled_font()), the default
* font size is 10.0.
**/ **/
void void
cairo_set_font_size (cairo_t *cr, double size) cairo_set_font_size (cairo_t *cr, double size)

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

@ -373,6 +373,8 @@ cairo_pop_group_to_source (cairo_t *cr);
* #cairo_operator_t is used to set the compositing operator for all cairo * #cairo_operator_t is used to set the compositing operator for all cairo
* drawing operations. * drawing operations.
* *
* The default operator is %CAIRO_OPERATOR_OVER.
*
* The operators marked as <firstterm>unbounded</firstterm> modify their * The operators marked as <firstterm>unbounded</firstterm> modify their
* destination even outside of the mask layer (that is, their effect is not * destination even outside of the mask layer (that is, their effect is not
* bound by the mask layer). However, their effect can still be limited by * bound by the mask layer). However, their effect can still be limited by
@ -473,6 +475,8 @@ cairo_set_antialias (cairo_t *cr, cairo_antialias_t antialias);
* (Note that filling is not actually implemented in this way. This * (Note that filling is not actually implemented in this way. This
* is just a description of the rule that is applied.) * is just a description of the rule that is applied.)
* *
* The default fill rule is %CAIRO_FILL_RULE_WINDING.
*
* New entries may be added in future versions. * New entries may be added in future versions.
**/ **/
typedef enum _cairo_fill_rule { typedef enum _cairo_fill_rule {
@ -492,7 +496,9 @@ cairo_set_line_width (cairo_t *cr, double width);
* @CAIRO_LINE_CAP_ROUND: use a round ending, the center of the circle is the end point * @CAIRO_LINE_CAP_ROUND: use a round ending, the center of the circle is the end point
* @CAIRO_LINE_CAP_SQUARE: use squared ending, the center of the square is the end point * @CAIRO_LINE_CAP_SQUARE: use squared ending, the center of the square is the end point
* *
* Specifies how to render the endpoint of a line when stroking. * Specifies how to render the endpoints of the path when stroking.
*
* The default line cap style is %CAIRO_LINE_CAP_BUTT.
**/ **/
typedef enum _cairo_line_cap { typedef enum _cairo_line_cap {
CAIRO_LINE_CAP_BUTT, CAIRO_LINE_CAP_BUTT,
@ -513,6 +519,8 @@ cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap);
* the line width from the joint point * the line width from the joint point
* *
* Specifies how to render the junction of two lines when stroking. * Specifies how to render the junction of two lines when stroking.
*
* The default line join style is %CAIRO_LINE_JOIN_MITER.
**/ **/
typedef enum _cairo_line_join { typedef enum _cairo_line_join {
CAIRO_LINE_JOIN_MITER, CAIRO_LINE_JOIN_MITER,
@ -1789,13 +1797,18 @@ cairo_pattern_get_matrix (cairo_pattern_t *pattern,
* are fully transparent * are fully transparent
* @CAIRO_EXTEND_REPEAT: the pattern is tiled by repeating * @CAIRO_EXTEND_REPEAT: the pattern is tiled by repeating
* @CAIRO_EXTEND_REFLECT: the pattern is tiled by reflecting * @CAIRO_EXTEND_REFLECT: the pattern is tiled by reflecting
* at the edges (not implemented for surface patterns currently) * at the edges (Implemented for surface patterns since 1.6)
* @CAIRO_EXTEND_PAD: pixels outside of the pattern copy * @CAIRO_EXTEND_PAD: pixels outside of the pattern copy
* the closest pixel from the source (Since 1.2; not implemented * the closest pixel from the source (Since 1.2; but only
* for surface patterns currently) * implemented for surface patterns since 1.6)
* *
* #cairo_extend_t is used to describe how the area outside * #cairo_extend_t is used to describe how pattern color/alpha will be
* of a pattern will be drawn. * determined for areas "outside" the pattern's natural area, (for
* example, outside the surface bounds or outside the gradient
* geometry).
*
* The default extend mode is %CAIRO_EXTEND_NONE for surface patterns
* and %CAIRO_EXTEND_PAD for gradient patterns.
* *
* New entries may be added in future versions. * New entries may be added in future versions.
**/ **/

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

@ -768,7 +768,7 @@ struct _cairo_color {
#define CAIRO_EXTEND_SURFACE_DEFAULT CAIRO_EXTEND_NONE #define CAIRO_EXTEND_SURFACE_DEFAULT CAIRO_EXTEND_NONE
#define CAIRO_EXTEND_GRADIENT_DEFAULT CAIRO_EXTEND_PAD #define CAIRO_EXTEND_GRADIENT_DEFAULT CAIRO_EXTEND_PAD
#define CAIRO_FILTER_DEFAULT CAIRO_FILTER_BEST #define CAIRO_FILTER_DEFAULT CAIRO_FILTER_GOOD
struct _cairo_pattern { struct _cairo_pattern {
cairo_pattern_type_t type; cairo_pattern_type_t type;

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

@ -13,7 +13,6 @@
* this difference will have two versions using the same convention. * this difference will have two versions using the same convention.
*/ */
/* /*
* Combine src and mask * Combine src and mask
*/ */
@ -1210,6 +1209,7 @@ static CombineFuncU pixman_fbCombineFuncU[] = {
fbCombineConjointAtopU, fbCombineConjointAtopU,
fbCombineConjointAtopReverseU, fbCombineConjointAtopReverseU,
fbCombineConjointXorU, fbCombineConjointXorU,
NULL /* Noop */
}; };
static CombineFuncC pixman_fbCombineFuncC[] = { static CombineFuncC pixman_fbCombineFuncC[] = {
@ -1257,6 +1257,7 @@ static CombineFuncC pixman_fbCombineFuncC[] = {
fbCombineConjointAtopC, fbCombineConjointAtopC,
fbCombineConjointAtopReverseC, fbCombineConjointAtopReverseC,
fbCombineConjointXorC, fbCombineConjointXorC,
NULL /* Noop */
}; };
FbComposeFunctions pixman_composeFunctions = { FbComposeFunctions pixman_composeFunctions = {

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

@ -717,3 +717,87 @@ pixman_image_fill_rectangles (pixman_op_t op,
return TRUE; return TRUE;
} }
pixman_bool_t
pixman_image_can_get_solid (pixman_image_t *image)
{
if (image->type == SOLID)
return TRUE;
if (image->type != BITS ||
image->bits.width != 1 ||
image->bits.height != 1)
{
return FALSE;
}
if (image->common.repeat != PIXMAN_REPEAT_NORMAL)
return FALSE;
switch (image->bits.format)
{
case PIXMAN_a8r8g8b8:
case PIXMAN_x8r8g8b8:
case PIXMAN_a8b8g8r8:
case PIXMAN_x8b8g8r8:
case PIXMAN_r8g8b8:
case PIXMAN_b8g8r8:
case PIXMAN_r5g6b5:
case PIXMAN_b5g6r5:
return TRUE;
default:
return FALSE;
}
}
pixman_bool_t
pixman_image_is_opaque(pixman_image_t *image)
{
int i = 0;
int gradientNumberOfColors = 0;
if(image->common.alpha_map)
return FALSE;
switch(image->type)
{
case BITS:
if(PIXMAN_FORMAT_A(image->bits.format))
return FALSE;
break;
case LINEAR:
case CONICAL:
case RADIAL:
gradientNumberOfColors = image->gradient.n_stops;
i=0;
while(i<gradientNumberOfColors)
{
if(image->gradient.stops[i].color.alpha != 0xffff)
return FALSE;
i++;
}
break;
case SOLID:
if(Alpha(image->solid.color) != 0xff)
return FALSE;
break;
}
/* Convolution filters can introduce translucency if the sum of the weights
is lower than 1. */
if (image->common.filter == PIXMAN_FILTER_CONVOLUTION)
return FALSE;
if (image->common.repeat == PIXMAN_REPEAT_NONE)
{
if (image->common.filter != PIXMAN_FILTER_NEAREST)
return FALSE;
if (image->common.transform)
return FALSE;
}
return TRUE;
}

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

@ -1261,38 +1261,6 @@ pixman_walk_composite_region (pixman_op_t op,
pixman_region_fini (&reg); pixman_region_fini (&reg);
} }
static pixman_bool_t
can_get_solid (pixman_image_t *image)
{
if (image->type == SOLID)
return TRUE;
if (image->type != BITS ||
image->bits.width != 1 ||
image->bits.height != 1)
{
return FALSE;
}
if (image->common.repeat != PIXMAN_REPEAT_NORMAL)
return FALSE;
switch (image->bits.format)
{
case PIXMAN_a8r8g8b8:
case PIXMAN_x8r8g8b8:
case PIXMAN_a8b8g8r8:
case PIXMAN_x8b8g8r8:
case PIXMAN_r8g8b8:
case PIXMAN_b8g8r8:
case PIXMAN_r5g6b5:
case PIXMAN_b5g6r5:
return TRUE;
default:
return FALSE;
}
}
#define SCANLINE_BUFFER_LENGTH 2048 #define SCANLINE_BUFFER_LENGTH 2048
static void static void
@ -1554,7 +1522,7 @@ get_fast_path (const FastPathInfo *fast_paths,
if (info->op != op) if (info->op != op)
continue; continue;
if ((info->src_format == PIXMAN_solid && can_get_solid (pSrc)) || if ((info->src_format == PIXMAN_solid && pixman_image_can_get_solid (pSrc)) ||
(pSrc->type == BITS && info->src_format == pSrc->bits.format)) (pSrc->type == BITS && info->src_format == pSrc->bits.format))
{ {
valid_src = TRUE; valid_src = TRUE;
@ -1596,6 +1564,82 @@ get_fast_path (const FastPathInfo *fast_paths,
return NULL; return NULL;
} }
/*
* Operator optimizations based on source or destination opacity
*/
typedef struct
{
pixman_op_t op;
pixman_op_t opSrcDstOpaque;
pixman_op_t opSrcOpaque;
pixman_op_t opDstOpaque;
} OptimizedOperatorInfo;
static const OptimizedOperatorInfo optimized_operators[] =
{
/* Input Operator SRC&DST Opaque SRC Opaque DST Opaque */
{ PIXMAN_OP_OVER, PIXMAN_OP_SRC, PIXMAN_OP_SRC, PIXMAN_OP_OVER },
{ PIXMAN_OP_OVER_REVERSE, PIXMAN_OP_DST, PIXMAN_OP_OVER_REVERSE, PIXMAN_OP_DST },
{ PIXMAN_OP_IN, PIXMAN_OP_SRC, PIXMAN_OP_IN, PIXMAN_OP_SRC },
{ PIXMAN_OP_IN_REVERSE, PIXMAN_OP_DST, PIXMAN_OP_DST, PIXMAN_OP_IN_REVERSE },
{ PIXMAN_OP_OUT, PIXMAN_OP_CLEAR, PIXMAN_OP_OUT, PIXMAN_OP_CLEAR },
{ PIXMAN_OP_OUT_REVERSE, PIXMAN_OP_CLEAR, PIXMAN_OP_CLEAR, PIXMAN_OP_OUT_REVERSE },
{ PIXMAN_OP_ATOP, PIXMAN_OP_SRC, PIXMAN_OP_IN, PIXMAN_OP_OVER },
{ PIXMAN_OP_ATOP_REVERSE, PIXMAN_OP_DST, PIXMAN_OP_OVER_REVERSE, PIXMAN_OP_IN_REVERSE },
{ PIXMAN_OP_XOR, PIXMAN_OP_CLEAR, PIXMAN_OP_OUT, PIXMAN_OP_OUT_REVERSE },
{ PIXMAN_OP_SATURATE, PIXMAN_OP_DST, PIXMAN_OP_OVER_REVERSE, PIXMAN_OP_DST },
{ PIXMAN_OP_NONE }
};
/*
* Check if the current operator could be optimized
*/
static const OptimizedOperatorInfo*
pixman_operator_can_be_optimized(pixman_op_t op)
{
const OptimizedOperatorInfo *info;
for (info = optimized_operators; info->op != PIXMAN_OP_NONE; info++)
{
if(info->op == op)
return info;
}
return NULL;
}
/*
* Optimize the current operator based on opacity of source or destination
* The output operator should be mathematically equivalent to the source.
*/
static pixman_op_t
pixman_optimize_operator(pixman_op_t op, pixman_image_t *pSrc, pixman_image_t *pMask, pixman_image_t *pDst )
{
pixman_bool_t is_source_opaque;
pixman_bool_t is_dest_opaque;
const OptimizedOperatorInfo *info = pixman_operator_can_be_optimized(op);
if(!info || pMask)
return op;
is_source_opaque = pixman_image_is_opaque(pSrc);
is_dest_opaque = pixman_image_is_opaque(pDst);
if(is_source_opaque == FALSE && is_dest_opaque == FALSE)
return op;
if(is_source_opaque && is_dest_opaque)
return info->opSrcDstOpaque;
else if(is_source_opaque)
return info->opSrcOpaque;
else if(is_dest_opaque)
return info->opDstOpaque;
return op;
}
void void
pixman_image_composite (pixman_op_t op, pixman_image_composite (pixman_op_t op,
pixman_image_t * pSrc, pixman_image_t * pSrc,
@ -1652,7 +1696,15 @@ pixman_image_composite (pixman_op_t op,
} }
} }
if ((pSrc->type == BITS || can_get_solid (pSrc)) && (!pMask || pMask->type == BITS) /*
* Check if we can replace our operator by a simpler one if the src or dest are opaque
* The output operator should be mathematically equivalent to the source.
*/
op = pixman_optimize_operator(op, pSrc, pMask, pDst);
if(op == PIXMAN_OP_DST)
return;
if ((pSrc->type == BITS || pixman_image_can_get_solid (pSrc)) && (!pMask || pMask->type == BITS)
&& !srcTransform && !maskTransform && !srcTransform && !maskTransform
&& !maskAlphaMap && !srcAlphaMap && !dstAlphaMap && !maskAlphaMap && !srcAlphaMap && !dstAlphaMap
&& (pSrc->common.filter != PIXMAN_FILTER_CONVOLUTION) && (pSrc->common.filter != PIXMAN_FILTER_CONVOLUTION)
@ -1753,6 +1805,7 @@ pixman_image_composite (pixman_op_t op,
} }
#ifdef USE_MMX #ifdef USE_MMX
/* The CPU detection code needs to be in a file not compiled with /* The CPU detection code needs to be in a file not compiled with
* "-mmmx -msse", as gcc would generate CMOV instructions otherwise * "-mmmx -msse", as gcc would generate CMOV instructions otherwise

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

@ -839,6 +839,12 @@ pixman_rasterize_edges_accessors (pixman_image_t *image,
pixman_fixed_t t, pixman_fixed_t t,
pixman_fixed_t b); pixman_fixed_t b);
pixman_bool_t
pixman_image_is_opaque(pixman_image_t *image);
pixman_bool_t
pixman_image_can_get_solid (pixman_image_t *image);
#ifdef PIXMAN_TIMING #ifdef PIXMAN_TIMING