src/cairo-font-options.c src/cairo.h src/cairoint.h src/Makefile.am: Add an opaque cairo_font_options_t structure.

src/cairo-font.c src/cairo.h src/cairoint.h: Add a cairo_font_options_t object to cairo_scaled_font_create().
src/cairo-surface.c src/cairoint.h: Add virtualized cairo_surface_get_font_options() to get the font options for a surface.
Adapt to cairo_scaled_font_create() change.
Add an implementation of get_font_options() that turns off metrics hinting.
src/cairo-xlib-screen.c src/cairo-xlib-private.h: Add a "screen info" structure that holds (for now) information about the default font options for the screen.
Implement get_font_options()
src/cairo-ft-font.c src/cairo-ft.h: Add functions to apply a cairo_font_options_t to a FcPattern or get the load flags for a cairo_font_options_t.
Adapt to font options additions. Add support for non-antialiased rendering of scalable fonts. Add support for turning off metrics hinting.
Adapt to font options additions.
doc/public/Makefile.am doc/public/cairo-sections.txt: Update.
reviewed by: cworth
This commit is contained in:
Owen Taylor 2005-07-21 06:52:13 +00:00
parent a43c9eb7b0
commit 075cf23cdc
22 changed files with 1762 additions and 195 deletions

View file

@ -1,3 +1,40 @@
2005-07-13 Owen Taylor <otaylor@redhat.com>
reviewed by: cworth
* src/cairo-font-options.c src/cairo.h src/cairoint.h
src/Makefile.am: Add an opaque cairo_font_options_t structure.
* src/cairo-font.c src/cairo.h src/cairoint.h: Add a
cairo_font_options_t object to cairo_scaled_font_create().
* src/cairo-surface.c src/cairoint.h: Add virtualized
cairo_surface_get_font_options() to get the font options for
a surface.
* src/cairo-gstate.c: Adapt to cairo_scaled_font_create() change.
* src/cairo-pdf-surface.c: Add an implementation of
get_font_options() that turns off metrics hinting.
* src/cairo-xlib-screen.c src/cairo-xlib-private.h: Add
a "screen info" structure that holds (for now) information
about the default font options for the screen.
* src/cairo-xlib-surface.c: Implement get_font_options()
* src/cairo-ft-font.c src/cairo-ft.h: Add functions to apply
a cairo_font_options_t to a FcPattern or get the load flags
for a cairo_font_options_t.
* src/cairo-ft-font.c: Adapt to font options additions.
Add support for non-antialiased rendering of scalable fonts.
Add support for turning off metrics hinting.
* src/cairo-win32-font.c: Adapt to font options additions.
* doc/public/Makefile.am doc/public/cairo-sections.txt: Update.
2005-07-21 Carl Worth <cworth@cworth.org>
* src/cairo-glitz-surface.c:

View file

