Text in a CorelDRAW file is two things: the characters with their settings, in a
txsm record, and the styles those settings build on, in a style sheet.
Everything here is how libcdr reads them; where it steps over bytes they are marked
unknown. “Coordinate”, “unsigned” and “angle” change size with the version, as on the
objects page.
How an object finds its text
- The object’s loda has type 4 (artistic text)
or 6 (paragraph text; 3 and 5 before version 4). Its
0xC8argument names the style, its0x1Eargument holds the frame (below). - A
spndchunk in the object holds an unsigned number: the text id. - The text id is the frame id in a
txsmrecord. libcdr keeps the last frame id of a record as the record’s text id. - Each paragraph of the record names a style from the style sheet and carries style overrides for runs of its characters.
The geometry argument of a text object is two coordinates for artistic text, which libcdr does not use (the text sits at the origin of the object’s transformation, the first baseline on the alignment point). For paragraph text it is a field as long as a coordinate (2 bytes before version 6, 4 later), then the frame’s width and height; the frame’s top left corner is the origin and it runs down. In CorelDRAW 4 an artistic text’s characters are in the object itself (below).
txsm: the text record
Version 5 and later. After the record’s header the layout depends on the version. All counts are as wide as an unsigned (16 bits up to version 5, 32 bits later).
Versions 7 to 15 (and 6, with fewer fields)
| Field | Size | Description |
|---|---|---|
| Frame flag | 4 | Not zero: paragraph text in a frame. Zero: artistic text. |
| Unknown | 32 (33 from X5) | |
| Text on a path | 4 | Version 7 only here; later versions have it in each frame. 1: the text is fitted to a path; 32 unknown bytes follow. |
| Number of frames | 4 | |
| Frames | varies | Each: frame id (4); 48 bytes (a transformation of six doubles); from version 8 the text-on-a-path flag (4), then, if it is 1, 32 unknown bytes (40 from version 13, 48 from X5) or, from X5 and if it is not, 8 unknown bytes; for artistic text unknown bytes after that (36 in version 7, 32 in 8, 34 in 9 to 13, 36 in 14, 40 from X5), for a frame 4 unknown bytes from X5. |
| Number of paragraphs | 4 | |
| Paragraphs | varies | Each as below. |
A paragraph
| Field | Size | Description |
|---|---|---|
| Style id | 4 | The paragraph’s style in the style sheet. |
| Unknown | 1 (2 for version 13 and later with a frame) | |
| Number of overrides | 4 | n. Override i has the number 2i. |
| Overrides | varies | As below. |
| Number of characters | 4 | c, at most as many as there are bytes for. |
| Character descriptions | c × 4 (c × 8 from version 12) | Bits 17 to 23 of the first 4 bytes: the number of the override the character takes. Bit 0: the character has two bytes (UTF-16). |
| Number of text bytes | 4 | Version 12 and later only; before that it is c. |
| Text | that many | The characters, one byte each in the code page of their override or style, or two bytes (UTF-16) where bit 0 is set. A line break is 0x0D. |
| Zero | 1 | |
| Places | c × 24 | Only for text on a path: each character’s shift x and y (1/100 em, y up), rotation (millionths of a degree, counter-clockwise) and 12 more bytes. |
A style override
| Field | Size | Present when |
|---|---|---|
| Characters using it | 2 | always |
| Flags 1 | 1 | always; below |
| Flags 2 | 1 | version 8 and later |
| Font id and character set | 2 + 2 | flags 1 bit 0x01. A character set of 0 is the font’s own. |
| Font style | 4 | bit 0x02. The low 16 bits: 0x40 normal, 0x80 italic, 0x1000 bold, 0x2000 bold italic. |
| Font size | coordinate | bit 0x04 |
| Rotation | 4 | bit 0x08, millionths of a degree |
| Shift x | 4 | bit 0x10, 1/100 em |
| Shift y | 4 | bit 0x20, 1/100 em, up positive |
| Fill id | 4 (+48 from X3) | bit 0x40 |
| Outline id | 4 | bit 0x80 |
| Encoding | 4 (a length and 2 × that many bytes from X3) | flags 2 bit 0x08 |
| Fill | 1, or 5 (53 from X5) | flags 2 bit 0x20: a zero byte alone, else a fill id and more |
The rotation and shifts are what CorelDRAW stores for text fitted to a path and for characters moved with the Shape tool.
CorelDRAW 6
Frame flag (4), 24 unknown bytes, text on a path (4; 1 adds 32 bytes), number of frames (4), then per frame the frame id (4), 48 bytes and, for artistic text, 8 more. Number of paragraphs (4); each: style id (4), number of overrides (4) and for each override a flags byte, 3 unknown bytes, font id and character set (2 + 2, or 4 unknown bytes), 4 unknown, a size (a 32-bit coordinate, or 4 unknown), 44 unknown, the fill id (flags bit 0x10) and the outline id (0x20). Then the number of characters (4), 4 unknown bytes, and for each character 12 bytes: the character, 5 unknown bytes, a byte that is the override’s number halved, 5 unknown bytes.
CorelDRAW 5
2 unknown bytes, the number of frames (2), per frame an id (2) and 2 unknown bytes; the number of paragraphs (2); each: style id (2), number of overrides (2) and the overrides, 36 bytes each, then the number of characters (2) and 8 bytes a character.
| Override offset | Size | Field |
|---|---|---|
| 0 | 1 | Flags: 0x01 font, 0x02 style, 0x04 size, 0x08 rotation, 0x10 fill, 0x20 outline, 0x40 shift x, 0x80 shift y |
| 1 | 1 | Unknown |
| 2 | 1 + 1 | Font id, character set |
| 4 | 2 | Font style word (as above) |
| 6 | 3 | Unknown |
| 9 | 1 | Placement: 4 is a subscript, when the style flag is set |
| 10 | 2 | Size, a 16-bit coordinate |
| 12 | 2 | Rotation, tenths of a degree, counter-clockwise |
| 14 | 4 | Fill id |
| 18 | 4 | Outline id |
| 22 | 2 + 2 | Shift x, shift y, 1/100 em |
| 26 | 10 | Unknown |
A character of CorelDRAW 5: 4 unknown bytes, the character, 1 unknown byte and a 16-bit word whose bits 3 and up are the override number. One byte a character, so bit 0 of that word never means “two bytes” here. A CR LF pair counts as one line break.
CorelDRAW X6 and later
| Field | Size | Description |
|---|---|---|
| Frame flag | 4 | |
| Unknown | 37 | |
| Number of frames | 4 | |
| Frames | varies | Each: id (4), 48 bytes, text on a path (4); 48 unknown bytes if it is 1, else 8; for artistic text 16 unknown bytes, a length (4) and that many UTF-16 characters (or, after version 16, that many bytes) skipped. |
| Number of paragraphs | 4 | |
| Paragraph | varies | Style id (4), 1 unknown byte (2 with a frame), the length of the default style string (4; in UTF-16 characters before version 17, in bytes from 17), the style string, the number of overrides (4); each override: 2 unknown bytes, two 16-bit flags, an encoding (a length in UTF-16 characters and that text) when flags 2 has bit 4, and when either flag is set a length and a style string; then the number of characters (4), c descriptions of 8 bytes, the number of text bytes (4), the text, a zero and the places for text on a path. |
The first bytes of a real text record, from a file saved by CorelDRAW 2020 (the record
is in content/data/page1.dat, 4002 bytes long, referred to by a
txsm chunk of root.dat; the style string is UTF-8 JSON from version 17):
000: ff ff ff ff ff ff ff ff 00 00 00 00 ff ff ff ff
010: 08 00 00 00 0e 00 00 00 00 00 00 00 03 00 00 00
020: 00 00 00 00 08 07 00 00 00 01 00 00 00 80 b1 1b
030: 25 00 00 00 00 00 00 f0 3f 00 00 00 00 00 00 00
060: 41 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00
070: 00 88 6d a0 25 00 00 a2 0e 00 00 7b 0a 20 20 22
| Offset | Bytes | Field |
|---|---|---|
| 0 | ff ff ff ff | Frame flag: not zero, a frame |
| 4 | 37 bytes | Unknown |
| 41 | 01 00 00 00 | One frame |
| 45 | 80 b1 1b 25 | Frame id 0x251BB180 (622,571,904): the number a spnd chunk of the object holds |
| 49 | 48 bytes | The frame’s transformation: six doubles, 1.0 among them (00 00 00 00 00 00 f0 3f) |
| 97 | 00 00 00 00 | Text on a path: no; 8 unknown bytes follow |
| 109 | 01 00 00 00 | One paragraph |
| 113 | 88 6d a0 25 | Style id 0x25A06D88 (631,270,792), a style of the style sheet |
| 117 | 00 00 | Unknown (two bytes because the text is in a frame) |
| 119 | a2 0e 00 00 | The style string is 3,746 bytes |
| 123 | 7b 0a 20 20 22 … | The style string: {, a line feed, "character": {… |
Style strings (X6 and later)
A style string is JSON. libcdr reads these keys; the file has many more.
| Key | Meaning |
|---|---|
character.latin.font, .charset | The font name and Windows character set. |
character.latin.size | The size in 1/254,000 inch (84667 is 24 pt). |
character.latin.weight | 64 normal; bit 0x1000 set: bold. |
character.latin.italic | 0 or 1. |
character.h_shift, .v_shift | Character shifts, 1/100 em. |
character.fill.type, .primaryColor | The fill type (1 solid) and its colour string. |
character.outline.type, .width, .color | An outline of type 0 with a width above 0 is drawn; none otherwise. |
paragraph.justify | The alignment: 0 none, 1 left, 2 centre, 3 right, 4 full, 5 force justify. |
A colour string is a model, a palette, numbers and a GUID, separated by commas:
RGB255,USER,255,255,255,100,00000000-0000-0000-0000-000000000000 is white. The
models are CMYK and CMYK100 (CMYK, 0 to 100), CMYK255, RGB255, HSB, HLS, GRAY255, YIQ255, LAB, LAB255,
REGCOLOR, SPOT and PANTONEHX; the palettes USER, FOCTONE, DUPONT, TOYO, DIC, PAN_HEX and HKS
variants. The numbers are the components, then the opacity in percent. When fallback colours
follow after ,~, libcdr uses the first of them. The same strings fill the style
sheet of the package, styles/document.cdss.
stlt: the style sheet (CorelDRAW 7 and later)
From version 7 the styles are one record: a LIST stlt whose body is not
chunks (in X6 and later packages a chunk stlt with a reference). It is a
series of tables; each count is 32 bits. In order:
| Table | Entry size | Entry |
|---|---|---|
| Number of styles | The count of style records at the end. If 0, nothing else follows. | |
| Fills | 12 (60 from X3) | A number, 4 unknown bytes, the fill id of the fill list; 48 unknown bytes from X3. |
| Outlines | 12 | A number, 4 unknown, the outline id. |
| Fonts | 44 (60 from version 10) | A number; 12 (20) unknown; font id (2); character set (2); 8 unknown; the size (a coordinate); 8 unknown (version 10 and later: the sizes for right-to-left and East Asian text); the font style (4, low 16 bits are the style word); 8 unknown. |
| Alignments | 12 | A number, 4 unknown, the alignment (0 to 5). |
| Spacings | 52 | A number; 8 unknown; character spacing; 4 unknown; word spacing; line spacing; space before; space after; 12 unknown; the unit. |
| Set 5 | 152 | Not described. |
| Tabs | 784 | Not described. |
| Bullets | varies | 40 unknown bytes, 4 more after version 13, then a flag (32 bits) and 68 or 12 bytes (version 13 and later), or 20 bytes, 8 more from version 10, a flag, 8 bytes if set, and 8 bytes (earlier). Not described. |
| Indents | 16 or 28 | A number, 12 unknown, then the right, first-line and left indents (coordinates). |
| Hyphenations | 32 (36 from X3) | Not described. |
| Drop caps | 28 | Not described. |
| Set 11 | 12 | After version 8 only. Not described. |
| Styles | varies | Each: the number of fields (1 to 3); the style id; the parent style id; 8 unknown; the name’s length (in characters) and the name (UTF-16 from version 12); the fill and outline numbers; for 2 or more fields the font, alignment, spacing, set 5 (and set 11 after version 8) numbers; for 3 or more, the tab, bullet, indent, hyphenation and drop cap numbers. |
Spacing units: with the last field 0 the numbers are shares of the character height (1,000,000 is 100%); with 1 (version 14 and later) they are lengths in 1/254,000 inch. libcdr uses the line spacing, the spacing before and after a paragraph, and the character and word spacing (shares of a space’s width).
A style’s settings are found by following its parent ids upwards and applying the settings from the oldest ancestor down: a font, size, weight, shifts, rotation, alignment, indents, spacings, fill and outline each override only when set.
In X6 and later the whole stlt record may be inside the chunk, as
data inline (stream number
0xFFFFFFFF).
styd: a style (CorelDRAW 3 to 6)
Up to version 6 each style is one chunk in the style list (LIST styl). It has
the same shape as a loda:
| Field | Size | Description |
|---|---|---|
| Style id | 2 | |
| Length, number of arguments, offsets start, types start | 4 × unsigned | From the end of the style id. |
| Parent style id | unsigned | 0: none. |
| Arguments | varies | The offsets table, and the types table (last argument first). |
| Argument type | Meaning | Layout |
|---|---|---|
| 1 | name | Not read. |
| 2 | fill id | 4 bytes. |
| 3 | outline id | 4 bytes. |
| 4 | fonts | From version 6: 4 unknown. Font id and character set (a byte each up to version 5, 16 bits later); from version 6, 8 unknown; the size (coordinate); then the font style: 1 normal, 2 bold, 4 italic in version 4, the style word in version 5; none in version 6. |
| 5 | alignment | An unsigned. |
| 7 | intervals | Five 16-bit percents: character spacing (signed), word, line, before and after a paragraph. |
| 6, 8 to 12 | bullets, tabs, indents, hyphenation, set 5, drop caps | Not read. |
CorelDRAW 4: text in the object
Version 4 has no txsm. An artistic text’s 0x1E argument holds 2
unknown bytes, the number of characters (2), 2 more bytes, then 3 bytes a character: flags, the
character in the font’s code page, and a zero. Flag bit 0 adds 22 bytes of the character’s own
style, which libcdr does not read. Lines end in CR LF. The text takes its style from the object
and the fill and outline of the object itself. In a style (styd) of version 4
the font style is 1 normal, 2 bold, 4 italic.
Character sets
A font record, a style or an override names a Windows character set. 0 means none: libcdr then guesses from the text.
| Number | Set | Number | Set |
|---|---|---|---|
| 0x00 | none (guessed, usually Windows-1252) | 0xB1 | Hebrew, Windows-1255 |
| 0x02 | Symbol (mapped by a table to Greek letters and signs) | 0xB2 | Arabic, Windows-1256 |
| 0x80 | Shift-JIS | 0xBA | Baltic, Windows-1257 |
| 0x81 | Hangul | 0xCC | Cyrillic, Windows-1251 |
| 0x86 | GB2312 | 0xDE | Thai, Windows-874 |
| 0x88 | Big5 | 0xEE | Central European, Windows-1250 |
| 0xA1 | Greek, Windows-1253 | 0xA2 | Turkish, Windows-1254 |
CorelDRAW 5 marks Central European text with the East Asian sets too; libcdr turns those to 0. A font whose name ends in a script name (for example “Arial Cyr”, “Times CE”, “Arial Greek”) has the set of that script, and a name beginning “GOST” is Cyrillic.
Laying the text out
CorelDRAW’s layout rules were measured by libcdr’s authors on PDF exports; the explorer applies only the simplest of them.
- A baseline is the line spacing times the previous line’s descent plus this line’s ascent below the previous one.
- Character spacing is a share of a space’s width added after each character; a space is the space width times the word spacing minus the character spacing.
- An empty line has the previous line’s height; a leading line break makes no line.
- Artistic text is anchored at the transformed origin of the object, its first baseline on the anchor; a stretched object keeps the font size and scales the text.
- Text on a path has the characters’ places in the record (the shifts and rotations), laid out left aligned.
- A text outline is drawn over the fill; a text with no fill has outlined characters only.
Worked example
The text “MPEG 3” in a real CorelDRAW 6 drawing, a txsm chunk of 240 bytes
(the chunk’s own 8-byte header is not in the offsets):
| Offset | Bytes | Field |
|---|---|---|
| 0 | ff ff ff ff | Frame flag (not zero: paragraph text in a frame) |
| 4 | ff ff ff ff 00 00 00 00 ff ff ff ff 00 00 00 00 … | 24 unknown bytes |
| 28 | 00 00 00 00 | Text on a path: 0 |
| 32 | 01 00 00 00 | One frame |
| 36 | 09 00 00 00 | Frame id 9, the text id a spnd chunk names |
| 40 | f4 64 aa 4d ac b6 02 40 00 … | 48 bytes, six doubles; the first is 2.3394… |
| 88 | 01 00 00 00 | One paragraph |
| 92 | 0a 00 00 00 | Style id 10 |
| 96 | 01 00 00 00 | One override |
| 100 | 00 01 00 00 … (60 bytes) | The override: flags 0, so it sets nothing |
| 160 | 06 00 00 00 | Six characters |
| 164 | 40 7e 01 00 | 4 unknown bytes |
| 168 | 4d 00 00 00 00 00 | 00 | c0 b1 51 01 00 | The character 0x4D, “M”; 5 unknown bytes; the override number 0; 5 unknown bytes. The next characters are 0x50 “P”, 0x45 “E”, 0x47 “G”, 0x20 “ ” and 0x33 “3”, 12 bytes each. |
The style, number 10, is a styd chunk of the style list; it gives the font,
size and fill. The object’s loda names style 10 in its 0xC8
argument and the text id 9 is in its spnd chunk.
In the explorer
The tree shows each txsm, stlt and styd field by field, with
the characters decoded in the code page of their style. The Contents tab lists the texts and the
styles with their fonts, sizes and colours, and the Drawing tab draws the text approximately: it
places each line from the style’s size and alignment with the browser’s own fonts, which are not
CorelDRAW’s, so line breaks and widths differ.