/usr/share/gtk-doc/html/harfbuzz
NameSizeModeActions
a-clustering-example-for-levels-0-and-1.html53070644editdlrm
aat-shaping.html23590644editdlrm
adding-text-to-the-buffer.html58000644editdlrm
annotation-glossary.html56440644editdlrm
api-index-0-9-2.html444470644editdlrm
api-index-0-9-5.html33390644editdlrm
api-index-0-9-7.html123060644editdlrm
api-index-0-9-8.html20880644editdlrm
api-index-0-9-10.html32000644editdlrm
api-index-0-9-11.html20700644editdlrm
api-index-0-9-20.html23030644editdlrm
api-index-0-9-22.html21150644editdlrm
api-index-0-9-28.html20620644editdlrm
api-index-0-9-30.html25250644editdlrm
api-index-0-9-31.html29320644editdlrm
api-index-0-9-38.html38220644editdlrm
api-index-0-9-39.html20580644editdlrm
api-index-0-9-41.html20670644editdlrm
api-index-0-9-42.html25870644editdlrm
api-index-1-0-5.html27370644editdlrm
api-index-1-1-2.html23740644editdlrm
api-index-1-1-3.html29570644editdlrm
api-index-1-2-3.html28720644editdlrm
api-index-1-3-3.html55360644editdlrm
api-index-1-4-0.html23470644editdlrm
api-index-1-4-2.html53690644editdlrm
api-index-1-4-3.html20290644editdlrm
api-index-1-5-0.html29000644editdlrm
api-index-1-6-0.html22660644editdlrm
api-index-1-7-5.html17010644editdlrm
api-index-1-7-7.html55500644editdlrm
api-index-1-8-0.html26620644editdlrm
api-index-1-8-1.html24850644editdlrm
api-index-1-8-5.html20880644editdlrm
api-index-1-8-6.html31870644editdlrm
api-index-1-9-0.html34600644editdlrm
api-index-2-0-0.html59260644editdlrm
api-index-2-1-0.html80690644editdlrm
api-index-2-2-0.html53260644editdlrm
api-index-2-3-0.html26500644editdlrm
api-index-2-4-0.html20870644editdlrm
api-index-2-5-0.html21080644editdlrm
api-index-2-6-0.html52400644editdlrm
api-index-2-7-3.html28240644editdlrm
api-index-full.html1403400644editdlrm
buffers-language-script-and-direction.html49510644editdlrm
building.html153460644editdlrm
ch01s03.html44950644editdlrm
ch03s02.html60780644editdlrm
ch03s03.html45800644editdlrm
ch12.html35570644editdlrm
ch13.html30780644editdlrm
ch14.html18760644editdlrm
ch15.html30440644editdlrm
clusters.html64990644editdlrm
complex-scripts.html30010644editdlrm
customizing-unicode-functions.html64000644editdlrm
deprecated-api-index.html62230644editdlrm
fonts-and-faces-custom-functions.html73980644editdlrm
fonts-and-faces-native-opentype.html51960644editdlrm
fonts-and-faces-variable.html53040644editdlrm
fonts-and-faces.html76710644editdlrm
getting-started.html50430644editdlrm
graphite-shaping.html23080644editdlrm
harfbuzz-hb-aat-layout.html1393450644editdlrm
harfbuzz-hb-blob.html359020644editdlrm
harfbuzz-hb-buffer.html1954910644editdlrm
harfbuzz-hb-common.html653230644editdlrm
harfbuzz-hb-coretext.html113710644editdlrm
harfbuzz-hb-deprecated.html253280644editdlrm
harfbuzz-hb-directwrite.html61550644editdlrm
harfbuzz-hb-face.html521000644editdlrm
harfbuzz-hb-font.html2626960644editdlrm
harfbuzz-hb-ft.html287190644editdlrm
harfbuzz-hb-gdi.html43100644editdlrm
harfbuzz-hb-glib.html100860644editdlrm
harfbuzz-hb-gobject.html29530644editdlrm
harfbuzz-hb-graphite2.html58280644editdlrm
harfbuzz-hb-icu.html79690644editdlrm
harfbuzz-hb-map.html291880644editdlrm
harfbuzz-hb-ot-color.html399490644editdlrm
harfbuzz-hb-ot-font.html46300644editdlrm
harfbuzz-hb-ot-layout.html1450880644editdlrm
harfbuzz-hb-ot-math.html528860644editdlrm
harfbuzz-hb-ot-meta.html102860644editdlrm
harfbuzz-hb-ot-metrics.html179270644editdlrm
harfbuzz-hb-ot-name.html196030644editdlrm
harfbuzz-hb-ot-shape.html62570644editdlrm
harfbuzz-hb-ot-var.html367080644editdlrm
harfbuzz-hb-set.html594230644editdlrm
harfbuzz-hb-shape-plan.html384120644editdlrm
harfbuzz-hb-shape.html117020644editdlrm
harfbuzz-hb-unicode.html1067010644editdlrm
harfbuzz-hb-uniscribe.html60990644editdlrm
harfbuzz-hb-version.html104150644editdlrm
harfbuzz.devhelp21794570644editdlrm
HarfBuzz.png62540644editdlrm
HarfBuzz.svg67450644editdlrm
home.png1690644editdlrm
index.html195660644editdlrm
install-harfbuzz.html37870644editdlrm
integration-coretext.html64830644editdlrm
integration-freetype.html92930644editdlrm
integration-icu.html41860644editdlrm
integration-python.html31810644editdlrm
integration-uniscribe.html67250644editdlrm
integration.html99360644editdlrm
left-insensitive.png3340644editdlrm
left.png1850644editdlrm
level-2.html70090644editdlrm
object-model-blobs.html29020644editdlrm
object-model-lifecycle.html49780644editdlrm
object-model-object-types.html41110644editdlrm
object-model-user-data.html32550644editdlrm
object-model.html39780644editdlrm
opentype-shaping-models.html44630644editdlrm
pt01.html94170644editdlrm
pt02.html126740644editdlrm
reordering-in-levels-0-and-1.html31020644editdlrm
right-insensitive.png2330644editdlrm
right.png1840644editdlrm
setting-buffer-properties.html78300644editdlrm
shaping-and-shape-plans.html81960644editdlrm
shaping-concepts.html38690644editdlrm
shaping-opentype-features.html66630644editdlrm
shaping-operations.html45370644editdlrm
shaping-plans-and-caching.html46410644editdlrm
shaping-shaper-selection.html34060644editdlrm
style.css116060644editdlrm
text-runs.html25330644editdlrm
the-distinction-between-levels-0-and-1.html48640644editdlrm
unicode-character-categories.html42040644editdlrm
up-insensitive.png2880644editdlrm
up.png1860644editdlrm
utilities-common-types-apis.html43650644editdlrm
utilities-ucdn.html26320644editdlrm
utilities.html92740644editdlrm
what-harfbuzz-doesnt-do.html55350644editdlrm
what-is-harfbuzz.html55030644editdlrm
why-do-i-need-a-shaping-engine.html81240644editdlrm
why-is-it-called-harfbuzz.html21710644editdlrm
working-with-harfbuzz-clusters.html100830644editdlrm
Edit: /usr/share/gtk-doc/html/harfbuzz/working-with-harfbuzz-clusters.html (10083B)
Working with HarfBuzz clusters: HarfBuzz Manual