@ -21,8 +21,11 @@ CFILE_GLOB=$(top_srcdir)/src/*.c $(top_srcdir)/src/*.h
# Headers to ignore
IGNORE_HFILES= \
cairo-features.h \
cairo-font-subset-private.h \
cairo-ft-private.h \
cairo-gstate-private.h \
cairo-hash-private.h \
cairo-meta-surface-private.h \
cairo-path-fixed-private.h \
cairo-private.h \
cairo-win32-private.h \

View file

@ -1,6 +1,7 @@
<SECTION>
<FILE>cairo-ft</FILE>
<TITLE>FreeType Fonts</TITLE>
cairo_ft_font_options_substitute
cairo_ft_font_face_create_for_pattern
cairo_ft_font_face_create_for_ft_face
cairo_ft_scaled_font_lock_face
@ -90,6 +91,7 @@ cairo_surface_create_similar
cairo_surface_reference
cairo_surface_destroy
cairo_surface_finish
cairo_surface_get_font_options
cairo_surface_set_user_data
cairo_surface_get_user_data
cairo_surface_set_device_offset
@ -99,6 +101,8 @@ cairo_surface_set_device_offset
<FILE>cairo-pattern</FILE>
<TITLE>cairo_pattern_t</TITLE>
cairo_pattern_t
cairo_pattern_create_rgb
cairo_pattern_create_rgba
cairo_pattern_create_for_surface
cairo_pattern_create_linear
cairo_pattern_create_radial
@ -150,6 +154,26 @@ cairo_font_extents_t
cairo_scaled_font_extents
cairo_text_extents_t
cairo_scaled_font_glyph_extents
cairo_font_options_t
cairo_font_options_create
cairo_font_options_copy
cairo_font_options_destroy
cairo_font_options_status
cairo_font_options_merge
cairo_font_options_hash
cairo_font_options_equal
cairo_antialias_t
cairo_font_options_set_antialias
cairo_font_options_get_antialias
cairo_subpixel_order_t
cairo_font_options_set_subpixel_order
cairo_font_options_get_subpixel_order
cairo_hint_style_t
cairo_font_options_set_hint_style
cairo_font_options_get_hint_style
cairo_hint_metrics_t
cairo_font_options_set_hint_metrics
cairo_font_options_get_hint_metrics
</SECTION>
<SECTION>
@ -161,7 +185,10 @@ cairo_reference
cairo_destroy
cairo_save
cairo_restore
cairo_content_t
CAIRO_CONTENT_VALID
cairo_format_t
CAIRO_FORMAT_VALID
cairo_operator_t
cairo_set_operator
cairo_set_source_rgb
@ -255,8 +282,6 @@ cairo_status_t
cairo_status
cairo_status_string
cairo_status_to_string
cairo_error_notify_func_t
cairo_set_error_notify
cairo_filter_t
cairo_image_surface_create
cairo_image_surface_create_for_data

View file

@ -75,6 +75,7 @@ Font Handling
@font_face:
@font_matrix:
@ctm:
@options:
@Returns:
@ -138,3 +139,186 @@ Font Handling
@extents:
<!-- ##### TYPEDEF cairo_font_options_t ##### -->
<para>
</para>
<!-- ##### FUNCTION cairo_font_options_create ##### -->
<para>
</para>
@Returns:
<!-- ##### FUNCTION cairo_font_options_copy ##### -->
<para>
</para>
@original:
@Returns:
<!-- ##### FUNCTION cairo_font_options_destroy ##### -->
<para>
</para>
@options:
<!-- ##### FUNCTION cairo_font_options_status ##### -->
<para>
</para>
@options:
@Returns:
<!-- ##### FUNCTION cairo_font_options_merge ##### -->
<para>
</para>
@options:
@other:
<!-- ##### FUNCTION cairo_font_options_hash ##### -->
<para>
</para>
@options:
@Returns:
<!-- ##### FUNCTION cairo_font_options_equal ##### -->
<para>
</para>
@options:
@other:
@Returns:
<!-- ##### ENUM cairo_antialias_t ##### -->
<para>
</para>
@CAIRO_ANTIALIAS_DEFAULT:
@CAIRO_ANTIALIAS_NONE:
@CAIRO_ANTIALIAS_GRAY:
@CAIRO_ANTIALIAS_SUBPIXEL:
<!-- ##### FUNCTION cairo_font_options_set_antialias ##### -->
<para>
</para>
@options:
@antialias:
<!-- ##### FUNCTION cairo_font_options_get_antialias ##### -->
<para>
</para>
@options:
@Returns:
<!-- ##### ENUM cairo_subpixel_order_t ##### -->
<para>
</para>
@CAIRO_SUBPIXEL_ORDER_DEFAULT:
@CAIRO_SUBPIXEL_ORDER_RGB:
@CAIRO_SUBPIXEL_ORDER_BGR:
@CAIRO_SUBPIXEL_ORDER_VRGB:
@CAIRO_SUBPIXEL_ORDER_VBGR:
<!-- ##### FUNCTION cairo_font_options_set_subpixel_order ##### -->
<para>
</para>
@options:
@subpixel_order:
<!-- ##### FUNCTION cairo_font_options_get_subpixel_order ##### -->
<para>
</para>
@options:
@Returns:
<!-- # Unused Parameters # -->
@option:
<!-- ##### ENUM cairo_hint_style_t ##### -->
<para>
</para>
@CAIRO_HINT_STYLE_DEFAULT:
@CAIRO_HINT_STYLE_NONE:
@CAIRO_HINT_STYLE_SLIGHT:
@CAIRO_HINT_STYLE_MEDIUM:
@CAIRO_HINT_STYLE_FULL:
<!-- ##### FUNCTION cairo_font_options_set_hint_style ##### -->
<para>
</para>
@options:
@hint_style:
<!-- ##### FUNCTION cairo_font_options_get_hint_style ##### -->
<para>
</para>
@options:
@Returns:
<!-- ##### ENUM cairo_hint_metrics_t ##### -->
<para>
</para>
@CAIRO_HINT_METRICS_DEFAULT:
@CAIRO_HINT_METRICS_OFF:
@CAIRO_HINT_METRICS_ON:
<!-- ##### FUNCTION cairo_font_options_set_hint_metrics ##### -->
<para>
</para>
@options:
@hint_metrics:
<!-- ##### FUNCTION cairo_font_options_get_hint_metrics ##### -->
<para>
</para>
@options:
@Returns:

View file

@ -17,6 +17,15 @@ FreeType Fonts
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### FUNCTION cairo_ft_font_options_substitute ##### -->
<para>
</para>
@options:
@pattern:
<!-- ##### FUNCTION cairo_ft_font_face_create_for_pattern ##### -->
<para>

View file

@ -23,6 +23,29 @@ cairo_pattern_t
</para>
<!-- ##### FUNCTION cairo_pattern_create_rgb ##### -->
<para>
</para>
@red:
@green:
@blue:
@Returns:
<!-- ##### FUNCTION cairo_pattern_create_rgba ##### -->
<para>
</para>
@red:
@green:
@blue:
@alpha:
@Returns:
<!-- ##### FUNCTION cairo_pattern_create_for_surface ##### -->
<para>

View file

@ -29,10 +29,12 @@ cairo_surface_t
</para>
@other:
@format:
@content:
@width:
@height:
@Returns:
<!-- # Unused Parameters # -->
@format:
<!-- ##### FUNCTION cairo_surface_reference ##### -->
@ -60,6 +62,15 @@ cairo_surface_t
@Returns:
<!-- ##### FUNCTION cairo_surface_get_font_options ##### -->
<para>
</para>
@surface:
@options:
<!-- ##### FUNCTION cairo_surface_set_user_data ##### -->
<para>

View file

@ -74,6 +74,23 @@ Drawing contexts.
@cr:
<!-- ##### ENUM cairo_content_t ##### -->
<para>
</para>
@CAIRO_CONTENT_COLOR:
@CAIRO_CONTENT_ALPHA:
@CAIRO_CONTENT_COLOR_ALPHA:
<!-- ##### MACRO CAIRO_CONTENT_VALID ##### -->
<para>
</para>
@content:
<!-- ##### ENUM cairo_format_t ##### -->
<para>
@ -84,6 +101,14 @@ Drawing contexts.
@CAIRO_FORMAT_A8:
@CAIRO_FORMAT_A1:
<!-- ##### MACRO CAIRO_FORMAT_VALID ##### -->
<para>
</para>
@format:
<!-- ##### ENUM cairo_operator_t ##### -->
<para>
@ -942,7 +967,7 @@ Drawing contexts.
@CAIRO_STATUS_INVALID_POP_GROUP:
@CAIRO_STATUS_NO_CURRENT_POINT:
@CAIRO_STATUS_INVALID_MATRIX:
@CAIRO_STATUS_NO_TARGET_SURFACE:
@CAIRO_STATUS_INVALID_STATUS:
@CAIRO_STATUS_NULL_POINTER:
@CAIRO_STATUS_INVALID_STRING:
@CAIRO_STATUS_INVALID_PATH_DATA:

View file

@ -17,7 +17,7 @@ endif
if CAIRO_HAS_XLIB_SURFACE
libcairo_xlib_headers = cairo-xlib.h cairo-xlib-xrender.h
libcairo_xlib_sources = cairo-xlib-surface.c cairo-xlib-test.h
libcairo_xlib_sources = cairo-xlib-surface.c cairo-xlib-screen.c cairo-xlib-private.h cairo-xlib-test.h
endif
if CAIRO_HAS_QUARTZ_SURFACE
@ -88,6 +88,7 @@ libcairo_la_SOURCES = \
cairo-color.c \
cairo-fixed.c \
cairo-font.c \
cairo-font-options.c \
cairo-gstate.c \
cairo-gstate-private.h \
cairo-hull.c \

352
src/cairo-font-options.c Normal file
View file

@ -0,0 +1,352 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is University of Southern
* California.
*
* Contributor(s):
* Owen Taylor <otaylor@redhat.com>
*/
#include "cairoint.h"
static const cairo_font_options_t cairo_font_options_nil = {
CAIRO_ANTIALIAS_DEFAULT,
CAIRO_SUBPIXEL_ORDER_DEFAULT,
CAIRO_HINT_STYLE_DEFAULT,
CAIRO_HINT_METRICS_DEFAULT
};
/**
* _cairo_font_options_init_default:
* @options: a #cairo_font_options_t
*
* Initializes all fileds of the font options object to default values.
**/
void
_cairo_font_options_init_default (cairo_font_options_t *options)
{
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
return;
options->antialias = CAIRO_ANTIALIAS_DEFAULT;
options->subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
options->hint_style = CAIRO_HINT_STYLE_DEFAULT;
options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT;
}
/**
* cairo_font_options_create:
*
* Allocates a new font options object with all options initialized
* to default values.
*
* Return value: a newly allocated #cairo_font_options_t. Free with
* cairo_font_options_destroy(). This function always returns a
* valid pointer; if memory cannot be allocated, then a special
* error object is returned where all operations on the object do nothing.
* You can check for this with cairo_font_options_status().
**/
cairo_font_options_t *
cairo_font_options_create (void)
{
cairo_font_options_t *options = malloc (sizeof (cairo_font_options_t));
if (!options)
return (cairo_font_options_t *)&cairo_font_options_nil;
_cairo_font_options_init_default (options);
return options;
}
/**
* cairo_font_options_copy:
* @original: a #cairo_font_options_t
*
* Allocates a new font options object copying the option values from
* @original.
*
* Return value: a newly allocated #cairo_font_options_t. Free with
* cairo_font_options_destroy(). This function always returns a
* valid pointer; if memory cannot be allocated, then a special
* error object is returned where all operations on the object do nothing.
* You can check for this with cairo_font_options_status().
**/
cairo_font_options_t *
cairo_font_options_copy (const cairo_font_options_t *original)
{
cairo_font_options_t *options = malloc (sizeof (cairo_font_options_t));
if (!options)
return (cairo_font_options_t *)&cairo_font_options_nil;
*options = *original;
return options;
}
/**
* cairo_font_options_destroy:
* @options: a #cairo_font_options_t
*
* Destroys a #cairo_font_options_t object created with with
* cairo_font_options_create() or cairo_font_options_copy().
**/
void
cairo_font_options_destroy (cairo_font_options_t *options)
{
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
return;
free (options);
}
/**
* cairo_font_options_status:
* @options: a #cairo_font_options_t
*
* Checks whether an error has previously occurred for this
* font options object
*
* Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
**/
cairo_status_t
cairo_font_options_status (cairo_font_options_t *options)
{
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
return CAIRO_STATUS_NO_MEMORY;
else
return CAIRO_STATUS_SUCCESS;
}
/**
* cairo_font_options_merge:
* @options: a #cairo_font_options_t
* @other: another #cairo_font_options_t
*
* Merges non-default options from @other into @options, replacing
* existing values. This operation can be thought of as somewhat
* similar to compositing @other onto @options with the operation
* of %CAIRO_OPERATION_OVER.
**/
void
cairo_font_options_merge (cairo_font_options_t *options,
const cairo_font_options_t *other)
{
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
return;
if (other->antialias != CAIRO_ANTIALIAS_DEFAULT)
options->antialias = other->antialias;
if (other->subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT)
options->subpixel_order = other->subpixel_order;
if (other->hint_style != CAIRO_HINT_STYLE_DEFAULT)
options->hint_style = other->hint_style;
if (other->hint_metrics != CAIRO_HINT_METRICS_DEFAULT)
options->hint_metrics = other->hint_metrics;
}
/**
* cairo_font_options_equual:
* @options: a #cairo_font_options_t
* @other: another #cairo_font_options_t
*
* Compares two font options objects for equality.
*
* Return value: %TRUE if all fields of the two font options objects match
**/
cairo_bool_t
cairo_font_options_equal (const cairo_font_options_t *options,
const cairo_font_options_t *other)
{
return (options->antialias == other->antialias &&
options->subpixel_order == other->subpixel_order &&
options->hint_style == other->hint_style &&
options->hint_metrics == other->hint_metrics);
}
/**
* cairo_font_options_hash:
* @options: a #cairo_font_options_t
*
* Compute a hash for the font options object; this value will
* be useful when storing an object containing a cairo_font_options_t
* in a hash table.
*
* Return value: the hash value for the font options object.
* The return value can be cast to a 32-bit type if a
* 32-bit hash value is needed.
**/
unsigned long
cairo_font_options_hash (const cairo_font_options_t *options)
{
return ((options->antialias) |
(options->subpixel_order << 4) |
(options->hint_style << 8) |
(options->hint_metrics << 16));
}
/**
* cairo_font_options_set_antialias:
* @options: a #cairo_font_options_t
* @antialias: the new antialiasing mode
*
* Sets the antiliasing mode for the font options object. This
* specifies the type of antialiasing to do when rendering text.
**/
void
cairo_font_options_set_antialias (cairo_font_options_t *options,
cairo_antialias_t antialias)
{
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
return;
options->antialias = antialias;
}
/**
* cairo_font_options_get_antialias:
* @options: a #cairo_font_options_t
*
* Gets the antialising mode for the font options object.
*
* Return value: the antialiasing mode
**/
cairo_antialias_t
cairo_font_options_get_antialias (const cairo_font_options_t *options)
{
return options->antialias;
}
/**
* cairo_font_options_set_subpixel_order:
* @options: a #cairo_font_options_t
* @subpixel_order: the new subpixel order
*
* Sets the subpixel order for the font options object. The subpixel
* order specifies the order of color elements within each pixel on
* the display device when rendering with an antialiasing mode of
* %CAIRO_ANTIALIAS_SUBPIXEL. See the documentation for
* #cairo_subpixel_order_t for full details.
**/
void
cairo_font_options_set_subpixel_order (cairo_font_options_t *options,
cairo_subpixel_order_t subpixel_order)
{
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
return;
options->subpixel_order = subpixel_order;
}
/**
* cairo_font_options_get_subpixel_order:
* @options: a #cairo_font_options_t
*
* Gets the subpixel order for the font options object.
* See the documentation for #cairo_subpixel_order_t for full details.
*
* Return value: the subpixel order for the font options object
**/
cairo_subpixel_order_t
cairo_font_options_get_subpixel_order (const cairo_font_options_t *options)
{
return options->subpixel_order;
}
/**
* cairo_font_options_set_hint_style:
* @options: a #cairo_font_options_t
* @hint_style: the new hint style
*
* Sets the hint style for font outlines for the font options object.
* This controls whether to fit font outlines to the pixel grid,
* and if so, whether to optimize for fidelity or contrast.
* See the documentation for #cairo_hint_style_t for full details.
**/
void
cairo_font_options_set_hint_style (cairo_font_options_t *options,
cairo_hint_style_t hint_style)
{
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
return;
options->hint_style = hint_style;
}
/**
* cairo_font_options_get_hint_style:
* @options: a #cairo_font_options_t
*
* Gets the hint style for font outlines for the font options object.
* See the documentation for #cairo_hint_style_t for full details.
*
* Return value: the hint style for the font options object
**/
cairo_hint_style_t
cairo_font_options_get_hint_style (const cairo_font_options_t *options)
{
return options->hint_style;
}
/**
* cairo_font_options_set_hint_metrics:
* @options: a #cairo_font_options_t
* @hint_metrics: the new metrics hinting mode
*
* Sets the metrics hinting mode for the font options object. This
* controls whether metrics are quantized to integer values in
* device units.
* See the documentation for #cairo_hint_metrics_t for full details.
**/
void
cairo_font_options_set_hint_metrics (cairo_font_options_t *options,
cairo_hint_metrics_t hint_metrics)
{
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
return;
options->hint_metrics = hint_metrics;
}
/**
* cairo_font_options_get_hint_metrics:
* @options: a #cairo_font_options_t
*
* Gets the metrics hinting mode for the font options object.
* See the documentation for #cairo_hint_metrics_t for full details.
*
* Return value: the metrics hinting mode for the font options object
**/
cairo_hint_metrics_t
cairo_font_options_get_hint_metrics (const cairo_font_options_t *options)
{
return options->hint_metrics;
}

