Change cairo_font_t to refer to a font scaled to a particular output device resolution.

src/cairoint.h src/cairo_font.c src/cairo_ft_font.c src/cairo_xlib_surface.c src/cairo_pdf_surface.c src/cairo_gstate.c src/cairo.c: Switch many internal methods from handling cairo_unscaled_font_t and cairo_font_scale_t pairs to handling cairo_font_t.
src/cairo-ft-private.h src/cairo_ft_fontc: Add some internal interfaces for use by the FreeType backend.
Clear the gstate's current font when the transform or target surface changes.
src/cairo.h src/cairo_ft_font.c: Rename cairo_ft_font_pattern to cairo_ft_font_get_pattern().
src/cairo.h src/cairo_ft_font.c: Make cairo_ft_font_create() and cairo_ft_font_create_for_ft_face() take a font scale; make the latter take load_flags for FT_Load_Glyph() as well. Change cairo_ft_font_face() to Xft-style cairo_ft_font_lock_face, cairo_ft_font_unlock_face.
Remove the name/slant/weight=>unscaled font cache, it didn't work with the new cairo_font_t setup. If it turns out to be needed, it can be added back in some other form.
src/cairoint.h src/cairo_font.c: Add a 'flags' field to cairo_glyph_cache_key_t, we use it for load flags with freetype backend.
Switch the caching to be from resolved fontconfig pattern => file; keep only a fixed number of FT_Face objects open at once, similar to FreeType.
src/cairo_gstate.c src/cairoint.h: Add public cairo_font_glyph_extents, use it to implement _cairo_gstate_glyph_extents().
Add refcounting for glyph cache elements; there was an bug where elements got ejected from the cache and freed before they could be used.
src/cairoint.h src/cairo_cache.c (_cairo_cache_random_entry()) New function to return a random entry in the cache matching a predicate; reuse the internals for the previous _random_live_entry().
src/cairoint.h src/cairo_cache.c (_cairo_cache_lookup()): Add an optional created_entry return value.
src/cairo_ft_font.c src/cairo_xlib_surface.c: Adapt to _cairo_cache_lookup() change.
Support max_memory == 0 to indicate an unbounded cache.
src/cairoint.h src/cairo_cache.c (_cairo_cache_remove()): Add a function to manually remove entries from the cache.
Update for changes, document cairo_matrix_t, cairo_glyph_t, etc.
src/cairo.h src/cairo-atsui.h src/cairo-ft.h src/cairo-glitz.h src/cairo-pdf.h src/cairo-png.h src/cairo-ps.h src/cairo-quartz.h src/cairo-xcb.h src/cairo-xlib.h: Add CAIRO_BEGIN/END_DECLS for extern "C", use it on all public headers. Move header guards outermost.
Fix encoding.
This commit is contained in:
Owen Taylor 2005-01-21 14:33:47 +00:00
parent 9068937026
commit 97424a3c2a
42 changed files with 3143 additions and 2004 deletions

View file

@ -1,3 +1,77 @@
2005-01-16 Owen Taylor <otaylor@redhat.com>
Change cairo_font_t to refer to a font scaled to a particular
output device resolution.
* src/cairoint.h src/cairo_font.c src/cairo_ft_font.c
src/cairo_xlib_surface.c src/cairo_pdf_surface.c src/cairo_gstate.c
src/cairo.c: Switch many internal methods from handling
cairo_unscaled_font_t and cairo_font_scale_t pairs to handling
cairo_font_t.
* src/cairo-ft-private.h src/cairo_ft_fontc: Add some internal
interfaces for use by the FreeType backend.
* src/cairo_gstate.c: Clear the gstate's current font when
the transform or target surface changes.
* src/cairo.h src/cairo_ft_font.c: Rename cairo_ft_font_pattern
to cairo_ft_font_get_pattern().
* src/cairo.h src/cairo_ft_font.c: Make cairo_ft_font_create()
and cairo_ft_font_create_for_ft_face() take a font scale;
make the latter take load_flags for FT_Load_Glyph() as well.
Change cairo_ft_font_face() to Xft-style cairo_ft_font_lock_face,
cairo_ft_font_unlock_face.
* src/cairo_font.c: Remove the name/slant/weight=>unscaled font
cache, it didn't work with the new cairo_font_t setup. If it turns
out to be needed, it can be added back in some other form.
* src/cairoint.h src/cairo_font.c: Add a 'flags' field
to cairo_glyph_cache_key_t, we use it for load flags with
freetype backend.
* src/cairo_ft_font.c: Switch the caching to be from
resolved fontconfig pattern => file; keep only a fixed number
of FT_Face objects open at once, similar to FreeType.
* src/cairo_font.c (cairo_font_glyph_extents) src/cairo_gstate.c
src/cairoint.h: Add public cairo_font_glyph_extents, use it
to implement _cairo_gstate_glyph_extents().
* src/cairo_xlib_surface.c (_glyphset_cache_entry_reference):
Add refcounting for glyph cache elements; there was an
bug where elements got ejected from the cache and freed before
they could be used.
* src/cairoint.h src/cairo_cache.c (_cairo_cache_random_entry())
New function to return a random entry in the cache matching a predicate;
reuse the internals for the previous _random_live_entry().
* src/cairoint.h src/cairo_cache.c (_cairo_cache_lookup()): Add an
optional created_entry return value.
* src/cairo_ft_font.c src/cairo_xlib_surface.c: Adapt to
_cairo_cache_lookup() change.
* src/cairo_cache.c (_cairo_cache_lookup()): Support max_memory == 0
to indicate an unbounded cache.
* src/cairoint.h src/cairo_cache.c (_cairo_cache_remove()): Add a
function to manually remove entries from the cache.
* doc/reference: Update for changes, document cairo_matrix_t,
cairo_glyph_t, etc.
* src/cairo.h src/cairo-atsui.h src/cairo-ft.h src/cairo-glitz.h
src/cairo-pdf.h src/cairo-png.h src/cairo-ps.h src/cairo-quartz.h
src/cairo-xcb.h src/cairo-xlib.h: Add CAIRO_BEGIN/END_DECLS for
extern "C", use it on all public headers. Move header guards
outermost.
* src/cairo_quartz_surface.c: Fix encoding.
2005-01-21 Carl Worth <cworth@cworth.org>
* configure.in: Increment CAIRO_VERSION to 0.3.0

View file

@ -51,6 +51,7 @@
<!ENTITY cairo_clip SYSTEM "xml/cairo_clip.xml">
<!ENTITY cairo_select_font SYSTEM "xml/cairo_select_font.xml">
<!ENTITY cairo_scale_font SYSTEM "xml/cairo_scale_font.xml">
<!ENTITY cairo_set_font SYSTEM "xml/cairo_set_font.xml">
<!ENTITY cairo_show_text SYSTEM "xml/cairo_show_text.xml">
<!ENTITY cairo_text_extents SYSTEM "xml/cairo_text_extents.xml">
<!ENTITY cairo_current_operator SYSTEM "xml/cairo_current_operator.xml">
@ -85,13 +86,22 @@
<!ENTITY cairo_matrix_multiply SYSTEM "xml/cairo_matrix_multiply.xml">
<!ENTITY cairo_matrix_transform_distance SYSTEM "xml/cairo_matrix_transform_distance.xml">
<!ENTITY cairo_matrix_transform_point SYSTEM "xml/cairo_matrix_transform_point.xml">
<!ENTITY cairo_font_glyph_extents SYSTEM "xml/cairo_font_glyph_extents.xml">
<!ENTITY cairo_ft_font_create SYSTEM "xml/cairo_ft_font_create.xml">
<!ENTITY cairo_ft_font_create_for_ft_face SYSTEM "xml/cairo_ft_font_create_for_ft_face.xml">
<!ENTITY cairo_ft_font_lock_face SYSTEM "xml/cairo_ft_font_lock_face.xml">
<!ENTITY cairo_ft_font_unlock_face SYSTEM "xml/cairo_ft_font_unlock_face.xml">
<!ENTITY cairo_ft_font_get_pattern SYSTEM "xml/cairo_ft_font_get_pattern.xml">
<!ENTITY cairo_t SYSTEM "xml/cairo_t.xml">
<!ENTITY cairo_font_t SYSTEM "xml/cairo_font_t.xml">
<!ENTITY cairo_glyph_t SYSTEM "xml/cairo_glyph_t.xml">
<!ENTITY cairo_matrix_t SYSTEM "xml/cairo_matrix_t.xml">
<!ENTITY cairo_surface_t SYSTEM "xml/cairo_surface_t.xml">
<!ENTITY cairo_format_t SYSTEM "xml/cairo_format_t.xml">
<!ENTITY cairo_operator_t SYSTEM "xml/cairo_operator_t.xml">
<!ENTITY cairo_fill_rule_t SYSTEM "xml/cairo_fill_rule_t.xml">
<!ENTITY cairo_line_cap_t SYSTEM "xml/cairo_line_cap_t.xml">
<!ENTITY cairo_matrix_t SYSTEM "xml/cairo_matrix_t.xml">
<!ENTITY cairo_text_extents_t SYSTEM "xml/cairo_text_extents_t.xml">
]>
<book lang="en">
@ -150,6 +160,7 @@
&cairo_clip;
&cairo_select_font;
&cairo_scale_font;
&cairo_set_font;
&cairo_show_text;
&cairo_text_extents;
&cairo_current_operator;
@ -184,16 +195,24 @@
&cairo_matrix_multiply;
&cairo_matrix_transform_distance;
&cairo_matrix_transform_point;
&cairo_font_glyph_extents;
&cairo_ft_font_create;
&cairo_ft_font_create_for_ft_face;
&cairo_ft_font_lock_face;
&cairo_ft_font_unlock_face;
&cairo_ft_font_get_pattern;
</reference>
<reference>
<title>types and enums</title>
&cairo_t;
&cairo_matrix_t;
&cairo_font_t;
&cairo_glyph_t;
&cairo_surface_t;
&cairo_format_t;
&cairo_operator_t;
&cairo_fill_rule_t;
&cairo_line_cap_t;
&cairo_matrix_t;
&cairo_text_extents_t;
</reference>
</book>

View file

@ -10,7 +10,7 @@
</refnamediv>
<refsynopsisdiv>
<programlisting>
cairo_font_t *
<link linkend="cairo_font_t">cairo_font_t</link> *
cairo_current_font (<link linkend="cairo_t">cairo_t</link> *cr)</programlisting>
<variablelist role="params">
<varlistentry>
@ -31,7 +31,7 @@
<indexterm>
<primary/>
</indexterm>
returns pointer to the current cairo_font_t object in the <link linkend="cairo_t">cairo_t</link>
returns pointer to the current <link linkend="cairo_font_t">cairo_font_t</link> object in the <link linkend="cairo_t">cairo_t</link>
</para>
</refsect1>
</refentry>

View file

@ -0,0 +1,72 @@
<refentry id="cairo_font_glyph_extents">
<refmeta>
<refentrytitle>cairo_font_glyph_extents</refentrytitle>
<manvolnum>3</manvolnum>
</refmeta>
<refnamediv>
<refname>cairo_font_glyph_extents</refname>
<refpurpose>Gets the metrics for a string of glyphs</refpurpose>
</refnamediv>
<refsynopsisdiv>
<programlisting>
<structname>void </structname> cairo_font_glyph_extents (<link linkend="cairo_font_t">cairo_font_t</link> *font, <link linkend="cairo_matrix_t">cairo_matrix_t</link> *font_matrix, <link linkend="cairo_glyph_t">cairo_glyph_t</link> *glyphs, int num_glyphs, <link linkend="cairo_text_extents_t">cairo_text_extents_t</link> *extents)</programlisting>
<variablelist role="params">
<varlistentry>
<term><parameter>font</parameter> :</term>
<listitem>
<simpara>A <link linkend="cairo_font_t">cairo_font_t</link>.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>font_matrix</parameter> :</term>
<listitem>
<simpara>
The font transformation for which this font was
created. (See <link linkend="cairo_transform_font">cairo_transform_font</link>.) This is needed
properly convert the metrics from the font into user space.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>glyphs</parameter> :</term>
<listitem>
<simpara>
An array of glyph IDs with x and y offsets.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>num_glyphs</parameter> :</term>
<listitem>
<simpara>
The number of glyphs in the <parameter>glyphs</parameter> array.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>extents</parameter> :</term>
<listitem>
<simpara>
A <link linkend="cairo_text_extents_t">cairo_text_extents_t</link> in which to store the retrieved extents.
</simpara>
</listitem>
</varlistentry>
</variablelist>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
<indexterm>
<primary>functions</primary>
<secondary>cairo_font_glyph_extents</secondary>
</indexterm>
<indexterm>
<primary/>
</indexterm>
<function>cairo_font_glyph_extents</function> gets the metrics
for a string of glyphs.
</para>
</refsect1>
</refentry>

View file

@ -0,0 +1,25 @@
<refentry id="cairo_font_t">
<refmeta>
<refentrytitle>cairo_font_t</refentrytitle>
<manvolnum>3</manvolnum>
</refmeta>
<refnamediv>
<refname>cairo_font_t</refname>
<refpurpose>scaled font object</refpurpose>
</refnamediv>
<refsect1>
<title>Description</title>
<para><indexterm><primary>types</primary><secondary>cairo_font_t</secondary></indexterm>
A <structname>cairo_font_t</structname> is a font scaled to a
particular size and device resolution. A font can be set on a
<link linkend="cairo_t">cairo_t</link> by using <link linkend="cairo_set_font">cairo_set_font</link>, assuming that the
current transformation and target surface of the
<structname><link linkend="cairo_t">cairo_t</link></structname> match that for which the
<structname>cairo_font_t</structname> was created. The effect of
using a mismatched <structname>cairo_font_t</structname> will be
incorrect font metrics.
</para>
</refsect1>
</refentry>

View file

@ -0,0 +1,59 @@
<refentry id="cairo_ft_font_create">
<refmeta>
<refentrytitle>cairo_ft_font_create</refentrytitle>
<manvolnum>3</manvolnum>
</refmeta>
<refnamediv>
<refname>cairo_ft_font_create</refname>
<refpurpose>creates a font for the FreeType font backend</refpurpose>
</refnamediv>
<refsynopsisdiv>
<programlisting>
<link linkend="cairo_font_t">cairo_font_t</link> *cairo_ft_font_create (FcPattern *pattern, <link linkend="cairo_matrix_t">cairo_matrix_t</link> *scale)</programlisting>
<variablelist role="params">
<varlistentry>
<term><parameter>pattern</parameter> :</term>
<listitem>
<simpara>A fully resolved fontconfig pattern. A pattern can
be resolved, by, among other things, calling <function>FcConfigSubstitute</function>,
<function>FcDefaultSubstitute</function>, then
<function>FcFontMatch</function>. Cairo will call
<function>FcPatternReference</function> on this pattern, so you should not
further modify the pattern, but you can release your
reference to the pattern with <function>FcPatternDestroy</function> if you
no longer need to access it.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>scale</parameter> :</term>
<listitem>
<simpara>The scale at which this font will be used. The
scale is given by multiplying the font matrix (see
<link linkend="cairo_transform_font">cairo_transform_font</link>)
by the current transformation matrix. The translation
elements of the resulting matrix are ignored.
</simpara>
</listitem>
</varlistentry>
</variablelist>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
<indexterm>
<primary>functions</primary>
<secondary>cairo_ft_font_create</secondary>
</indexterm>
<indexterm>
<primary/>
</indexterm>
<function>cairo_ft_font_create</function> creates a new font for
the FreeType font backend based on a fontconfig pattern. This
font can then be used with <link linkend="cairo_set_font">cairo_set_font</link>,
<link linkend="cairo_font_glyph_extents">cairo_font_glyph_extents</link>, or FreeType backend specific functions
like <link linkend="cairo_ft_font_lock_face">cairo_ft_font_lock_face</link>.
</para>
</refsect1>
</refentry>

View file

@ -0,0 +1,69 @@
<refentry id="cairo_ft_font_create_for_ft_face">
<refmeta>
<refentrytitle>cairo_ft_font_create_for_ft_face</refentrytitle>
<manvolnum>3</manvolnum>
</refmeta>
<refnamediv>
<refname>cairo_ft_font_create_for_ft_face</refname>
<refpurpose>creates a font for the FreeType font backend from a
pre-opened FreeType face</refpurpose>
</refnamediv>
<refsynopsisdiv>
<programlisting>
<link linkend="cairo_font_t">cairo_font_t</link> *cairo_ft_font_create_for_ft_face (FT_Face face, int load_flags, <link linkend="cairo_matrix_t">cairo_matrix_t</link> *scale)</programlisting>
<variablelist role="params">
<varlistentry>
<term><parameter>face</parameter> :</term>
<listitem>
<simpara>A FreeType face object, already opened. This must
be kept around until the font object's refcount drops to
zero and it is freed. The font object can be kept alive by
internal caching, so it's safest to keep the face object
around forever.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>load_flags</parameter> :</term>
<listitem>
<simpara>The flags to pass to <function>FT_Load_Glyph</function> when loading
glyphs from the font. These flags control aspects of
rendering such as hinting and antialiasing. See the FreeType
docs for full information.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>scale</parameter> :</term>
<listitem>
<simpara>The scale at which this font will be used. The
scale is given by multiplying the font matrix (see
<link linkend="cairo_transform_font">cairo_transform_font</link>)
by the current transformation matrix. The translation
elements of the resulting transformation are ignored.</simpara>
</listitem>
</varlistentry>
</variablelist>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
<indexterm>
<primary>functions</primary>
<secondary>cairo_ft_font_create_for_ft_face</secondary>
</indexterm>
<indexterm>
<primary/>
</indexterm>
<function>cairo_ft_font_create_for_ft_face</function> creates a new font for
the FreeType font backend from a pre-opened FreeType face. This
font can then be used with <link linkend="cairo_set_font">cairo_set_font</link>,
<link linkend="cairo_font_glyph_extents">cairo_font_glyph_extents</link>, or FreeType backend specific functions
like <link linkend="cairo_ft_font_lock_face">cairo_ft_font_lock_face</link>. Cairo will determine the pixel
size and transformation from the <parameter>scale</parameter> parameter
and call <function>FT_Set_Transform</function> and
<function>FT_Set_Pixel_Sizes</function>.
</para>
</refsect1>
</refentry>

View file

@ -0,0 +1,49 @@
<refentry id="cairo_ft_font_get_pattern">
<refmeta>
<refentrytitle>cairo_ft_font_get_pattern</refentrytitle>
<manvolnum>3</manvolnum>
</refmeta>
<refnamediv>
<refname>cairo_ft_font_get_pattern</refname>
<refpurpose>Gets the <structname>FcPattern</structname> for a FreeType
backend font</refpurpose>
</refnamediv>
<refsynopsisdiv>
<programlisting>
<structname>FcPattern *</structname> cairo_ft_font_get_pattern
(<link linkend="cairo_font_t">cairo_font_t</link> *font)</programlisting>
<variablelist role="params">
<varlistentry>
<term><parameter>font</parameter> :</term>
<listitem>
<simpara>A <link linkend="cairo_font_t">cairo_font_t</link> from the FreeType font backend. Such
an object can be created with <link linkend="cairo_ft_font_create">cairo_ft_font_create</link> or
<link linkend="cairo_ft_font_create_for_ft_face">cairo_ft_font_create_for_ft_face</link>. On some platforms the font
from <link linkend="cairo_current_font">cairo_current_font</link> will also be a FreeType font, but
using this functionality with fonts you don't create
yourself is not recommended.
</simpara>
</listitem>
</varlistentry>
</variablelist>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
<indexterm>
<primary>functions</primary>
<secondary>cairo_ft_font_get_pattern</secondary>
</indexterm>
<indexterm>
<primary/>
</indexterm>
<function>cairo_ft_font_get_pattern</function> gets the <structname>FcPattern</structname>
for a FreeType backend font. The return value is owned
by the font, so you must not modify it, and must call
<function>FcPatternReference</function> to keep a persistant
reference to the pattern. If the font was created with
<link linkend="cairo_ft_font_create_for_ft_face">cairo_ft_font_create_for_ft_face</link> the result will be NULL.
</para>
</refsect1>
</refentry>

View file

@ -0,0 +1,61 @@
<refentry id="cairo_ft_font_lock_face">
<refmeta>
<refentrytitle>cairo_ft_font_lock_face</refentrytitle>
<manvolnum>3</manvolnum>
</refmeta>
<refnamediv>
<refname>cairo_ft_font_lock_face</refname>
<refpurpose>Gets the <structname>FT_Face</structname> from a FreeType
backend font</refpurpose>
</refnamediv>
<refsynopsisdiv>
<programlisting>
<structname>FT_Face</structname> cairo_ft_font_lock_face (<link linkend="cairo_font_t">cairo_font_t</link> *font)</programlisting>
<variablelist role="params">
<varlistentry>
<term><parameter>font</parameter> :</term>
<listitem>
<simpara>A <link linkend="cairo_font_t">cairo_font_t</link> from the FreeType font backend. Such
an object can be created with <link linkend="cairo_ft_font_create">cairo_ft_font_create</link> or
<link linkend="cairo_ft_font_create_for_ft_face">cairo_ft_font_create_for_ft_face</link>. On some platforms the font
from <link linkend="cairo_current_font">cairo_current_font</link> will also be a FreeType font, but
using this functionality with fonts you don't create
yourself is not recommended.
</simpara>
</listitem>
</varlistentry>
</variablelist>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
<indexterm>
<primary>functions</primary>
<secondary>cairo_ft_font_lock_face</secondary>
</indexterm>
<indexterm>
<primary/>
</indexterm>
<function>cairo_ft_font_lock_face</function> gets the <structname>FT_Face</structname>
object from a FreeType backend font and scales it appropriately
for the font. You must release the face with
<link linkend="cairo_ft_font_unlock_face">cairo_ft_font_unlock_face</link> when you are done using it.
Since the <structname>FT_Face</structname> object can be shared
between multiple <link linkend="cairo_font_t">cairo_font_t</link> objects, you must not lock any
other font objects until you unlock this one. A count is kept of
the number of times <function>cairo_ft_font_lock_face</function>
is called. <link linkend="cairo_ft_font_unlock_face">cairo_ft_font_unlock_face</link> must be called the same
number of times.
</para>
<para>
You must be careful when using this function in a library or in
a threaded application, because other threads may lock faces
that share the same <structname>FT_Face</structname> object. For
this reason, you must call cairo_ft_lock before locking any face
objects, and cairo_ft_unlock after you are done. (These
functions are not yet implemented, so this function cannot be
currently safely used in a threaded application.)
</para>
</refsect1>
</refentry>

View file

@ -0,0 +1,44 @@
<refentry id="cairo_ft_font_unlock_face">
<refmeta>
<refentrytitle>cairo_ft_font_unlock_face</refentrytitle>
<manvolnum>3</manvolnum>
</refmeta>
<refnamediv>
<refname>cairo_ft_font_unlock_face</refname>
<refpurpose>Releases the <structname>FT_Face</structname> from a FreeType
backend font</refpurpose>
</refnamediv>
<refsynopsisdiv>
<programlisting>
void cairo_ft_font_unlock_face (<link linkend="cairo_font_t">cairo_font_t</link> *font)</programlisting>
<variablelist role="params">
<varlistentry>
<term><parameter>font</parameter> :</term>
<listitem>
<simpara>A <link linkend="cairo_font_t">cairo_font_t</link> from the FreeType font backend. Such
an object can be created with <link linkend="cairo_ft_font_create">cairo_ft_font_create</link> or
<link linkend="cairo_ft_font_create_for_ft_face">cairo_ft_font_create_for_ft_face</link>. On some platforms the font
from <link linkend="cairo_current_font">cairo_current_font</link> will also be a FreeType font, but
using this functionality with fonts you don't create
yourself is not recommended.
</simpara>
</listitem>
</varlistentry>
</variablelist>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
<indexterm>
<primary>functions</primary>
<secondary>cairo_ft_font_unlock_face</secondary>
</indexterm>
<indexterm>
<primary/>
</indexterm>
Releases a face obtained with <link linkend="cairo_ft_font_lock_face">cairo_ft_font_lock_face</link>. See the
documentation for that function for full details.
</para>
</refsect1>
</refentry>

View file

@ -0,0 +1,62 @@
<refentry id="cairo_glyph_t">
<refmeta>
<refentrytitle>cairo_glyph_t</refentrytitle>
<manvolnum>3</manvolnum>
</refmeta>
<refnamediv>
<refname>cairo_glyph_t</refname>
<refpurpose>struct holding information about a glyph</refpurpose>
</refnamediv>
<refsect1>
<title>Description</title>
<para><indexterm><primary>types</primary><secondary>cairo_glyph_t</secondary></indexterm><indexterm><primary/></indexterm>
<programlisting>
typedef struct {
double index;
double x;
double y;
} cairo_glyph_t;
</programlisting>
</para>
<para>
The <structname>cairo_glyph_t</structname> structure holds
information about a single glyph when drawing or measuring
text. A font is (in simple terms) a collection of shapes used to
draw text. A glyph is one of these shapes. There can be multiple
glyphs for a single character (alternates to be used in
different contexts, for example), or a glyph can be a
<firstterm>ligature</firstterm> of multiple characters. Cairo
doesn't expose any way of converting input text into glyphs, so
in order to use the Cairo interfaces that take arrays of glyphs,
you must directly access the appropriate underlying font system.
</para>
<variablelist role="struct">
<varlistentry>
<term><structfield>index</structfield></term>
<listitem><simpara>glyph index in the font. The exact
interpretation of the glyph index depends on the font
technology being used.
</simpara></listitem>
</varlistentry>
<varlistentry>
<term><structfield>x</structfield></term>
<listitem><simpara>the offset in the x direction between the
origin used for drawing or measuring the string and the
origin of this glyph. These offsets are not cumulative; each
glyph is indiviually positioned with respect to the
overall origin.
</simpara></listitem>
</varlistentry>
<varlistentry>
<term><structfield>y</structfield></term>
<listitem><simpara>the offset in the y direction between the
origin used for drawing or measuring the string and the
origin of this glyph. These offsets are not cumulative; each
glyph is indiviually positioned with respect to the
overall origin.
</simpara></listitem>
</varlistentry>
</variablelist>
</refsect1>
</refentry>

View file

@ -11,13 +11,23 @@
<refsect1>
<title>Description</title>
<para><indexterm><primary>types</primary><secondary>cairo_matrix</secondary></indexterm><indexterm><primary/></indexterm>
A <varname>cairo_matrix</varname> contains the current state of the rendering device,
including coordinates of yet to be drawn shapes.
<varname>cairo_matrix</varname>'s can be pushed to a stack via
<link linkend="cairo_save">cairo_save</link>.
They may then savely be changed, without loosing the current state.
Use <link linkend="cairo_restore">cairo_restore</link> to
restore to the saved state.
<structname>cairo_matrix_t</structname> is used throughout
Cairo to represents between different coordinates spaces.
A <structname>cairo_matrix</structname> holds an affine
transformation, such as a scale, rotation, or shear, or a
combination of those. Mathematically, the effect of an affine
transformation on a point (<literal>x</literal>,<literal>y</literal>) is given by:
</para>
<programlisting>
x_new = x * a + y * c + tx;
y_new = x * b + y * d + ty;
</programlisting>
<para>
The paramaters <literal>a</literal>, <literal>b</literal>,
<literal>c</literal>, <literal>d</literal>,
<literal>tx</literal>, <literal>ty</literal> can be retrieved
with cairo_matrix_get_affine and set with
cairo_matrix_get_affine.
</para>
</refsect1>
</refentry>

View file