Working with HarfBuzz clusters

When you add text to a HarfBuzz buffer, each code point must be assigned a cluster value.

This cluster value is an arbitrary number; HarfBuzz uses it only to distinguish between clusters. Many client programs will use the index of each code point in the input text stream as the cluster value. This is for the sake of convenience; the actual value does not matter.

Some of the shaping operations performed by HarfBuzz — such as reordering, composition, decomposition, and substitution — may alter the cluster values of some characters. The final cluster values in the buffer at the end of the shaping process will indicate to client programs which subsequences of glyphs represent a cluster and, therefore, must not be separated.

In addition, client programs can query the final cluster values to discern other potentially important information about the glyphs in the output buffer (such as whether or not a ligature was formed).

For example, if the initial sequence of cluster values was:

      0,1,2,3,4
    

and the final sequence of cluster values is:

      0,0,3,3
    

then there are two clusters in the output buffer: the first cluster includes the first two glyphs, and the second cluster includes the third and fourth glyphs. It is also evident that a ligature or conjunct has been formed, because there are fewer glyphs in the output buffer (four) than there were code points in the input buffer (five).

Although client programs using HarfBuzz are free to assign initial cluster values in any manner they choose to, HarfBuzz does offer some useful guarantees if the cluster values are assigned in a monotonic (either non-decreasing or non-increasing) order.