View file

@ -355,17 +355,18 @@ _cairo_simple_font_face_destroy (void *abstract_face)
}
static cairo_status_t
_cairo_simple_font_face_create_font (void *abstract_face,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
cairo_scaled_font_t **scaled_font)
_cairo_simple_font_face_create_font (void *abstract_face,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
const cairo_font_options_t *options,
cairo_scaled_font_t **scaled_font)
{
const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT;
cairo_simple_font_face_t *simple_face = abstract_face;
return backend->create (simple_face->family, simple_face->slant, simple_face->weight,
font_matrix, ctm, scaled_font);
font_matrix, ctm, options, scaled_font);
}
static const cairo_font_face_backend_t _cairo_simple_font_face_backend = {
@ -444,6 +445,7 @@ typedef struct {
cairo_font_face_t *font_face;
const cairo_matrix_t *font_matrix;
const cairo_matrix_t *ctm;
cairo_font_options_t options;
} cairo_font_cache_key_t;
typedef struct {
@ -554,7 +556,9 @@ _cairo_font_cache_hash (void *cache, void *key)
sizeof(double) * 4,
hash);
return hash ^ (unsigned long)k->font_face;
return (hash ^
(unsigned long)k->font_face ^
cairo_font_options_hash (&k->options));
}
static int
@ -573,7 +577,8 @@ _cairo_font_cache_keys_equal (void *cache,
sizeof(double) * 4) == 0 &&
memcmp ((unsigned char *)(&a->ctm->xx),
(unsigned char *)(&b->ctm->xx),
sizeof(double) * 4) == 0);
sizeof(double) * 4) == 0 &&
cairo_font_options_equal (&a->options, &b->options));
}
/* The cache lookup failed in the outer cache, so we pull
@ -614,6 +619,7 @@ _cairo_outer_font_cache_create_entry (void *cache,
entry->key.font_face = entry->scaled_font->font_face;
entry->key.font_matrix = &entry->scaled_font->font_matrix;
entry->key.ctm = &entry->scaled_font->ctm;
entry->key.options = ((cairo_font_cache_key_t *) key)->options;
*return_entry = entry;
@ -650,6 +656,7 @@ _cairo_inner_font_cache_create_entry (void *cache,
status = k->font_face->backend->create_font (k->font_face,
k->font_matrix,
k->ctm,
&k->options,
&entry->scaled_font);
if (status) {
free (entry);
@ -663,6 +670,7 @@ _cairo_inner_font_cache_create_entry (void *cache,
entry->key.font_face = k->font_face;
entry->key.font_matrix = &entry->scaled_font->font_matrix;
entry->key.ctm = &entry->scaled_font->ctm;
entry->key.options = k->options;
*return_entry = entry;
@ -712,6 +720,8 @@ static const cairo_cache_backend_t _cairo_inner_font_cache_backend = {
* cairo_set_font_matrix().
* @ctm: user to device transformation matrix with which the font will
* be used.
* @options: options to use when getting metrics for the font and
* rendering with it.
*
* Creates a #cairo_scaled_font_t object from a font face and matrices that
* describe the size of the font and the environment in which it will
@ -721,9 +731,10 @@ static const cairo_cache_backend_t _cairo_inner_font_cache_backend = {
* cairo_scaled_font_destroy()
**/
cairo_scaled_font_t *
cairo_scaled_font_create (cairo_font_face_t *font_face,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm)
cairo_scaled_font_create (cairo_font_face_t *font_face,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
const cairo_font_options_t *options)
{
cairo_font_cache_entry_t *entry;
cairo_font_cache_key_t key;
@ -733,6 +744,7 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
key.font_face = font_face;
key.font_matrix = font_matrix;
key.ctm = ctm;
key.options = *options;
_lock_global_font_cache ();
cache = _get_outer_font_cache ();

View file

@ -51,6 +51,19 @@
#define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
#define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0)
/* We pack some of our own information into the bits unused
* by FreeType's load flags. If FreeType ever uses up all
* the load flag bits, we'll have to do something else.
* (probably just store what we care about in load_flags
* then convert into FreeType terms.
*/
#define PRIVATE_FLAG_HINT_METRICS (0x01 << 24)
#define PRIVATE_FLAGS_MASK (0xff << 24)
/* This is the max number of FT_face objects we keep open at once
*/
#define MAX_OPEN_FACES 10
/* This is the max number of FT_face objects we keep open at once
*/
#define MAX_OPEN_FACES 10
@ -551,6 +564,87 @@ _cairo_ft_unscaled_font_destroy (void *abstract_font)
}
}
/* Fills in val->image with an image surface created from @bitmap
*/
static cairo_status_t
_get_bitmap_surface (cairo_image_glyph_cache_entry_t *val,
FT_Bitmap *bitmap,
cairo_bool_t own_buffer)
{
int width, height, stride;
unsigned char *data;
int i, j;
width = bitmap->width;
height = bitmap->rows;
if (width * height == 0) {
if (own_buffer && bitmap->buffer)
free (bitmap->buffer);
val->image = NULL;
} else {
switch (bitmap->pixel_mode) {
case FT_PIXEL_MODE_MONO:
stride = (width + 3) & ~3;
data = calloc (stride * height, 1);
if (!data)
return CAIRO_STATUS_NO_MEMORY;
for (j = 0; j < height; j++) {
const unsigned char *p = bitmap->buffer + j * bitmap->pitch;
unsigned char *q = data + j * stride;
for (i = 0; i < width; i++) {
/* FreeType bitmaps are always stored MSB */
unsigned char byte = p[i >> 3];
unsigned char bit = 1 << (7 - (i % 8));
if (byte & bit)
q[i] = 0xff;
}
}
if (own_buffer)
free (bitmap->buffer);
break;
case FT_PIXEL_MODE_GRAY:
stride = bitmap->pitch;
if (own_buffer) {
data = bitmap->buffer;
} else {
data = malloc (stride * height);
if (!data)
return CAIRO_STATUS_NO_MEMORY;
memcpy (data, bitmap->buffer, stride * height);
}
break;
case FT_PIXEL_MODE_GRAY2:
case FT_PIXEL_MODE_GRAY4:
/* These could be triggered by very rare types of TrueType fonts */
case FT_PIXEL_MODE_LCD:
case FT_PIXEL_MODE_LCD_V:
/* These should never be triggered unless we ask for them */
default:
return CAIRO_STATUS_NO_MEMORY;
}
val->image = (cairo_image_surface_t *)
cairo_image_surface_create_for_data (data,
CAIRO_FORMAT_A8,
width, height, stride);
if (val->image == NULL) {
free (data);
return CAIRO_STATUS_NO_MEMORY;
}
_cairo_image_surface_assume_ownership_of_data (val->image);
}
val->size.width = width;
val->size.height = height;
return CAIRO_STATUS_SUCCESS;
}
/* Converts an outline FT_GlyphSlot into an image
*
* This could go through _render_glyph_bitmap as well, letting
@ -586,17 +680,23 @@ _render_glyph_outline (FT_Face face,
width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
stride = (width + 3) & -4;
if (width * height == 0) {
val->image = NULL;
} else {
bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
bitmap.num_grays = 256;
if ((val->key.flags & FT_LOAD_MONOCHROME) != 0) {
bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
bitmap.num_grays = 1;
stride = ((width + 31) & -32) >> 3;
} else {
bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
bitmap.num_grays = 256;
stride = (width + 3) & -4;
}
bitmap.pitch = stride;
bitmap.width = width;
bitmap.rows = height;
bitmap.pitch = stride;
bitmap.buffer = calloc (1, stride * height);
if (bitmap.buffer == NULL) {
@ -609,17 +709,10 @@ _render_glyph_outline (FT_Face face,
free (bitmap.buffer);
return CAIRO_STATUS_NO_MEMORY;
}
val->image = (cairo_image_surface_t *)
cairo_image_surface_create_for_data (bitmap.buffer,
CAIRO_FORMAT_A8,
width, height, stride);
if (val->image == NULL) {
free (bitmap.buffer);
return CAIRO_STATUS_NO_MEMORY;
}
_cairo_image_surface_assume_ownership_of_data (val->image);
status = _get_bitmap_surface (val, &bitmap, TRUE);
if (status)
return status;
}
/*
@ -627,8 +720,6 @@ _render_glyph_outline (FT_Face face,
* Y coordinate of the control box needs to be negated.
*/
val->size.width = (unsigned short) width;
val->size.height = (unsigned short) height;
val->size.x = (short) (cbox.xMin >> 6);
val->size.y = - (short) (cbox.yMax >> 6);
@ -655,12 +746,8 @@ _render_glyph_bitmap (FT_Face face,
cairo_image_glyph_cache_entry_t *val)
{
FT_GlyphSlot glyphslot = face->glyph;
FT_Bitmap *bitmap;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
int width, height, stride;
unsigned char *data;
FT_Error error;
int i, j;
/* According to the FreeType docs, glyphslot->format could be
* something other than FT_GLYPH_FORMAT_OUTLINE or
@ -673,64 +760,8 @@ _render_glyph_bitmap (FT_Face face,
if (error)
return CAIRO_STATUS_NO_MEMORY;
bitmap = &glyphslot->bitmap;
_get_bitmap_surface (val, &glyphslot->bitmap, FALSE);
width = bitmap->width;
height = bitmap->rows;
if (width * height == 0) {
val->image = NULL;
} else {
switch (bitmap->pixel_mode) {
case FT_PIXEL_MODE_MONO:
stride = (width + 3) & ~3;
data = calloc (stride * height, 1);
if (!data)
return CAIRO_STATUS_NO_MEMORY;
for (j = 0; j < height; j++) {
const unsigned char *p = bitmap->buffer + j * bitmap->pitch;
unsigned char *q = data + j * stride;
for (i = 0; i < width; i++) {
/* FreeType bitmaps are always stored MSB */
unsigned char byte = p[i >> 3];
unsigned char bit = 1 << (7 - (i % 8));
if (byte & bit)
q[i] = 0xff;
}
}
break;
case FT_PIXEL_MODE_GRAY:
stride = bitmap->pitch;
data = malloc (stride * height);
if (!data)
return CAIRO_STATUS_NO_MEMORY;
memcpy (data, bitmap->buffer, stride * height);
break;
case FT_PIXEL_MODE_GRAY2:
case FT_PIXEL_MODE_GRAY4:
/* These could be triggered by very rare types of TrueType fonts */
case FT_PIXEL_MODE_LCD:
case FT_PIXEL_MODE_LCD_V:
/* These should never be triggered unless we ask for them */
default:
return CAIRO_STATUS_NO_MEMORY;
}
val->image = (cairo_image_surface_t *)
cairo_image_surface_create_for_data (data,
CAIRO_FORMAT_A8,
width, height, stride);
if (val->image == NULL) {
free (data);
return CAIRO_STATUS_NO_MEMORY;
}
_cairo_image_surface_assume_ownership_of_data (val->image);
}
val->size.width = width;
val->size.height = height;
val->size.x = - glyphslot->bitmap_left;
val->size.y = - glyphslot->bitmap_top;
@ -875,7 +906,7 @@ _cairo_ft_unscaled_font_create_glyph (void *abstract_
_ft_unscaled_font_set_scale (unscaled, &val->key.scale);
if (FT_Load_Glyph (face, val->key.index, val->key.flags) != 0) {
if (FT_Load_Glyph (face, val->key.index, val->key.flags & ~PRIVATE_FLAGS_MASK) != 0) {
status = CAIRO_STATUS_NO_MEMORY;
goto FAIL;
}
@ -886,22 +917,46 @@ _cairo_ft_unscaled_font_create_glyph (void *abstract_
*
* Scale metrics back to glyph space from the scaled glyph space returned
* by FreeType
*
* If we want hinted metrics but aren't asking for hinted glyphs from
* FreeType, then we need to do the metric hinting ourselves.
*/
val->extents.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) / unscaled->x_scale;
val->extents.y_bearing = -DOUBLE_FROM_26_6 (metrics->horiBearingY) / unscaled->y_scale;
val->extents.width = DOUBLE_FROM_26_6 (metrics->width) / unscaled->x_scale;
val->extents.height = DOUBLE_FROM_26_6 (metrics->height) / unscaled->y_scale;
/*
* 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 (face->glyph->metrics.horiAdvance) / unscaled->x_scale;
val->extents.y_advance = 0 / unscaled->y_scale;
if ((val->key.flags & PRIVATE_FLAG_HINT_METRICS) &&
(val->key.flags & FT_LOAD_NO_HINTING)) {
FT_Pos x1, x2;
FT_Pos y1, y2;
FT_Pos advance;
x1 = (metrics->horiBearingX) & -64;
x2 = (metrics->horiBearingX + metrics->width + 63) & -64;
y1 = (metrics->horiBearingY) & -64;
y2 = (metrics->horiBearingY + metrics->height + 63) & -64;
advance = ((metrics->horiAdvance + 32) & -64);
val->extents.x_bearing = DOUBLE_FROM_26_6 (x1) / unscaled->x_scale;
val->extents.y_bearing = -DOUBLE_FROM_26_6 (y1) / unscaled->y_scale;
val->extents.width = DOUBLE_FROM_26_6 (x2 - x1) / unscaled->x_scale;
val->extents.height = DOUBLE_FROM_26_6 (y2 - y1) / unscaled->y_scale;
/*
* 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 (advance) / unscaled->x_scale;
val->extents.y_advance = 0;
} else {
val->extents.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) / unscaled->x_scale;
val->extents.y_bearing = -DOUBLE_FROM_26_6 (metrics->horiBearingY) / unscaled->y_scale;
val->extents.width = DOUBLE_FROM_26_6 (metrics->width) / unscaled->x_scale;
val->extents.height = DOUBLE_FROM_26_6 (metrics->height) / unscaled->y_scale;
val->extents.x_advance = DOUBLE_FROM_26_6 (face->glyph->metrics.horiAdvance) / unscaled->x_scale;
val->extents.y_advance = 0 / unscaled->y_scale;
}
if (glyphslot->format == FT_GLYPH_FORMAT_OUTLINE)
status = _render_glyph_outline (face, val);
@ -933,23 +988,19 @@ const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend = {
typedef struct {
cairo_scaled_font_t base;
int load_flags;
cairo_font_options_t options;
ft_unscaled_font_t *unscaled;
} cairo_ft_scaled_font_t;
const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend;
/* for compatibility with older freetype versions */
#ifndef FT_LOAD_TARGET_MONO
#define FT_LOAD_TARGET_MONO FT_LOAD_MONOCHROME
#endif
/* The load flags passed to FT_Load_Glyph control aspects like hinting and
* antialiasing. Here we compute them from the fields of a FcPattern.
*/
static int
_get_load_flags (FcPattern *pattern)
_get_pattern_load_flags (FcPattern *pattern)
{
FcBool antialias, hinting, autohint;
FcBool antialias, vertical_layout, hinting, autohint;
#ifdef FC_HINT_STYLE
int hintstyle;
#endif
@ -959,17 +1010,17 @@ _get_load_flags (FcPattern *pattern)
if (FcPatternGetBool (pattern,
FC_ANTIALIAS, 0, &antialias) != FcResultMatch)
antialias = FcTrue;
if (antialias)
load_flags |= FT_LOAD_NO_BITMAP;
else
load_flags |= FT_LOAD_TARGET_MONO;
load_flags |= FT_LOAD_MONOCHROME;
/* disable hinting if requested */
if (FcPatternGetBool (pattern,
FC_HINTING, 0, &hinting) != FcResultMatch)
hinting = FcTrue;
#ifdef FC_HINT_STYLE
if (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch)
hintstyle = FC_HINT_FULL;
@ -977,20 +1028,26 @@ _get_load_flags (FcPattern *pattern)
if (!hinting || hintstyle == FC_HINT_NONE)
load_flags |= FT_LOAD_NO_HINTING;
switch (hintstyle) {
case FC_HINT_SLIGHT:
case FC_HINT_MEDIUM:
load_flags |= FT_LOAD_TARGET_LIGHT;
break;
default:
load_flags |= FT_LOAD_TARGET_NORMAL;
break;
if (antialias) {
switch (hintstyle) {
case FC_HINT_SLIGHT:
case FC_HINT_MEDIUM:
load_flags |= FT_LOAD_TARGET_LIGHT;
break;
default:
load_flags |= FT_LOAD_TARGET_NORMAL;
break;
}
} else {
#ifdef FT_LOAD_TARGET_MONO
load_flags |= FT_LOAD_TARGET_MONO;
#endif
}
#else /* !FC_HINT_STYLE */
if (!hinting)
load_flags |= FT_LOAD_NO_HINTING;
#endif /* FC_FHINT_STYLE */
/* force autohinting if requested */
if (FcPatternGetBool (pattern,
FC_AUTOHINT, 0, &autohint) != FcResultMatch)
@ -999,14 +1056,51 @@ _get_load_flags (FcPattern *pattern)
if (autohint)
load_flags |= FT_LOAD_FORCE_AUTOHINT;
if (FcPatternGetBool (pattern,
FC_VERTICAL_LAYOUT, 0, &vertical_layout) != FcResultMatch)
vertical_layout = FcFalse;
if (vertical_layout)
load_flags |= FT_LOAD_VERTICAL_LAYOUT;
return load_flags;
}
static int
_get_options_load_flags (const cairo_font_options_t *options)
{
int load_flags = 0;
/* disable antialiasing if requested */
if (options->antialias == CAIRO_ANTIALIAS_NONE)
load_flags |= FT_LOAD_TARGET_MONO;
else
load_flags |= FT_LOAD_NO_BITMAP;
/* disable hinting if requested */
switch (options->hint_style) {
case CAIRO_HINT_STYLE_NONE:
load_flags |= FT_LOAD_NO_HINTING;
break;
case CAIRO_HINT_STYLE_SLIGHT:
case CAIRO_HINT_STYLE_MEDIUM:
load_flags |= FT_LOAD_TARGET_LIGHT;
break;
case CAIRO_HINT_STYLE_FULL:
default:
load_flags |= FT_LOAD_TARGET_NORMAL;
break;
}
return load_flags;
}
static cairo_scaled_font_t *
_ft_scaled_font_create (ft_unscaled_font_t *unscaled,
int load_flags,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm)
_ft_scaled_font_create (ft_unscaled_font_t *unscaled,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
const cairo_font_options_t *options,
int load_flags)
{
cairo_ft_scaled_font_t *f = NULL;
@ -1017,6 +1111,11 @@ _ft_scaled_font_create (ft_unscaled_font_t *unscaled,
f->unscaled = unscaled;
_cairo_unscaled_font_reference (&unscaled->base);
f->options = *options;
if (options->hint_metrics != CAIRO_HINT_METRICS_OFF)
load_flags |= PRIVATE_FLAG_HINT_METRICS;
f->load_flags = load_flags;
_cairo_scaled_font_init (&f->base, font_matrix, ctm, &cairo_ft_scaled_font_backend);
@ -1031,12 +1130,13 @@ _cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font)
}
static cairo_status_t
_cairo_ft_scaled_font_create (const char *family,
cairo_font_slant_t slant,
cairo_font_weight_t weight,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
cairo_scaled_font_t **font)
_cairo_ft_scaled_font_create (const char *family,
cairo_font_slant_t slant,
cairo_font_weight_t weight,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
const cairo_font_options_t *options,
cairo_scaled_font_t **font)
{
FcPattern *pattern, *resolved;
ft_unscaled_font_t *unscaled;
@ -1089,6 +1189,7 @@ _cairo_ft_scaled_font_create (const char *family,
FcPatternAddInteger (pattern, FC_PIXEL_SIZE, sf.y_scale);
FcConfigSubstitute (NULL, pattern, FcMatchPattern);
cairo_ft_font_options_substitute (options, pattern);
FcDefaultSubstitute (pattern);
resolved = FcFontMatch (NULL, pattern, &result);
@ -1099,8 +1200,9 @@ _cairo_ft_scaled_font_create (const char *family,
if (!unscaled)
goto FREE_RESOLVED;
new_font = _ft_scaled_font_create (unscaled, _get_load_flags (pattern),
font_matrix, ctm);
new_font = _ft_scaled_font_create (unscaled,
font_matrix, ctm,
options, _get_pattern_load_flags (pattern));
_cairo_unscaled_font_destroy (&unscaled->base);
FcPatternDestroy (resolved);
@ -1230,15 +1332,24 @@ _cairo_ft_scaled_font_font_extents (void *abstract_font,
metrics = &face->size->metrics;
_ft_unscaled_font_set_scale (scaled_font->unscaled, &scaled_font->base.scale);
/*
* Get to unscaled metrics so that the upper level can get back to
* user space
*/
extents->ascent = DOUBLE_FROM_26_6(metrics->ascender) / scaled_font->unscaled->y_scale;
extents->descent = DOUBLE_FROM_26_6(- metrics->descender) / scaled_font->unscaled->y_scale;
extents->height = DOUBLE_FROM_26_6(metrics->height) / scaled_font->unscaled->y_scale;
extents->max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance) / scaled_font->unscaled->x_scale;
if (scaled_font->options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
extents->ascent = DOUBLE_FROM_26_6(metrics->ascender) / scaled_font->unscaled->y_scale;
extents->descent = DOUBLE_FROM_26_6(- metrics->descender) / scaled_font->unscaled->y_scale;
extents->height = DOUBLE_FROM_26_6(metrics->height) / scaled_font->unscaled->y_scale;
extents->max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance) / scaled_font->unscaled->x_scale;
} else {
double scale = face->units_per_EM;
extents->ascent = face->ascender / scale;
extents->descent = - face->descender / scale;
extents->height = face->height / scale;
extents->max_x_advance = face->max_advance_width / scale;
}
/* FIXME: this doesn't do vertical layout atm. */
extents->max_y_advance = 0.0;
@ -1688,16 +1799,32 @@ _ft_font_face_destroy (void *abstract_face)
}
static cairo_status_t
_ft_font_face_create_font (void *abstract_face,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
cairo_scaled_font_t **scaled_font)
_ft_font_face_create_font (void *abstract_face,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
const cairo_font_options_t *options,
cairo_scaled_font_t **scaled_font)
{
ft_font_face_t *font_face = abstract_face;
int load_flags;
/* The handling of font options is different depending on how the
* font face was created. When the user creates a font face with
* cairo_ft_font_face_create_for_ft_face(), then the load flags
* passed in augment the load flags for the options. But for
* cairo_ft_font_face_create_for_pattern(), the load flags are
* derived from a pattern where the user has called
* cairo_ft_font_options_substitute(), so *just* use those load
* flags and ignore the options.
*/
if (font_face->unscaled->from_face)
load_flags = _get_options_load_flags (options) | font_face->load_flags;
else
load_flags = font_face->load_flags;
*scaled_font = _ft_scaled_font_create (font_face->unscaled,
font_face->load_flags,
font_matrix, ctm);
font_matrix, ctm,
options, load_flags);
if (*scaled_font)
return CAIRO_STATUS_SUCCESS;
else
@ -1743,6 +1870,92 @@ _ft_font_face_create (ft_unscaled_font_t *unscaled,
/* implement the platform-specific interface */
/**
* cairo_ft_font_options_substitute:
* @options: a #cairo_font_options_t object
*
* Add options to a #FcPattern based on a #cairo_font_options_t font
* options object. Options that are already in the pattern, are not
* overriden, so you should call this function after calling FcConfigSubstitute()
* (the user's settings should override options based on the surface type),
* but before calling FcDefaultSubstitute().
**/
void
cairo_ft_font_options_substitute (const cairo_font_options_t *options,
FcPattern *pattern)
{
FcValue v;
if (options->antialias != CAIRO_ANTIALIAS_DEFAULT)
{
if (FcPatternGet (pattern, FC_ANTIALIAS, 0, &v) == FcResultNoMatch)
{
FcPatternAddBool (pattern, FC_ANTIALIAS, options->antialias != CAIRO_ANTIALIAS_NONE);
}
}
if (options->antialias != CAIRO_ANTIALIAS_DEFAULT)
{
if (FcPatternGet (pattern, FC_RGBA, 0, &v) == FcResultNoMatch)
{
int rgba;
if (options->antialias == CAIRO_ANTIALIAS_SUBPIXEL) {
switch (options->subpixel_order) {
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
case CAIRO_SUBPIXEL_ORDER_RGB:
default:
rgba = FC_RGBA_RGB;
break;
case CAIRO_SUBPIXEL_ORDER_BGR:
rgba = FC_RGBA_BGR;
break;
case CAIRO_SUBPIXEL_ORDER_VRGB:
rgba = FC_RGBA_VRGB;
break;
case CAIRO_SUBPIXEL_ORDER_VBGR:
rgba = FC_RGBA_VBGR;
break;
}
} else {
rgba = FC_RGBA_NONE;
}
FcPatternAddInteger (pattern, FC_RGBA, rgba);
}
}
if (options->hint_style != CAIRO_HINT_STYLE_DEFAULT)
{
if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch)
{
FcPatternAddBool (pattern, FC_HINTING, options->hint_style != CAIRO_HINT_STYLE_NONE);
}
#ifdef FC_HINT_STYLE
if (FcPatternGet (pattern, FC_HINT_STYLE, 0, &v) == FcResultNoMatch)
{
int hint_style;
switch (options->hint_style) {
case CAIRO_HINT_STYLE_SLIGHT:
hint_style = FC_HINT_SLIGHT;
break;
case CAIRO_HINT_STYLE_MEDIUM:
hint_style = FC_HINT_MEDIUM;
break;
case CAIRO_HINT_STYLE_FULL:
default:
hint_style = FC_HINT_FULL;
break;
}
FcPatternAddInteger (pattern, FC_HINT_STYLE, hint_style);
}
#endif
}
}
/**
* cairo_ft_font_face_create_for_pattern:
* @pattern: A fully resolved fontconfig
@ -1759,6 +1972,12 @@ _ft_font_face_create (ft_unscaled_font_t *unscaled,
* returned from cairo_font_create() is also for the FreeType backend
* and can be used with functions such as cairo_ft_font_lock_face().
*
* Font rendering options are representated both here and when you
* call cairo_scaled_font_create(). Font options that have a representation
* in a #FcPattern must be passed in here; to modify #FcPattern
* appropriately to reflect the options in a #cairo_font_options_t, call
* cairo_ft_font_options_substitute().
*
* Return value: a newly created #cairo_font_face_t. Free with
* cairo_font_face_destroy() when you are done using it.
**/
@ -1772,7 +1991,7 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
if (unscaled == NULL)
return NULL;
font_face = _ft_font_face_create (unscaled, _get_load_flags (pattern));
font_face = _ft_font_face_create (unscaled, _get_pattern_load_flags (pattern));
_cairo_unscaled_font_destroy (&unscaled->base);
return font_face;
@ -1786,10 +2005,13 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
* internally to Cairo, the best way to determine when it
* is safe to free the face is to pass a
* #cairo_destroy_func_t to cairo_font_face_set_user_data()
* @load_flags: The flags to pass to FT_Load_Glyph when loading
* glyphs from the font. These flags control aspects of
* rendering such as hinting and antialiasing. See the FreeType
* docs for full information.
* @load_flags: flags to pass to FT_Load_Glyph when loading
* glyphs from the font. These flags are OR'ed together with
* the flags derived from the #cairo_font_options_t passed
* to cairo_scaled_font_create(), so only a few values such
* as %FT_LOAD_VERTICAL_LAYOUT, and %FT_LOAD_FORCE_AUTOHINT
* are useful. You should not pass any of the flags affecting
* the load target, such as %FT_LOAD_TARGET_LIGHT.
*
* Creates a new font face for the FreeType font backend from a pre-opened
* FreeType face. This font can then be used with

View file

@ -52,6 +52,9 @@ CAIRO_BEGIN_DECLS
cairo_font_face_t *
cairo_ft_font_face_create_for_pattern (FcPattern *pattern);
void cairo_ft_font_options_substitute (const cairo_font_options_t *options,
FcPattern *pattern);
cairo_font_face_t *
cairo_ft_font_face_create_for_ft_face (FT_Face face,
int load_flags);

View file

@ -1974,6 +1974,7 @@ static cairo_status_t
_cairo_gstate_ensure_font (cairo_gstate_t *gstate)
{
cairo_status_t status;
cairo_font_options_t options;
if (gstate->scaled_font)
return CAIRO_STATUS_SUCCESS;
@ -1982,9 +1983,11 @@ _cairo_gstate_ensure_font (cairo_gstate_t *gstate)
if (status)
return status;
cairo_surface_get_font_options (gstate->target, &options);
gstate->scaled_font = cairo_scaled_font_create (gstate->font_face,
&gstate->font_matrix,
&gstate->ctm);
&gstate->ctm,
&options);
if (!gstate->scaled_font)
return CAIRO_STATUS_NO_MEMORY;

View file

@ -1379,6 +1379,16 @@ _cairo_pdf_surface_intersect_clip_path (void *dst,
return status;
}
static void
_cairo_pdf_surface_get_font_options (void *abstract_surface,
cairo_font_options_t *options)
{
_cairo_font_options_init_default (options);
cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
}
static const cairo_surface_backend_t cairo_pdf_surface_backend = {
_cairo_pdf_surface_create_similar,
_cairo_pdf_surface_finish,
@ -1396,7 +1406,8 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = {
_cairo_pdf_surface_intersect_clip_path,
_cairo_pdf_surface_get_extents,
_cairo_pdf_surface_show_glyphs,
_cairo_pdf_surface_fill_path
_cairo_pdf_surface_fill_path,
_cairo_pdf_surface_get_font_options
};
static cairo_pdf_document_t *

View file

@ -256,6 +256,33 @@ cairo_surface_set_user_data (cairo_surface_t *surface,
key, user_data, destroy);
}
/**
* cairo_surface_get_font_options:
* @surface: a #cairo_surface_t
* @options: a #cairo_font_options_t object into which to store
* the retrieved options. All existing values are overwritten
*
* Retrieves the default font rendering options for the surface.
* This allows display surfaces to report the correct subpixel order
* for rendering on them, print surfaces to disable hinting of
* metrics and so forth. The result can then be used with
* cairo_scaled_font_create().
**/
void
cairo_surface_get_font_options (cairo_surface_t *surface,
cairo_font_options_t *options)
{
if (!surface->finished && surface->backend->get_font_options) {
surface->backend->get_font_options (surface, options);
} else {
options->antialias = CAIRO_ANTIALIAS_DEFAULT;
options->subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
options->hint_style = CAIRO_HINT_STYLE_DEFAULT;
options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT;
}
}
/**
* cairo_surface_set_device_offset:
* @surface: a #cairo_surface_t

View file

@ -55,6 +55,7 @@ typedef struct {
cairo_scaled_font_t base;
LOGFONTW logfont;
cairo_font_options_t options;
BYTE quality;
@ -162,6 +163,24 @@ _compute_transform (cairo_win32_scaled_font_t *scaled_font,
cairo_matrix_init_identity (&scaled_font->device_to_logical);
}
static cairo_bool_t
_have_cleartype_quality (void)
{
OSVERSIONINFO version_info;
version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (!GetVersionEx (&version_info)) {
_cairo_win32_print_gdi_error ("_have_cleartype_quality");
return FALSE;
}
return (version_info.dwMajorVersion > 5 ||
(version_info.dwMajorVersion == 5 &&
version_info.dwMinorVersion >= 1)); /* XP or newer */
}
static BYTE
_get_system_quality (void)
{
@ -169,28 +188,15 @@ _get_system_quality (void)
if (!SystemParametersInfo (SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0)) {
_cairo_win32_print_gdi_error ("_get_system_quality");
return FALSE;
return DEFAULT_QUALITY;
}
if (font_smoothing) {
OSVERSIONINFO version_info;
version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (!GetVersionEx (&version_info)) {
_cairo_win32_print_gdi_error ("_get_system_quality");
return FALSE;
}
if (version_info.dwMajorVersion > 5 ||
(version_info.dwMajorVersion == 5 &&
version_info.dwMinorVersion >= 1)) { /* XP or newer */
UINT smoothing_type;
if (_have_cleartype_quality ()) {
if (!SystemParametersInfo (SPI_GETFONTSMOOTHINGTYPE,
0, &smoothing_type, 0)) {
_cairo_win32_print_gdi_error ("_get_system_quality");
return FALSE;
return DEFAULT_QUALITY;
}
if (smoothing_type == FE_FONTSMOOTHINGCLEARTYPE)
@ -204,9 +210,10 @@ _get_system_quality (void)
}
static cairo_scaled_font_t *
_win32_scaled_font_create (LOGFONTW *logfont,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm)
_win32_scaled_font_create (LOGFONTW *logfont,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
const cairo_font_options_t *options)
{
cairo_win32_scaled_font_t *f;
cairo_matrix_t scale;
@ -216,7 +223,35 @@ _win32_scaled_font_create (LOGFONTW *logfont,
return NULL;
f->logfont = *logfont;
f->quality = _get_system_quality ();
f->options = *options;
/* We don't have any control over the hinting style or subpixel
* order in the Win32 font API, so we ignore those parts of
* cairo_font_options_t. We use the 'antialias' field to set
* the 'quality'.
*
* XXX: The other option we could pay attention to, but don't
* here is the hint_metrics options.
*/
if (options->antialias == CAIRO_ANTIALIAS_DEFAULT)
f->quality = _get_system_quality ();
else {
switch (options->antialias) {
case CAIRO_ANTIALIAS_NONE:
f->quality = NONANTIALIASED_QUALITY;
break;
case CAIRO_ANTIALIAS_GRAY:
f->quality = ANTIALIASED_QUALITY;
break;
case CAIRO_ANTIALIAS_SUBPIXEL:
if (_have_cleartype_quality ())
f->quality = CLEARTYPE_QUALITY;
else
f->quality = ANTIALIASED_QUALITY;
break;
}
}
f->em_square = 0;
f->scaled_hfont = NULL;
f->unscaled_hfont = NULL;
@ -390,12 +425,13 @@ _cairo_win32_scaled_font_done_unscaled_font (cairo_scaled_font_t *scaled_font)
/* implement the font backend interface */
static cairo_status_t
_cairo_win32_scaled_font_create (const char *family,
cairo_font_slant_t slant,
cairo_font_weight_t weight,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
cairo_scaled_font_t **scaled_font_out)
_cairo_win32_scaled_font_create (const char *family,
cairo_font_slant_t slant,
cairo_font_weight_t weight,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
const cairo_font_options_t *options,
cairo_scaled_font_t **scaled_font_out)
{
LOGFONTW logfont;
cairo_scaled_font_t *scaled_font;
@ -456,7 +492,7 @@ _cairo_win32_scaled_font_create (const char *family,
if (!logfont.lfFaceName)
return CAIRO_STATUS_NO_MEMORY;
scaled_font = _win32_scaled_font_create (&logfont, font_matrix, ctm);
scaled_font = _win32_scaled_font_create (&logfont, font_matrix, ctm, options);
if (!scaled_font)
return CAIRO_STATUS_NO_MEMORY;
@ -1262,15 +1298,16 @@ _cairo_win32_font_face_destroy (void *abstract_face)
}
static cairo_status_t
_cairo_win32_font_face_create_font (void *abstract_face,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
cairo_scaled_font_t **font)
_cairo_win32_font_face_create_font (void *abstract_face,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
const cairo_font_options_t *options,
cairo_scaled_font_t **font)
{
cairo_win32_font_face_t *font_face = abstract_face;
*font = _win32_scaled_font_create (&font_face->logfont,
font_matrix, ctm);
font_matrix, ctm, options);
if (*font)
return CAIRO_STATUS_SUCCESS;
else

54
src/cairo-xlib-private.h Normal file
View file

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

345
src/cairo-xlib-screen.c Normal file
View file

@ -0,0 +1,345 @@
/* Cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Partially on code from xftdpy.c
*
* Copyright © 2000 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include "cairo-xlib-private.h"
#include <fontconfig/fontconfig.h>
#include <X11/Xlibint.h> /* For XESetCloseDisplay */
#include <X11/extensions/Xrender.h>
static int
parse_boolean (const char *v)
{
char c0, c1;
c0 = *v;
if (c0 == 't' || c0 == 'T' || c0 == 'y' || c0 == 'Y' || c0 == '1')
return 1;
if (c0 == 'f' || c0 == 'F' || c0 == 'n' || c0 == 'N' || c0 == '0')
return 0;
if (c0 == 'o')
{
c1 = v[1];
if (c1 == 'n' || c1 == 'N')
return 1;
if (c1 == 'f' || c1 == 'F')
return 0;
}
return -1;
}
static cairo_bool_t
get_boolean_default (Display *dpy,
const char *option,
cairo_bool_t *value)
{
char *v;
int i;
v = XGetDefault (dpy, "Xft", option);
if (v) {
i = parse_boolean (v);
if (i >= 0) {
*value = i;
return TRUE;
}
}
return FALSE;
}
static cairo_bool_t
get_integer_default (Display *dpy,
const char *option,
int *value)
{
int i;
char *v, *e;
v = XGetDefault (dpy, "Xft", option);
if (v) {
if (FcNameConstant ((FcChar8 *) v, value))
return TRUE;
i = strtol (v, &e, 0);
if (e != v)
return TRUE;
}
return FALSE;
}
/* Old versions of fontconfig didn't have these options */
#ifndef FC_HINT_NONE
#define FC_HINT_NONE 0
#define FC_HINT_SLIGHT 1
#define FC_HINT_MEDIUM 2
#define FC_HINT_FULL 3
#endif
static void
_cairo_xlib_init_screen_font_options (cairo_xlib_screen_info_t *info)
{
cairo_bool_t xft_hinting;
cairo_bool_t xft_antialias;
int xft_hintstyle;
int xft_rgba;
cairo_antialias_t antialias;
cairo_subpixel_order_t subpixel_order;
cairo_hint_style_t hint_style;
if (!get_boolean_default (info->display, "antialias", &xft_antialias))
xft_antialias = TRUE;
if (!get_boolean_default (info->display, "hinting", &xft_hinting))
xft_hinting = TRUE;
if (!get_integer_default (info->display, "hintstyle", &xft_hintstyle))
xft_hintstyle = FC_HINT_FULL;
if (!get_integer_default (info->display, "rgba", &xft_rgba))
{
xft_rgba = FC_RGBA_UNKNOWN;
#if RENDER_MAJOR > 0 || RENDER_MINOR >= 6
if (info->has_render)
{
int render_order = XRenderQuerySubpixelOrder (info->display, info->screen);
switch (render_order)
{
default:
case SubPixelUnknown:
xft_rgba = FC_RGBA_UNKNOWN;
break;
case SubPixelHorizontalRGB:
xft_rgba = FC_RGBA_RGB;
break;
case SubPixelHorizontalBGR:
xft_rgba = FC_RGBA_BGR;
break;
case SubPixelVerticalRGB:
xft_rgba = FC_RGBA_VRGB;
break;
case SubPixelVerticalBGR:
xft_rgba = FC_RGBA_VBGR;
break;
case SubPixelNone:
xft_rgba = FC_RGBA_NONE;
break;
}
}
#endif
}
if (xft_hinting) {
switch (xft_hintstyle) {
case FC_HINT_NONE:
hint_style = CAIRO_HINT_STYLE_NONE;
break;
case FC_HINT_SLIGHT:
hint_style = CAIRO_HINT_STYLE_SLIGHT;
break;
case FC_HINT_MEDIUM:
hint_style = CAIRO_HINT_STYLE_MEDIUM;
break;
case FC_HINT_FULL:
hint_style = CAIRO_HINT_STYLE_FULL;
break;
default:
hint_style = CAIRO_HINT_STYLE_DEFAULT;
}
} else {
hint_style = CAIRO_HINT_STYLE_NONE;
}
switch (xft_rgba) {
case FC_RGBA_RGB:
subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
break;
case FC_RGBA_BGR:
subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
break;
case FC_RGBA_VRGB:
subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
break;
case FC_RGBA_VBGR:
subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
break;
case FC_RGBA_UNKNOWN:
case FC_RGBA_NONE:
default:
subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
}
if (xft_antialias) {
if (subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT)
antialias = CAIRO_ANTIALIAS_GRAY;
else
antialias = CAIRO_ANTIALIAS_SUBPIXEL;
} else {
antialias = CAIRO_ANTIALIAS_NONE;
}
_cairo_font_options_init_default (&info->font_options);
cairo_font_options_set_hint_style (&info->font_options, hint_style);
cairo_font_options_set_antialias (&info->font_options, antialias);
cairo_font_options_set_subpixel_order (&info->font_options, subpixel_order);
}
CAIRO_MUTEX_DECLARE(_xlib_screen_mutex);
static cairo_xlib_screen_info_t *_cairo_xlib_screen_list;
static int
_cairo_xlib_close_display (Display *dpy, XExtCodes *codes)
{
cairo_xlib_screen_info_t *info;
cairo_xlib_screen_info_t **prev;
/*
* Unhook from the global list
*/
CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
for (prev = &_cairo_xlib_screen_list; (info = *prev); prev = &(*prev)->next) {
if (info->display == dpy) {
*prev = info->next;
free (info);
if (!*prev)
break;
}
}
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
return 0;
}
cairo_private cairo_xlib_screen_info_t *
_cairo_xlib_screen_info_get (Display *dpy, int screen)
{
cairo_xlib_screen_info_t *info;
cairo_xlib_screen_info_t **prev;
int event_base, error_base;
XExtCodes *codes;
cairo_bool_t seen_display = FALSE;
/* There is an apparent deadlock between this mutex and the
* mutex for the display, but it's actually safe. For the
* app to call XCloseDisplay() while any other thread is
* inside this function would be an error in the logic
* app, and the CloseDisplay hook is the only other place we
* acquire this mutex.
*/
CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
for (prev = &_cairo_xlib_screen_list; (info = *prev); prev = &(*prev)->next)
{
if (info->display == dpy) {
seen_display = TRUE;
if (info->screen == screen)
{
/*
* MRU the list
*/
if (prev != &_cairo_xlib_screen_list)
{
*prev = info->next;
info->next = _cairo_xlib_screen_list;
_cairo_xlib_screen_list = info;
}
break;
}
}
}
if (info)
goto out;
info = malloc (sizeof (cairo_xlib_screen_info_t));
if (!info)
goto out;
if (!seen_display) {
codes = XAddExtension (dpy);
if (!codes) {
free (info);
info = NULL;
goto out;
}
XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display);
}
info->display = dpy;
info->screen = screen;
info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
(XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0));
_cairo_xlib_init_screen_font_options (info);
info->next = _cairo_xlib_screen_list;
_cairo_xlib_screen_list = info;
out:
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
return info;
}

View file

@ -38,6 +38,7 @@
#include "cairo-xlib.h"
#include "cairo-xlib-xrender.h"
#include "cairo-xlib-test.h"
#include "cairo-xlib-private.h"
#include <X11/extensions/Xrender.h>
/* Xlib doesn't define a typedef, so define one ourselves */
@ -70,6 +71,8 @@ struct _cairo_xlib_surface {
cairo_surface_t base;
Display *dpy;
cairo_xlib_screen_info_t *screen_info;
GC gc;
Drawable drawable;
Screen *screen;
@ -1321,6 +1324,15 @@ _cairo_xlib_surface_get_extents (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_xlib_surface_get_font_options (void *abstract_surface,
cairo_font_options_t *options)
{
cairo_xlib_surface_t *surface = abstract_surface;
*options = surface->screen_info->font_options;
}
static cairo_int_status_t
_cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
@ -1351,7 +1363,9 @@ static const cairo_surface_backend_t cairo_xlib_surface_backend = {
_cairo_xlib_surface_set_clip_region,
NULL, /* intersect_clip_path */
_cairo_xlib_surface_get_extents,
_cairo_xlib_surface_show_glyphs
_cairo_xlib_surface_show_glyphs,
NULL, /* fill_path */
_cairo_xlib_surface_get_font_options
};
/**
@ -1379,6 +1393,11 @@ _cairo_xlib_surface_create_internal (Display *dpy,
int depth)
{
cairo_xlib_surface_t *surface;
cairo_xlib_screen_info_t *screen_info;
screen_info = _cairo_xlib_screen_info_get (dpy, DefaultScreen (dpy));
if (!screen_info)
return NULL;
surface = malloc (sizeof (cairo_xlib_surface_t));
if (surface == NULL)
@ -1387,6 +1406,7 @@ _cairo_xlib_surface_create_internal (Display *dpy,
_cairo_surface_init (&surface->base, &cairo_xlib_surface_backend);
surface->dpy = dpy;
surface->screen_info = screen_info;
surface->gc = NULL;
surface->drawable = drawable;

View file

@ -635,7 +635,148 @@ typedef enum _cairo_font_weight {
CAIRO_FONT_WEIGHT_NORMAL,
CAIRO_FONT_WEIGHT_BOLD
} cairo_font_weight_t;
/**
* cairo_antialias_t:
* @CAIRO_ANTIALIAS_DEFAULT: Use the default antialiasing for
* the font subsystem and target device
* @CAIRO_ANTIALIAS_NONE: Do no antialiasing of fonts; use bilevel text
* @CAIRO_ANTIALIAS_GRAY: Perform single-color antialiasing (using
* shades of gray for black text on a white background, for example).
* @CAIRO_ANTIALIAS_SUBPIXEL: Perform antialiasing by taking
* advantage of the order of subpixel elements on devices
* such as LCD panels
*
* Specifies the type of antialiasing to do when rendering text.
**/
typedef enum _cairo_antialias {
CAIRO_ANTIALIAS_DEFAULT,
CAIRO_ANTIALIAS_NONE,
CAIRO_ANTIALIAS_GRAY,
CAIRO_ANTIALIAS_SUBPIXEL
} cairo_antialias_t;
/**
* cairo_subpixel_order_t:
* @CAIRO_SUBPIXEL_ORDER_DEFAULT: Use the default subpixel order for
* for the target device
* @CAIRO_SUBPIXEL_ORDER_RGB: Subpixel elements are arranged horizontally
* with red at the left
* @CAIRO_SUBPIXEL_ORDER_BGR: Subpixel elements are arranged horizontally
* with blue at the left
* @CAIRO_SUBPIXEL_ORDER_VRGB: Subpixel elements are arranged vertically
* with red at the top
* @CAIRO_SUBPIXEL_ORDER_VBGR: Subpixel elements are arranged vertically
* with blue at the top
*
* The subpixel order specifies the order of color elements within
* each pixel on the display device when rendering with an
* antialiasing mode of %CAIRO_ANTIALIAS_SUBPIXEL.
**/
typedef enum _cairo_subpixel_order {
CAIRO_SUBPIXEL_ORDER_DEFAULT,
CAIRO_SUBPIXEL_ORDER_RGB,
CAIRO_SUBPIXEL_ORDER_BGR,
CAIRO_SUBPIXEL_ORDER_VRGB,
CAIRO_SUBPIXEL_ORDER_VBGR
} cairo_subpixel_order_t;
/**
* cairo_hint_style_t:
* @CAIRO_HINT_STYLE_DEFAULT: Use the default hint style for
* for font backend and target device
* @CAIRO_HINT_STYLE_NONE: Do not hint outlines
* @CAIRO_HINT_STYLE_SLIGHT: Hint outlines slightly to improve
* contrast while retaining good fidelity to the original
* shapes.
* @CAIRO_HINT_STYLE_MEDIUM: Hint outlines with medium strength
* giving a compromise between fidelity to the original shapes
* and contrast
* @CAIRO_HINT_STYLE_FULL: Hint outlines to maximize contrast
*
* Specifies the type of hinting to do on font outlines. Hinting
* is the process of fitting outlines to the pixel grid in order
* to improve the appearance of the result. Since hinting outlines
* involves distorting them, it also reduces the faithfulness
* to the original outline shapes. Not all of the outline hinting
* styles are supported by all font backends.
*/
typedef enum _cairo_hint_style {
CAIRO_HINT_STYLE_DEFAULT,
CAIRO_HINT_STYLE_NONE,
CAIRO_HINT_STYLE_SLIGHT,
CAIRO_HINT_STYLE_MEDIUM,
CAIRO_HINT_STYLE_FULL
} cairo_hint_style_t;
/**
* cairo_hint_metrics_t:
* @CAIRO_HINT_METRICS_DEFAULT: Hint metrics in the default
* manner for the font backend and target device
* @CAIRO_HINT_METRICS_OFF: Do not hint font metrics
* @CAIRO_HINT_METRICS_ON: Hint font metrics
*
* Specifies whether to hint font metrics; hinting font metrics
* means quantizing them so that they are integer values in
* device space. Doing this improves the consistency of
* letter and line spacing, however it also means that text
* will be laid out differently at different zoom factors.
*/
typedef enum _cairo_hint_metrics {
CAIRO_HINT_METRICS_DEFAULT,
CAIRO_HINT_METRICS_OFF,
CAIRO_HINT_METRICS_ON
} cairo_hint_metrics_t;
typedef struct _cairo_font_options cairo_font_options_t;
cairo_font_options_t *
cairo_font_options_create (void);
cairo_font_options_t *
cairo_font_options_copy (const cairo_font_options_t *original);
void
cairo_font_options_destroy (cairo_font_options_t *options);
cairo_status_t
cairo_font_options_status (cairo_font_options_t *options);
void
cairo_font_options_merge (cairo_font_options_t *options,
const cairo_font_options_t *other);
cairo_bool_t
cairo_font_options_equal (const cairo_font_options_t *options,
const cairo_font_options_t *other);
unsigned long
cairo_font_options_hash (const cairo_font_options_t *options);
void
cairo_font_options_set_antialias (cairo_font_options_t *options,
cairo_antialias_t antialias);
cairo_antialias_t
cairo_font_options_get_antialias (const cairo_font_options_t *options);
void
cairo_font_options_set_subpixel_order (cairo_font_options_t *options,
cairo_subpixel_order_t subpixel_order);
cairo_subpixel_order_t
cairo_font_options_get_subpixel_order (const cairo_font_options_t *options);
void
cairo_font_options_set_hint_style (cairo_font_options_t *options,
cairo_hint_style_t hint_style);
cairo_hint_style_t
cairo_font_options_get_hint_style (const cairo_font_options_t *options);
void
cairo_font_options_set_hint_metrics (cairo_font_options_t *options,
cairo_hint_metrics_t hint_metrics);
cairo_hint_metrics_t
cairo_font_options_get_hint_metrics (const cairo_font_options_t *options);
/* This interface is for dealing with text as text, not caring about the
font object inside the the cairo_t. */
@ -710,9 +851,10 @@ cairo_font_face_set_user_data (cairo_font_face_t *font_face,
/* Portable interface to general font features. */
cairo_scaled_font_t *
cairo_scaled_font_create (cairo_font_face_t *font_face,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm);
cairo_scaled_font_create (cairo_font_face_t *font_face,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
const cairo_font_options_t *options);
void
cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font);
@ -951,6 +1093,10 @@ cairo_surface_set_user_data (cairo_surface_t *surface,
void *user_data,
cairo_destroy_func_t destroy);
void
cairo_surface_get_font_options (cairo_surface_t *surface,
cairo_font_options_t *options);
void
cairo_surface_set_device_offset (cairo_surface_t *surface,
double x_offset,

View file

@ -476,6 +476,13 @@ struct _cairo_font_face {
const cairo_font_face_backend_t *backend;
};
struct _cairo_font_options {
cairo_antialias_t antialias;
cairo_subpixel_order_t subpixel_order;
cairo_hint_style_t hint_style;
cairo_hint_metrics_t hint_metrics;
};
/* cairo_font.c is responsible for a global glyph cache:
*
* - glyph entries: [[[base], cairo_unscaled_font_t, scale, flags, index],
@ -534,6 +541,7 @@ struct _cairo_scaled_font_backend {
cairo_font_weight_t weight,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
const cairo_font_options_t *options,
cairo_scaled_font_t **font);
void (*destroy) (void *font);
@ -585,6 +593,7 @@ struct _cairo_font_face_backend {
cairo_status_t (*create_font) (void *font_face,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
const cairo_font_options_t *options,
cairo_scaled_font_t **scaled_font);
};
@ -766,6 +775,9 @@ typedef struct _cairo_surface_backend {
cairo_fill_rule_t fill_rule,
double tolerance);
void
(*get_font_options) (void *surface,
cairo_font_options_t *options);
} cairo_surface_backend_t;
typedef struct _cairo_format_masks {
@ -1348,6 +1360,11 @@ cairo_private void
_cairo_scaled_font_get_glyph_cache_key (cairo_scaled_font_t *scaled_font,
cairo_glyph_cache_key_t *key);
/* cairo-font-options.c */
cairo_private void
_cairo_font_options_init_default (cairo_font_options_t *options);
/* cairo_hull.c */
cairo_private cairo_status_t
_cairo_hull_compute (cairo_pen_vertex_t *vertices, int *num_vertices);