Fix math library detection to use autotools helper

Remove cache memory usage assertions as single objects can be larger than the cache size
Decompose font matrix transformations into a couple of helper routines. Return all metrics in font space.
Eliminate compiler warning
Expect glyph metrics to be in font space. Compute text extents by fetching one glyph metric at a time, transforming to user space and computing the overall bounding box.
use 'sincos' where available. Scale factors now ensure the non-scale transform is area preserving. Scale factors requires another parameter to mark the fixed axis.
Change license to LGPL Mark int32x32_64_mul as broken (which it still is)
Ensure each glyph is located as close to the specified position as possible
interface change to _cairo_matrix_compute_scale_factors
This commit is contained in:
Keith Packard 2005-01-11 10:03:01 +00:00
parent dc0d812f6c
commit ad2225c6f4
22 changed files with 735 additions and 291 deletions

View file

@ -1,3 +1,51 @@
2005-01-11 Keith Packard <keithp@keithp.com>
* cairo.pc.in:
* configure.in:
* src/Makefile.am:
Fix math library detection to use autotools helper
* src/cairo_cache.c: (_cache_sane_state), (_cairo_cache_lookup):
Remove cache memory usage assertions as single objects can
be larger than the cache size
* src/cairo_ft_font.c: (_cairo_ft_font_compute_transform),
(_cairo_ft_font_install_transform), (_install_font_scale),
(_cairo_ft_font_font_extents), (_cairo_ft_font_glyph_extents),
(_cairo_ft_font_create_glyph):
Decompose font matrix transformations into a couple of
helper routines.
Return all metrics in font space.
* src/cairo_glitz_surface.c: (_glitz_format):
Eliminate compiler warning
* src/cairo_gstate.c: (_cairo_gstate_current_font_extents),
(_cairo_gstate_text_to_glyphs), (_cairo_gstate_glyph_extents):
Expect glyph metrics to be in font space. Compute text extents
by fetching one glyph metric at a time, transforming to user
space and computing the overall bounding box.
* src/cairo_matrix.c: (_cairo_matrix_set_rotate),
(_cairo_matrix_compute_scale_factors):
use 'sincos' where available.
Scale factors now ensure the non-scale transform is area preserving.
Scale factors requires another parameter to mark the fixed axis.
* src/cairo_wideint.c:
* src/cairo_wideint.h:
Change license to LGPL
Mark int32x32_64_mul as broken (which it still is)
* src/cairo_xlib_surface.c: (_cairo_xlib_surface_show_glyphs32),
(_cairo_xlib_surface_show_glyphs16),
(_cairo_xlib_surface_show_glyphs8):
Ensure each glyph is located as close to the specified position
as possible
* src/cairoint.h:
interface change to _cairo_matrix_compute_scale_factors
2005-01-07 Kristian Høgsberg <krh@redhat.com>
* configure.in: Add -lz to CAIRO_LIBS when compiling the PDF

View file

@ -8,6 +8,6 @@ Description: Multi-platform 2D graphics library
Version: @VERSION@
Requires: fontconfig libpixman @XRENDER_REQUIRES@ @PNG_REQUIRES@ @GLITZ_REQUIRES@
Libs: -L${libdir} -lcairo -lm
Cflags: -I${includedir} @FREETYPE_CFLAGS@
Libs: -L${libdir} -lcairo
Cflags: -I${includedir}

View file

@ -34,6 +34,12 @@ AC_PROG_CPP
AM_PROG_LIBTOOL
AC_STDC_HEADERS
AC_CHECK_LIBM
LIBS="$LIBS $LIBM"
AC_CHECK_FUNCS(sincos)
dnl ===========================================================================
AC_ARG_ENABLE(xlib,
@ -268,7 +274,7 @@ if test "x$GCC" = "xyes"; then
fi
CAIRO_CFLAGS="$CAIRO_CFLAGS $WARN_CFLAGS"
CAIRO_LIBS="$CAIRO_LIBS -lm"
CAIRO_LIBS="$CAIRO_LIBS"
AC_SUBST(CAIRO_CFLAGS)
AC_SUBST(CAIRO_LIBS)

View file

@ -70,4 +70,4 @@ libcairo_la_LDFLAGS = -version-info @VERSION_INFO@ -no-undefined
INCLUDES = -I$(srcdir) $(CAIRO_CFLAGS)
libcairo_la_LIBADD = $(CAIRO_LIBS) -lm
libcairo_la_LIBADD = $(CAIRO_LIBS)

View file

@ -121,7 +121,8 @@ _cache_sane_state (cairo_cache_t *cache)
assert (cache->entries != NULL);
assert (cache->backend != NULL);
assert (cache->arrangement != NULL);
assert (cache->used_memory <= cache->max_memory);
/* Cannot check this, a single object may larger */
/* assert (cache->used_memory <= cache->max_memory); */
assert (cache->live_entries <= cache->arrangement->size);
}
#else
@ -417,7 +418,8 @@ _cairo_cache_lookup (cairo_cache_t *cache,
_entry_destroy (cache, idx);
}
assert(cache->max_memory >= (cache->used_memory + new_entry->memory));
/* Can't assert this; new_entry->memory may be larger than max_memory */
/* assert(cache->max_memory >= (cache->used_memory + new_entry->memory)); */
/* Make room in the table for a new slot. */
status = _resize_cache (cache, cache->live_entries + 1);

View file

