Pango font API problems, gnome-print
- From: Owen Taylor <otaylor redhat com>
- To: gtk-devel-list gnome org, gnome-print ximian com
- Subject: Pango font API problems, gnome-print
- Date: 11 Sep 2001 22:16:38 -0400
One API freeze issue that has been lurking around under the surface
is the Pango Font API. Currently we have two fairly major problems:
* GNOME-2.0 is currently shaping up to have two different
font APIs, one for Pango, and one for gnome-print. There is
no excuse for this, and if we don't fix it, its going
to be a major blot on presenting GNOME as a coherent API set.
Of course, it's fine for gnome-print to introduce additional
font API that is specific to printing / postscript output; but
this should be done as an extension to the Pango API, just
as there is additional API for X11 fonts, for Xft fonts, and
so forth.
* Some Pango structures that will need to be improved in the future
are not expandable in a binary or source compatible fashion.
Having spent some time reviewing the current gnome-print font APIs,
let me list the issues with the Pango font APIs which might cause
problems for replacing the gnome-print font APIs with the Pango
APIs.
* There is no explicit representation of a "face". pango_context_list_fonts()
does list all faces, but the representation is implicit - as a pattern
that happens load that face.
* There is no way of getting the original name of a face ... all
we can get is the style parameters, which may not be one-to-one with
the actual style names.
* There is no way to get the foundry for a particular famiily. The original
idea was that for conflicting foundaries, if the backend wanted not
to merge them, then it would report "Adobe Symbol" and "ITC Symbol"
as the family names. Unfortunately, this means that the name of one
font depends on other fonts on the system.
* The set of metrics in PangoFontMetrics is quite limited. (It
includes only ascent, descent, approximate_digit_width,
approximate_char_width.)
* There is no way of adding to the set of parameters that Pango uses
to convert PangoFontDescription to PangoFont. You can't add
a transform, or convert for a particular resolution ... the
API is currently:
PangoFont *pango_font_map_load_font (PangoFontMap *fontmap,
const PangoFontDescription *desc);
In addition, I would identify some other problems:
* PangoFontDescription can be allocated on the stack and direct
manipulation of members is allowed, so it can't be extended in
the future.
* PangoFontDescription forces all of style/variant/weight/stretch to
be specified. This means that, for instance, gtk_widget_modify_font()
can't only change, say, the size while leaving the style unmodified.
Also, relative sizes aren't possible in PangoFontDescription. This would
also be useful for gtk_widget_modify_font().
* PangoFontMetrics is allocated on the stack, so it can't be
extended in the future.
So, what can we do about these problems? I think the first thing
to do would be to make PangoFontMetrics and PangoFontDescription
heap allocated opaque structures.
So, we have:
PangoMetrics *pango_context_load_metrics (PangoContext *context,
const PangoFontDescription *desc,
PangoLanguage *language);
gint pango_metrics_get_ascent (PangoMetrics *metrics);
void pango_metrics_ref (PangoMetrics *metrics);
void pango_metrics_unref (PangoMetrics *metrics);
Or, make PangoMetrics a GObject. And for PangoFontDescription:
void pango_font_description_new (void);
PangoWeight pango_font_description_get_weight (PangoFontDescription *desc);
void pango_font_description_set_weight (PangoFontDescription *desc,
PangoWeight weight);
[...]
By adding:
void pango_font_description_merge (PangoFontDescription *desc,
PangoFontDescription *other);
void pango_font_description_unset_weight (PangoFontDescription *desc);
[...]
We can can handle the possibility of having partial font descriptions.
With the change to PangoMetrics, adding additional metrics to PangoMetrics
becomes simply a question of figuring out what we need to add.
Handling the question of faces and foundaries is perhaps a bit
tricker. There are a number of possible strategies:
A) Create PangoFontFamily and PangoFontFace objects, so you have something
along the lines of:
void pango_list_families (PangoContext *context,
PangoFontFamily **families,
gint **n_families);
/* Full name including foundary */
const char *pango_font_family_get_name (PangoFontFamily *family);
/* Short unique name */
const char *pango_font_family_get_display_name (PangoFontFamily *family);
/* Foundary name */
const char *pango_font_family_get_foundary (PangoFontFamily *family);
void pango_font_family_list_faces (PangoFontFamily *family,
PangoFontFace **faces,
gint **n_faces);
gboolean pango_font_family_is_fixed_pitch (PangoFontFamily *family);
[...]
const char * pango_font_face_get_name (PangoFontFace *face);
const char * pango_font_face_get_style_name (PangoFontFace *face);
PangoFontDescription *pango_font_face_describe (PangoFontFace *face);
This does pose potential memory management problems, which is why
I avoided it in the first place, though the FontFace and FontFamily
objects could potentially be about as lightweight as strings.
Then, you'd probably want to add:
void pango_font_description_set_face (PangoFontDescription *description,
PangoFontFace *face);
void pango_font_description_set_family (PangoFontDescription *description,
PangoFontFamily *family);
To allow exactly specifying the face or the family.
B) Leave the representation of a family as a string, and of a face
as a PangoFontDescription, but add some extra accessors along the
lines of:
char *pango_font_family_get_foundary (PangoContext *context,
const char *family);
char *pango_font_family_get_full_name (PangoContext *context,
const char *family);
char *pango_font_face_get_style_name (PangoContext *context,
PangoFontDescription *description);
C) [ Somewhat between the previous two ] Add style_name, full_family_name
string properties to PangoFontDescription, using
'full_family_name' as a unique identifier for the family, and
'full_family_name' + 'style_name' as unique identifier for
the face, then have:
gboolean pango_font_family_is_fixed_pitch (PangoContext *context,
const char *family_name);
PangoFontDescription *pango_font_face_describe (PangoContext *context,
const char *family_name,
const char *style name);
Finally, I intend to declare fairly large portions of the Pango API
to be evolving, and make no commitment to future source or binary
compatibility for those portions. In particular, I plan to do this
for:
- The PangoFontClass structure and deriving from PangoFont
- All of pango-fontmap.h
- All of pango-engine.h
I think if we control the internal interfaces inside Pango, we can
maintain compatibility for the interfaces used by Pango - if
necessary we can just make the external interfaces wrappers around
new extended interfaces.
I think the right way to mark things evolving is to surround them
in the header files with:
#ifndef PANGO_ENABLE_EVOLVING
#endif /* PANGO_ENABLE_EVOLVING */
Regards,
Owen
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]