mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 00:38:06 +02:00
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:
parent
9068937026
commit
97424a3c2a
42 changed files with 3143 additions and 2004 deletions
74
ChangeLog
74
ChangeLog
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
72
doc/reference/xml/cairo_font_glyph_extents.xml
Normal file
72
doc/reference/xml/cairo_font_glyph_extents.xml
Normal 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>
|
||||
25
doc/reference/xml/cairo_font_t.xml
Normal file
25
doc/reference/xml/cairo_font_t.xml
Normal 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>
|
||||
59
doc/reference/xml/cairo_ft_font_create.xml
Normal file
59
doc/reference/xml/cairo_ft_font_create.xml
Normal 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>
|
||||
69
doc/reference/xml/cairo_ft_font_create_for_ft_face.xml
Normal file
69
doc/reference/xml/cairo_ft_font_create_for_ft_face.xml
Normal 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>
|
||||
49
doc/reference/xml/cairo_ft_font_get_pattern.xml
Normal file
49
doc/reference/xml/cairo_ft_font_get_pattern.xml
Normal 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>
|
||||
61
doc/reference/xml/cairo_ft_font_lock_face.xml
Normal file
61
doc/reference/xml/cairo_ft_font_lock_face.xml
Normal 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>
|
||||
44
doc/reference/xml/cairo_ft_font_unlock_face.xml
Normal file
44
doc/reference/xml/cairo_ft_font_unlock_face.xml
Normal 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>
|
||||
62
doc/reference/xml/cairo_glyph_t.xml
Normal file
62
doc/reference/xml/cairo_glyph_t.xml
Normal 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>
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
410
src/cairo-font.c
410
src/cairo-font.c
|
|
@ -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])
|
||||
|
|
|
|||
1071
src/cairo-ft-font.c
1071
src/cairo-ft-font.c
File diff suppressed because it is too large
Load diff
63
src/cairo-ft-private.h
Normal file
63
src/cairo-ft-private.h
Normal 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 */
|
||||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
104
src/cairo-hash.c
104
src/cairo-hash.c
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
29
src/cairo.h
29
src/cairo.h
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
410
src/cairo_font.c
410
src/cairo_font.c
|
|
@ -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])
|
||||
|
|
|
|||
1071
src/cairo_ft_font.c
1071
src/cairo_ft_font.c
File diff suppressed because it is too large
Load diff
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
157
src/cairoint.h
157
src/cairoint.h
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue