gnome font RFC II



Hello!
This is 1st part of second RFC for improving gnome-font subsystem. Second
part will follow soon, describing proposed font use, both from userland
and from display object implementations.
Flames, please ;)

Objectives

1 - font installation
2 - font selection
3 - output platform independence
4 - multilanguage support
5 - rendering
6 - exporting

1,4,5,6 will be discussed later...

2 - font selection
Problems:
- users will have thousands of fonts, most of which are strictly designed
  for decorative headlines
- not all fonts fit nicely together
- usually people are interested only in font for given language

2.1. GnomeFontGroup - opaque named object

There will be several pre-defined groups, such as:
  Latin-Renaissance
  Latin-Baroque
  etc.
Also, users can create and reorder groups

Methods so far:

GnomeFontGroup * gnome_font_get_group (const gchar * name);

Finds group, given its name. Group is referenced to keep it consistent
with future implementations (adding/removing fonts, etc.)

gnome_font_group_ref (GnomeFontGroup * group);
gnome_font_group_unref (GnomeFontGroup * group);

const GSList * gnome_font_group_list (const gchar * language);

Returns list of group names, covering given language (at least one font in
group should cover it)
This is mainly intended for constructing font browsing widgets, so user
have to copy list, if he wants to preserve its contents between successive
calls. Constructing list/menu/whatever widget from it means, that it can
be discarded safely after that.

2.2. GnomeFontFamily - opaque named object
It is completely gnome font responsibility to construct families from
different font files/formats.

GnomeFontFamily * gnome_font_get_family (const gchar * name);

Returns referenced family, given canonical font name, such as "Trump
mediäval"

Browsing functions, mainly intended for constructing font-selection
widgets

const GSList * gnome_font_get_families (...)
const GSList * gnome_font_group_get_families (GnomeFontgroup * group, ...)

Return list, which has to be copied, if not consumed immediately (like
group list)
These functions take variable argument lists, to constrain searches:
"language" - like "en_US"
"group" - like "Latin Decorative"

Now comes the tricky part - extracting available typefaces from family
Objective: We cannot make any prejudgements, which kinds of typefaces are
available. usually these are "Bold", "Italic", "Bold Italic" etc. - but
these are probably meaningless for many non-european scripts.

const GSList * gnome_font_family_get_face_attributes (GnomeFontFamily *
	family)

Returns list of available attribute names, ordered by relative
importance. For most Western fonts, the list should be:
"subfamily" - Roman/Antique/Italic/Slanted/Oblique...
"weight" - Normal/Book/Semibold/Black...
"stretch" - Normal/Condensed/Extrawide...
"type" - Small Caps/All Caps...
etc.

const GSList * gnome_font_family_get_faces (GnomeFontFamily * family,
	const gchar * attribute, ...)

Returns list of attribute names for given font, such as {"Book", "Bold",
"Medium"...}
Takes variable, NULL terminated  list of arguments, for constraining
typeface, such as:

gnome_font_family_get_faces (f, "stretch", "subfamily", "roman",
	"weight", "bold", NULL);
May return:
{"Normal", "Semicondensed", "Condensed"}


const GSList * gnome_font_family_get_faces_rest (GnomeFontFamily * family,
	...)

Returns list of composite attribute names. For example, given argument
list:
"subfamily", "roman", NULL
It may return:
"Book"
"Book Small Caps"
"Book Semicondensed"
"Book Semicondensed Small Caps"
"Bold"
"Bold Small Caps"

This is usable mainly for constructing font selection widgets, so instead
of 5 different lists/menus/radiogroups, several attributes can be combined
into one selector.

Resulting string can be fed to font selection, using attribute name
"face". For example:
gnome_font_get ("family", "Helvetica", "subfamily" "Roman",
	"face", "Bold Semicondensed", NULL);

All the above is quite complex, but fortunately should be mostly hidden by
users via font selection (and manipulation - such as changing font
weight) widgets. What users really are interested in, is simple GnomeFont
object.

2.3. GnomeFont - opaque object

GnomeFont is language agnostic - i.e. it has no exact encoding, nor can
user expect anything about it's glyph numbering. Ensuring support for
given language is done in font selection, and before rendering any user
text has to be translated into font internal encoding. For convenience
this can be done transparently still - by canvasitems, gnome-print and
such subsystems.

GnomeFont * gnome_font_get (...)

Return referenced GnomeFont structure, given variable argument
list. Arguments should come in the order of relative importance:
"family"
"subfamily"
"weight"
...
Last arguments can be specified as "face", or omitted. In latter case
font-specific default will be used.

Various convenience functions:

GnomeFont * gnome_font_closest (...)
GnomeFont * gnome_font_closest_swss (const gchar * family,
	const gchar * language,
	enum slant, enum weight, enum stretch, enum type);

Various accessor functions:

GnomeFontFamily * gnome_font_get_family (const GnomeFont * font);
const gchar * gnome_font_get_canonical_name (const GnomeFont * font);
const gchar * gnome_font_get_family_name (const GnomeFont * font);
etc...

Now, current implementation uses GnomeFont for sized font, and
GnomeFontMap for unsized one. Unfortunately sized font can mean two mostly
different things:
a - font sized to given final output resolution - which means specific,
  usually integer metrics, adjusted glyph shape & so on
b - font sized to given userland units. This is relative size and does not
  have any connection to real glyph rendering
For (a) I would implement separate class GnomeFontTransformed (as scaling
has not to be uniform). This class will be used (and cached) mostly by
canvasitem and print context implementations, to do final, resolution
adjusted rendering.
Implementing (b) depends, how the connection with output resolution is
established in user API. As I currently tend to prefer infinite output
resolution, b is simply double number, kept in font structure. So it
should be set:

GnomeFont * gnome_font_scalefont (GnomeFont * font, double pointsize);


3. Output platform independence

GnomeFont should be output independent. Unfortunately if not before, then
now we are running into problems.
Almost everyone has got angry, if MSWord has reformatted pages after
changing printer. Unfortunately this is almost the right thing to do - as
exact font metrics depend on output resolution.
Usually the effects can be hidden in normal text, changing inter-word
spacing. But not always. Take 2 lines - one of 'm'-s and another of 'l'-s,
and print these in different point sizes. Either:

The lengths of lines will be different
or
The distances between chars are not uniform
or
you have to use antialiasing

All three effects are undesirable.
Still using desired output resolution is mostly impossible in networked
environment. Included bonobo component usually cannot know the output
resolution, it will be printed one day. etc.

So I propose, that gnome font subsystem should expect output resolution to
be infinite. I.e. while creating canvas items, or sending text to printer,
do not bother about final resolution.

Still, mentioned subsystems (canvasitems and print contexts) should take
resolution into account internally, adjusting whitespaces between
words. This can produce undesirable artefacts sometimes, but hopefully
will work well most times.

I am not sure, how high quality layouting system can be so produced. Still
I hope that:
- anyone doing real layout, is using >1200dpi printers, so final
  resolution can be considered infinite with minimal distorts
- for on-screen preview it is always possible to request full antialiased
  display (which gives correct overall impression, although is more
  difficult to read)

I'll contiune soon...

Lauris Kaplinski






[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]