@ -9,7 +9,7 @@
</refnamediv>
<refsynopsisdiv>
<programlisting>
void cairo_set_font (<link linkend="cairo_t">cairo_t</link> *cr, cairo_font_t *font)</programlisting>
void cairo_set_font (<link linkend="cairo_t">cairo_t</link> *cr, <link linkend="cairo_font_t">cairo_font_t</link> *font)</programlisting>
<variablelist role="params">
<varlistentry>
<term><parameter>cr</parameter> :</term>
@ -20,7 +20,7 @@ void cairo_set_font (<link linkend="cairo_t">cairo_t</link> *cr, cairo_font_t *f
<varlistentry>
<term><parameter>font</parameter> :</term>
<listitem>
<simpara>replaces the current cairo_font_t object in the <link linkend="cairo_t">cairo_t</link> with font. The replaced font in the <link linkend="cairo_t">cairo_t</link> will be destroyed if there are no other references to it.</simpara>
<simpara>a <link linkend="cairo_font_t">cairo_font_t</link></simpara>
</listitem>
</varlistentry>
</variablelist>
@ -35,6 +35,18 @@ void cairo_set_font (<link linkend="cairo_t">cairo_t</link> *cr, cairo_font_t *f
<indexterm>
<primary/>
</indexterm>
Replaces the current <link linkend="cairo_font_t">cairo_font_t</link> object in the <link linkend="cairo_t">cairo_t</link> with font. The replaced font in
the <link linkend="cairo_t">cairo_t</link> will be destroyed if
there are no other references to it. Since a <link linkend="cairo_font_t">cairo_font_t</link> is
specific to a particular output device and size, changing the
transformation, font transformation, or target surfaces of a
<structname><link linkend="cairo_t">cairo_t</link></structname>
will clear any previously set font. Setting the font using
<function>cairo_set_font</function> is exclusive with the
simple font selection API provided by <link linkend="cairo_select_font">cairo_select_font</link>. The
size and transformation set by <link linkend="cairo_scale_font">cairo_scale_font</link>() and
<link linkend="cairo_transform_font">cairo_transform_font</link>() are ignored unless they were taken into
account when creating <parameter>font</parameter>.
</para>
</refsect1>
</refentry>

View file

@ -9,7 +9,7 @@
</refnamediv>
<refsynopsisdiv>
<programlisting>
void cairo_show_glyphs (<link linkend="cairo_t">cairo_t</link> *cr, cairo_glyph_t *glyphs, int num_glyphs);</programlisting>
void cairo_show_glyphs (<link linkend="cairo_t">cairo_t</link> *cr, <link linkend="cairo_glyph_t">cairo_glyph_t</link> *glyphs, int num_glyphs);</programlisting>
<variablelist role="params">
<varlistentry>
<term><parameter>cr</parameter> :</term>

View file

@ -23,7 +23,54 @@
</programlisting>
</para>
<para>
XXX. not sure what the status is right know.
The <structname>cairo_text_extents_t</structname> structure
stores the extents of a single glyph or a string of glyphs in
user-space coordinates. Because text extents are in user-space
coordinates, they don't scale along with the current
transformation matrix. If you call <link linkend="cairo_scale">cairo_scale</link>(cr, 2.0, 2.0),
text will be drawn twice as big, but the reported text extents
will not be doubled. They will change slightly due to hinting
(so you can't assume that metrics are independent of the
transformation matrix), but otherwise will remain unchanged.
</para>
<variablelist role="struct">
<varlistentry>
<term><structfield>x_bearing</structfield></term>
<listitem><simpara>the horizontal distance from the origin to the
leftmost part of the glyphs as drawn. Positive if the
glyphs lie entirely to the right of the origin.
</simpara></listitem>
</varlistentry>
<varlistentry>
<term><structfield>y_bearing</structfield></term>
<listitem><simpara>the vertical distance from the origin to the
topmost part of the glyphs as drawn. Positive only if the
glyphs lie completely below the origin; will usually be negative.
</simpara></listitem>
</varlistentry>
<varlistentry>
<term><structfield>width</structfield></term>
<listitem><simpara>width of the glyphs as drawn.
</simpara></listitem>
</varlistentry>
<varlistentry>
<term><structfield>height</structfield></term>
<listitem><simpara>height of the glyphs as drawn.
</simpara></listitem>
</varlistentry>
<varlistentry>
<term><structfield>x_advance</structfield></term>
<listitem><simpara>distance to advance in the X direction
after drawing these glyphs.
</simpara></listitem>
</varlistentry>
<varlistentry>
<term><structfield>y_advance</structfield></term>
<listitem><simpara>distance to advance in the Y direction
after drawing these glyphs. Will typically be zero except
for vertical text layout as found in East-Asian languages.
</simpara></listitem>
</varlistentry>
</variablelist>
</refsect1>
</refentry>

View file

@ -33,18 +33,23 @@
* Calum Robinson <calumr@mac.com>
*/
#include <cairo.h>
#ifndef CAIRO_ATSUI_H
#define CAIRO_ATSUI_H
#include <cairo.h>
#ifdef CAIRO_HAS_ATSUI_FONT
/* ATSUI platform-specific font interface */
#include <Carbon/Carbon.h>
CAIRO_BEGIN_DECLS
cairo_font_t *
cairo_atsui_font_create(ATSUStyle style);
CAIRO_END_DECLS
#endif /* CAIRO_HAS_ATSUI_FONT */
#endif /* CAIRO_ATSUI_H */

View file

@ -94,9 +94,9 @@ static const cairo_cache_arrangement_t cache_arrangements [] = {
* a mostly-dead table.
*
* Generally you do not need to worry about freeing cache entries; the
* cache will expire entries randomly as it experiences memory pressure.
* There is currently no explicit entry-removing call, though one can be
* added easily.
* cache will expire entries randomly as it experiences memory pressure.
* If max_memory is set, entries are not expired, and must be explicitely
* removed.
*
* This table is open-addressed with double hashing. Each table size is a
* prime chosen to be a little more than double the high water mark for a
@ -282,17 +282,51 @@ _load_factor (cairo_cache_t *cache)
}
#endif
static unsigned long
_random_live_entry (cairo_cache_t *cache)
{
unsigned long idx;
assert(cache != NULL);
do {
idx = rand () % cache->arrangement->size;
} while (! LIVE_ENTRY_P(cache, idx));
return idx;
}
/* Find a random in the cache matching the given predicate. We use the
* same algorithm as the probing algorithm to walk over the entries in
* the hash table in a pseudo-random order. Walking linearly would
* favor entries following gaps in the hash table. We could also
* call rand() repeatedly, which works well for almost-full tables,
* but degrades when the table is almost empty, or predicate
* returns false for most entries.
*/
static cairo_cache_entry_base_t **
_random_entry (cairo_cache_t *cache,
int (*predicate)(void*))
{
cairo_cache_entry_base_t **probe;
unsigned long hash;
unsigned long table_size, i, idx, step;
_cache_sane_state (cache);
table_size = cache->arrangement->size;
hash = rand ();
idx = hash % table_size;
step = 0;
for (i = 0; i < table_size; ++i)
{
assert(idx < table_size);
probe = cache->entries + idx;
if (LIVE_ENTRY_P(cache, idx)
&& (!predicate || predicate (*probe)))
return probe;
if (step == 0) {
step = hash % cache->arrangement->rehash;
if (step == 0)
step = 1;
}
idx += step;
if (idx >= table_size)
idx -= table_size;
}
return NULL;
}
/* public API follows */
@ -356,8 +390,9 @@ _cairo_cache_destroy (cairo_cache_t *cache)
cairo_status_t
_cairo_cache_lookup (cairo_cache_t *cache,
void *key,
void **entry_return)
void *key,
void **entry_return,
int *created_entry)
{
unsigned long idx;
@ -392,6 +427,8 @@ _cairo_cache_lookup (cairo_cache_t *cache,
cache->hits++;
#endif
*entry_return = *slot;
if (created_entry)
*created_entry = 0;
return status;
}
@ -401,19 +438,18 @@ _cairo_cache_lookup (cairo_cache_t *cache,
/* Build the new entry. */
status = cache->backend->create_entry (cache, key,
entry_return);
(void **)&new_entry);
if (status != CAIRO_STATUS_SUCCESS)
return status;
new_entry = (cairo_cache_entry_base_t *) (*entry_return);
/* Store the hash value in case the backend forgot. */
new_entry->hashcode = cache->backend->hash (cache, key);
/* Make some entries die if we're under memory pressure. */
while (cache->live_entries > 0 &&
cache->max_memory > 0 &&
((cache->max_memory - cache->used_memory) < new_entry->memory)) {
idx = _random_live_entry (cache);
idx = _random_entry (cache, NULL) - cache->entries;
assert (idx < cache->arrangement->size);
_entry_destroy (cache, idx);
}
@ -425,7 +461,6 @@ _cairo_cache_lookup (cairo_cache_t *cache,
status = _resize_cache (cache, cache->live_entries + 1);
if (status != CAIRO_STATUS_SUCCESS) {
cache->backend->destroy_entry (cache, new_entry);
*entry_return = NULL;
return status;
}
@ -439,9 +474,38 @@ _cairo_cache_lookup (cairo_cache_t *cache,
_cache_sane_state (cache);
*entry_return = new_entry;
if (created_entry)
*created_entry = 1;
return status;
}
cairo_status_t
_cairo_cache_remove (cairo_cache_t *cache,
void *key)
{
cairo_cache_entry_base_t **slot;
_cache_sane_state (cache);
/* See if we have an entry in the table already. */
slot = _find_exact_live_entry_for (cache, key);
if (slot != NULL)
_entry_destroy (cache, slot - cache->entries);
return CAIRO_STATUS_SUCCESS;
}
void *
_cairo_cache_random_entry (cairo_cache_t *cache,
int (*predicate)(void*))
{
cairo_cache_entry_base_t **slot = _random_entry (cache, predicate);
return *slot;
}
unsigned long
_cairo_hash_string (const char *c)
{

View file

@ -1,6 +1,7 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2002 University of Southern California
* Copyright © 2005 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@ -32,264 +33,85 @@
*
* Contributor(s):
* Carl D. Worth <cworth@isi.edu>
* Graydon Hoare <graydon@redhat.com>
* Owen Taylor <otaylor@redhat.com>
*/
#include "cairoint.h"
/* First we implement a global font cache for named fonts. */
typedef struct {
cairo_cache_entry_base_t base;
const char *family;
cairo_font_slant_t slant;
cairo_font_weight_t weight;
} cairo_font_cache_key_t;
typedef struct {
cairo_font_cache_key_t key;
cairo_unscaled_font_t *unscaled;
} cairo_font_cache_entry_t;
static unsigned long
_font_cache_hash (void *cache, void *key)
{
unsigned long hash;
cairo_font_cache_key_t *in;
in = (cairo_font_cache_key_t *) key;
/* 1607 and 1451 are just a couple random primes. */
hash = _cairo_hash_string (in->family);
hash += ((unsigned long) in->slant) * 1607;
hash += ((unsigned long) in->weight) * 1451;
return hash;
}
static int
_font_cache_keys_equal (void *cache,
void *k1,
void *k2)
{
cairo_font_cache_key_t *a, *b;
a = (cairo_font_cache_key_t *) k1;
b = (cairo_font_cache_key_t *) k2;
return (strcmp (a->family, b->family) == 0)
&& (a->weight == b->weight)
&& (a->slant == b->slant);
}
static cairo_status_t
_font_cache_create_entry (void *cache,
void *key,
void **return_value)
{
const cairo_font_backend_t *backend = CAIRO_FONT_BACKEND_DEFAULT;
cairo_font_cache_key_t *k;
cairo_font_cache_entry_t *entry;
k = (cairo_font_cache_key_t *) key;
/* XXX: The current freetype backend may return NULL, (for example
* if no fonts are installed), but I would like to guarantee that
* the toy API always returns at least *some* font, so I would
* like to build in some sort fo font here, (even a really lame,
* ugly one if necessary). */
entry = malloc (sizeof (cairo_font_cache_entry_t));
if (entry == NULL)
goto FAIL;
entry->key.slant = k->slant;
entry->key.weight = k->weight;
entry->key.family = strdup(k->family);
if (entry->key.family == NULL)
goto FREE_ENTRY;
entry->unscaled = backend->create (k->family, k->slant, k->weight);
if (entry->unscaled == NULL)
goto FREE_FAMILY;
/* Not sure how to measure backend font mem; use a simple count for now.*/
entry->key.base.memory = 1;
*return_value = entry;
return CAIRO_STATUS_SUCCESS;
FREE_FAMILY:
free ((void *) entry->key.family);
FREE_ENTRY:
free (entry);
FAIL:
return CAIRO_STATUS_NO_MEMORY;
}
static void
_font_cache_destroy_entry (void *cache,
void *entry)
{
cairo_font_cache_entry_t *e;
e = (cairo_font_cache_entry_t *) entry;
_cairo_unscaled_font_destroy (e->unscaled);
free ((void *) e->key.family);
free (e);
}
static void
_font_cache_destroy_cache (void *cache)
{
free (cache);
}
static const cairo_cache_backend_t cairo_font_cache_backend = {
_font_cache_hash,
_font_cache_keys_equal,
_font_cache_create_entry,
_font_cache_destroy_entry,
_font_cache_destroy_cache
};
static void
_lock_global_font_cache (void)
{
/* FIXME: implement locking. */
}
static void
_unlock_global_font_cache (void)
{
/* FIXME: implement locking. */
}
static cairo_cache_t *
_global_font_cache = NULL;
static cairo_cache_t *
_get_global_font_cache (void)
{
if (_global_font_cache == NULL) {
_global_font_cache = malloc (sizeof (cairo_cache_t));
if (_global_font_cache == NULL)
goto FAIL;
if (_cairo_cache_init (_global_font_cache,
&cairo_font_cache_backend,
CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT))
goto FAIL;
}
return _global_font_cache;
FAIL:
if (_global_font_cache)
free (_global_font_cache);
_global_font_cache = NULL;
return NULL;
}
/* Now the internal "unscaled + scale" font API */
cairo_unscaled_font_t *
_cairo_unscaled_font_create (const char *family,
cairo_font_slant_t slant,
cairo_font_weight_t weight)
cairo_private cairo_status_t
_cairo_font_create (const char *family,
cairo_font_slant_t slant,
cairo_font_weight_t weight,
cairo_font_scale_t *sc,
cairo_font_t **font)
{
cairo_cache_t * cache;
cairo_font_cache_key_t key;
cairo_font_cache_entry_t *font;
cairo_status_t status;
const cairo_font_backend_t *backend = CAIRO_FONT_BACKEND_DEFAULT;
_lock_global_font_cache ();
cache = _get_global_font_cache ();
if (cache == NULL) {
_unlock_global_font_cache ();
return NULL;
}
key.family = family;
key.slant = slant;
key.weight = weight;
status = _cairo_cache_lookup (cache, &key, (void **) &font);
if (status) {
_unlock_global_font_cache ();
return NULL;
}
_cairo_unscaled_font_reference (font->unscaled);
_unlock_global_font_cache ();
return font->unscaled;
return backend->create (family, slant, weight, sc, font);
}
void
_cairo_font_init (cairo_font_t *scaled,
cairo_font_scale_t *scale,
cairo_unscaled_font_t *unscaled)
_cairo_font_init (cairo_font_t *font,
cairo_font_scale_t *scale,
const cairo_font_backend_t *backend)
{
scaled->scale = *scale;
scaled->unscaled = unscaled;
scaled->refcount = 1;
font->scale = *scale;
font->refcount = 1;
font->backend = backend;
}
cairo_status_t
_cairo_unscaled_font_init (cairo_unscaled_font_t *font,
const cairo_font_backend_t *backend)
void
_cairo_unscaled_font_init (cairo_unscaled_font_t *font,
const cairo_font_backend_t *backend)
{
font->refcount = 1;
font->backend = backend;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_unscaled_font_text_to_glyphs (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
const unsigned char *utf8,
cairo_glyph_t **glyphs,
int *num_glyphs)
_cairo_font_text_to_glyphs (cairo_font_t *font,
const unsigned char *utf8,
cairo_glyph_t **glyphs,
int *num_glyphs)
{
return font->backend->text_to_glyphs (font, scale, utf8, glyphs, num_glyphs);
return font->backend->text_to_glyphs (font, utf8, glyphs, num_glyphs);
}
cairo_status_t
_cairo_unscaled_font_glyph_extents (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_text_extents_t *extents)
_cairo_font_glyph_extents (cairo_font_t *font,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_text_extents_t *extents)
{
return font->backend->glyph_extents(font, scale, glyphs, num_glyphs, extents);
return font->backend->glyph_extents(font, glyphs, num_glyphs, extents);
}
cairo_status_t
_cairo_unscaled_font_glyph_bbox (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_box_t *bbox)
_cairo_font_glyph_bbox (cairo_font_t *font,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_box_t *bbox)
{
return font->backend->glyph_bbox (font, scale, glyphs, num_glyphs, bbox);
return font->backend->glyph_bbox (font, glyphs, num_glyphs, bbox);
}
cairo_status_t
_cairo_unscaled_font_show_glyphs (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
cairo_operator_t operator,
cairo_surface_t *source,
cairo_surface_t *surface,
int source_x,
int source_y,
cairo_glyph_t *glyphs,
int num_glyphs)
_cairo_font_show_glyphs (cairo_font_t *font,
cairo_operator_t operator,
cairo_surface_t *source,
cairo_surface_t *surface,
int source_x,
int source_y,
cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_status_t status;
if (surface->backend->show_glyphs != NULL) {
status = surface->backend->show_glyphs (font, scale, operator, source,
status = surface->backend->show_glyphs (font, operator, source,
surface, source_x, source_y,
glyphs, num_glyphs);
if (status == CAIRO_STATUS_SUCCESS)
@ -297,27 +119,32 @@ _cairo_unscaled_font_show_glyphs (cairo_unscaled_font_t *font,
}
/* Surface display routine either does not exist or failed. */
return font->backend->show_glyphs (font, scale, operator, source,
return font->backend->show_glyphs (font, operator, source,
surface, source_x, source_y,
glyphs, num_glyphs);
}
cairo_status_t
_cairo_unscaled_font_glyph_path (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_path_t *path)
_cairo_font_glyph_path (cairo_font_t *font,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_path_t *path)
{
return font->backend->glyph_path (font, scale, glyphs, num_glyphs, path);
return font->backend->glyph_path (font, glyphs, num_glyphs, path);
}
void
_cairo_font_get_glyph_cache_key (cairo_font_t *font,
cairo_glyph_cache_key_t *key)
{
font->backend->get_glyph_cache_key (font, key);
}
cairo_status_t
_cairo_unscaled_font_font_extents (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
cairo_font_extents_t *extents)
_cairo_font_font_extents (cairo_font_t *font,
cairo_font_extents_t *extents)
{
return font->backend->font_extents(font, scale, extents);
return font->backend->font_extents (font, extents);
}
void
@ -332,8 +159,7 @@ _cairo_unscaled_font_destroy (cairo_unscaled_font_t *font)
if (--(font->refcount) > 0)
return;
if (font->backend)
font->backend->destroy (font);
font->backend->destroy_unscaled_font (font);
}
@ -352,37 +178,97 @@ cairo_font_destroy (cairo_font_t *font)
if (--(font->refcount) > 0)
return;
if (font->unscaled)
_cairo_unscaled_font_destroy (font->unscaled);
free (font);
font->backend->destroy_font (font);
}
void
cairo_font_set_transform (cairo_font_t *font,
cairo_matrix_t *matrix)
cairo_font_glyph_extents (cairo_font_t *font,
cairo_matrix_t *font_matrix,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_text_extents_t *extents)
{
double dummy;
cairo_matrix_get_affine (matrix,
&font->scale.matrix[0][0],
&font->scale.matrix[0][1],
&font->scale.matrix[1][0],
&font->scale.matrix[1][1],
&dummy, &dummy);
}
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_glyph_t origin_glyph;
cairo_text_extents_t origin_extents;
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;
void
cairo_font_current_transform (cairo_font_t *font,
cairo_matrix_t *matrix)
{
cairo_matrix_set_affine (matrix,
font->scale.matrix[0][0],
font->scale.matrix[0][1],
font->scale.matrix[1][0],
font->scale.matrix[1][1],
0, 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;
}
for (i = 0; i < num_glyphs; i++)
{
double x, y;
double wm, hm;
origin_glyph = glyphs[i];
origin_glyph.x = 0.0;
origin_glyph.y = 0.0;
status = _cairo_font_glyph_extents (font,
&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 = origin_extents.x_bearing;
y = origin_extents.y_bearing;
cairo_matrix_transform_point (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 (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 (font_matrix,
&x, &y);
x_pos = glyphs[i].x + x;
y_pos = glyphs[i].y + y;
}
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;
}
/* Now we implement functions to access a default global image & metrics
* cache.
@ -398,7 +284,8 @@ _cairo_glyph_cache_hash (void *cache, void *key)
^ ((unsigned long) in->scale.matrix[0][0])
^ ((unsigned long) in->scale.matrix[0][1])
^ ((unsigned long) in->scale.matrix[1][0])
^ ((unsigned long) in->scale.matrix[1][1])
^ ((unsigned long) in->scale.matrix[1][1])
^ (in->flags * 1451) /* 1451 is just an abitrary prime */
^ in->index;
}
@ -412,6 +299,7 @@ _cairo_glyph_cache_keys_equal (void *cache,
b = (cairo_glyph_cache_key_t *) k2;
return (a->index == b->index)
&& (a->unscaled == b->unscaled)
&& (a->flags == b->flags)
&& (a->scale.matrix[0][0] == b->scale.matrix[0][0])
&& (a->scale.matrix[0][1] == b->scale.matrix[0][1])
&& (a->scale.matrix[1][0] == b->scale.matrix[1][0])

File diff suppressed because it is too large Load diff

63
src/cairo-ft-private.h Normal file
View file

@ -0,0 +1,63 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Graydon Hoare <graydon@redhat.com>
* Owen Taylor <otaylor@redhat.com>
*/
#ifndef CAIRO_FT_PRIVATE_H
#define CAIRO_FT_PRIVATE_H
#include <cairo-ft.h>
#include <cairoint.h>
#ifdef CAIRO_HAS_FT_FONT
CAIRO_BEGIN_DECLS
/* These functions are needed by the PDF backend, which needs to keep track of the
* the different fonts-on-disk used by a document, so it can embed them
*/
cairo_private cairo_unscaled_font_t *
_cairo_ft_font_get_unscaled_font (cairo_font_t *font);
cairo_private FT_Face
_cairo_ft_unscaled_font_lock_face (cairo_unscaled_font_t *unscaled_font);
cairo_private void
_cairo_ft_unscaled_font_unlock_face (cairo_unscaled_font_t *unscaled_font);
CAIRO_END_DECLS
#endif /* CAIRO_HAS_FT_FONT */
#endif /* CAIRO_FT_PRIVATE_H */

View file

@ -1,6 +1,6 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2002 University of Southern California
* Copyright © 2005 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@ -27,17 +27,18 @@
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is University of Southern
* California.
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Carl D. Worth <cworth@isi.edu>
* Graydon Hoare <graydon@redhat.com>
* Owen Taylor <otaylor@redhat.com>
*/
#include <cairo.h>
#ifndef CAIRO_FT_H
#define CAIRO_FT_H
#include <cairo.h>
#ifdef CAIRO_HAS_FT_FONT
/* Fontconfig/Freetype platform-specific font interface */
@ -46,17 +47,27 @@
#include <ft2build.h>
#include FT_FREETYPE_H
cairo_font_t *
cairo_ft_font_create (FT_Library ft_library, FcPattern *pattern);
CAIRO_BEGIN_DECLS
cairo_font_t *
cairo_ft_font_create_for_ft_face (FT_Face face);
cairo_ft_font_create (FcPattern *pattern,
cairo_matrix_t *scale);
cairo_font_t *
cairo_ft_font_create_for_ft_face (FT_Face face,
int load_flags,
cairo_matrix_t *scale);
FT_Face
cairo_ft_font_face (cairo_font_t *ft_font);
cairo_ft_font_lock_face (cairo_font_t *ft_font);
void
cairo_ft_font_unlock_face (cairo_font_t *ft_font);
FcPattern *
cairo_ft_font_pattern (cairo_font_t *ft_font);
cairo_ft_font_get_pattern (cairo_font_t *ft_font);
CAIRO_END_DECLS
#endif /* CAIRO_HAS_FT_FONT */
#endif /* CAIRO_FT_H */

View file

@ -34,14 +34,17 @@
* Carl D. Worth <cworth@isi.edu>
*/
#include <cairo.h>
#ifndef CAIRO_GLITZ_H
#define CAIRO_GLITZ_H
#include <cairo.h>
#ifdef CAIRO_HAS_GLITZ_SURFACE
#include <glitz.h>
CAIRO_BEGIN_DECLS
void
cairo_set_target_glitz (cairo_t *cr,
glitz_surface_t *surface);
@ -49,5 +52,7 @@ cairo_set_target_glitz (cairo_t *cr,
cairo_surface_t *
cairo_glitz_surface_create (glitz_surface_t *surface);
CAIRO_END_DECLS
#endif /* CAIRO_HAS_GLITZ_SURFACE */
#endif /* CAIRO_GLITZ_H */

View file

@ -45,6 +45,8 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
cairo_operator_t operator,
cairo_surface_t *dst,
cairo_traps_t *traps);
static void
_cairo_gstate_unset_font (cairo_gstate_t *gstate);
cairo_gstate_t *
_cairo_gstate_create ()
@ -77,9 +79,11 @@ _cairo_gstate_init (cairo_gstate_t *gstate)
gstate->num_dashes = 0;
gstate->dash_offset = 0.0;
gstate->font = _cairo_unscaled_font_create (CAIRO_FONT_FAMILY_DEFAULT,
CAIRO_FONT_SLANT_DEFAULT,
CAIRO_FONT_WEIGHT_DEFAULT);
gstate->font_family = NULL;
gstate->font_slant = CAIRO_FONT_SLANT_DEFAULT;
gstate->font_weight = CAIRO_FONT_WEIGHT_DEFAULT;
gstate->font = NULL;
gstate->surface = NULL;
@ -118,9 +122,15 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
memcpy (gstate->dash, other->dash, other->num_dashes * sizeof (double));
}
if (other->font_family) {
gstate->font_family = strdup (other->font_family);
if (!gstate->font_family)
goto CLEANUP_DASH;
}
if (other->font) {
gstate->font = other->font;
_cairo_unscaled_font_reference (gstate->font);
cairo_font_reference (gstate->font);
}
if (other->clip.region)
@ -148,18 +158,29 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
_cairo_path_fini (&gstate->path);
CLEANUP_FONT:
_cairo_unscaled_font_destroy (gstate->font);
cairo_font_destroy (gstate->font);
gstate->font = NULL;
if (gstate->font_family) {
free (gstate->font_family);
gstate->font_family = NULL;
}
CLEANUP_DASH:
free (gstate->dash);
gstate->dash = NULL;
return status;
return CAIRO_STATUS_NO_MEMORY;
}
void
_cairo_gstate_fini (cairo_gstate_t *gstate)
{
_cairo_unscaled_font_destroy (gstate->font);
if (gstate->font_family)
free (gstate->font_family);
if (gstate->font)
cairo_font_destroy (gstate->font);
if (gstate->surface)
cairo_surface_destroy (gstate->surface);
@ -323,6 +344,8 @@ _cairo_gstate_set_target_surface (cairo_gstate_t *gstate, cairo_surface_t *surfa
{
double scale;
_cairo_gstate_unset_font (gstate);
if (gstate->surface)
cairo_surface_destroy (gstate->surface);
@ -549,6 +572,8 @@ _cairo_gstate_translate (cairo_gstate_t *gstate, double tx, double ty)
{
cairo_matrix_t tmp;
_cairo_gstate_unset_font (gstate);
_cairo_matrix_set_translate (&tmp, tx, ty);
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
@ -566,6 +591,8 @@ _cairo_gstate_scale (cairo_gstate_t *gstate, double sx, double sy)
if (sx == 0 || sy == 0)
return CAIRO_STATUS_INVALID_MATRIX;
_cairo_gstate_unset_font (gstate);
_cairo_matrix_set_scale (&tmp, sx, sy);
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
@ -580,6 +607,8 @@ _cairo_gstate_rotate (cairo_gstate_t *gstate, double angle)
{
cairo_matrix_t tmp;
_cairo_gstate_unset_font (gstate);
_cairo_matrix_set_rotate (&tmp, angle);
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
@ -595,6 +624,8 @@ _cairo_gstate_concat_matrix (cairo_gstate_t *gstate,
{
cairo_matrix_t tmp;
_cairo_gstate_unset_font (gstate);
cairo_matrix_copy (&tmp, matrix);
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
@ -610,6 +641,8 @@ _cairo_gstate_set_matrix (cairo_gstate_t *gstate,
{
cairo_status_t status;
_cairo_gstate_unset_font (gstate);
cairo_matrix_copy (&gstate->ctm, matrix);
cairo_matrix_copy (&gstate->ctm_inverse, matrix);
@ -627,6 +660,8 @@ _cairo_gstate_default_matrix (cairo_gstate_t *gstate)
if (scale == 0)
scale = 1;
_cairo_gstate_unset_font (gstate);
cairo_matrix_set_identity (&gstate->font_matrix);
cairo_matrix_set_identity (&gstate->ctm);
@ -640,6 +675,8 @@ _cairo_gstate_default_matrix (cairo_gstate_t *gstate)
cairo_status_t
_cairo_gstate_identity_matrix (cairo_gstate_t *gstate)
{
_cairo_gstate_unset_font (gstate);
cairo_matrix_set_identity (&gstate->ctm);
cairo_matrix_set_identity (&gstate->ctm_inverse);
@ -2121,6 +2158,14 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate,
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_gstate_unset_font (cairo_gstate_t *gstate)
{
if (gstate->font) {
cairo_font_destroy (gstate->font);
gstate->font = NULL;
}
}
cairo_status_t
_cairo_gstate_select_font (cairo_gstate_t *gstate,
@ -2128,12 +2173,17 @@ _cairo_gstate_select_font (cairo_gstate_t *gstate,
cairo_font_slant_t slant,
cairo_font_weight_t weight)
{
if (gstate->font)
_cairo_unscaled_font_destroy (gstate->font);
char *new_family;
gstate->font = _cairo_unscaled_font_create (family, slant, weight);
if (gstate->font == NULL)
new_family = strdup (family);
if (!new_family)
return CAIRO_STATUS_NO_MEMORY;
_cairo_gstate_unset_font (gstate);
gstate->font_family = new_family;
gstate->font_slant = slant;
gstate->font_weight = weight;
cairo_matrix_set_identity (&gstate->font_matrix);
@ -2144,6 +2194,8 @@ cairo_status_t
_cairo_gstate_scale_font (cairo_gstate_t *gstate,
double scale)
{
_cairo_gstate_unset_font (gstate);
return cairo_matrix_scale (&gstate->font_matrix, scale, scale);
}
@ -2153,6 +2205,9 @@ _cairo_gstate_transform_font (cairo_gstate_t *gstate,
{
cairo_matrix_t tmp;
double a, b, c, d, tx, ty;
_cairo_gstate_unset_font (gstate);
cairo_matrix_get_affine (matrix, &a, &b, &c, &d, &tx, &ty);
cairo_matrix_set_affine (&tmp, a, b, c, d, 0, 0);
return cairo_matrix_multiply (&gstate->font_matrix, &gstate->font_matrix, &tmp);
@ -2160,28 +2215,10 @@ _cairo_gstate_transform_font (cairo_gstate_t *gstate,
cairo_status_t
_cairo_gstate_current_font (cairo_gstate_t *gstate,
cairo_font_t **font)
_cairo_gstate_current_font (cairo_gstate_t *gstate, cairo_font_t **font)
{
cairo_font_scale_t scale;
cairo_font_t *scaled;
double dummy;
scaled = malloc (sizeof (cairo_font_t));
if (scaled == NULL)
return CAIRO_STATUS_NO_MEMORY;
cairo_matrix_get_affine (&gstate->font_matrix,
&scale.matrix[0][0],
&scale.matrix[0][1],
&scale.matrix[1][0],
&scale.matrix[1][1],
&dummy, &dummy);
_cairo_font_init (scaled, &scale, gstate->font);
_cairo_unscaled_font_reference (gstate->font);
*font = scaled;
*font = gstate->font;
cairo_font_reference (*font);
return CAIRO_STATUS_SUCCESS;
}
@ -2190,6 +2227,8 @@ void
_cairo_gstate_set_font_transform (cairo_gstate_t *gstate,
cairo_matrix_t *matrix)
{
_cairo_gstate_unset_font (gstate);
cairo_matrix_copy (&gstate->font_matrix, matrix);
}
@ -2214,12 +2253,10 @@ _cairo_gstate_current_font_transform (cairo_gstate_t *gstate,
* independently scale the user coordinate system *or* the font matrix, in
* order to adjust the rendered size of the font.
*
* If the user asks for a permanent reference to "a font", they are given a
* handle to a structure holding a scale matrix and an unscaled font. This
* effectively decouples the font from further changes to user space. Even
* if the user then "sets" the current cairo_t font to the handle they were
* passed, further changes to the cairo_t CTM will not affect externally
* held references to the font.
* The only font type exposed to the user is cairo_font_t which is a
* a font specialized to a particular scale matrix, CTM, and target
* surface. The user is responsible for not using a cairo_font_t
* after changing the parameters; doing so will produce garbled metrics.
*
*
* The font's view
@ -2279,9 +2316,9 @@ _cairo_gstate_current_font_transform (cairo_gstate_t *gstate,
*
*/
static void
_build_font_scale (cairo_gstate_t *gstate,
cairo_font_scale_t *sc)
void
_cairo_gstate_current_font_scale (cairo_gstate_t *gstate,
cairo_font_scale_t *sc)
{
cairo_matrix_t tmp;
double dummy;
@ -2294,17 +2331,47 @@ _build_font_scale (cairo_gstate_t *gstate,
&dummy, &dummy);
}
static cairo_status_t
_cairo_gstate_ensure_font (cairo_gstate_t *gstate)
{
cairo_font_scale_t sc;
cairo_status_t status;
const char *family;
if (gstate->font)
return CAIRO_STATUS_SUCCESS;
_cairo_gstate_current_font_scale (gstate, &sc);
if (gstate->font_family)
family = gstate->font_family;
else
family = CAIRO_FONT_FAMILY_DEFAULT;
status = _cairo_font_create (family,
gstate->font_slant,
gstate->font_weight,
&sc,
&gstate->font);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_gstate_current_font_extents (cairo_gstate_t *gstate,
cairo_font_extents_t *extents)
{
cairo_int_status_t status;
cairo_font_scale_t sc;
double font_scale_x, font_scale_y;
_build_font_scale (gstate, &sc);
status = _cairo_unscaled_font_font_extents (gstate->font, &sc, extents);
status = _cairo_gstate_ensure_font (gstate);
if (status)
return status;
status = _cairo_font_font_extents (gstate->font, extents);
_cairo_matrix_compute_scale_factors (&gstate->font_matrix,
&font_scale_x, &font_scale_y,
@ -2331,14 +2398,15 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
int *nglyphs)
{
cairo_status_t status;
cairo_font_scale_t sc;
cairo_point_t point;
double origin_x, origin_y;
int i;
_build_font_scale (gstate, &sc);
status = _cairo_gstate_ensure_font (gstate);
if (status)
return status;
status = _cairo_path_current_point (&gstate->path, &point);
if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
origin_x = 0.0;
@ -2350,8 +2418,8 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
&origin_x, &origin_y);
}
status = _cairo_unscaled_font_text_to_glyphs (gstate->font,
&sc, utf8, glyphs, nglyphs);
status = _cairo_font_text_to_glyphs (gstate->font,
utf8, glyphs, nglyphs);
if (status || !glyphs || !nglyphs || !(*glyphs) || !(nglyphs))
return status;
@ -2373,18 +2441,13 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
cairo_status_t
_cairo_gstate_set_font (cairo_gstate_t *gstate,
cairo_font_t *font)
cairo_font_t *font)
{
if (gstate->font != NULL)
_cairo_unscaled_font_destroy (gstate->font);
gstate->font = font->unscaled;
_cairo_unscaled_font_reference (gstate->font);
cairo_matrix_set_affine (&gstate->font_matrix,
font->scale.matrix[0][0],
font->scale.matrix[0][1],
font->scale.matrix[1][0],
font->scale.matrix[1][1],
0, 0);
cairo_font_destroy (gstate->font);
gstate->font = font;
cairo_font_reference (gstate->font);
return CAIRO_STATUS_SUCCESS;
}
@ -2394,90 +2457,18 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
int num_glyphs,
cairo_text_extents_t *extents)
{
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;
cairo_status_t status;
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;
}
status = _cairo_gstate_ensure_font (gstate);
if (status)
return status;
_build_font_scale (gstate, &sc);
cairo_font_glyph_extents (gstate->font,
&gstate->font_matrix,
glyphs, num_glyphs,
extents);
for (i = 0; i < num_glyphs; i++)
{
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 = origin_extents.x_bearing;
y = origin_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;
}
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;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
@ -2488,12 +2479,13 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
cairo_status_t status;
int i;
cairo_glyph_t *transformed_glyphs = NULL;
cairo_font_scale_t sc;
cairo_pattern_t pattern;
cairo_box_t bbox;
_build_font_scale (gstate, &sc);
status = _cairo_gstate_ensure_font (gstate);
if (status)
return status;
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
if (transformed_glyphs == NULL)
return CAIRO_STATUS_NO_MEMORY;
@ -2507,9 +2499,9 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
}
_cairo_pattern_init_copy (&pattern, gstate->pattern);
status = _cairo_unscaled_font_glyph_bbox (gstate->font, &sc,
transformed_glyphs, num_glyphs,
&bbox);
status = _cairo_font_glyph_bbox (gstate->font,
transformed_glyphs, num_glyphs,
&bbox);
if (status)
goto CLEANUP_GLYPHS;
@ -2565,14 +2557,13 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
transformed_glyphs[i].y -= draw_extents->y1;
}
status = _cairo_unscaled_font_show_glyphs (gstate->font,
&sc,
CAIRO_OPERATOR_ADD,
pattern.source, intermediate,
draw_extents->x1 - pattern.source_offset.x,
draw_extents->y1 - pattern.source_offset.y,
transformed_glyphs, num_glyphs);
status = _cairo_font_show_glyphs (gstate->font,
CAIRO_OPERATOR_ADD,
pattern.source, intermediate,
draw_extents->x1 - pattern.source_offset.x,
draw_extents->y1 - pattern.source_offset.y,
transformed_glyphs, num_glyphs);
if (status)
goto BAIL2;
@ -2610,13 +2601,12 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
}
else
{
status = _cairo_unscaled_font_show_glyphs (gstate->font,
&sc,
gstate->operator, pattern.source,
gstate->surface,
-pattern.source_offset.x,
-pattern.source_offset.y,
transformed_glyphs, num_glyphs);
status = _cairo_font_show_glyphs (gstate->font,
gstate->operator, pattern.source,
gstate->surface,
-pattern.source_offset.x,
-pattern.source_offset.y,
transformed_glyphs, num_glyphs);
}
_cairo_pattern_fini (&pattern);
@ -2635,9 +2625,6 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
cairo_status_t status;
int i;
cairo_glyph_t *transformed_glyphs = NULL;
cairo_font_scale_t sc;
_build_font_scale (gstate, &sc);
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
if (transformed_glyphs == NULL)
@ -2651,9 +2638,9 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
&(transformed_glyphs[i].y));
}
status = _cairo_unscaled_font_glyph_path (gstate->font, &sc,
transformed_glyphs, num_glyphs,
&gstate->path);
status = _cairo_font_glyph_path (gstate->font,
transformed_glyphs, num_glyphs,
&gstate->path);
free (transformed_glyphs);
return status;

View file

@ -94,9 +94,9 @@ static const cairo_cache_arrangement_t cache_arrangements [] = {
* a mostly-dead table.
*
* Generally you do not need to worry about freeing cache entries; the
* cache will expire entries randomly as it experiences memory pressure.
* There is currently no explicit entry-removing call, though one can be
* added easily.
* cache will expire entries randomly as it experiences memory pressure.
* If max_memory is set, entries are not expired, and must be explicitely
* removed.
*
* This table is open-addressed with double hashing. Each table size is a
* prime chosen to be a little more than double the high water mark for a
@ -282,17 +282,51 @@ _load_factor (cairo_cache_t *cache)
}
#endif
static unsigned long
_random_live_entry (cairo_cache_t *cache)
{
unsigned long idx;
assert(cache != NULL);
do {
idx = rand () % cache->arrangement->size;
} while (! LIVE_ENTRY_P(cache, idx));
return idx;
}
/* Find a random in the cache matching the given predicate. We use the
* same algorithm as the probing algorithm to walk over the entries in
* the hash table in a pseudo-random order. Walking linearly would
* favor entries following gaps in the hash table. We could also
* call rand() repeatedly, which works well for almost-full tables,
* but degrades when the table is almost empty, or predicate
* returns false for most entries.
*/
static cairo_cache_entry_base_t **
_random_entry (cairo_cache_t *cache,
int (*predicate)(void*))
{
cairo_cache_entry_base_t **probe;
unsigned long hash;
unsigned long table_size, i, idx, step;
_cache_sane_state (cache);
table_size = cache->arrangement->size;
hash = rand ();
idx = hash % table_size;
step = 0;
for (i = 0; i < table_size; ++i)
{
assert(idx < table_size);
probe = cache->entries + idx;
if (LIVE_ENTRY_P(cache, idx)
&& (!predicate || predicate (*probe)))
return probe;
if (step == 0) {
step = hash % cache->arrangement->rehash;
if (step == 0)
step = 1;
}
idx += step;
if (idx >= table_size)
idx -= table_size;
}
return NULL;
}
/* public API follows */
@ -356,8 +390,9 @@ _cairo_cache_destroy (cairo_cache_t *cache)
cairo_status_t
_cairo_cache_lookup (cairo_cache_t *cache,
void *key,
void **entry_return)
void *key,
void **entry_return,
int *created_entry)
{
unsigned long idx;
@ -392,6 +427,8 @@ _cairo_cache_lookup (cairo_cache_t *cache,
cache->hits++;
#endif
*entry_return = *slot;
if (created_entry)
*created_entry = 0;
return status;
}
@ -401,19 +438,18 @@ _cairo_cache_lookup (cairo_cache_t *cache,
/* Build the new entry. */
status = cache->backend->create_entry (cache, key,
entry_return);
(void **)&new_entry);
if (status != CAIRO_STATUS_SUCCESS)
return status;
new_entry = (cairo_cache_entry_base_t *) (*entry_return);
/* Store the hash value in case the backend forgot. */
new_entry->hashcode = cache->backend->hash (cache, key);
/* Make some entries die if we're under memory pressure. */
while (cache->live_entries > 0 &&
cache->max_memory > 0 &&
((cache->max_memory - cache->used_memory) < new_entry->memory)) {
idx = _random_live_entry (cache);
idx = _random_entry (cache, NULL) - cache->entries;
assert (idx < cache->arrangement->size);
_entry_destroy (cache, idx);
}
@ -425,7 +461,6 @@ _cairo_cache_lookup (cairo_cache_t *cache,
status = _resize_cache (cache, cache->live_entries + 1);
if (status != CAIRO_STATUS_SUCCESS) {
cache->backend->destroy_entry (cache, new_entry);
*entry_return = NULL;
return status;
}
@ -439,9 +474,38 @@ _cairo_cache_lookup (cairo_cache_t *cache,
_cache_sane_state (cache);
*entry_return = new_entry;
if (created_entry)
*created_entry = 1;
return status;
}
cairo_status_t
_cairo_cache_remove (cairo_cache_t *cache,
void *key)
{
cairo_cache_entry_base_t **slot;
_cache_sane_state (cache);
/* See if we have an entry in the table already. */
slot = _find_exact_live_entry_for (cache, key);
if (slot != NULL)
_entry_destroy (cache, slot - cache->entries);
return CAIRO_STATUS_SUCCESS;
}
void *
_cairo_cache_random_entry (cairo_cache_t *cache,
int (*predicate)(void*))
{
cairo_cache_entry_base_t **slot = _random_entry (cache, predicate);
return *slot;
}
unsigned long
_cairo_hash_string (const char *c)
{

View file

@ -36,9 +36,8 @@
#include "cairoint.h"
#include "cairo-pdf.h"
/* XXX: This seems broken to me. What about users without freetype
* that want to use a cairo PDF surface? */
#include "cairo-ft.h"
/* XXX: Eventually, we need to handle other font backends */
#include "cairo-ft-private.h"
#include <ft2build.h>
#include FT_FREETYPE_H
@ -300,19 +299,15 @@ cairo_pdf_font_destroy (cairo_pdf_font_t *font)
}
static cairo_pdf_font_t *
cairo_pdf_ft_font_create (cairo_pdf_document_t *document,
cairo_unscaled_font_t *unscaled_font,
cairo_font_scale_t *scale)
cairo_pdf_ft_font_create (cairo_pdf_document_t *document,
cairo_unscaled_font_t *unscaled_font)
{
cairo_font_t scaled_font;
FT_Face face;
cairo_pdf_ft_font_t *font;
unsigned long size;
int i, j;
/* FIXME: Why do I have to pass a scaled font to get the FT_Face? */
_cairo_font_init (&scaled_font, scale, unscaled_font);
face = cairo_ft_font_face (&scaled_font);
face = _cairo_ft_unscaled_font_lock_face (unscaled_font);
/* We currently only support freetype truetype fonts. */
size = 0;
@ -333,7 +328,8 @@ cairo_pdf_ft_font_create (cairo_pdf_document_t *document,
if (_cairo_array_grow_by (&font->output, 4096) != CAIRO_STATUS_SUCCESS)
goto fail1;
font->face = face;
font->base.unscaled_font = unscaled_font;
_cairo_unscaled_font_reference (unscaled_font);
font->glyphs = calloc (face->num_glyphs + 1, sizeof (ft_subset_glyph_t));
if (font->glyphs == NULL)
goto fail2;
@ -364,6 +360,8 @@ cairo_pdf_ft_font_create (cairo_pdf_document_t *document,
if (font->base.widths == NULL)
goto fail5;
_cairo_ft_unscaled_font_unlock_face (unscaled_font);
font->status = CAIRO_STATUS_SUCCESS;
return &font->base;
@ -764,12 +762,15 @@ cairo_pdf_ft_font_generate (void *abstract_font,
unsigned long start, end, next, checksum;
int i;
font->face = _cairo_ft_unscaled_font_lock_face (font->base.unscaled_font);
if (cairo_pdf_ft_font_write_offset_table (font))
return font->status;
goto fail;
start = cairo_pdf_ft_font_align_output (font);
end = start;
end = 0;
for (i = 0; i < ARRAY_LENGTH (truetype_tables); i++) {
if (truetype_tables[i].write (font, truetype_tables[i].tag))
goto fail;
@ -789,6 +790,9 @@ cairo_pdf_ft_font_generate (void *abstract_font,
*length = _cairo_array_num_elements (&font->output);
fail:
_cairo_ft_unscaled_font_unlock_face (font->base.unscaled_font);
font->face = NULL;
return font->status;
}
@ -1704,36 +1708,37 @@ _cairo_pdf_surface_create_pattern (void *abstract_surface,
static cairo_pdf_font_t *
_cairo_pdf_document_get_font (cairo_pdf_document_t *document,
cairo_unscaled_font_t *unscaled_font,
cairo_font_scale_t *scale)
cairo_font_t *font)
{
cairo_pdf_font_t *font;
cairo_unscaled_font_t *unscaled_font;
cairo_pdf_font_t *pdf_font;
unsigned int num_fonts, i;
unscaled_font = _cairo_ft_font_get_unscaled_font (font);
num_fonts = _cairo_array_num_elements (&document->fonts);
for (i = 0; i < num_fonts; i++) {
_cairo_array_copy_element (&document->fonts, i, &font);
if (font->unscaled_font == unscaled_font)
return font;
_cairo_array_copy_element (&document->fonts, i, &pdf_font);
if (pdf_font->unscaled_font == unscaled_font)
return pdf_font;
}
/* FIXME: Figure out here which font backend is in use and call
* the appropriate constructor. */
font = cairo_pdf_ft_font_create (document, unscaled_font, scale);
pdf_font = cairo_pdf_ft_font_create (document, unscaled_font);
if (font == NULL)
return NULL;
if (_cairo_array_append (&document->fonts, &font, 1) == NULL) {
cairo_pdf_font_destroy (font);
if (_cairo_array_append (&document->fonts, &pdf_font, 1) == NULL) {
cairo_pdf_font_destroy (pdf_font);
return NULL;
}
return font;
return pdf_font;
}
static cairo_status_t
_cairo_pdf_surface_show_glyphs (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
_cairo_pdf_surface_show_glyphs (cairo_font_t *font,
cairo_operator_t operator,
cairo_surface_t *source,
void *abstract_surface,
@ -1748,7 +1753,7 @@ _cairo_pdf_surface_show_glyphs (cairo_unscaled_font_t *font,
cairo_pdf_font_t *pdf_font;
int i, index;
pdf_font = _cairo_pdf_document_get_font (document, font, scale);
pdf_font = _cairo_pdf_document_get_font (document, font);
if (pdf_font == NULL)
return CAIRO_STATUS_NO_MEMORY;
@ -1761,10 +1766,10 @@ _cairo_pdf_surface_show_glyphs (cairo_unscaled_font_t *font,
fprintf (file,
" %f %f %f %f %f %f Tm (%c) Tj",
scale->matrix[0][0],
scale->matrix[0][1],
scale->matrix[1][0],
-scale->matrix[1][1],
font->scale.matrix[0][0],
font->scale.matrix[0][1],
font->scale.matrix[1][0],
-font->scale.matrix[1][1],
glyphs[i].x,
glyphs[i].y,
index);

View file

@ -34,14 +34,17 @@
* Carl D. Worth <cworth@isi.edu>
*/
#include <cairo.h>
#ifndef CAIRO_PDF_H
#define CAIRO_PDF_H
#include <cairo.h>
#ifdef CAIRO_HAS_PDF_SURFACE
#include <stdio.h>
CAIRO_BEGIN_DECLS
void
cairo_set_target_pdf (cairo_t *cr,
FILE *file,
@ -58,5 +61,7 @@ cairo_pdf_surface_create (FILE *file,
double x_pixels_per_inch,
double y_pixels_per_inch);
CAIRO_END_DECLS
#endif /* CAIRO_HAS_PDF_SURFACE */
#endif /* CAIRO_PDF_H */

View file

@ -34,14 +34,17 @@
* Carl D. Worth <cworth@isi.edu>
*/
#include <cairo.h>
#ifndef CAIRO_PNG_H
#define CAIRO_PNG_H
#ifdef CAIRO_HAS_PNG_SURFACE
#include <cairo.h>
#ifdef CAIRO_HAS_PNG_SURFACE
#include <stdio.h>
CAIRO_BEGIN_DECLS
void
cairo_set_target_png (cairo_t *cr,
FILE *file,
@ -55,5 +58,7 @@ cairo_png_surface_create (FILE *file,
int width,
int height);
CAIRO_END_DECLS
#endif /* CAIRO_HAS_PNG_SURFACE */
#endif /* CAIRO_PNG_H */

View file

@ -34,14 +34,17 @@
* Carl D. Worth <cworth@isi.edu>
*/
#include <cairo.h>
#ifndef CAIRO_PS_H
#define CAIRO_PS_H
#include <cairo.h>
#ifdef CAIRO_HAS_PS_SURFACE
#include <stdio.h>
CAIRO_BEGIN_DECLS
void
cairo_set_target_ps (cairo_t *cr,
FILE *file,
@ -59,5 +62,7 @@ cairo_ps_surface_create (FILE *file,
double x_pixels_per_inch,
double y_pixels_per_inch);
CAIRO_END_DECLS
#endif /* CAIRO_HAS_PS_SURFACE */
#endif /* CAIRO_PS_H */

View file

@ -1,6 +1,6 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2004 Calum Robinson
* Copyright © 2004 Calum Robinson
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public

View file

@ -34,14 +34,17 @@
* Carl D. Worth <cworth@isi.edu>
*/
#include <cairo.h>
#ifndef CAIRO_QUARTZ_H
#define CAIRO_QUARTZ_H
#include <cairo.h>
#ifdef CAIRO_HAS_QUARTZ_SURFACE
#include <Carbon/Carbon.h>
CAIRO_BEGIN_DECLS
void
cairo_set_target_quartz_context( cairo_t *cr,
CGContextRef context,
@ -53,6 +56,8 @@ cairo_quartz_surface_create ( CGContextRef context,
int width,
int height);
CAIRO_END_DECLS
#endif /* CAIRO_HAS_QUARTZ_SURFACE */
#endif /* CAIRO_QUARTZ_H */

View file

@ -34,15 +34,18 @@
* Carl D. Worth <cworth@isi.edu>
*/
#include <cairo.h>
#ifndef CAIRO_XCB_H
#define CAIRO_XCB_H
#include <cairo.h>
#ifdef CAIRO_HAS_XCB_SURFACE
#include <X11/XCB/xcb.h>
#include <X11/XCB/render.h>
CAIRO_BEGIN_DECLS
void
cairo_set_target_xcb (cairo_t *cr,
XCBConnection *dpy,
@ -50,5 +53,7 @@ cairo_set_target_xcb (cairo_t *cr,
XCBVISUALTYPE *visual,
cairo_format_t format);
CAIRO_END_DECLS
#endif /* CAIRO_HAS_XCB_SURFACE */
#endif /* CAIRO_XCB_H */

View file

@ -694,8 +694,7 @@ _cairo_xlib_surface_create_pattern (void *abstract_surface,
}
static cairo_status_t
_cairo_xlib_surface_show_glyphs (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
_cairo_xlib_surface_show_glyphs (cairo_font_t *font,
cairo_operator_t operator,
cairo_surface_t *source,
void *abstract_surface,
@ -824,6 +823,7 @@ typedef struct glyphset_cache {
} glyphset_cache_t;
typedef struct {
int refcount;
cairo_glyph_cache_key_t key;
Glyph glyph;
XGlyphInfo info;
@ -854,17 +854,18 @@ _xlib_glyphset_cache_create_entry (void *cache,
_cairo_lock_global_image_glyph_cache ();
im_cache = _cairo_get_global_image_glyph_cache ();
if (g == NULL || v == NULL ||g == NULL || im_cache == NULL) {
if (g == NULL || v == NULL || im_cache == NULL) {
_cairo_unlock_global_image_glyph_cache ();
return CAIRO_STATUS_NO_MEMORY;
}
status = _cairo_cache_lookup (im_cache, key, (void **) (&im));
status = _cairo_cache_lookup (im_cache, key, (void **) (&im), NULL);
if (status != CAIRO_STATUS_SUCCESS || im == NULL) {
_cairo_unlock_global_image_glyph_cache ();
return CAIRO_STATUS_NO_MEMORY;
}
v->refcount = 1;
v->key = *k;
_cairo_unscaled_font_reference (v->key.unscaled);
@ -925,6 +926,12 @@ _xlib_glyphset_cache_create_entry (void *cache,
return CAIRO_STATUS_SUCCESS;
}
static void
_glyphset_cache_entry_reference (glyphset_cache_entry_t *e)
{
e->refcount++;
}
static void
_xlib_glyphset_cache_destroy_cache (void *cache)
{
@ -940,6 +947,9 @@ _xlib_glyphset_cache_destroy_entry (void *cache, void *entry)
g = (glyphset_cache_t *) cache;
v = (glyphset_cache_entry_t *) entry;
if (--v->refcount > 0)
return;
_cairo_unscaled_font_destroy (v->key.unscaled);
XRenderFreeGlyphs (g->display, g->glyphset, &(v->glyph), 1);
free (v);
@ -1014,8 +1024,7 @@ _get_glyphset_cache (Display *d)
#define N_STACK_BUF 1024
static cairo_status_t
_cairo_xlib_surface_show_glyphs32 (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
_cairo_xlib_surface_show_glyphs32 (cairo_font_t *font,
cairo_operator_t operator,
glyphset_cache_t *g,
cairo_glyph_cache_key_t *key,
@ -1092,8 +1101,7 @@ _cairo_xlib_surface_show_glyphs32 (cairo_unscaled_font_t *font,
static cairo_status_t
_cairo_xlib_surface_show_glyphs16 (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
_cairo_xlib_surface_show_glyphs16 (cairo_font_t *font,
cairo_operator_t operator,
glyphset_cache_t *g,
cairo_glyph_cache_key_t *key,
@ -1169,10 +1177,9 @@ _cairo_xlib_surface_show_glyphs16 (cairo_unscaled_font_t *font,
}
static cairo_status_t
_cairo_xlib_surface_show_glyphs8 (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
_cairo_xlib_surface_show_glyphs8 (cairo_font_t *font,
cairo_operator_t operator,
glyphset_cache_t *g,
glyphset_cache_t *g,
cairo_glyph_cache_key_t *key,
cairo_xlib_surface_t *src,
cairo_xlib_surface_t *self,
@ -1247,8 +1254,7 @@ _cairo_xlib_surface_show_glyphs8 (cairo_unscaled_font_t *font,
static cairo_status_t
_cairo_xlib_surface_show_glyphs (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
_cairo_xlib_surface_show_glyphs (cairo_font_t *font,
cairo_operator_t operator,
cairo_surface_t *source,
void *abstract_surface,
@ -1305,15 +1311,23 @@ _cairo_xlib_surface_show_glyphs (cairo_unscaled_font_t *font,
/* Work out the index size to use. */
elt_size = 8;
key.scale = *scale;
key.unscaled = font;
_cairo_font_get_glyph_cache_key (font, &key);
for (i = 0; i < num_glyphs; ++i) {
key.index = glyphs[i].index;
status = _cairo_cache_lookup (&g->base, &key, (void **) (&entries[i]));
status = _cairo_cache_lookup (&g->base, &key, (void **) (&entries[i]), NULL);
if (status != CAIRO_STATUS_SUCCESS || entries[i] == NULL)
goto UNLOCK;
/* Referencing the glyph entries we use prevents them from
* being freed if lookup of later entries causes them to
* be ejected from the cache. It would be more efficient
* (though more complex) to prevent them from being ejected
* from the cache at all, so they could get reused later
* in the same string.
*/
_glyphset_cache_entry_reference (entries[i]);
if (elt_size == 8 && entries[i]->glyph > 0xff)
elt_size = 16;
if (elt_size == 16 && entries[i]->glyph > 0xffff) {
@ -1325,18 +1339,21 @@ _cairo_xlib_surface_show_glyphs (cairo_unscaled_font_t *font,
/* Call the appropriate sub-function. */
if (elt_size == 8)
status = _cairo_xlib_surface_show_glyphs8 (font, scale, operator, g, &key, src, self,
status = _cairo_xlib_surface_show_glyphs8 (font, operator, g, &key, src, self,
source_x, source_y,
glyphs, entries, num_glyphs);
else if (elt_size == 16)
status = _cairo_xlib_surface_show_glyphs16 (font, scale, operator, g, &key, src, self,
status = _cairo_xlib_surface_show_glyphs16 (font, operator, g, &key, src, self,
source_x, source_y,
glyphs, entries, num_glyphs);
else
status = _cairo_xlib_surface_show_glyphs32 (font, scale, operator, g, &key, src, self,
status = _cairo_xlib_surface_show_glyphs32 (font, operator, g, &key, src, self,
source_x, source_y,
glyphs, entries, num_glyphs);
for (i = 0; i < num_glyphs; ++i)
_xlib_glyphset_cache_destroy_entry (g, entries[i]);
_unlock_xlib_glyphset_caches ();
if (tmp != NULL) {

View file

@ -34,14 +34,17 @@
* Carl D. Worth <cworth@isi.edu>
*/
#include <cairo.h>
#ifndef CAIRO_XLIB_H
#define CAIRO_XLIB_H
#include <cairo.h>
#ifdef CAIRO_HAS_XLIB_SURFACE
#include <X11/extensions/Xrender.h>
CAIRO_BEGIN_DECLS
/* XXX: This shold be renamed to cairo_set_target_xlib to match the
* other backends */
void
@ -66,6 +69,8 @@ cairo_status_t
cairo_xlib_surface_set_size (cairo_surface_t *surface, int width, int height);
*/
CAIRO_END_DECLS
#endif /* CAIRO_HAS_XLIB_SURFACE */
#endif /* CAIRO_XLIB_H */

View file

@ -37,18 +37,24 @@
#ifndef CAIRO_H
#define CAIRO_H
#ifdef __cplusplus
# define CAIRO_BEGIN_DECLS extern "C" {
# define CAIRO_END_DECLS }
#else
# define CAIRO_BEGIN_DECLS
# define CAIRO_END_DECLS
#endif
#include <cairo-features.h>
#include <pixman.h>
CAIRO_BEGIN_DECLS
typedef struct _cairo cairo_t;
typedef struct _cairo_surface cairo_surface_t;
typedef struct _cairo_matrix cairo_matrix_t;
typedef struct _cairo_pattern cairo_pattern_t;
#ifdef __cplusplus
extern "C" {
#endif
/* Functions for manipulating state objects */
cairo_t *
cairo_create (void);
@ -423,12 +429,11 @@ void
cairo_font_destroy (cairo_font_t *font);
void
cairo_font_set_transform (cairo_font_t *font,
cairo_matrix_t *matrix);
void
cairo_font_current_transform (cairo_font_t *font,
cairo_matrix_t *matrix);
cairo_font_glyph_extents (cairo_font_t *font,
cairo_matrix_t *font_matrix,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_text_extents_t *extents);
/* Image functions */
@ -724,8 +729,6 @@ cairo_matrix_transform_point (cairo_matrix_t *matrix, double *x, double *y);
#define cairo_get_status_string cairo_get_status_string_DEPRECATED_BY_cairo_status_string
#endif
#ifdef __cplusplus
}
#endif
CAIRO_END_DECLS
#endif /* CAIRO_H */

View file

@ -94,9 +94,9 @@ static const cairo_cache_arrangement_t cache_arrangements [] = {
* a mostly-dead table.
*
* Generally you do not need to worry about freeing cache entries; the
* cache will expire entries randomly as it experiences memory pressure.
* There is currently no explicit entry-removing call, though one can be
* added easily.
* cache will expire entries randomly as it experiences memory pressure.
* If max_memory is set, entries are not expired, and must be explicitely
* removed.
*
* This table is open-addressed with double hashing. Each table size is a
* prime chosen to be a little more than double the high water mark for a
@ -282,17 +282,51 @@ _load_factor (cairo_cache_t *cache)
}
#endif
static unsigned long
_random_live_entry (cairo_cache_t *cache)
{
unsigned long idx;
assert(cache != NULL);
do {
idx = rand () % cache->arrangement->size;
} while (! LIVE_ENTRY_P(cache, idx));
return idx;
}
/* Find a random in the cache matching the given predicate. We use the
* same algorithm as the probing algorithm to walk over the entries in
* the hash table in a pseudo-random order. Walking linearly would
* favor entries following gaps in the hash table. We could also
* call rand() repeatedly, which works well for almost-full tables,
* but degrades when the table is almost empty, or predicate
* returns false for most entries.
*/
static cairo_cache_entry_base_t **
_random_entry (cairo_cache_t *cache,
int (*predicate)(void*))
{
cairo_cache_entry_base_t **probe;
unsigned long hash;
unsigned long table_size, i, idx, step;
_cache_sane_state (cache);
table_size = cache->arrangement->size;
hash = rand ();
idx = hash % table_size;
step = 0;
for (i = 0; i < table_size; ++i)
{
assert(idx < table_size);
probe = cache->entries + idx;
if (LIVE_ENTRY_P(cache, idx)
&& (!predicate || predicate (*probe)))
return probe;
if (step == 0) {
step = hash % cache->arrangement->rehash;
if (step == 0)
step = 1;
}
idx += step;
if (idx >= table_size)
idx -= table_size;
}
return NULL;
}
/* public API follows */
@ -356,8 +390,9 @@ _cairo_cache_destroy (cairo_cache_t *cache)
cairo_status_t
_cairo_cache_lookup (cairo_cache_t *cache,
void *key,
void **entry_return)
void *key,
void **entry_return,
int *created_entry)
{
unsigned long idx;
@ -392,6 +427,8 @@ _cairo_cache_lookup (cairo_cache_t *cache,
cache->hits++;
#endif
*entry_return = *slot;
if (created_entry)
*created_entry = 0;
return status;
}
@ -401,19 +438,18 @@ _cairo_cache_lookup (cairo_cache_t *cache,
/* Build the new entry. */
status = cache->backend->create_entry (cache, key,
entry_return);
(void **)&new_entry);
if (status != CAIRO_STATUS_SUCCESS)
return status;
new_entry = (cairo_cache_entry_base_t *) (*entry_return);
/* Store the hash value in case the backend forgot. */
new_entry->hashcode = cache->backend->hash (cache, key);
/* Make some entries die if we're under memory pressure. */
while (cache->live_entries > 0 &&
cache->max_memory > 0 &&
((cache->max_memory - cache->used_memory) < new_entry->memory)) {
idx = _random_live_entry (cache);
idx = _random_entry (cache, NULL) - cache->entries;
assert (idx < cache->arrangement->size);
_entry_destroy (cache, idx);
}
@ -425,7 +461,6 @@ _cairo_cache_lookup (cairo_cache_t *cache,
status = _resize_cache (cache, cache->live_entries + 1);
if (status != CAIRO_STATUS_SUCCESS) {
cache->backend->destroy_entry (cache, new_entry);
*entry_return = NULL;
return status;
}
@ -439,9 +474,38 @@ _cairo_cache_lookup (cairo_cache_t *cache,
_cache_sane_state (cache);
*entry_return = new_entry;
if (created_entry)
*created_entry = 1;
return status;
}
cairo_status_t
_cairo_cache_remove (cairo_cache_t *cache,
void *key)
{
cairo_cache_entry_base_t **slot;
_cache_sane_state (cache);
/* See if we have an entry in the table already. */
slot = _find_exact_live_entry_for (cache, key);
if (slot != NULL)
_entry_destroy (cache, slot - cache->entries);
return CAIRO_STATUS_SUCCESS;
}
void *
_cairo_cache_random_entry (cairo_cache_t *cache,
int (*predicate)(void*))
{
cairo_cache_entry_base_t **slot = _random_entry (cache, predicate);
return *slot;
}
unsigned long
_cairo_hash_string (const char *c)
{

View file

@ -1,6 +1,7 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2002 University of Southern California
* Copyright © 2005 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@ -32,264 +33,85 @@
*
* Contributor(s):
* Carl D. Worth <cworth@isi.edu>
* Graydon Hoare <graydon@redhat.com>
* Owen Taylor <otaylor@redhat.com>
*/
#include "cairoint.h"
/* First we implement a global font cache for named fonts. */
typedef struct {
cairo_cache_entry_base_t base;
const char *family;
cairo_font_slant_t slant;
cairo_font_weight_t weight;
} cairo_font_cache_key_t;
typedef struct {
cairo_font_cache_key_t key;
cairo_unscaled_font_t *unscaled;
} cairo_font_cache_entry_t;
static unsigned long
_font_cache_hash (void *cache, void *key)
{
unsigned long hash;
cairo_font_cache_key_t *in;
in = (cairo_font_cache_key_t *) key;
/* 1607 and 1451 are just a couple random primes. */
hash = _cairo_hash_string (in->family);
hash += ((unsigned long) in->slant) * 1607;
hash += ((unsigned long) in->weight) * 1451;
return hash;
}
static int
_font_cache_keys_equal (void *cache,
void *k1,
void *k2)
{
cairo_font_cache_key_t *a, *b;
a = (cairo_font_cache_key_t *) k1;
b = (cairo_font_cache_key_t *) k2;
return (strcmp (a->family, b->family) == 0)
&& (a->weight == b->weight)
&& (a->slant == b->slant);
}
static cairo_status_t
_font_cache_create_entry (void *cache,
void *key,
void **return_value)
{
const cairo_font_backend_t *backend = CAIRO_FONT_BACKEND_DEFAULT;
cairo_font_cache_key_t *k;
cairo_font_cache_entry_t *entry;
k = (cairo_font_cache_key_t *) key;
/* XXX: The current freetype backend may return NULL, (for example
* if no fonts are installed), but I would like to guarantee that
* the toy API always returns at least *some* font, so I would
* like to build in some sort fo font here, (even a really lame,
* ugly one if necessary). */
entry = malloc (sizeof (cairo_font_cache_entry_t));
if (entry == NULL)
goto FAIL;
entry->key.slant = k->slant;
entry->key.weight = k->weight;
entry->key.family = strdup(k->family);
if (entry->key.family == NULL)
goto FREE_ENTRY;
entry->unscaled = backend->create (k->family, k->slant, k->weight);
if (entry->unscaled == NULL)
goto FREE_FAMILY;
/* Not sure how to measure backend font mem; use a simple count for now.*/
entry->key.base.memory = 1;
*return_value = entry;
return CAIRO_STATUS_SUCCESS;
FREE_FAMILY:
free ((void *) entry->key.family);
FREE_ENTRY:
free (entry);
FAIL:
return CAIRO_STATUS_NO_MEMORY;
}
static void
_font_cache_destroy_entry (void *cache,
void *entry)
{
cairo_font_cache_entry_t *e;
e = (cairo_font_cache_entry_t *) entry;
_cairo_unscaled_font_destroy (e->unscaled);
free ((void *) e->key.family);
free (e);
}
static void
_font_cache_destroy_cache (void *cache)
{
free (cache);
}
static const cairo_cache_backend_t cairo_font_cache_backend = {
_font_cache_hash,
_font_cache_keys_equal,
_font_cache_create_entry,
_font_cache_destroy_entry,
_font_cache_destroy_cache
};
static void
_lock_global_font_cache (void)
{
/* FIXME: implement locking. */
}
static void
_unlock_global_font_cache (void)
{
/* FIXME: implement locking. */
}
static cairo_cache_t *
_global_font_cache = NULL;
static cairo_cache_t *
_get_global_font_cache (void)
{
if (_global_font_cache == NULL) {
_global_font_cache = malloc (sizeof (cairo_cache_t));
if (_global_font_cache == NULL)
goto FAIL;
if (_cairo_cache_init (_global_font_cache,
&cairo_font_cache_backend,
CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT))
goto FAIL;
}
return _global_font_cache;
FAIL:
if (_global_font_cache)
free (_global_font_cache);
_global_font_cache = NULL;
return NULL;
}
/* Now the internal "unscaled + scale" font API */
cairo_unscaled_font_t *
_cairo_unscaled_font_create (const char *family,
cairo_font_slant_t slant,
cairo_font_weight_t weight)
cairo_private cairo_status_t
_cairo_font_create (const char *family,
cairo_font_slant_t slant,
cairo_font_weight_t weight,
cairo_font_scale_t *sc,
cairo_font_t **font)
{
cairo_cache_t * cache;
cairo_font_cache_key_t key;
cairo_font_cache_entry_t *font;
cairo_status_t status;
const cairo_font_backend_t *backend = CAIRO_FONT_BACKEND_DEFAULT;
_lock_global_font_cache ();
cache = _get_global_font_cache ();
if (cache == NULL) {
_unlock_global_font_cache ();
return NULL;
}
key.family = family;
key.slant = slant;
key.weight = weight;
status = _cairo_cache_lookup (cache, &key, (void **) &font);
if (status) {
_unlock_global_font_cache ();
return NULL;
}
_cairo_unscaled_font_reference (font->unscaled);
_unlock_global_font_cache ();
return font->unscaled;
return backend->create (family, slant, weight, sc, font);
}
void
_cairo_font_init (cairo_font_t *scaled,
cairo_font_scale_t *scale,
cairo_unscaled_font_t *unscaled)
_cairo_font_init (cairo_font_t *font,
cairo_font_scale_t *scale,
const cairo_font_backend_t *backend)
{
scaled->scale = *scale;
scaled->unscaled = unscaled;
scaled->refcount = 1;
font->scale = *scale;
font->refcount = 1;
font->backend = backend;
}
cairo_status_t
_cairo_unscaled_font_init (cairo_unscaled_font_t *font,
const cairo_font_backend_t *backend)
void
_cairo_unscaled_font_init (cairo_unscaled_font_t *font,
const cairo_font_backend_t *backend)
{
font->refcount = 1;
font->backend = backend;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_unscaled_font_text_to_glyphs (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
const unsigned char *utf8,
cairo_glyph_t **glyphs,
int *num_glyphs)
_cairo_font_text_to_glyphs (cairo_font_t *font,
const unsigned char *utf8,
cairo_glyph_t **glyphs,
int *num_glyphs)
{
return font->backend->text_to_glyphs (font, scale, utf8, glyphs, num_glyphs);
return font->backend->text_to_glyphs (font, utf8, glyphs, num_glyphs);
}
cairo_status_t
_cairo_unscaled_font_glyph_extents (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_text_extents_t *extents)
_cairo_font_glyph_extents (cairo_font_t *font,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_text_extents_t *extents)
{
return font->backend->glyph_extents(font, scale, glyphs, num_glyphs, extents);
return font->backend->glyph_extents(font, glyphs, num_glyphs, extents);
}
cairo_status_t
_cairo_unscaled_font_glyph_bbox (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_box_t *bbox)
_cairo_font_glyph_bbox (cairo_font_t *font,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_box_t *bbox)
{
return font->backend->glyph_bbox (font, scale, glyphs, num_glyphs, bbox);
return font->backend->glyph_bbox (font, glyphs, num_glyphs, bbox);
}
cairo_status_t
_cairo_unscaled_font_show_glyphs (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
cairo_operator_t operator,
cairo_surface_t *source,
cairo_surface_t *surface,
int source_x,
int source_y,
cairo_glyph_t *glyphs,
int num_glyphs)
_cairo_font_show_glyphs (cairo_font_t *font,
cairo_operator_t operator,
cairo_surface_t *source,
cairo_surface_t *surface,
int source_x,
int source_y,
cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_status_t status;
if (surface->backend->show_glyphs != NULL) {
status = surface->backend->show_glyphs (font, scale, operator, source,
status = surface->backend->show_glyphs (font, operator, source,
surface, source_x, source_y,
glyphs, num_glyphs);
if (status == CAIRO_STATUS_SUCCESS)
@ -297,27 +119,32 @@ _cairo_unscaled_font_show_glyphs (cairo_unscaled_font_t *font,
}
/* Surface display routine either does not exist or failed. */
return font->backend->show_glyphs (font, scale, operator, source,
return font->backend->show_glyphs (font, operator, source,
surface, source_x, source_y,
glyphs, num_glyphs);
}
cairo_status_t
_cairo_unscaled_font_glyph_path (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_path_t *path)
_cairo_font_glyph_path (cairo_font_t *font,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_path_t *path)
{
return font->backend->glyph_path (font, scale, glyphs, num_glyphs, path);
return font->backend->glyph_path (font, glyphs, num_glyphs, path);
}
void
_cairo_font_get_glyph_cache_key (cairo_font_t *font,
cairo_glyph_cache_key_t *key)
{
font->backend->get_glyph_cache_key (font, key);
}
cairo_status_t
_cairo_unscaled_font_font_extents (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
cairo_font_extents_t *extents)
_cairo_font_font_extents (cairo_font_t *font,
cairo_font_extents_t *extents)
{
return font->backend->font_extents(font, scale, extents);
return font->backend->font_extents (font, extents);
}
void
@ -332,8 +159,7 @@ _cairo_unscaled_font_destroy (cairo_unscaled_font_t *font)
if (--(font->refcount) > 0)
return;
if (font->backend)
font->backend->destroy (font);
font->backend->destroy_unscaled_font (font);
}
@ -352,37 +178,97 @@ cairo_font_destroy (cairo_font_t *font)
if (--(font->refcount) > 0)
return;
if (font->unscaled)
_cairo_unscaled_font_destroy (font->unscaled);
free (font);
font->backend->destroy_font (font);
}
void
cairo_font_set_transform (cairo_font_t *font,
cairo_matrix_t *matrix)
cairo_font_glyph_extents (cairo_font_t *font,
cairo_matrix_t *font_matrix,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_text_extents_t *extents)
{
double dummy;
cairo_matrix_get_affine (matrix,
&font->scale.matrix[0][0],
&font->scale.matrix[0][1],
&font->scale.matrix[1][0],
&font->scale.matrix[1][1],
&dummy, &dummy);
}
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_glyph_t origin_glyph;
cairo_text_extents_t origin_extents;
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;
void
cairo_font_current_transform (cairo_font_t *font,
cairo_matrix_t *matrix)
{
cairo_matrix_set_affine (matrix,
font->scale.matrix[0][0],
font->scale.matrix[0][1],
font->scale.matrix[1][0],
font->scale.matrix[1][1],
0, 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;
}
for (i = 0; i < num_glyphs; i++)
{
double x, y;
double wm, hm;
origin_glyph = glyphs[i];
origin_glyph.x = 0.0;
origin_glyph.y = 0.0;
status = _cairo_font_glyph_extents (font,
&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 = origin_extents.x_bearing;
y = origin_extents.y_bearing;
cairo_matrix_transform_point (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 (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 (font_matrix,
&x, &y);
x_pos = glyphs[i].x + x;
y_pos = glyphs[i].y + y;
}
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;
}
/* Now we implement functions to access a default global image & metrics
* cache.
@ -398,7 +284,8 @@ _cairo_glyph_cache_hash (void *cache, void *key)
^ ((unsigned long) in->scale.matrix[0][0])
^ ((unsigned long) in->scale.matrix[0][1])
^ ((unsigned long) in->scale.matrix[1][0])
^ ((unsigned long) in->scale.matrix[1][1])
^ ((unsigned long) in->scale.matrix[1][1])
^ (in->flags * 1451) /* 1451 is just an abitrary prime */
^ in->index;
}
@ -412,6 +299,7 @@ _cairo_glyph_cache_keys_equal (void *cache,
b = (cairo_glyph_cache_key_t *) k2;
return (a->index == b->index)
&& (a->unscaled == b->unscaled)
&& (a->flags == b->flags)
&& (a->scale.matrix[0][0] == b->scale.matrix[0][0])
&& (a->scale.matrix[0][1] == b->scale.matrix[0][1])
&& (a->scale.matrix[1][0] == b->scale.matrix[1][0])

File diff suppressed because it is too large Load diff

View file

@ -45,6 +45,8 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
cairo_operator_t operator,
cairo_surface_t *dst,
cairo_traps_t *traps);
static void
_cairo_gstate_unset_font (cairo_gstate_t *gstate);
cairo_gstate_t *
_cairo_gstate_create ()
@ -77,9 +79,11 @@ _cairo_gstate_init (cairo_gstate_t *gstate)
gstate->num_dashes = 0;
gstate->dash_offset = 0.0;
gstate->font = _cairo_unscaled_font_create (CAIRO_FONT_FAMILY_DEFAULT,
CAIRO_FONT_SLANT_DEFAULT,
CAIRO_FONT_WEIGHT_DEFAULT);
gstate->font_family = NULL;
gstate->font_slant = CAIRO_FONT_SLANT_DEFAULT;
gstate->font_weight = CAIRO_FONT_WEIGHT_DEFAULT;
gstate->font = NULL;
gstate->surface = NULL;
@ -118,9 +122,15 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
memcpy (gstate->dash, other->dash, other->num_dashes * sizeof (double));
}
if (other->font_family) {
gstate->font_family = strdup (other->font_family);
if (!gstate->font_family)
goto CLEANUP_DASH;
}
if (other->font) {
gstate->font = other->font;
_cairo_unscaled_font_reference (gstate->font);
cairo_font_reference (gstate->font);
}
if (other->clip.region)
@ -148,18 +158,29 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
_cairo_path_fini (&gstate->path);
CLEANUP_FONT:
_cairo_unscaled_font_destroy (gstate->font);
cairo_font_destroy (gstate->font);
gstate->font = NULL;
if (gstate->font_family) {
free (gstate->font_family);
gstate->font_family = NULL;
}
CLEANUP_DASH:
free (gstate->dash);
gstate->dash = NULL;
return status;
return CAIRO_STATUS_NO_MEMORY;
}
void
_cairo_gstate_fini (cairo_gstate_t *gstate)
{
_cairo_unscaled_font_destroy (gstate->font);
if (gstate->font_family)
free (gstate->font_family);
if (gstate->font)
cairo_font_destroy (gstate->font);
if (gstate->surface)
cairo_surface_destroy (gstate->surface);
@ -323,6 +344,8 @@ _cairo_gstate_set_target_surface (cairo_gstate_t *gstate, cairo_surface_t *surfa
{
double scale;
_cairo_gstate_unset_font (gstate);
if (gstate->surface)
cairo_surface_destroy (gstate->surface);
@ -549,6 +572,8 @@ _cairo_gstate_translate (cairo_gstate_t *gstate, double tx, double ty)
{
cairo_matrix_t tmp;
_cairo_gstate_unset_font (gstate);
_cairo_matrix_set_translate (&tmp, tx, ty);
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
@ -566,6 +591,8 @@ _cairo_gstate_scale (cairo_gstate_t *gstate, double sx, double sy)
if (sx == 0 || sy == 0)
return CAIRO_STATUS_INVALID_MATRIX;
_cairo_gstate_unset_font (gstate);
_cairo_matrix_set_scale (&tmp, sx, sy);
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
@ -580,6 +607,8 @@ _cairo_gstate_rotate (cairo_gstate_t *gstate, double angle)
{
cairo_matrix_t tmp;
_cairo_gstate_unset_font (gstate);
_cairo_matrix_set_rotate (&tmp, angle);
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
@ -595,6 +624,8 @@ _cairo_gstate_concat_matrix (cairo_gstate_t *gstate,
{
cairo_matrix_t tmp;
_cairo_gstate_unset_font (gstate);
cairo_matrix_copy (&tmp, matrix);
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
@ -610,6 +641,8 @@ _cairo_gstate_set_matrix (cairo_gstate_t *gstate,
{
cairo_status_t status;
_cairo_gstate_unset_font (gstate);
cairo_matrix_copy (&gstate->ctm, matrix);
cairo_matrix_copy (&gstate->ctm_inverse, matrix);
@ -627,6 +660,8 @@ _cairo_gstate_default_matrix (cairo_gstate_t *gstate)
if (scale == 0)
scale = 1;
_cairo_gstate_unset_font (gstate);
cairo_matrix_set_identity (&gstate->font_matrix);
cairo_matrix_set_identity (&gstate->ctm);
@ -640,6 +675,8 @@ _cairo_gstate_default_matrix (cairo_gstate_t *gstate)
cairo_status_t
_cairo_gstate_identity_matrix (cairo_gstate_t *gstate)
{
_cairo_gstate_unset_font (gstate);
cairo_matrix_set_identity (&gstate->ctm);
cairo_matrix_set_identity (&gstate->ctm_inverse);
@ -2121,6 +2158,14 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate,
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_gstate_unset_font (cairo_gstate_t *gstate)
{
if (gstate->font) {
cairo_font_destroy (gstate->font);
gstate->font = NULL;
}
}
cairo_status_t
_cairo_gstate_select_font (cairo_gstate_t *gstate,
@ -2128,12 +2173,17 @@ _cairo_gstate_select_font (cairo_gstate_t *gstate,
cairo_font_slant_t slant,
cairo_font_weight_t weight)
{
if (gstate->font)
_cairo_unscaled_font_destroy (gstate->font);
char *new_family;
gstate->font = _cairo_unscaled_font_create (family, slant, weight);
if (gstate->font == NULL)
new_family = strdup (family);
if (!new_family)
return CAIRO_STATUS_NO_MEMORY;
_cairo_gstate_unset_font (gstate);
gstate->font_family = new_family;
gstate->font_slant = slant;
gstate->font_weight = weight;
cairo_matrix_set_identity (&gstate->font_matrix);
@ -2144,6 +2194,8 @@ cairo_status_t
_cairo_gstate_scale_font (cairo_gstate_t *gstate,
double scale)
{
_cairo_gstate_unset_font (gstate);
return cairo_matrix_scale (&gstate->font_matrix, scale, scale);
}
@ -2153,6 +2205,9 @@ _cairo_gstate_transform_font (cairo_gstate_t *gstate,
{
cairo_matrix_t tmp;
double a, b, c, d, tx, ty;
_cairo_gstate_unset_font (gstate);
cairo_matrix_get_affine (matrix, &a, &b, &c, &d, &tx, &ty);
cairo_matrix_set_affine (&tmp, a, b, c, d, 0, 0);
return cairo_matrix_multiply (&gstate->font_matrix, &gstate->font_matrix, &tmp);
@ -2160,28 +2215,10 @@ _cairo_gstate_transform_font (cairo_gstate_t *gstate,
cairo_status_t
_cairo_gstate_current_font (cairo_gstate_t *gstate,
cairo_font_t **font)
_cairo_gstate_current_font (cairo_gstate_t *gstate, cairo_font_t **font)
{
cairo_font_scale_t scale;
cairo_font_t *scaled;
double dummy;
scaled = malloc (sizeof (cairo_font_t));
if (scaled == NULL)
return CAIRO_STATUS_NO_MEMORY;
cairo_matrix_get_affine (&gstate->font_matrix,
&scale.matrix[0][0],
&scale.matrix[0][1],
&scale.matrix[1][0],
&scale.matrix[1][1],
&dummy, &dummy);
_cairo_font_init (scaled, &scale, gstate->font);
_cairo_unscaled_font_reference (gstate->font);
*font = scaled;
*font = gstate->font;
cairo_font_reference (*font);
return CAIRO_STATUS_SUCCESS;
}
@ -2190,6 +2227,8 @@ void
_cairo_gstate_set_font_transform (cairo_gstate_t *gstate,
cairo_matrix_t *matrix)
{
_cairo_gstate_unset_font (gstate);
cairo_matrix_copy (&gstate->font_matrix, matrix);
}
@ -2214,12 +2253,10 @@ _cairo_gstate_current_font_transform (cairo_gstate_t *gstate,
* independently scale the user coordinate system *or* the font matrix, in
* order to adjust the rendered size of the font.
*
* If the user asks for a permanent reference to "a font", they are given a
* handle to a structure holding a scale matrix and an unscaled font. This
* effectively decouples the font from further changes to user space. Even
* if the user then "sets" the current cairo_t font to the handle they were
* passed, further changes to the cairo_t CTM will not affect externally
* held references to the font.
* The only font type exposed to the user is cairo_font_t which is a
* a font specialized to a particular scale matrix, CTM, and target
* surface. The user is responsible for not using a cairo_font_t
* after changing the parameters; doing so will produce garbled metrics.
*
*
* The font's view
@ -2279,9 +2316,9 @@ _cairo_gstate_current_font_transform (cairo_gstate_t *gstate,
*
*/
static void
_build_font_scale (cairo_gstate_t *gstate,
cairo_font_scale_t *sc)
void
_cairo_gstate_current_font_scale (cairo_gstate_t *gstate,
cairo_font_scale_t *sc)
{
cairo_matrix_t tmp;
double dummy;
@ -2294,17 +2331,47 @@ _build_font_scale (cairo_gstate_t *gstate,
&dummy, &dummy);
}
static cairo_status_t
_cairo_gstate_ensure_font (cairo_gstate_t *gstate)
{
cairo_font_scale_t sc;
cairo_status_t status;
const char *family;
if (gstate->font)
return CAIRO_STATUS_SUCCESS;
_cairo_gstate_current_font_scale (gstate, &sc);
if (gstate->font_family)
family = gstate->font_family;
else
family = CAIRO_FONT_FAMILY_DEFAULT;
status = _cairo_font_create (family,
gstate->font_slant,
gstate->font_weight,
&sc,
&gstate->font);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_gstate_current_font_extents (cairo_gstate_t *gstate,
cairo_font_extents_t *extents)
{
cairo_int_status_t status;
cairo_font_scale_t sc;
double font_scale_x, font_scale_y;
_build_font_scale (gstate, &sc);
status = _cairo_unscaled_font_font_extents (gstate->font, &sc, extents);
status = _cairo_gstate_ensure_font (gstate);
if (status)
return status;
status = _cairo_font_font_extents (gstate->font, extents);
_cairo_matrix_compute_scale_factors (&gstate->font_matrix,
&font_scale_x, &font_scale_y,
@ -2331,14 +2398,15 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
int *nglyphs)
{
cairo_status_t status;
cairo_font_scale_t sc;
cairo_point_t point;
double origin_x, origin_y;
int i;
_build_font_scale (gstate, &sc);
status = _cairo_gstate_ensure_font (gstate);
if (status)
return status;
status = _cairo_path_current_point (&gstate->path, &point);
if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
origin_x = 0.0;
@ -2350,8 +2418,8 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
&origin_x, &origin_y);
}
status = _cairo_unscaled_font_text_to_glyphs (gstate->font,
&sc, utf8, glyphs, nglyphs);
status = _cairo_font_text_to_glyphs (gstate->font,
utf8, glyphs, nglyphs);
if (status || !glyphs || !nglyphs || !(*glyphs) || !(nglyphs))
return status;
@ -2373,18 +2441,13 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
cairo_status_t
_cairo_gstate_set_font (cairo_gstate_t *gstate,
cairo_font_t *font)
cairo_font_t *font)
{
if (gstate->font != NULL)
_cairo_unscaled_font_destroy (gstate->font);
gstate->font = font->unscaled;
_cairo_unscaled_font_reference (gstate->font);
cairo_matrix_set_affine (&gstate->font_matrix,
font->scale.matrix[0][0],
font->scale.matrix[0][1],
font->scale.matrix[1][0],
font->scale.matrix[1][1],
0, 0);
cairo_font_destroy (gstate->font);
gstate->font = font;
cairo_font_reference (gstate->font);
return CAIRO_STATUS_SUCCESS;
}
@ -2394,90 +2457,18 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
int num_glyphs,
cairo_text_extents_t *extents)
{
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;
cairo_status_t status;
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;
}
status = _cairo_gstate_ensure_font (gstate);
if (status)
return status;
_build_font_scale (gstate, &sc);
cairo_font_glyph_extents (gstate->font,
&gstate->font_matrix,
glyphs, num_glyphs,
extents);
for (i = 0; i < num_glyphs; i++)
{
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 = origin_extents.x_bearing;
y = origin_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;
}
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;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
@ -2488,12 +2479,13 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
cairo_status_t status;
int i;
cairo_glyph_t *transformed_glyphs = NULL;
cairo_font_scale_t sc;
cairo_pattern_t pattern;
cairo_box_t bbox;
_build_font_scale (gstate, &sc);
status = _cairo_gstate_ensure_font (gstate);
if (status)
return status;
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
if (transformed_glyphs == NULL)
return CAIRO_STATUS_NO_MEMORY;
@ -2507,9 +2499,9 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
}
_cairo_pattern_init_copy (&pattern, gstate->pattern);
status = _cairo_unscaled_font_glyph_bbox (gstate->font, &sc,
transformed_glyphs, num_glyphs,
&bbox);
status = _cairo_font_glyph_bbox (gstate->font,
transformed_glyphs, num_glyphs,
&bbox);
if (status)
goto CLEANUP_GLYPHS;
@ -2565,14 +2557,13 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
transformed_glyphs[i].y -= draw_extents->y1;
}
status = _cairo_unscaled_font_show_glyphs (gstate->font,
&sc,
CAIRO_OPERATOR_ADD,
pattern.source, intermediate,
draw_extents->x1 - pattern.source_offset.x,
draw_extents->y1 - pattern.source_offset.y,
transformed_glyphs, num_glyphs);
status = _cairo_font_show_glyphs (gstate->font,
CAIRO_OPERATOR_ADD,
pattern.source, intermediate,
draw_extents->x1 - pattern.source_offset.x,
draw_extents->y1 - pattern.source_offset.y,
transformed_glyphs, num_glyphs);
if (status)
goto BAIL2;
@ -2610,13 +2601,12 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
}
else
{
status = _cairo_unscaled_font_show_glyphs (gstate->font,
&sc,
gstate->operator, pattern.source,
gstate->surface,
-pattern.source_offset.x,
-pattern.source_offset.y,
transformed_glyphs, num_glyphs);
status = _cairo_font_show_glyphs (gstate->font,
gstate->operator, pattern.source,
gstate->surface,
-pattern.source_offset.x,
-pattern.source_offset.y,
transformed_glyphs, num_glyphs);
}
_cairo_pattern_fini (&pattern);
@ -2635,9 +2625,6 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
cairo_status_t status;
int i;
cairo_glyph_t *transformed_glyphs = NULL;
cairo_font_scale_t sc;
_build_font_scale (gstate, &sc);
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
if (transformed_glyphs == NULL)
@ -2651,9 +2638,9 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
&(transformed_glyphs[i].y));
}
status = _cairo_unscaled_font_glyph_path (gstate->font, &sc,
transformed_glyphs, num_glyphs,
&gstate->path);
status = _cairo_font_glyph_path (gstate->font,
transformed_glyphs, num_glyphs,
&gstate->path);
free (transformed_glyphs);
return status;

View file

@ -36,9 +36,8 @@
#include "cairoint.h"
#include "cairo-pdf.h"
/* XXX: This seems broken to me. What about users without freetype
* that want to use a cairo PDF surface? */
#include "cairo-ft.h"
/* XXX: Eventually, we need to handle other font backends */
#include "cairo-ft-private.h"
#include <ft2build.h>
#include FT_FREETYPE_H
@ -300,19 +299,15 @@ cairo_pdf_font_destroy (cairo_pdf_font_t *font)
}
static cairo_pdf_font_t *
cairo_pdf_ft_font_create (cairo_pdf_document_t *document,
cairo_unscaled_font_t *unscaled_font,
cairo_font_scale_t *scale)
cairo_pdf_ft_font_create (cairo_pdf_document_t *document,
cairo_unscaled_font_t *unscaled_font)
{
cairo_font_t scaled_font;
FT_Face face;
cairo_pdf_ft_font_t *font;
unsigned long size;
int i, j;
/* FIXME: Why do I have to pass a scaled font to get the FT_Face? */
_cairo_font_init (&scaled_font, scale, unscaled_font);
face = cairo_ft_font_face (&scaled_font);
face = _cairo_ft_unscaled_font_lock_face (unscaled_font);
/* We currently only support freetype truetype fonts. */
size = 0;
@ -333,7 +328,8 @@ cairo_pdf_ft_font_create (cairo_pdf_document_t *document,
if (_cairo_array_grow_by (&font->output, 4096) != CAIRO_STATUS_SUCCESS)
goto fail1;
font->face = face;
font->base.unscaled_font = unscaled_font;
_cairo_unscaled_font_reference (unscaled_font);
font->glyphs = calloc (face->num_glyphs + 1, sizeof (ft_subset_glyph_t));
if (font->glyphs == NULL)
goto fail2;
@ -364,6 +360,8 @@ cairo_pdf_ft_font_create (cairo_pdf_document_t *document,
if (font->base.widths == NULL)
goto fail5;
_cairo_ft_unscaled_font_unlock_face (unscaled_font);
font->status = CAIRO_STATUS_SUCCESS;
return &font->base;
@ -764,12 +762,15 @@ cairo_pdf_ft_font_generate (void *abstract_font,
unsigned long start, end, next, checksum;
int i;
font->face = _cairo_ft_unscaled_font_lock_face (font->base.unscaled_font);
if (cairo_pdf_ft_font_write_offset_table (font))
return font->status;
goto fail;
start = cairo_pdf_ft_font_align_output (font);
end = start;
end = 0;
for (i = 0; i < ARRAY_LENGTH (truetype_tables); i++) {
if (truetype_tables[i].write (font, truetype_tables[i].tag))
goto fail;
@ -789,6 +790,9 @@ cairo_pdf_ft_font_generate (void *abstract_font,
*length = _cairo_array_num_elements (&font->output);
fail:
_cairo_ft_unscaled_font_unlock_face (font->base.unscaled_font);
font->face = NULL;
return font->status;
}
@ -1704,36 +1708,37 @@ _cairo_pdf_surface_create_pattern (void *abstract_surface,
static cairo_pdf_font_t *
_cairo_pdf_document_get_font (cairo_pdf_document_t *document,
cairo_unscaled_font_t *unscaled_font,
cairo_font_scale_t *scale)
cairo_font_t *font)
{
cairo_pdf_font_t *font;
cairo_unscaled_font_t *unscaled_font;
cairo_pdf_font_t *pdf_font;
unsigned int num_fonts, i;
unscaled_font = _cairo_ft_font_get_unscaled_font (font);
num_fonts = _cairo_array_num_elements (&document->fonts);
for (i = 0; i < num_fonts; i++) {
_cairo_array_copy_element (&document->fonts, i, &font);
if (font->unscaled_font == unscaled_font)
return font;
_cairo_array_copy_element (&document->fonts, i, &pdf_font);
if (pdf_font->unscaled_font == unscaled_font)
return pdf_font;
}
/* FIXME: Figure out here which font backend is in use and call
* the appropriate constructor. */
font = cairo_pdf_ft_font_create (document, unscaled_font, scale);
pdf_font = cairo_pdf_ft_font_create (document, unscaled_font);
if (font == NULL)
return NULL;
if (_cairo_array_append (&document->fonts, &font, 1) == NULL) {
cairo_pdf_font_destroy (font);
if (_cairo_array_append (&document->fonts, &pdf_font, 1) == NULL) {
cairo_pdf_font_destroy (pdf_font);
return NULL;
}
return font;
return pdf_font;
}
static cairo_status_t
_cairo_pdf_surface_show_glyphs (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
_cairo_pdf_surface_show_glyphs (cairo_font_t *font,
cairo_operator_t operator,
cairo_surface_t *source,
void *abstract_surface,
@ -1748,7 +1753,7 @@ _cairo_pdf_surface_show_glyphs (cairo_unscaled_font_t *font,
cairo_pdf_font_t *pdf_font;
int i, index;
pdf_font = _cairo_pdf_document_get_font (document, font, scale);
pdf_font = _cairo_pdf_document_get_font (document, font);
if (pdf_font == NULL)
return CAIRO_STATUS_NO_MEMORY;
@ -1761,10 +1766,10 @@ _cairo_pdf_surface_show_glyphs (cairo_unscaled_font_t *font,
fprintf (file,
" %f %f %f %f %f %f Tm (%c) Tj",
scale->matrix[0][0],
scale->matrix[0][1],
scale->matrix[1][0],
-scale->matrix[1][1],
font->scale.matrix[0][0],
font->scale.matrix[0][1],
font->scale.matrix[1][0],
-font->scale.matrix[1][1],
glyphs[i].x,
glyphs[i].y,
index);

View file

@ -1,6 +1,6 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2004 Calum Robinson
* Copyright © 2004 Calum Robinson
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public

View file

@ -694,8 +694,7 @@ _cairo_xlib_surface_create_pattern (void *abstract_surface,
}
static cairo_status_t
_cairo_xlib_surface_show_glyphs (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
_cairo_xlib_surface_show_glyphs (cairo_font_t *font,
cairo_operator_t operator,
cairo_surface_t *source,
void *abstract_surface,
@ -824,6 +823,7 @@ typedef struct glyphset_cache {
} glyphset_cache_t;
typedef struct {
int refcount;
cairo_glyph_cache_key_t key;
Glyph glyph;
XGlyphInfo info;
@ -854,17 +854,18 @@ _xlib_glyphset_cache_create_entry (void *cache,
_cairo_lock_global_image_glyph_cache ();
im_cache = _cairo_get_global_image_glyph_cache ();
if (g == NULL || v == NULL ||g == NULL || im_cache == NULL) {
if (g == NULL || v == NULL || im_cache == NULL) {
_cairo_unlock_global_image_glyph_cache ();
return CAIRO_STATUS_NO_MEMORY;
}
status = _cairo_cache_lookup (im_cache, key, (void **) (&im));
status = _cairo_cache_lookup (im_cache, key, (void **) (&im), NULL);
if (status != CAIRO_STATUS_SUCCESS || im == NULL) {
_cairo_unlock_global_image_glyph_cache ();
return CAIRO_STATUS_NO_MEMORY;
}
v->refcount = 1;
v->key = *k;
_cairo_unscaled_font_reference (v->key.unscaled);
@ -925,6 +926,12 @@ _xlib_glyphset_cache_create_entry (void *cache,
return CAIRO_STATUS_SUCCESS;
}
static void
_glyphset_cache_entry_reference (glyphset_cache_entry_t *e)
{
e->refcount++;
}
static void
_xlib_glyphset_cache_destroy_cache (void *cache)
{
@ -940,6 +947,9 @@ _xlib_glyphset_cache_destroy_entry (void *cache, void *entry)
g = (glyphset_cache_t *) cache;
v = (glyphset_cache_entry_t *) entry;
if (--v->refcount > 0)
return;
_cairo_unscaled_font_destroy (v->key.unscaled);
XRenderFreeGlyphs (g->display, g->glyphset, &(v->glyph), 1);
free (v);
@ -1014,8 +1024,7 @@ _get_glyphset_cache (Display *d)
#define N_STACK_BUF 1024
static cairo_status_t
_cairo_xlib_surface_show_glyphs32 (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
_cairo_xlib_surface_show_glyphs32 (cairo_font_t *font,
cairo_operator_t operator,
glyphset_cache_t *g,
cairo_glyph_cache_key_t *key,
@ -1092,8 +1101,7 @@ _cairo_xlib_surface_show_glyphs32 (cairo_unscaled_font_t *font,
static cairo_status_t
_cairo_xlib_surface_show_glyphs16 (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
_cairo_xlib_surface_show_glyphs16 (cairo_font_t *font,
cairo_operator_t operator,
glyphset_cache_t *g,
cairo_glyph_cache_key_t *key,
@ -1169,10 +1177,9 @@ _cairo_xlib_surface_show_glyphs16 (cairo_unscaled_font_t *font,
}
static cairo_status_t
_cairo_xlib_surface_show_glyphs8 (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
_cairo_xlib_surface_show_glyphs8 (cairo_font_t *font,
cairo_operator_t operator,
glyphset_cache_t *g,
glyphset_cache_t *g,
cairo_glyph_cache_key_t *key,
cairo_xlib_surface_t *src,
cairo_xlib_surface_t *self,
@ -1247,8 +1254,7 @@ _cairo_xlib_surface_show_glyphs8 (cairo_unscaled_font_t *font,
static cairo_status_t
_cairo_xlib_surface_show_glyphs (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
_cairo_xlib_surface_show_glyphs (cairo_font_t *font,
cairo_operator_t operator,
cairo_surface_t *source,
void *abstract_surface,
@ -1305,15 +1311,23 @@ _cairo_xlib_surface_show_glyphs (cairo_unscaled_font_t *font,
/* Work out the index size to use. */
elt_size = 8;
key.scale = *scale;
key.unscaled = font;
_cairo_font_get_glyph_cache_key (font, &key);
for (i = 0; i < num_glyphs; ++i) {
key.index = glyphs[i].index;
status = _cairo_cache_lookup (&g->base, &key, (void **) (&entries[i]));
status = _cairo_cache_lookup (&g->base, &key, (void **) (&entries[i]), NULL);
if (status != CAIRO_STATUS_SUCCESS || entries[i] == NULL)
goto UNLOCK;
/* Referencing the glyph entries we use prevents them from
* being freed if lookup of later entries causes them to
* be ejected from the cache. It would be more efficient
* (though more complex) to prevent them from being ejected
* from the cache at all, so they could get reused later
* in the same string.
*/
_glyphset_cache_entry_reference (entries[i]);
if (elt_size == 8 && entries[i]->glyph > 0xff)
elt_size = 16;
if (elt_size == 16 && entries[i]->glyph > 0xffff) {
@ -1325,18 +1339,21 @@ _cairo_xlib_surface_show_glyphs (cairo_unscaled_font_t *font,
/* Call the appropriate sub-function. */
if (elt_size == 8)
status = _cairo_xlib_surface_show_glyphs8 (font, scale, operator, g, &key, src, self,
status = _cairo_xlib_surface_show_glyphs8 (font, operator, g, &key, src, self,
source_x, source_y,
glyphs, entries, num_glyphs);
else if (elt_size == 16)
status = _cairo_xlib_surface_show_glyphs16 (font, scale, operator, g, &key, src, self,
status = _cairo_xlib_surface_show_glyphs16 (font, operator, g, &key, src, self,
source_x, source_y,
glyphs, entries, num_glyphs);
else
status = _cairo_xlib_surface_show_glyphs32 (font, scale, operator, g, &key, src, self,
status = _cairo_xlib_surface_show_glyphs32 (font, operator, g, &key, src, self,
source_x, source_y,
glyphs, entries, num_glyphs);
for (i = 0; i < num_glyphs; ++i)
_xlib_glyphset_cache_destroy_entry (g, entries[i]);
_unlock_xlib_glyphset_caches ();
if (tmp != NULL) {

View file

@ -373,43 +373,49 @@ _cairo_cache_destroy (cairo_cache_t *cache);
cairo_private cairo_status_t
_cairo_cache_lookup (cairo_cache_t *cache,
void *key,
void **entry_return);
void *key,
void **entry_return,
int *created_entry);
cairo_private cairo_status_t
_cairo_cache_remove (cairo_cache_t *cache,
void *key);
cairo_private void *
_cairo_cache_random_entry (cairo_cache_t *cache,
int (*predicate) (void*));
cairo_private unsigned long
_cairo_hash_string (const char *c);
#define CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT 0x100000
#define CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT 0x100000
#define CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT 20
#define CAIRO_FT_CACHE_NUM_FONTS_DEFAULT 20
typedef struct {
double matrix[2][2];
double matrix[2][2];
} cairo_font_scale_t;
struct _cairo_font_backend;
/*
* A cairo_unscaled_font_t is just an opaque handle we use in the
* glyph cache.
*/
typedef struct {
int refcount;
const struct _cairo_font_backend *backend;
} cairo_unscaled_font_t;
/*
* A cairo_font contains a pointer to a cairo_unscaled_font_t and a scale
* matrix. These are the things the user holds references to.
*/
struct _cairo_font {
int refcount;
cairo_font_scale_t scale;
cairo_unscaled_font_t *unscaled;
cairo_font_scale_t scale; /* font space => device space */
const struct _cairo_font_backend *backend;
};
/* cairo_font.c is responsible for two global caches:
/* cairo_font.c is responsible for a global glyph cache:
*
* - font entries: [[[base], name, weight, slant], cairo_unscaled_font_t ]
* - glyph entries: [[[base], cairo_font_t, index], image, size, extents ]
* - glyph entries: [[[base], cairo_unscaled_font_t, scale, flags, index],
* image, size, extents]
*
* Surfaces may build their own glyph caches if they have surface-specific
* glyph resources to maintain; those caches can feed off of the global
@ -420,6 +426,7 @@ typedef struct {
cairo_cache_entry_base_t base;
cairo_unscaled_font_t *unscaled;
cairo_font_scale_t scale;
int flags;
unsigned long index;
} cairo_glyph_cache_key_t;
@ -452,36 +459,34 @@ _cairo_glyph_cache_keys_equal (void *cache,
/* the font backend interface */
typedef struct _cairo_font_backend {
cairo_unscaled_font_t *(*create) (const char *family,
cairo_status_t (*create) (const char *family,
cairo_font_slant_t slant,
cairo_font_weight_t weight);
cairo_font_weight_t weight,
cairo_font_scale_t *scale,
cairo_font_t **font);
void (*destroy) (void *font);
void (*destroy_font) (void *font);
void (*destroy_unscaled_font) (void *font);
cairo_status_t (*font_extents) (void *font,
cairo_font_scale_t *scale,
cairo_font_extents_t *extents);
cairo_status_t (*text_to_glyphs) (void *font,
cairo_font_scale_t *scale,
const unsigned char *utf8,
cairo_glyph_t **glyphs,
int *num_glyphs);
cairo_status_t (*glyph_extents) (void *font,
cairo_font_scale_t *scale,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_text_extents_t *extents);
cairo_status_t (*glyph_bbox) (void *font,
cairo_font_scale_t *scale,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_box_t *bbox);
cairo_status_t (*show_glyphs) (void *font,
cairo_font_scale_t *scale,
cairo_operator_t operator,
cairo_surface_t *source,
cairo_surface_t *surface,
@ -491,10 +496,11 @@ typedef struct _cairo_font_backend {
int num_glyphs);
cairo_status_t (*glyph_path) (void *font,
cairo_font_scale_t *scale,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_path_t *path);
void (*get_glyph_cache_key) (void *font,
cairo_glyph_cache_key_t *key);
cairo_status_t (*create_glyph) (cairo_image_glyph_cache_entry_t *entry);
@ -603,8 +609,7 @@ typedef struct _cairo_surface_backend {
* surface, using image surfaces as glyphs.
*/
cairo_status_t
(*show_glyphs) (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
(*show_glyphs) (cairo_font_t *font,
cairo_operator_t operator,
cairo_surface_t *source,
void *surface,
@ -797,7 +802,11 @@ typedef struct _cairo_gstate {
int num_dashes;
double dash_offset;
cairo_unscaled_font_t *font;
char *font_family; /* NULL means CAIRO_FONT_FAMILY_DEFAULT; */
cairo_font_slant_t font_slant;
cairo_font_weight_t font_weight;
cairo_font_t *font; /* Specific to the current CTM */
cairo_surface_t *surface;
@ -1119,6 +1128,10 @@ cairo_private cairo_status_t
_cairo_gstate_scale_font (cairo_gstate_t *gstate,
double scale);
cairo_private void
_cairo_gstate_current_font_scale (cairo_gstate_t *gstate,
cairo_font_scale_t *sc);
cairo_private cairo_status_t
_cairo_gstate_transform_font (cairo_gstate_t *gstate,
cairo_matrix_t *matrix);
@ -1184,19 +1197,21 @@ _cairo_color_set_alpha (cairo_color_t *color, double alpha);
/* cairo_font.c */
cairo_private cairo_unscaled_font_t *
_cairo_unscaled_font_create (const char *family,
cairo_font_slant_t slant,
cairo_font_weight_t weight);
cairo_private cairo_status_t
_cairo_font_create (const char *family,
cairo_font_slant_t slant,
cairo_font_weight_t weight,
cairo_font_scale_t *sc,
cairo_font_t **font);
cairo_private void
_cairo_font_init (cairo_font_t *scaled,
cairo_font_scale_t *scale,
cairo_unscaled_font_t *unscaled);
_cairo_font_init (cairo_font_t *font,
cairo_font_scale_t *scale,
const cairo_font_backend_t *backend);
cairo_private cairo_status_t
_cairo_unscaled_font_init (cairo_unscaled_font_t *font,
const struct _cairo_font_backend *backend);
cairo_private void
_cairo_unscaled_font_init (cairo_unscaled_font_t *font,
const struct _cairo_font_backend *backend);
cairo_private void
_cairo_unscaled_font_reference (cairo_unscaled_font_t *font);
@ -1205,48 +1220,52 @@ cairo_private void
_cairo_unscaled_font_destroy (cairo_unscaled_font_t *font);
cairo_private cairo_status_t
_cairo_unscaled_font_font_extents (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
cairo_font_extents_t *extents);
_cairo_font_font_extents (cairo_font_t *font,
cairo_font_extents_t *extents);
cairo_private cairo_status_t
_cairo_unscaled_font_text_to_glyphs (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
const unsigned char *utf8,
cairo_glyph_t **glyphs,
int *num_glyphs);
_cairo_font_text_to_glyphs (cairo_font_t *font,
const unsigned char *utf8,
cairo_glyph_t **glyphs,
int *num_glyphs);
cairo_private cairo_status_t
_cairo_unscaled_font_glyph_extents (cairo_unscaled_font_t *font,
cairo_font_scale_t *scale,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_text_extents_t *extents);
_cairo_font_glyph_extents (cairo_font_t *font,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_text_extents_t *extents);
cairo_private cairo_status_t
_cairo_unscaled_font_glyph_bbox (cairo_unscaled_font_t *font,
cairo_font_scale_t *size,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_box_t *bbox);
_cairo_font_glyph_bbox (cairo_font_t *font,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_box_t *bbox);
cairo_private cairo_status_t
_cairo_unscaled_font_show_glyphs (cairo_unscaled_font_t *font,
cairo_font_scale_t *size,
cairo_operator_t operator,
cairo_surface_t *source,
cairo_surface_t *surface,
int source_x,
int source_y,
cairo_glyph_t *glyphs,
int num_glyphs);
_cairo_font_show_glyphs (cairo_font_t *font,
cairo_operator_t operator,
cairo_surface_t *source,
cairo_surface_t *surface,
int source_x,
int source_y,
cairo_glyph_t *glyphs,
int num_glyphs);
cairo_private cairo_status_t
_cairo_unscaled_font_glyph_path (cairo_unscaled_font_t *font,
cairo_font_scale_t *size,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_path_t *path);
_cairo_font_glyph_path (cairo_font_t *font,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_path_t *path);
cairo_private cairo_status_t
_cairo_font_glyph_path (cairo_font_t *font,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_path_t *path);
cairo_private void
_cairo_font_get_glyph_cache_key (cairo_font_t *font,
cairo_glyph_cache_key_t *key);
/* cairo_hull.c */
cairo_private cairo_status_t