@ -50,6 +50,16 @@ typedef struct {
} ft_font_val_t;
/*
* The simple 2x2 matrix is converted into separate scale and shape
* factors so that hinting works right
*/
typedef struct {
double x_scale, y_scale;
double shape[2][2];
} ft_font_transform_t;
static ft_font_val_t *
_create_from_face (FT_Face face, int owns_face)
{
@ -432,11 +442,67 @@ _utf8_to_ucs4 (char const *utf8,
*nchars = n;
}
/*
* Split a matrix into the component pieces of scale and shape
*/
static void
_cairo_ft_font_compute_transform (ft_font_transform_t *sf, cairo_font_scale_t *sc)
{
cairo_matrix_t normalized;
double tx, ty;
/* The font matrix has x and y "scale" components which we extract and
* use as character scale values. These influence the way freetype
* chooses hints, as well as selecting different bitmaps in
* hand-rendered fonts. We also copy the normalized matrix to
* freetype's transformation.
*/
cairo_matrix_set_affine (&normalized,
sc->matrix[0][0],
sc->matrix[0][1],
sc->matrix[1][0],
sc->matrix[1][1],
0, 0);
_cairo_matrix_compute_scale_factors (&normalized,
&sf->x_scale, &sf->y_scale,
/* XXX */ 1);
cairo_matrix_scale (&normalized, 1.0 / sf->x_scale, 1.0 / sf->y_scale);
cairo_matrix_get_affine (&normalized,
&sf->shape[0][0], &sf->shape[0][1],
&sf->shape[1][0], &sf->shape[1][1],
&tx, &ty);
}
/*
* Set the font transformation
*/
static void
_cairo_ft_font_install_transform (ft_font_transform_t *sf, FT_Face face)
{
FT_Matrix mat;
mat.xx = DOUBLE_TO_16_16(sf->shape[0][0]);
mat.yx = -DOUBLE_TO_16_16(sf->shape[0][1]);
mat.xy = -DOUBLE_TO_16_16(sf->shape[1][0]);
mat.yy = DOUBLE_TO_16_16(sf->shape[1][1]);
FT_Set_Transform(face, &mat, NULL);
FT_Set_Char_Size(face,
(FT_F26Dot6) (sf->x_scale * 64.0),
(FT_F26Dot6) (sf->y_scale * 64.0),
0, 0);
}
static void
_install_font_scale (cairo_font_scale_t *sc, FT_Face face)
{
cairo_matrix_t normalized;
double scale_x, scale_y;
double x_scale, y_scale;
double xx, xy, yx, yy, tx, ty;
FT_Matrix mat;
@ -454,8 +520,9 @@ _install_font_scale (cairo_font_scale_t *sc, FT_Face face)
sc->matrix[1][1],
0, 0);
_cairo_matrix_compute_scale_factors (&normalized, &scale_x, &scale_y);
cairo_matrix_scale (&normalized, 1.0 / scale_x, 1.0 / scale_y);
_cairo_matrix_compute_scale_factors (&normalized, &x_scale, &y_scale,
/* XXX */ 1);
cairo_matrix_scale (&normalized, 1.0 / x_scale, 1.0 / y_scale);
cairo_matrix_get_affine (&normalized,
&xx /* 00 */ , &yx /* 01 */,
&xy /* 10 */, &yy /* 11 */,
@ -469,8 +536,8 @@ _install_font_scale (cairo_font_scale_t *sc, FT_Face face)
FT_Set_Transform(face, &mat, NULL);
FT_Set_Pixel_Sizes(face,
(FT_UInt) scale_x,
(FT_UInt) scale_y);
(FT_UInt) x_scale,
(FT_UInt) y_scale);
}
static cairo_status_t
@ -542,13 +609,19 @@ _cairo_ft_font_font_extents (void *abstract_font,
cairo_ft_font_t *font = abstract_font;
FT_Face face = font->val->face;
FT_Size_Metrics *metrics = &face->size->metrics;
ft_font_transform_t sf;
_install_font_scale (sc, face);
_cairo_ft_font_compute_transform (&sf, sc);
_cairo_ft_font_install_transform (&sf, face);
extents->ascent = DOUBLE_FROM_26_6(metrics->ascender);
extents->descent = DOUBLE_FROM_26_6(metrics->descender);
extents->height = DOUBLE_FROM_26_6(metrics->height);
extents->max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance);
/*
* Get to unscaled metrics so that the upper level can get back to
* user space
*/
extents->ascent = DOUBLE_FROM_26_6(metrics->ascender) / sf.y_scale;
extents->descent = DOUBLE_FROM_26_6(metrics->descender) / sf.y_scale;
extents->height = DOUBLE_FROM_26_6(metrics->height) / sf.y_scale;
extents->max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance) / sf.x_scale;
/* FIXME: this doesn't do vertical layout atm. */
extents->max_y_advance = 0.0;
@ -633,10 +706,10 @@ _cairo_ft_font_glyph_extents (void *abstract_font,
}
_cairo_unlock_global_image_glyph_cache ();
extents->x_bearing = total_min.x - origin.x;
extents->y_bearing = total_min.y - origin.y;
extents->width = total_max.x - total_min.x;
extents->height = total_max.y - total_min.y;
extents->x_bearing = (total_min.x - origin.x);
extents->y_bearing = (total_min.y - origin.y);
extents->width = (total_max.x - total_min.x);
extents->height = (total_max.y - total_min.y);
extents->x_advance = glyphs[i-1].x + (img == NULL ? 0 : img->extents.x_advance) - origin.x;
extents->y_advance = glyphs[i-1].y + (img == NULL ? 0 : img->extents.y_advance) - origin.y;
@ -917,11 +990,13 @@ _cairo_ft_font_create_glyph(cairo_image_glyph_cache_entry_t *val)
FT_BBox cbox;
FT_Bitmap bitmap;
FT_Glyph_Metrics *metrics;
ft_font_transform_t sf;
glyphslot = font->val->face->glyph;
metrics = &glyphslot->metrics;
_install_font_scale (&val->key.scale, font->val->face);
_cairo_ft_font_compute_transform (&sf, &val->key.scale);
_cairo_ft_font_install_transform (&sf, font->val->face);
if (FT_Load_Glyph (font->val->face, val->key.index, FT_LOAD_DEFAULT) != 0)
return CAIRO_STATUS_NO_MEMORY;
@ -929,16 +1004,25 @@ _cairo_ft_font_create_glyph(cairo_image_glyph_cache_entry_t *val)
/*
* Note: the font's coordinate system is upside down from ours, so the
* Y coordinates of the bearing and advance need to be negated.
*
* Scale metrics back to glyph space from the scaled glyph space returned
* by FreeType
*/
val->extents.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX);
val->extents.y_bearing = -DOUBLE_FROM_26_6 (metrics->horiBearingY);
val->extents.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) / sf.x_scale;
val->extents.y_bearing = -DOUBLE_FROM_26_6 (metrics->horiBearingY) / sf.y_scale;
val->extents.width = DOUBLE_FROM_26_6 (metrics->width);
val->extents.height = DOUBLE_FROM_26_6 (metrics->height);
val->extents.width = DOUBLE_FROM_26_6 (metrics->width) / sf.x_scale;
val->extents.height = DOUBLE_FROM_26_6 (metrics->height) / sf.y_scale;
val->extents.x_advance = DOUBLE_FROM_26_6 (font->val->face->glyph->advance.x);
val->extents.y_advance = -DOUBLE_FROM_26_6 (font->val->face->glyph->advance.y);
/*
* use untransformed advance values
* XXX uses horizontal advance only at present;
should provide FT_LOAD_VERTICAL_LAYOUT
*/
val->extents.x_advance = DOUBLE_FROM_26_6 (font->val->face->glyph->metrics.horiAdvance) / sf.x_scale;
val->extents.y_advance = 0 / sf.y_scale;
outline = &glyphslot->outline;

