File: calling.txt

package info (click to toggle)
graphite2 1.3.13-7
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 23,300 kB
  • sloc: cpp: 14,690; cs: 1,998; ansic: 1,673; python: 1,481; perl: 184; xml: 123; sh: 96; makefile: 58
file content (289 lines) | stat: -rw-r--r-- 14,463 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
== Calling Graphite2 ==

=== Introduction ===
The basic model for running graphite is to pass text, font and face information
to create a segment. A segment consists of a linked list of slots which each
correspond to an output glyph. In addition a segment holds charinfo for each
character in the input text.

[source, c]
----
include::../tests/examples/simple.c[]
----

<1> The first parameter to the program is the full path to the font file to be
    used for rendering. This function loads the font and reads all the graphite
    tables, etc. If there is a fault in the font, it will fail to load and the
    function will return NULL.

<2> A font is merely a face at a given size in pixels per em. It is possible to
    support hinted advances, but this is done via a callback function.

<3> For simplification of memory allocation, graphite works on characters
    (Unicode codepoints) rather than bytes or gr_uint16s, etc. We need to
    calculate the number of characters in the input string (the second parameter
    to the program). Very often applications already know this. If there is an
    error in the utf-8, the pError variable will point to it and we just exit.
    But it is possible to render up to that point.
    +
    If your string is null terminated, then you don't necessarily have to
    calculate a precise number of characters. You can use a value that is
    greater than the number in the string and rely on graphite to stop at the
    terminating null. It is necessary to pass some value for the number of
    characters so that graphite can initialise its internal memory structures
    appropriately and not waste time updating them. Thus for UTF-16 and UTF-32
    strings, one could simply pass the number of code units in the string.
    For UTF-8 it may be preferable to call gr_count_unicode_characters.

<4> Here we create a segment. A segment is the results of processing a string
    of text with graphite. It contains all the information necessary for final
    rendering including all the glyphs, their positions, relationships between
    glyphs and underlying characters, etc.

<5> A segment primarily consists of a linked list of slots. Each slot
    corresponds to a glyph in the output. The information about a glyph and its
    relationships is queried from the slot.

Source for this program may be found in tests/examples/simple.c

Assuming that graphite2 has been built and installed, this example can be built
and run on linux using:

----
gcc -o simple -lgraphite2 simple.c
LD_LIBRARY_PATH=/usr/local/lib ./simple ../fonts/Padauk.ttf 'Hello World!'
----

Running simple gives the results:

----
43(0.000000,0.000000) 72(9.859375,0.000000) 79(17.609375,0.000000) 79(20.796875,0.000000) 82(23.984375,0.000000) 3(32.203125,0.000000) 58(38.109375,0.000000) 82(51.625000,0.000000) 85(59.843750,0.000000) 79(64.875000,0.000000) 71(68.062500,0.000000) 4(76.281250,0.000000)
----

Not very pretty, but reassuring! Graphite isn't a graphical rendering engine, it
merely calculates which glyphs should render where and leaves the actual process
of displaying those glyphs to other libraries.

This example is pretty simple and uses a convenient way to load fonts into
Graphite for testing purposes. But when integrating into real applications, that
is rarely the most appropriate way. Instead the necessary font information comes
to Graphite via some other data structure with its own accessor functions.
In the following example we show the same application but using a FreeType font
rather than a font file.

[source, c]
----
include::../tests/examples/freetype.c[]
----

<1> We cast the pointer to remove its const restriction. Since when the memory
    was allocated, it was passed to Graphite as a read only memory block, via
    const, it gets passed back to us as a read only memory block. But we are the
    owner of the block and so can mess with it (like freeing it). So we are free
    to break the const restriction here.

<2> The structure of an operations structure is to first hold the size of the
    structure and then the pointers to the functions. Storing the size allows an
    older application to call a newer version of the Graphite engine which might
    support more function pointers. In such a case, all those newer pointers are
    assumed to be NULL.

<3> Pass the function pointers structure for creating the font face. The first
    function is called to load a table from the font and pass it back to
    Graphite. The second is called by Graphite to say that it no longer needs
    the table loaded in memory and will make no further reference to it.

