NAME
Prima::Drawable::TextBlock - rich text representation
API
Block header
A block's fixed header consists of tb::BLK_START - 1 integer scalars, each of those is accessible via the corresponding tb::BLK_XXX constant. The constants are separated into two logical groups:
BLK_FLAGS
BLK_WIDTH
BLK_HEIGHT
BLK_X
BLK_Y
BLK_APERTURE_X
BLK_APERTURE_Y
BLK_TEXT_OFFSET
and
BLK_FONT_ID
BLK_FONT_SIZE
BLK_FONT_STYLE
BLK_COLOR
BLK_BACKCOLOR
The second group is enclosed in tb::BLK_DATA_START - tb::BLK_DATA_END range, like the whole header is contained in 0 - tb::BLK_START - 1 range. This is done for the backward compatibility, if the future development changes the length of the header.
The first group fields define the text block dimension, aperture position and text offset ( remember, the text is stored as one big chunk ). The second defines the initial color and font settings. Prima::TextView needs all fields of every block to be initialized before displaying. block_wrap method can be used for automated assigning of these fields.
Block parameters
The scalars, beginning from tb::BLK_START, represent the commands to the renderer. These commands have their own parameters, that follow the command. The length of a command is high 16-bit word of the command. The basic command set includes OP_TEXT, OP_COLOR, OP_FONT, OP_TRANSPOSE, and OP_CODE. The additional codes are OP_WRAP and OP_MARK, not used in drawing but are special commands to block_wrap.
- OP_TEXT - TEXT_OFFSET, TEXT_LENGTH, TEXT_WIDTH
-
OP_TEXTcommands to draw a string, from offsettb::BLK_TEXT_OFFSET + TEXT_OFFSET, with a length TEXT_LENGTH. The third parameter TEXT_WIDTH contains the width of the text in pixels. Such the two-part offset scheme is made for simplification of an imaginary code, that would alter ( insert to, or delete part of ) the big text chunk; the updating procedure would not need to traverse all commands, but just the block headers.Relative to:
tb::BLK_TEXT_OFFSET - OP_COLOR - COLOR
-
OP_COLORsets foreground or background color. To set the background, COLOR must be or-ed withtb::BACKCOLOR_FLAGvalue. In addition to the two toolkit supported color values ( RRGGBB and system color index ), COLOR can also be or-ed withtb::COLOR_INDEXflags, in such case it is an index in::colormapproperty array.Relative to:
tb::BLK_COLOR,tb::BLK_BACKCOLOR. - OP_FONT - KEY, VALUE
-
As the font is a complex property, that itself includes font name, size, direction, etc keys,
OP_FONTKEY represents one of the three parameters -tb::F_ID,tb::F_SIZE,tb::F_STYLE. All three have different VALUE meaning.Relative to:
tb::BLK_FONT_ID,tb::BLK_FONT_SIZE,tb::BLK_FONT_STYLE.- F_STYLE
-
Contains a combination of
fs::XXXconstants, such asfs::Bold,fs::Italicetc.Default value: 0
- F_SIZE
-
Contains the relative font size. The size is relative to the current widget's font size. As such, 0 is a default value, and -2 is the widget's default font decreased by 2 points. Prima::TextView provides no range checking ( but the toolkit does ), so while it is o.k. to set the negative
F_SIZEvalues larger than the default font size, one must be vary when relying on the combined font size value .If
F_SIZEvalue is added to aF_HEIGHTconstant, then it is treated as a font height in pixels rather than font size in points. The macros for these opcodes are named respectivelytb::fontSizeandtb::fontHeight, while the opcode is the same. - F_ID
-
All other font properties are collected under an 'ID'. ID is a index in the
::fontPaletteproperty array, which contains font hashes with the other font keys initialized - name, encoding, and pitch. These three are minimal required set, and the other font keys can be also selected.
- OP_TRANSPOSE X, Y, FLAGS
-
Contains a mark for an empty space. The space is extended to the relative coordinates (X,Y), so the block extension algorithms take this opcode in the account. If FLAGS does not contain
tb::X_EXTEND, then in addition to the block expansion, current coordinate is also moved to (X,Y). In this regard,(OP_TRANSPOSE,0,0,0)and(OP_TRANSPOSE,0,0,X_EXTEND)are identical and are empty operators.There are formatting-only flags,in effect with block_wrap function.
X_DIMENSION_FONT_HEIGHTindicates that (X,Y) values must be multiplied to the current font height. Another flagX_DIMENSION_POINTdoes the same but multiplies by current value of resolution property divided by 72 ( basically, treats X and Y not as pixel but point values).OP_TRANSPOSEcan be used for customized graphics, in conjunction withOP_CODEto assign a space, so the rendering algorithms do not need to be re-written every time the new graphic is invented. As an example, see how Prima::PodView deals with the images. - OP_CODE - SUB, PARAMETER
-
Contains a custom code pointer SUB with a parameter PARAMETER, passed when a block is about to be drawn. SUB is called with the following format:
( $widget, $canvas, $text_block, $font_and_color_state, $x, $y, $parameter);$font_and_color_state ( or $state, through the code ) contains the state of font and color commands in effect, and is changed as the rendering algorithm advances through a block. The format of the state is the same as of text block, so one may notice that for readability F_ID, F_SIZE, F_STYLE constants are paired to BLK_FONT_ID, BLK_FONT_SIZE and BLK_FONT_STYLE.
The SUB code is executed only when the block is about to draw.
- OP_WRAP mode
-
OP_WRAPis only in effect in block_wrap method.modeis a flag, selecting the wrapping command.WRAP_MODE_ON - default, block commands can be wrapped WRAP_MODE_OFF - cancels WRAP_MODE_ON, commands cannot be wrapped WRAP_IMMEDIATE - proceed with immediate wrapping, unless ignoreImmediateWrap options is setblock_wrap does not support stacking for the wrap commands, so the
(OP_WRAP,WRAP_MODE_ON,OP_WRAP,WRAP_MODE_ON,OP_WRAP,WRAP_MODE_OFF)has same effect as(OP_WRAP,WRAP_MODE_OFF). Ifmodeis WRAP_MODE_ON, wrapping is disabled - all following commands treated an non-wrapable until(OP_WRAP,WRAP_MODE_OFF)is met. - OP_MARK PARAMETER, X, Y
-
OP_MARKis only in effect in block_wrap method and is a user command. block_wrap only sets (!) X and Y to the current coordinates when the command is met. Thus,OP_MARKcan be used for arbitrary reasons, easy marking the geometrical positions that undergo the block wrapping.
As can be noticed, these opcodes are far not enough for the full-weight rich text viewer. However, the new opcodes can be created using tb::opcode, that accepts the opcode length and returns the new opcode value.
Rendering methods
- block_wrap %OPTIONS
-
block_wrapwraps a block into a given width. It returns one or more text blocks with fully assigned headers. The returned blocks are located one below another, providing an illusion that the text itself is wrapped. It does not only traverses the opcodes and sees if the command fit or not in the given width; it also splits the text strings if these do not fit.By default the wrapping can occur either on a command boundary or by the spaces or tab characters in the text strings. The unsolicited wrapping can be prevented by using
OP_WRAPcommand brackets. The commands inside these brackets are not wrapped;OP_WRAPcommands are removed from the output blocks.In general,
block_wrapcopies all commands and their parameters as is, ( as it is supposed to do ), but some commands are treated specially:-
OP_TEXT's third parameter,TEXT_WIDTH, is disregarded, and is recalculated for everyOP_TEXTmet.- If
OP_TRANSPOSE's third parameter,X_FLAGScontainsX_DIMENSION_FONT_HEIGHTflag, the command coordinates X and Y are multiplied to the current font height and the flag is cleared in the output block.-
OP_MARK's second and third parameters assigned to the current (X,Y) coordinates.-
OP_WRAPremoved from the output. - justify_interspace %OPTIONS
-
Uses
$OPTIONS{width}and$OPTIONS{min_text_to_space_ratio}to try to make inter-word spacing. Returns new block if successful, undef otherwise. - walk BLOCK, %OPTIONS
-
Cycles through block opcodes, calls supplied callbacks on each.
AUTHOR
Dmitry Karasik, <dmitry@karasik.eu.org>.
SEE ALSO
Prima::TextView, Prima::Drawable::Markup, examples/mouse_tale.pl.