View file

@ -425,6 +425,7 @@ static glitz_format_name_t
_glitz_format (cairo_format_t format)
{
switch (format) {
default:
case CAIRO_FORMAT_ARGB32:
return GLITZ_STANDARD_ARGB32;
case CAIRO_FORMAT_RGB24:

View file

@ -2298,30 +2298,27 @@ _cairo_gstate_current_font_extents (cairo_gstate_t *gstate,
{
cairo_int_status_t status;
cairo_font_scale_t sc;
double dummy = 0.0;
double font_scale_x, font_scale_y;
_build_font_scale (gstate, &sc);
status = _cairo_unscaled_font_font_extents (gstate->font, &sc, extents);
/* The font responded in device space; convert to user space. */
cairo_matrix_transform_distance (&gstate->ctm_inverse,
&dummy,
&extents->ascent);
cairo_matrix_transform_distance (&gstate->ctm_inverse,
&dummy,
&extents->descent);
cairo_matrix_transform_distance (&gstate->ctm_inverse,
&dummy,
&extents->height);
cairo_matrix_transform_distance (&gstate->ctm_inverse,
&extents->max_x_advance,
&extents->max_y_advance);
_cairo_matrix_compute_scale_factors (&gstate->font_matrix,
&font_scale_x, &font_scale_y,
/* XXX */ 1);
/*
* The font responded in unscaled units, scale by the font
* matrix scale factors to get to user space
*/
extents->ascent *= font_scale_y;
extents->descent *= font_scale_y;
extents->height *= font_scale_y;
extents->max_x_advance *= font_scale_x;
extents->max_y_advance *= font_scale_y;
return status;
}
@ -2335,18 +2332,20 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
cairo_font_scale_t sc;
cairo_point_t point;
double dev_x, dev_y;
double origin_x, origin_y;
int i;
_build_font_scale (gstate, &sc);
status = _cairo_path_current_point (&gstate->path, &point);
if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
dev_x = 0.0;
dev_y = 0.0;
origin_x = 0.0;
origin_y = 0.0;
} else {
dev_x = _cairo_fixed_to_double (point.x);
dev_y = _cairo_fixed_to_double (point.y);
origin_x = _cairo_fixed_to_double (point.x);
origin_y = _cairo_fixed_to_double (point.y);
cairo_matrix_transform_point (&gstate->ctm_inverse,
&origin_x, &origin_y);
}
status = _cairo_unscaled_font_text_to_glyphs (gstate->font,
@ -2355,15 +2354,16 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
if (status || !glyphs || !nglyphs || !(*glyphs) || !(nglyphs))
return status;
/* The font responded in device space, starting from (0,0); add any
current point offset in device space, and convert to user space. */
/* The font responded in glyph space, starting from (0,0). Convert to
user space by applying the font transform, then add any current point
offset. */
for (i = 0; i < *nglyphs; ++i) {
(*glyphs)[i].x += dev_x;
(*glyphs)[i].y += dev_y;
cairo_matrix_transform_point (&gstate->ctm_inverse,
&((*glyphs)[i].x),
&((*glyphs)[i].y));
cairo_matrix_transform_point (&gstate->font_matrix,
&((*glyphs)[i].x),
&((*glyphs)[i].y));
(*glyphs)[i].x += origin_x;
(*glyphs)[i].y += origin_y;
}
return CAIRO_STATUS_SUCCESS;
@ -2392,44 +2392,88 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
int num_glyphs,
cairo_text_extents_t *extents)
{
cairo_status_t status;
cairo_glyph_t *transformed_glyphs;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_glyph_t origin_glyph;
cairo_text_extents_t origin_extents;
cairo_font_scale_t sc;
int i;
double min_x = 0.0, min_y = 0.0, max_x = 0.0, max_y = 0.0;
double x_pos = 0.0, y_pos = 0.0;
int set = 0;
if (!num_glyphs)
{
extents->x_bearing = 0.0;
extents->y_bearing = 0.0;
extents->width = 0.0;
extents->height = 0.0;
extents->x_advance = 0.0;
extents->y_advance = 0.0;
return CAIRO_STATUS_SUCCESS;
}
_build_font_scale (gstate, &sc);
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
if (transformed_glyphs == NULL)
return CAIRO_STATUS_NO_MEMORY;
for (i = 0; i < num_glyphs; ++i)
for (i = 0; i < num_glyphs; i++)
{
transformed_glyphs[i] = glyphs[i];
cairo_matrix_transform_point (&gstate->ctm,
&transformed_glyphs[i].x,
&transformed_glyphs[i].y);
double x, y;
double wm, hm;
origin_glyph = glyphs[i];
origin_glyph.x = 0.0;
origin_glyph.y = 0.0;
status = _cairo_unscaled_font_glyph_extents (gstate->font, &sc,
&origin_glyph, 1,
&origin_extents);
/*
* Transform font space metrics into user space metrics
* by running the corners through the font matrix and
* expanding the bounding box as necessary
*/
x = extents->x_bearing;
y = extents->y_bearing;
cairo_matrix_transform_point (&gstate->font_matrix,
&x, &y);
for (hm = 0.0; hm <= 1.0; hm += 1.0)
for (wm = 0.0; wm <= 1.0; wm += 1.0)
{
x = origin_extents.x_bearing + origin_extents.width * wm;
y = origin_extents.y_bearing + origin_extents.height * hm;
cairo_matrix_transform_point (&gstate->font_matrix,
&x, &y);
x += glyphs[i].x;
y += glyphs[i].y;
if (!set)
{
min_x = max_x = x;
min_y = max_y = y;
set = 1;
}
else
{
if (x < min_x) min_x = x;
if (x > max_x) max_x = x;
if (y < min_y) min_y = y;
if (y > max_y) max_y = y;
}
}
x = origin_extents.x_advance;
y = origin_extents.y_advance;
cairo_matrix_transform_point (&gstate->font_matrix,
&x, &y);
x_pos = glyphs[i].x + x;
y_pos = glyphs[i].y + y;
}
status = _cairo_unscaled_font_glyph_extents (gstate->font, &sc,
transformed_glyphs, num_glyphs,
extents);
/* The font responded in device space; convert to user space. */
cairo_matrix_transform_distance (&gstate->ctm_inverse,
&extents->x_bearing,
&extents->y_bearing);
cairo_matrix_transform_distance (&gstate->ctm_inverse,
&extents->width,
&extents->height);
cairo_matrix_transform_distance (&gstate->ctm_inverse,
&extents->x_advance,
&extents->y_advance);
free (transformed_glyphs);
extents->x_bearing = min_x - glyphs[0].x;
extents->y_bearing = min_y - glyphs[0].y;
extents->width = max_x - min_x;
extents->height = max_y - min_y;
extents->x_advance = x_pos - glyphs[0].x;
extents->y_advance = y_pos - glyphs[0].y;
return status;
}

View file

@ -121,7 +121,8 @@ _cache_sane_state (cairo_cache_t *cache)
assert (cache->entries != NULL);
assert (cache->backend != NULL);
assert (cache->arrangement != NULL);
assert (cache->used_memory <= cache->max_memory);
/* Cannot check this, a single object may larger */
/* assert (cache->used_memory <= cache->max_memory); */
assert (cache->live_entries <= cache->arrangement->size);
}
#else
@ -417,7 +418,8 @@ _cairo_cache_lookup (cairo_cache_t *cache,
_entry_destroy (cache, idx);
}
assert(cache->max_memory >= (cache->used_memory + new_entry->memory));
/* Can't assert this; new_entry->memory may be larger than max_memory */
/* assert(cache->max_memory >= (cache->used_memory + new_entry->memory)); */
/* Make room in the table for a new slot. */
status = _resize_cache (cache, cache->live_entries + 1);

View file

@ -34,6 +34,7 @@
* Carl D. Worth <cworth@isi.edu>
*/
#define _GNU_SOURCE
#include <stdlib.h>
#include <math.h>
@ -176,9 +177,17 @@ cairo_status_t
_cairo_matrix_set_rotate (cairo_matrix_t *matrix,
double radians)
{
double s;
double c;
#if HAVE_SINCOS
sincos (radians, &s, &c);
#else
s = sin (radians);
c = cos (radians);
#endif
return cairo_matrix_set_affine (matrix,
cos (radians), sin (radians),
-sin (radians), cos (radians),
c, s,
-s, c,
0, 0);
}
@ -398,19 +407,37 @@ _cairo_matrix_compute_eigen_values (cairo_matrix_t *matrix, double *lambda1, dou
/* Compute the amount that each basis vector is scaled by. */
cairo_status_t
_cairo_matrix_compute_scale_factors (cairo_matrix_t *matrix, double *sx, double *sy)
_cairo_matrix_compute_scale_factors (cairo_matrix_t *matrix, double *sx, double *sy, int x_major)
{
double x, y;
double det;
x = 1.0;
y = 0.0;
cairo_matrix_transform_distance (matrix, &x, &y);
*sx = sqrt(x*x + y*y);
_cairo_matrix_compute_determinant (matrix, &det);
x = 0.0;
y = 1.0;
cairo_matrix_transform_distance (matrix, &x, &y);
*sy = sqrt(x*x + y*y);
if (det == 0)
*sx = *sy = 0;
else
{
double x = x_major != 0;
double y = x == 0;
double major, minor;
cairo_matrix_transform_distance (matrix, &x, &y);
major = sqrt(x*x + y*y);
if (major)
minor = det / major;
else
minor = 0.0;
if (x_major)
{
*sx = major;
*sy = minor;
}
else
{
*sx = minor;
*sy = major;
}
}
return CAIRO_STATUS_SUCCESS;
}

View file

@ -1,25 +1,37 @@
/*
* $Id: cairo-wideint.c,v 1.1 2004-05-28 19:37:15 keithp Exp $
* $Id: cairo-wideint.c,v 1.2 2005-01-11 18:03:01 keithp Exp $
*
* Copyright © 2004 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
* 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.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
* 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 Keith Packard
*
* Contributor(s):
* Keith R. Packard <keithp@keithp.com>
*/
#include "cairoint.h"

View file

@ -1,25 +1,38 @@
/*
* $Id: cairo-wideint.h,v 1.3 2004-12-21 21:22:44 cworth Exp $
* $Id: cairo-wideint.h,v 1.4 2005-01-11 18:03:01 keithp Exp $
*
* Copyright © 2004 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
* 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 Keith Packard
*
* Contributor(s):
* Keith R. Packard <keithp@keithp.com>
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef CAIRO_WIDEINT_H
@ -64,6 +77,7 @@ const cairo_int64_t I _cairo_int32_to_int64(int32_t i);
#define _cairo_int64_add(a,b) _cairo_uint64_add (a,b)
#define _cairo_int64_sub(a,b) _cairo_uint64_sub (a,b)
#define _cairo_int64_mul(a,b) _cairo_uint64_mul (a,b)
/* XXX this is wrong */
#define _cairo_int32x32_64_mul(a,b) _cairo_uint32x32_64_mul ((uint32_t) (a), (uint32_t) (b)))
const int I _cairo_int64_lt (cairo_uint64_t a, cairo_uint64_t b);
#define _cairo_int64_eq(a,b) _cairo_uint64_eq (a,b)
@ -187,6 +201,7 @@ const cairo_int128_t I _cairo_int64_to_int128 (cairo_int64_t i);
#define _cairo_int128_add(a,b) _cairo_uint128_add(a,b)
#define _cairo_int128_sub(a,b) _cairo_uint128_sub(a,b)
#define _cairo_int128_mul(a,b) _cairo_uint128_mul(a,b)
/* XXX this is wrong */
#define _cairo_int64x64_128_mul(a,b) _cairo_uint64x64_128_mul ((cairo_uint64_t) (a), (cairo_uint64_t) (b))
#define _cairo_int128_lsl(a,b) _cairo_uint128_lsl(a,b)
#define _cairo_int128_rsl(a,b) _cairo_uint128_rsl(a,b)

View file

@ -1033,6 +1033,7 @@ _cairo_xlib_surface_show_glyphs32 (cairo_unscaled_font_t *font,
unsigned int stack_chars [N_STACK_BUF];
int i;
int thisX, thisY;
int lastX = 0, lastY = 0;
/* Acquire arrays of suitable sizes. */
@ -1056,10 +1057,12 @@ _cairo_xlib_surface_show_glyphs32 (cairo_unscaled_font_t *font,
elts[i].chars = &(chars[i]);
elts[i].nchars = 1;
elts[i].glyphset = g->glyphset;
elts[i].xOff = glyphs[i].x - lastX;
elts[i].yOff = glyphs[i].y - lastY;
lastX = glyphs[i].x;
lastY = glyphs[i].y;
thisX = (int) floor (glyphs[i].x + 0.5);
thisY = (int) floor (glyphs[i].y + 0.5);
elts[i].xOff = thisX - lastX;
elts[i].yOff = thisY - lastY;
lastX = thisX;
lastY = thisY;
}
XRenderCompositeText32 (self->dpy,
@ -1108,6 +1111,7 @@ _cairo_xlib_surface_show_glyphs16 (cairo_unscaled_font_t *font,
unsigned short stack_chars [N_STACK_BUF];
int i;
int thisX, thisY;
int lastX = 0, lastY = 0;
/* Acquire arrays of suitable sizes. */
@ -1131,10 +1135,12 @@ _cairo_xlib_surface_show_glyphs16 (cairo_unscaled_font_t *font,
elts[i].chars = &(chars[i]);
elts[i].nchars = 1;
elts[i].glyphset = g->glyphset;
elts[i].xOff = glyphs[i].x - lastX;
elts[i].yOff = glyphs[i].y - lastY;
lastX = glyphs[i].x;
lastY = glyphs[i].y;
thisX = (int) floor (glyphs[i].x + 0.5);
thisY = (int) floor (glyphs[i].y + 0.5);
elts[i].xOff = thisX - lastX;
elts[i].yOff = thisY - lastY;
lastX = thisX;
lastY = thisY;
}
XRenderCompositeText16 (self->dpy,
@ -1182,6 +1188,7 @@ _cairo_xlib_surface_show_glyphs8 (cairo_unscaled_font_t *font,
char stack_chars [N_STACK_BUF];
int i;
int thisX, thisY;
int lastX = 0, lastY = 0;
/* Acquire arrays of suitable sizes. */
@ -1205,10 +1212,12 @@ _cairo_xlib_surface_show_glyphs8 (cairo_unscaled_font_t *font,
elts[i].chars = &(chars[i]);
elts[i].nchars = 1;
elts[i].glyphset = g->glyphset;
elts[i].xOff = glyphs[i].x - lastX;
elts[i].yOff = glyphs[i].y - lastY;
lastX = glyphs[i].x;
lastY = glyphs[i].y;
thisX = (int) floor (glyphs[i].x + 0.5);
thisY = (int) floor (glyphs[i].y + 0.5);
elts[i].xOff = thisX - lastX;
elts[i].yOff = thisY - lastY;
lastX = thisX;
lastY = thisY;
}
XRenderCompositeText8 (self->dpy,

View file

@ -121,7 +121,8 @@ _cache_sane_state (cairo_cache_t *cache)
assert (cache->entries != NULL);
assert (cache->backend != NULL);
assert (cache->arrangement != NULL);
assert (cache->used_memory <= cache->max_memory);
/* Cannot check this, a single object may larger */
/* assert (cache->used_memory <= cache->max_memory); */
assert (cache->live_entries <= cache->arrangement->size);
}
#else
@ -417,7 +418,8 @@ _cairo_cache_lookup (cairo_cache_t *cache,
_entry_destroy (cache, idx);
}
assert(cache->max_memory >= (cache->used_memory + new_entry->memory));
/* Can't assert this; new_entry->memory may be larger than max_memory */
/* assert(cache->max_memory >= (cache->used_memory + new_entry->memory)); */
/* Make room in the table for a new slot. */
status = _resize_cache (cache, cache->live_entries + 1);

View file

@ -50,6 +50,16 @@ typedef struct {
} ft_font_val_t;
/*
* The simple 2x2 matrix is converted into separate scale and shape
* factors so that hinting works right
*/
typedef struct {
double x_scale, y_scale;
double shape[2][2];
} ft_font_transform_t;
static ft_font_val_t *
_create_from_face (FT_Face face, int owns_face)
{
@ -432,11 +442,67 @@ _utf8_to_ucs4 (char const *utf8,
*nchars = n;
}
/*
* Split a matrix into the component pieces of scale and shape
*/
static void
_cairo_ft_font_compute_transform (ft_font_transform_t *sf, cairo_font_scale_t *sc)
{
cairo_matrix_t normalized;
double tx, ty;
/* The font matrix has x and y "scale" components which we extract and
* use as character scale values. These influence the way freetype
* chooses hints, as well as selecting different bitmaps in
* hand-rendered fonts. We also copy the normalized matrix to
* freetype's transformation.
*/
cairo_matrix_set_affine (&normalized,
sc->matrix[0][0],
sc->matrix[0][1],
sc->matrix[1][0],
sc->matrix[1][1],
0, 0);
_cairo_matrix_compute_scale_factors (&normalized,
&sf->x_scale, &sf->y_scale,
/* XXX */ 1);
cairo_matrix_scale (&normalized, 1.0 / sf->x_scale, 1.0 / sf->y_scale);
cairo_matrix_get_affine (&normalized,
&sf->shape[0][0], &sf->shape[0][1],
&sf->shape[1][0], &sf->shape[1][1],
&tx, &ty);
}
/*
* Set the font transformation
*/
static void
_cairo_ft_font_install_transform (ft_font_transform_t *sf, FT_Face face)
{
FT_Matrix mat;
mat.xx = DOUBLE_TO_16_16(sf->shape[0][0]);
mat.yx = -DOUBLE_TO_16_16(sf->shape[0][1]);
mat.xy = -DOUBLE_TO_16_16(sf->shape[1][0]);
mat.yy = DOUBLE_TO_16_16(sf->shape[1][1]);
FT_Set_Transform(face, &mat, NULL);
FT_Set_Char_Size(face,
(FT_F26Dot6) (sf->x_scale * 64.0),
(FT_F26Dot6) (sf->y_scale * 64.0),
0, 0);
}
static void
_install_font_scale (cairo_font_scale_t *sc, FT_Face face)
{
cairo_matrix_t normalized;
double scale_x, scale_y;
double x_scale, y_scale;
double xx, xy, yx, yy, tx, ty;
FT_Matrix mat;
@ -454,8 +520,9 @@ _install_font_scale (cairo_font_scale_t *sc, FT_Face face)
sc->matrix[1][1],
0, 0);
_cairo_matrix_compute_scale_factors (&normalized, &scale_x, &scale_y);
cairo_matrix_scale (&normalized, 1.0 / scale_x, 1.0 / scale_y);
_cairo_matrix_compute_scale_factors (&normalized, &x_scale, &y_scale,
/* XXX */ 1);
cairo_matrix_scale (&normalized, 1.0 / x_scale, 1.0 / y_scale);
cairo_matrix_get_affine (&normalized,
&xx /* 00 */ , &yx /* 01 */,
&xy /* 10 */, &yy /* 11 */,
@ -469,8 +536,8 @@ _install_font_scale (cairo_font_scale_t *sc, FT_Face face)
FT_Set_Transform(face, &mat, NULL);
FT_Set_Pixel_Sizes(face,
(FT_UInt) scale_x,
(FT_UInt) scale_y);
(FT_UInt) x_scale,
(FT_UInt) y_scale);
}
static cairo_status_t
@ -542,13 +609,19 @@ _cairo_ft_font_font_extents (void *abstract_font,
cairo_ft_font_t *font = abstract_font;
FT_Face face = font->val->face;
FT_Size_Metrics *metrics = &face->size->metrics;
ft_font_transform_t sf;
_install_font_scale (sc, face);
_cairo_ft_font_compute_transform (&sf, sc);
_cairo_ft_font_install_transform (&sf, face);
extents->ascent = DOUBLE_FROM_26_6(metrics->ascender);
extents->descent = DOUBLE_FROM_26_6(metrics->descender);
extents->height = DOUBLE_FROM_26_6(metrics->height);
extents->max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance);
/*
* Get to unscaled metrics so that the upper level can get back to
* user space
*/
extents->ascent = DOUBLE_FROM_26_6(metrics->ascender) / sf.y_scale;
extents->descent = DOUBLE_FROM_26_6(metrics->descender) / sf.y_scale;
extents->height = DOUBLE_FROM_26_6(metrics->height) / sf.y_scale;
extents->max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance) / sf.x_scale;
/* FIXME: this doesn't do vertical layout atm. */
extents->max_y_advance = 0.0;
@ -633,10 +706,10 @@ _cairo_ft_font_glyph_extents (void *abstract_font,
}
_cairo_unlock_global_image_glyph_cache ();
extents->x_bearing = total_min.x - origin.x;
extents->y_bearing = total_min.y - origin.y;
extents->width = total_max.x - total_min.x;
extents->height = total_max.y - total_min.y;
extents->x_bearing = (total_min.x - origin.x);
extents->y_bearing = (total_min.y - origin.y);
extents->width = (total_max.x - total_min.x);
extents->height = (total_max.y - total_min.y);
extents->x_advance = glyphs[i-1].x + (img == NULL ? 0 : img->extents.x_advance) - origin.x;
extents->y_advance = glyphs[i-1].y + (img == NULL ? 0 : img->extents.y_advance) - origin.y;
@ -917,11 +990,13 @@ _cairo_ft_font_create_glyph(cairo_image_glyph_cache_entry_t *val)
FT_BBox cbox;
FT_Bitmap bitmap;
FT_Glyph_Metrics *metrics;
ft_font_transform_t sf;
glyphslot = font->val->face->glyph;
metrics = &glyphslot->metrics;
_install_font_scale (&val->key.scale, font->val->face);
_cairo_ft_font_compute_transform (&sf, &val->key.scale);
_cairo_ft_font_install_transform (&sf, font->val->face);
if (FT_Load_Glyph (font->val->face, val->key.index, FT_LOAD_DEFAULT) != 0)
return CAIRO_STATUS_NO_MEMORY;
@ -929,16 +1004,25 @@ _cairo_ft_font_create_glyph(cairo_image_glyph_cache_entry_t *val)
/*
* Note: the font's coordinate system is upside down from ours, so the
* Y coordinates of the bearing and advance need to be negated.
*
* Scale metrics back to glyph space from the scaled glyph space returned
* by FreeType
*/
val->extents.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX);
val->extents.y_bearing = -DOUBLE_FROM_26_6 (metrics->horiBearingY);
val->extents.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) / sf.x_scale;
val->extents.y_bearing = -DOUBLE_FROM_26_6 (metrics->horiBearingY) / sf.y_scale;
val->extents.width = DOUBLE_FROM_26_6 (metrics->width);
val->extents.height = DOUBLE_FROM_26_6 (metrics->height);
val->extents.width = DOUBLE_FROM_26_6 (metrics->width) / sf.x_scale;
val->extents.height = DOUBLE_FROM_26_6 (metrics->height) / sf.y_scale;
val->extents.x_advance = DOUBLE_FROM_26_6 (font->val->face->glyph->advance.x);
val->extents.y_advance = -DOUBLE_FROM_26_6 (font->val->face->glyph->advance.y);
/*
* use untransformed advance values
* XXX uses horizontal advance only at present;
should provide FT_LOAD_VERTICAL_LAYOUT
*/
val->extents.x_advance = DOUBLE_FROM_26_6 (font->val->face->glyph->metrics.horiAdvance) / sf.x_scale;
val->extents.y_advance = 0 / sf.y_scale;
outline = &glyphslot->outline;

View file

@ -425,6 +425,7 @@ static glitz_format_name_t
_glitz_format (cairo_format_t format)
{
switch (format) {
default:
case CAIRO_FORMAT_ARGB32:
return GLITZ_STANDARD_ARGB32;
case CAIRO_FORMAT_RGB24:

View file

@ -2298,30 +2298,27 @@ _cairo_gstate_current_font_extents (cairo_gstate_t *gstate,
{
cairo_int_status_t status;
cairo_font_scale_t sc;
double dummy = 0.0;
double font_scale_x, font_scale_y;
_build_font_scale (gstate, &sc);
status = _cairo_unscaled_font_font_extents (gstate->font, &sc, extents);
/* The font responded in device space; convert to user space. */
cairo_matrix_transform_distance (&gstate->ctm_inverse,
&dummy,
&extents->ascent);
cairo_matrix_transform_distance (&gstate->ctm_inverse,
&dummy,
&extents->descent);
cairo_matrix_transform_distance (&gstate->ctm_inverse,
&dummy,
&extents->height);
cairo_matrix_transform_distance (&gstate->ctm_inverse,
&extents->max_x_advance,
&extents->max_y_advance);
_cairo_matrix_compute_scale_factors (&gstate->font_matrix,
&font_scale_x, &font_scale_y,
/* XXX */ 1);
/*
* The font responded in unscaled units, scale by the font
* matrix scale factors to get to user space
*/
extents->ascent *= font_scale_y;
extents->descent *= font_scale_y;
extents->height *= font_scale_y;
extents->max_x_advance *= font_scale_x;
extents->max_y_advance *= font_scale_y;
return status;
}
@ -2335,18 +2332,20 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
cairo_font_scale_t sc;
cairo_point_t point;
double dev_x, dev_y;
double origin_x, origin_y;
int i;
_build_font_scale (gstate, &sc);
status = _cairo_path_current_point (&gstate->path, &point);
if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
dev_x = 0.0;
dev_y = 0.0;
origin_x = 0.0;
origin_y = 0.0;
} else {
dev_x = _cairo_fixed_to_double (point.x);
dev_y = _cairo_fixed_to_double (point.y);
origin_x = _cairo_fixed_to_double (point.x);
origin_y = _cairo_fixed_to_double (point.y);
cairo_matrix_transform_point (&gstate->ctm_inverse,
&origin_x, &origin_y);
}
status = _cairo_unscaled_font_text_to_glyphs (gstate->font,
@ -2355,15 +2354,16 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
if (status || !glyphs || !nglyphs || !(*glyphs) || !(nglyphs))
return status;
/* The font responded in device space, starting from (0,0); add any
current point offset in device space, and convert to user space. */
/* The font responded in glyph space, starting from (0,0). Convert to
user space by applying the font transform, then add any current point
offset. */
for (i = 0; i < *nglyphs; ++i) {
(*glyphs)[i].x += dev_x;
(*glyphs)[i].y += dev_y;
cairo_matrix_transform_point (&gstate->ctm_inverse,
&((*glyphs)[i].x),
&((*glyphs)[i].y));
cairo_matrix_transform_point (&gstate->font_matrix,
&((*glyphs)[i].x),
&((*glyphs)[i].y));
(*glyphs)[i].x += origin_x;
(*glyphs)[i].y += origin_y;
}
return CAIRO_STATUS_SUCCESS;
@ -2392,44 +2392,88 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
int num_glyphs,
cairo_text_extents_t *extents)
{
cairo_status_t status;
cairo_glyph_t *transformed_glyphs;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_glyph_t origin_glyph;
cairo_text_extents_t origin_extents;
cairo_font_scale_t sc;
int i;
double min_x = 0.0, min_y = 0.0, max_x = 0.0, max_y = 0.0;
double x_pos = 0.0, y_pos = 0.0;
int set = 0;
if (!num_glyphs)
{
extents->x_bearing = 0.0;
extents->y_bearing = 0.0;
extents->width = 0.0;
extents->height = 0.0;
extents->x_advance = 0.0;
extents->y_advance = 0.0;
return CAIRO_STATUS_SUCCESS;
}
_build_font_scale (gstate, &sc);
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
if (transformed_glyphs == NULL)
return CAIRO_STATUS_NO_MEMORY;
for (i = 0; i < num_glyphs; ++i)
for (i = 0; i < num_glyphs; i++)
{
transformed_glyphs[i] = glyphs[i];
cairo_matrix_transform_point (&gstate->ctm,
&transformed_glyphs[i].x,
&transformed_glyphs[i].y);
double x, y;
double wm, hm;
origin_glyph = glyphs[i];
origin_glyph.x = 0.0;
origin_glyph.y = 0.0;
status = _cairo_unscaled_font_glyph_extents (gstate->font, &sc,
&origin_glyph, 1,
&origin_extents);
/*
* Transform font space metrics into user space metrics
* by running the corners through the font matrix and
* expanding the bounding box as necessary
*/
x = extents->x_bearing;
y = extents->y_bearing;
cairo_matrix_transform_point (&gstate->font_matrix,
&x, &y);
for (hm = 0.0; hm <= 1.0; hm += 1.0)
for (wm = 0.0; wm <= 1.0; wm += 1.0)
{
x = origin_extents.x_bearing + origin_extents.width * wm;
y = origin_extents.y_bearing + origin_extents.height * hm;
cairo_matrix_transform_point (&gstate->font_matrix,
&x, &y);
x += glyphs[i].x;
y += glyphs[i].y;
if (!set)
{
min_x = max_x = x;
min_y = max_y = y;
set = 1;
}
else
{
if (x < min_x) min_x = x;
if (x > max_x) max_x = x;
if (y < min_y) min_y = y;
if (y > max_y) max_y = y;
}
}
x = origin_extents.x_advance;
y = origin_extents.y_advance;
cairo_matrix_transform_point (&gstate->font_matrix,
&x, &y);
x_pos = glyphs[i].x + x;
y_pos = glyphs[i].y + y;
}
status = _cairo_unscaled_font_glyph_extents (gstate->font, &sc,
transformed_glyphs, num_glyphs,
extents);
/* The font responded in device space; convert to user space. */
cairo_matrix_transform_distance (&gstate->ctm_inverse,
&extents->x_bearing,
&extents->y_bearing);
cairo_matrix_transform_distance (&gstate->ctm_inverse,
&extents->width,
&extents->height);
cairo_matrix_transform_distance (&gstate->ctm_inverse,
&extents->x_advance,
&extents->y_advance);
free (transformed_glyphs);
extents->x_bearing = min_x - glyphs[0].x;
extents->y_bearing = min_y - glyphs[0].y;
extents->width = max_x - min_x;
extents->height = max_y - min_y;
extents->x_advance = x_pos - glyphs[0].x;
extents->y_advance = y_pos - glyphs[0].y;
return status;
}

View file

@ -34,6 +34,7 @@
* Carl D. Worth <cworth@isi.edu>
*/
#define _GNU_SOURCE
#include <stdlib.h>
#include <math.h>
@ -176,9 +177,17 @@ cairo_status_t
_cairo_matrix_set_rotate (cairo_matrix_t *matrix,
double radians)
{
double s;
double c;
#if HAVE_SINCOS
sincos (radians, &s, &c);
#else
s = sin (radians);
c = cos (radians);
#endif
return cairo_matrix_set_affine (matrix,
cos (radians), sin (radians),
-sin (radians), cos (radians),
c, s,
-s, c,
0, 0);
}
@ -398,19 +407,37 @@ _cairo_matrix_compute_eigen_values (cairo_matrix_t *matrix, double *lambda1, dou
/* Compute the amount that each basis vector is scaled by. */
cairo_status_t
_cairo_matrix_compute_scale_factors (cairo_matrix_t *matrix, double *sx, double *sy)
_cairo_matrix_compute_scale_factors (cairo_matrix_t *matrix, double *sx, double *sy, int x_major)
{
double x, y;
double det;
x = 1.0;
y = 0.0;
cairo_matrix_transform_distance (matrix, &x, &y);
*sx = sqrt(x*x + y*y);
_cairo_matrix_compute_determinant (matrix, &det);
x = 0.0;
y = 1.0;
cairo_matrix_transform_distance (matrix, &x, &y);
*sy = sqrt(x*x + y*y);
if (det == 0)
*sx = *sy = 0;
else
{
double x = x_major != 0;
double y = x == 0;
double major, minor;
cairo_matrix_transform_distance (matrix, &x, &y);
major = sqrt(x*x + y*y);
if (major)
minor = det / major;
else
minor = 0.0;
if (x_major)
{
*sx = major;
*sy = minor;
}
else
{
*sx = minor;
*sy = major;
}
}
return CAIRO_STATUS_SUCCESS;
}

View file

@ -1,25 +1,37 @@
/*
* $Id: cairo_wideint.c,v 1.1 2004-05-28 19:37:15 keithp Exp $
* $Id: cairo_wideint.c,v 1.2 2005-01-11 18:03:01 keithp Exp $
*
* Copyright © 2004 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
* 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.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
* 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 Keith Packard
*
* Contributor(s):
* Keith R. Packard <keithp@keithp.com>
*/
#include "cairoint.h"

View file

@ -1,25 +1,38 @@
/*
* $Id: cairo_wideint.h,v 1.3 2004-12-21 21:22:44 cworth Exp $
* $Id: cairo_wideint.h,v 1.4 2005-01-11 18:03:01 keithp Exp $
*
* Copyright © 2004 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
* 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 Keith Packard
*
* Contributor(s):
* Keith R. Packard <keithp@keithp.com>
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef CAIRO_WIDEINT_H
@ -64,6 +77,7 @@ const cairo_int64_t I _cairo_int32_to_int64(int32_t i);
#define _cairo_int64_add(a,b) _cairo_uint64_add (a,b)
#define _cairo_int64_sub(a,b) _cairo_uint64_sub (a,b)
#define _cairo_int64_mul(a,b) _cairo_uint64_mul (a,b)
/* XXX this is wrong */
#define _cairo_int32x32_64_mul(a,b) _cairo_uint32x32_64_mul ((uint32_t) (a), (uint32_t) (b)))
const int I _cairo_int64_lt (cairo_uint64_t a, cairo_uint64_t b);
#define _cairo_int64_eq(a,b) _cairo_uint64_eq (a,b)
@ -187,6 +201,7 @@ const cairo_int128_t I _cairo_int64_to_int128 (cairo_int64_t i);
#define _cairo_int128_add(a,b) _cairo_uint128_add(a,b)
#define _cairo_int128_sub(a,b) _cairo_uint128_sub(a,b)
#define _cairo_int128_mul(a,b) _cairo_uint128_mul(a,b)
/* XXX this is wrong */
#define _cairo_int64x64_128_mul(a,b) _cairo_uint64x64_128_mul ((cairo_uint64_t) (a), (cairo_uint64_t) (b))
#define _cairo_int128_lsl(a,b) _cairo_uint128_lsl(a,b)
#define _cairo_int128_rsl(a,b) _cairo_uint128_rsl(a,b)

View file

@ -1033,6 +1033,7 @@ _cairo_xlib_surface_show_glyphs32 (cairo_unscaled_font_t *font,
unsigned int stack_chars [N_STACK_BUF];
int i;
int thisX, thisY;
int lastX = 0, lastY = 0;
/* Acquire arrays of suitable sizes. */
@ -1056,10 +1057,12 @@ _cairo_xlib_surface_show_glyphs32 (cairo_unscaled_font_t *font,
elts[i].chars = &(chars[i]);
elts[i].nchars = 1;
elts[i].glyphset = g->glyphset;
elts[i].xOff = glyphs[i].x - lastX;
elts[i].yOff = glyphs[i].y - lastY;
lastX = glyphs[i].x;
lastY = glyphs[i].y;
thisX = (int) floor (glyphs[i].x + 0.5);
thisY = (int) floor (glyphs[i].y + 0.5);
elts[i].xOff = thisX - lastX;
elts[i].yOff = thisY - lastY;
lastX = thisX;
lastY = thisY;
}
XRenderCompositeText32 (self->dpy,
@ -1108,6 +1111,7 @@ _cairo_xlib_surface_show_glyphs16 (cairo_unscaled_font_t *font,
unsigned short stack_chars [N_STACK_BUF];
int i;
int thisX, thisY;
int lastX = 0, lastY = 0;
/* Acquire arrays of suitable sizes. */
@ -1131,10 +1135,12 @@ _cairo_xlib_surface_show_glyphs16 (cairo_unscaled_font_t *font,
elts[i].chars = &(chars[i]);
elts[i].nchars = 1;
elts[i].glyphset = g->glyphset;
elts[i].xOff = glyphs[i].x - lastX;
elts[i].yOff = glyphs[i].y - lastY;
lastX = glyphs[i].x;
lastY = glyphs[i].y;
thisX = (int) floor (glyphs[i].x + 0.5);
thisY = (int) floor (glyphs[i].y + 0.5);
elts[i].xOff = thisX - lastX;
elts[i].yOff = thisY - lastY;
lastX = thisX;
lastY = thisY;
}
XRenderCompositeText16 (self->dpy,
@ -1182,6 +1188,7 @@ _cairo_xlib_surface_show_glyphs8 (cairo_unscaled_font_t *font,
char stack_chars [N_STACK_BUF];
int i;
int thisX, thisY;
int lastX = 0, lastY = 0;
/* Acquire arrays of suitable sizes. */
@ -1205,10 +1212,12 @@ _cairo_xlib_surface_show_glyphs8 (cairo_unscaled_font_t *font,
elts[i].chars = &(chars[i]);
elts[i].nchars = 1;
elts[i].glyphset = g->glyphset;
elts[i].xOff = glyphs[i].x - lastX;
elts[i].yOff = glyphs[i].y - lastY;
lastX = glyphs[i].x;
lastY = glyphs[i].y;
thisX = (int) floor (glyphs[i].x + 0.5);
thisY = (int) floor (glyphs[i].y + 0.5);
elts[i].xOff = thisX - lastX;
elts[i].yOff = thisY - lastY;
lastX = thisX;
lastY = thisY;
}
XRenderCompositeText8 (self->dpy,

View file

@ -1518,7 +1518,7 @@ cairo_private cairo_status_t
_cairo_matrix_compute_eigen_values (cairo_matrix_t *matrix, double *lambda1, double *lambda2);
cairo_private cairo_status_t
_cairo_matrix_compute_scale_factors (cairo_matrix_t *matrix, double *sx, double *sy);
_cairo_matrix_compute_scale_factors (cairo_matrix_t *matrix, double *sx, double *sy, int x_major);
cairo_private int
_cairo_matrix_is_integer_translation(cairo_matrix_t *matrix, int *itx, int *ity);