<4> Pass a function pointers structure for fonts. The two functions (either can
    be NULL) return the horizontal or vertical advance for a glyph in pixels.
    Notice that usually fractional advances are preferable to grid fit advances,
    unless working entirely in a low resolution graphical framework.
    +
    The code following is virtually identical to the fileface code, apart from
    some housekeeping at the end.

<5> Note that freetype works with fixed point arithmetic of 26.6, thus 1.0 is
    stored as 64. We therefore multiply the pointsize by 64 (or shift left by 6)
    and divide the resulting positions down by 64 to true floating point values.

Building and running this example gives similar, but not identical, results to
the simple case. Notice that since the advances are grid fit, all the positions
are integral, unlike the fractional positioning in the simple application:

----
43(0.000000,0.000000) 72(9.000000,0.000000) 79(17.000000,0.000000) 79(20.000000,0.000000) 82(23.000000,0.000000) 3(31.000000,0.000000) 58(37.000000,0.000000) 82(51.000000,0.000000) 85(59.000000,0.000000) 79(64.000000,0.000000) 71(67.000000,0.000000) 4(75.000000,0.000000)
----

=== Slots ===

The primary contents of a segment is slots. These slots are organised into a
doubly linked list and each corresponds to a glyph to be rendered. The linked
list is terminated at each end by a NULL. There are also functions to get the
first and last slot in a segment.

In addition to the main slot list, slots may be attached to each other. This
means that two glyphs have been attached to each other in the GDL. Again,
attached slots are held in a separate singly linked list associated with the
slot to which they attach. Thus slots will be in the main linked list and may
be in an attachment linked list. Each slot in an attachment linked list has the
same attachment parent accessed via `gr_slot_attached_to()`. To get the start of
the linked list of all the slots directly attached to a parent, one calls
`gr_slot_first_attachment()` and then `gr_slot_next_attachment()` to walk
forwards through that linked list. Given that a diacritic may attach to another
diacritic, an attached slot may in its turn have a linked list of attached
slots. In all cases, linked lists terminate with a NULL.

image::glyph_string.png[]

The core information held by a slot is the glyph id of the glyph the slot
corresponds to (`gr_slot_gid()`); the position relative to the start of the
segment that the glyph is to be rendered at (`gr_slot_origin_X()` and
`gr_slot_origin_Y()`); the advance for the glyph which corresponds to the glyph
metric advance as adjusted by kerning. In addition a slot indicates whether the
font designer wants to allow a cursor to be placed before this glyph or not.
This information is accessible via `gr_slot_can_insert_before()`.

=== CharInfo ===

For each unicode character in the input, there is a CharInfo structure that can
be queried for such information as the code unit position in the input string,
the before slot index (if we are before this character, which is the earliest
slot we are before) and the corresponding after slot index.

=== Face ===

The `gr_face` type is the memory correspondance of a font. It holds the data
structures corresponding to those in a font file as required to process text
using that font. In creating a `gr_face` it is necessary to pass a function by
which graphite can get hold of font tables. The tables that graphite queries
for must be available for the lifetime of the `gr_face`, except when a `gr_face`
is created with the faceOptions of `gr_face_preloadAll`. This then loads
everything from the font at `gr_face` construction time, leaving nothing further
to be read from the font when the `gr_face` is used. This reduces the required
lifetime of the in memory font tables to the `gr_make_face` call. In situations
where the tables are only stored for the purposes of creating a `gr_face`, it
can save memory to preload everything and delete the tables.

=== Caching ===

Graphite2 had the capability to make use of a subsegmental cache. Each sub run
was then looked up in the cache rather than calculating the values from scratch.
While the cache could be effective when similar runs of text were being
processed, it often didn't fit with target applications exisiting framework and
was a source of several bugs, it was marked as deprecated in 1.3.7.  In order to
avoid an API change `gr_make_face_with_seg_cache`,
`gr_make_face_with_seg_cache_and_ops` and `gr_make_file_face_with_seg_cache` now
simply alias their non-caching counterparts and ignore the cacheSize paramter.