For buffers in the left-to-right (LTR) or top-to-bottom (TTB) text flow direction, HarfBuzz will preserve the monotonic property: client programs are guaranteed that monotonically increasing initial cluster values will be returned as monotonically increasing final cluster values.

For buffers in the right-to-left (RTL) or bottom-to-top (BTT) text flow direction, the directionality of the buffer itself is reversed for final output as a matter of design. Therefore, HarfBuzz inverts the monotonic property: client programs are guaranteed that monotonically increasing initial cluster values will be returned as monotonically decreasing final cluster values.

Client programs can adjust how HarfBuzz handles clusters during shaping by setting the cluster_level of the buffer. HarfBuzz offers three levels of clustering support for this property:

  • Level 0 is the default and reproduces the behavior of the old HarfBuzz library.

    The distinguishing feature of level 0 behavior is that, at the beginning of processing the buffer, all code points that are categorized as marks, modifier symbols, or Emoji extended pictographic modifiers, as well as the Zero Width Joiner and Zero Width Non-Joiner code points, are assigned the cluster value of the closest preceding code point from different category.

    In essence, whenever a base character is followed by a mark character or a sequence of mark characters, those marks are reassigned to the same initial cluster value as the base character. This reassignment is referred to as "merging" the affected clusters. This behavior is based on the Grapheme Cluster Boundary specification in Unicode Technical Report 29.

    Client programs can specify level 0 behavior for a buffer by setting its cluster_level to HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES.

  • Level 1 tweaks the old behavior slightly to produce better results. Therefore, level 1 clustering is recommended for code that is not required to implement backward compatibility with the old HarfBuzz.

    Level 1 differs from level 0 by not merging the clusters of marks and other modifier code points with the preceding "base" code point's cluster. By preserving the separate cluster values of these marks and modifier code points, script shapers can perform additional operations that might lead to improved results (for example, reordering a sequence of marks).

    Client programs can specify level 1 behavior for a buffer by setting its cluster_level to HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS.

  • Level 2 differs significantly in how it treats cluster values. In level 2, HarfBuzz never merges clusters.

    This difference can be seen most clearly when HarfBuzz processes ligature substitutions and glyph decompositions. In level 0 and level 1, ligatures and glyph decomposition both involve merging clusters; in level 2, neither of these operations triggers a merge.

    Client programs can specify level 2 behavior for a buffer by setting its cluster_level to HB_BUFFER_CLUSTER_LEVEL_CHARACTERS.

As mentioned earlier, client programs using HarfBuzz often assign initial cluster values in a buffer by reusing the indices of the code points in the input text. This gives a sequence of cluster values that is monotonically increasing (for example, 0,1,2,3,4).

It is not required that the cluster values in a buffer be monotonically increasing. However, if the initial cluster values in a buffer are monotonic and the buffer is configured to use cluster level 0 or 1, then HarfBuzz guarantees that the final cluster values in the shaped buffer will also be monotonic. No such guarantee is made for cluster level 2.

In levels 0 and 1, HarfBuzz implements the following conceptual model for cluster values:

  • If the sequence of input cluster values is monotonic, the sequence of cluster values will remain monotonic.

  • Each cluster value represents a single cluster.

  • Each cluster contains one or more glyphs and one or more characters.

In practice, this model offers several benefits. Assuming that the initial cluster values were monotonically increasing and distinct before shaping began, then, in the final output:

  • All adjacent glyphs having the same final cluster value belong to the same cluster.

  • Each character belongs to the cluster that has the highest cluster value not larger than its initial cluster value.