... | ... | @@ -4,6 +4,8 @@ Table of Contents |
|
|
|
|
|
- [Overview](#overview)
|
|
|
- [General Process](#general-process)
|
|
|
* [Text in Complex Scripts](#text-in-complex-scripts)
|
|
|
* [Text in Complex Scripts](#text-in-complex-scripts-1)
|
|
|
- [Internals](#internals)
|
|
|
- [Example](#example)
|
|
|
|
... | ... | @@ -78,34 +80,121 @@ scripts, for example, Latin, Arabic, and Chinese. |
|
|
|
|
|
## General Process
|
|
|
|
|
|
To lay out, shape, and render a text in mixed scripts, you should call
|
|
|
`GetUCharsUntilParagraphBoundary` function first to convert
|
|
|
### Text in Standard Scripts
|
|
|
|
|
|
If you can determine the text to process is in standard scripts, you
|
|
|
can still to use MiniGUI GDI functions (`TextOut`, `DrawText` and so on)
|
|
|
to show the text. For more information, please refer to:
|
|
|
|
|
|
<http://www.minigui.com/doc-api-ref-minigui-sa-4.0.0/html/group__text__output__fns.html>
|
|
|
|
|
|
### Text in Complex Scripts
|
|
|
|
|
|
Before dealing with the bidirectional algorithm and the glyph shaping,
|
|
|
we first need to divide the text into paragraphs and get the relevant
|
|
|
properties of the characters, such as whether there is a breaking
|
|
|
opportunity before or after each character.
|
|
|
|
|
|
Moreover, all of the above processing needs to be done under the Unicode
|
|
|
character set.
|
|
|
|
|
|
Therefore, you call `GetUCharsUntilParagraphBoundary` function to convert
|
|
|
a multi-byte string to a Unicode string under the specified white space
|
|
|
rule, breaking rule, and transformation rule. For example, converting a
|
|
|
general C string in UTF-8 or GB18030 to a Uchar32 string by calling this
|
|
|
function. You can call `CreateLogFontForMChar2UChar` function to create
|
|
|
a dummy logfont object for this purpose in order to expense a minimal
|
|
|
memory.
|
|
|
|
|
|
If the text is in simple scripts, like Latin or Chinese, you can call
|
|
|
`GetGlyphsExtentPointEx` function to lay out the paragraph. This function
|
|
|
returns a glyph string which can fit in a line with the specified
|
|
|
maximal extent and rendering flags. After this, you call
|
|
|
rule. For example, you can convert a general C string in `UTF-8` or
|
|
|
`GB18030` charset to a `Uchar32` string by calling this function.
|
|
|
|
|
|
```
|
|
|
LOGFONT* lf;
|
|
|
int left_len_text;
|
|
|
|
|
|
char* text = "中华人民共和国万岁!\n中国共产党万岁!";
|
|
|
|
|
|
if (!(lf = CreateLogFontForMChar2UChar("utf-8"))) {
|
|
|
_ERR_PRINTF("%s: failed to create logfont for utf-8 charset\n",
|
|
|
__FUNCTION__);
|
|
|
exit(1);
|
|
|
}
|
|
|
|
|
|
left_len_text = strlen(text);
|
|
|
while (left_len_text > 0) {
|
|
|
Uchar32* ucs = NULL;
|
|
|
int consumed, n;
|
|
|
|
|
|
consumed = GetUCharsUntilParagraphBoundary(lf, text, left_len_text,
|
|
|
WSR_NOWRAP, &ucs, &n);
|
|
|
if (consumed > 0) {
|
|
|
|
|
|
// got a paragraph and go on.
|
|
|
...
|
|
|
|
|
|
// when we are done.
|
|
|
free (ucs);
|
|
|
ucs = NULL;
|
|
|
}
|
|
|
|
|
|
text += consumed;
|
|
|
left_len_text -= consumed;
|
|
|
}
|
|
|
|
|
|
DestroyLogFont(lf);
|
|
|
```
|
|
|
|
|
|
In the above code, we call `CreateLogFontForMChar2UChar` function to create
|
|
|
a dummy logfont object only for converting C-string in UTF-8 to Uchar32 string.
|
|
|
The logfont object created by `CreateLogFontForMChar2UChar` will expense
|
|
|
a minimal memory. But note that if you use the logfont object returned by this
|
|
|
function to show a text, you will see nothing.
|
|
|
|
|
|
Obviously, the original text has two paragraphs. So we use a `while` loop
|
|
|
to deal with a paragraph in one loop.
|
|
|
|
|
|
Next, you should call `UStrGetBreaks` to get the breaking opportunities of
|
|
|
each characters in the paragraph. This information are very important to the
|
|
|
layout algorithm.
|
|
|
|
|
|
If the text is in a standard script, like Latin or Chinese, you can call
|
|
|
`GetGlyphsExtentFromUChars` function to lay out the paragraph to a line.
|
|
|
This function returns a glyph string which can fit in a line with the
|
|
|
specified maximal extent and rendering flags. After this, you call
|
|
|
`DrawGlyphStringEx` function to draw the glyph string to the
|
|
|
specific position of a DC.
|
|
|
|
|
|
If there are characters left to lay out, you can call this function again,
|
|
|
until there is no any character left.
|
|
|
|
|
|
For a complete sample, please refer to:
|
|
|
|
|
|
<https://github.com/VincentWei/mg-tests/blob/master/4.0/drawglyphstringex.c>
|
|
|
|
|
|
If the text is in complex and/or mixed scripts, like Arabic, Thai,
|
|
|
and Indic, you should create a TEXTRUNS object first by calling
|
|
|
`CreateTextRuns` function, then initialize the shaping engine for
|
|
|
laying out the text.
|
|
|
|
|
|
For the usage sample of TEXTRUNS object, please refer to:
|
|
|
|
|
|
<https://github.com/VincentWei/mg-tests/blob/master/4.0/createtextruns.c>
|
|
|
|
|
|
MiniGUI provides two types of shaping engine. One is the basic
|
|
|
shaping engine. The corresponding function is `InitBasicShapingEngine`.
|
|
|
The other is called complex shaping engine, which is based on HarfBuzz.
|
|
|
The corresponding function is `InitComplexShapingEngine`. The latter
|
|
|
one can give you a better shaping result.
|
|
|
|
|
|
After this, you should call `CreateLayout` to create a layout object
|
|
|
For the sample of the basic shaping engine, please refer to:
|
|
|
|
|
|
<https://github.com/VincentWei/mg-tests/blob/master/4.0/basicshapingengine.c>
|
|
|
|
|
|
Note that, to use the complex shaping engine, you need to compile MiniGUI
|
|
|
with the option `--enable-complexscripts`, and HarfBuzz should be installed
|
|
|
in your system. Also note that, you should use TrueType fonts with the
|
|
|
complex shaping engine.
|
|
|
|
|
|
For the sample of the complex shaping engine, please refer to:
|
|
|
|
|
|
<https://github.com/VincentWei/mg-tests/blob/master/4.0/complexshapingengine.c>
|
|
|
|
|
|
After this, you should call `CreateLayout` to create a LAYOUT object
|
|
|
for laying out the text, then call `LayoutNextLine` to lay out the lines
|
|
|
one by one.
|
|
|
|
... | ... | @@ -118,6 +207,15 @@ Before rendering the glyphs laid out, you can also call `GetLayoutLineRect` |
|
|
to get the line rectangle, or call `CalcLayoutBoundingRect` to get
|
|
|
the bounding rectangle of one paragraph.
|
|
|
|
|
|
For the sample for layout object, please refer to:
|
|
|
|
|
|
<https://github.com/VincentWei/mg-tests/blob/master/4.0/createlayout.c>
|
|
|
|
|
|
For the detailed API description related to complex/mixed scripts,
|
|
|
please refer to:
|
|
|
|
|
|
<http://www.minigui.com/doc-api-ref-minigui-sa-4.0.0/html/group__complex__scripts.html>
|
|
|
|
|
|
## Internals
|
|
|
|
|
|
These new APIs provide a very flexible implementation for your apps
|
... | ... | @@ -145,5 +243,6 @@ in the following respects: |
|
|
basic shaping engine and other is the complex shaping engine based
|
|
|
on HarfBuzz. The former can be used for some simple applications.
|
|
|
|
|
|
##
|
|
|
## Restrictions
|
|
|
|
|
|
|