=== Clustering ===

It is common for applications to work with simplified clusters, these are
sequences of glyphs associated with a sequence of characters, such that these
simplified clusters are as small as possible and are never reordered or split in
relation to each other. In addition, a cursor may occur between simplified
clusters.

The following code gives an example algorithm for calculating such clusters:

[source, c]
----
include::../tests/examples/cluster.c[]
----

<1> Create a segment as per the example in the introduction.

<2> If this slot starts before the start of this cluster, then merge this
    cluster with the previous one and try again until this slot is within the
    current cluster.

<3> If this slot starts after the end of the current cluster, then create a new
    cluster for it. You can't start a new cluster with a glyph that cannot take
    a cursor position before it. Also don't make a new cluster the first time
    around (i.e. at the start of the string).

<4> If this slot ends after the end of this cluster then extend this cluster to
    include it.

<5> Output a line break between each cluster.

=== Line Breaking and Justification ===

Whilst most applications will convert glyphs and positions out of the gr_slot
structure into some internal structure, if graphite is to be used for
justification, then it is necessary to line break the text and justify it within
graphite's data structures. Graphite provides two functions to help with this.
The first is gr_slot_linebreak_before() which will chop the slot linked list
before a given slot. The application needs to keep track of the start of each of
the subsequent linked lists itself, since graphite does not do that. After line
breaking, the application may call gr_seg_justify() on each line linked list.
The following example shows how this might be done in an application.

Notice that this example does not take into considering whitespace hanging
outside the right margin.

[source, c]
----
include::../tests/examples/linebreak.c[]
----

<1> Create a segment as per the example in the introduction

<2> Create an area to store line starts. There won't be more line starts than
    characters in the text. The first line starts at the start of the segment.

<3> A simplistic approach would scan forwards using
    `gr_slot_next_sibling_attachment`, thus walking the bases. The bases are
    guaranteed to be ordered graphically, and so we can chop when we pass the
    line end. But in some cases, particularly Arabic, fonts are implemented with
    one base per word and all the other base characters are attached in a chain
    from that. So we need to walk the segment by slot, even considering attached
    slots. This is not a problem since attached slots are not going to have a
    wildly different position to their base and if one leaks over the end of the
    line, the breakweight considerations will get us back to a good base.

<4> Scan through the slots, if we are past the end of the line then find
    somewhere to chop.

<5> We use 15 (word break) as an appropriate break value.

<6> Scan backwards for a valid linebreak location.

<7> Break the line here.

<8> Update the line width for the new line based on the start of the new line.

<9> Justify each line to be width wide. And tell it to skip final whitespace
    (as if that whitespace were outside the width).

<10> Each line is a complete linked list that we can iterate over. We can no
     longer iterate over the whole segment. We have to do it line by line now.

=== Bidi ===

Bidirectional processing is complex; not so much because of any algorithms
involved, but because of the tendency for applications to address bidi text
processing differently. Some try to do everything themselves, inverting the text
order, etc. While others do nothing, expecting the shaper to resolve all the
orders. In addition, there is the question of mirroring characters and where
that is done. Graphite2 adds the complexity that it tries to enable extensions
to the bidi algorithm by giving PUA characters directionality. To facilitate all
these different ways of working, Graphite2 uses the `rtl` attribute to pass
various bits to control bidi processing within the Graphite engine.

[width="100%",cols="^2,^3,<15",options="header"]
|=======================================================
| gr_nobidi | gr_nomirror | Description

| 0         | 0           | Runs the bidi algorithm and does all mirroring

| 0         | 1           | Runs the bidi algorithm and mirrors those chars that
                            don't have char replacements. It also un/remirrors
                            anything that ends up in the opposite direction to
                            the stated text direction on input.

| 1         | 0           | Doesn't run the bidi algorithm but does do mirroring
                            of all characters if direction is rtl.

| 1         | 1           | Doesn't run the bidi algorithm and only mirrors
                            those glyphs for which there is no corresponding
                            mirroring character.
|=======================================================