Q-8-1. How is font fallback handled when displaying text (for example, CJK glyphs missing in a Roman font)?
For each Unicode script you can specify one or more fonts that are associated with it (in the order of importance/preference). See the fontmap.inf file for details. D-Type will then use only those fonts when rendering characters of that script. The assumption is that the specified fonts have all the characters needed to properly render the associated Unicode script.
Q-8-2. Our application draws text within a text box which is measured in inches. How can we get D-Type Unicode Text Module to use inches? My understanding is that we would have to determine our document units scale (e.g. 1 document unit = 1/72 inch), create a text flow area with the relevant document units and use txTextSetFlow to set the flow. We would then also scale the text font sizes by the document unit scale when styling or text. Is this correct?
Yes, this is one option. The other option is to use inches (perhaps multiplied by 100 or 1,000) as your internal document units and just apply the appropriate transform matrix (via txTextSetScale) when drawing your text document to the memory surface. In other words, you are free to chose any unit you want as your base document unit. Then, when drawing, simply apply the right scale factor to display your text document on the screen.
Q-8-3. To scale the text to the required output size do we just pass the required pixel dimensions in our DT_MDC when calling txTextDraw or do we also have to call txTextSetScale?
Setting the pixel dimensions in your DT_MDC when calling txTextDraw only sets the size of your memory surface in pixels. This does not scale the text. If your text is too big to fit within the memory surface, it will be clipped. If it's too small, you will have some empty space around it.
To scale the text to the required output size you just call txTextSetScale.
Q-8-4. If we want to draw text on top of an existing image we first need to have the image within the memory pointed to by DT_MDC and then pass 0 in the Background parameter of the DT_PD_DOCDRAW_PARAMS structure. Is this correct?
Yes.
Q-8-5. Is it possible to detect if the text overflows the txTextSetFlow bounds?
Yes, this can be done in two different ways:
a) Call the txTextInfo function. Make sure the info_type parameter is set to TX_INFO_TEXTAREA.
b) Process the Frames, one by one. See the Text Flows and Frames document for more information.
Q-8-10. We will be providing a PDF output option from our software. Is it possible to determine where each soft break occurs in the text?
Yes, this can be accomplished using the Frames concept mentioned above. This works the same as with Power Engine. See the Text Flows and Frames document for more information.
Q-8-11. We need to make sure that the text in the PDF wraps at the same point as the text on-screen. Could we get the index of where characters wrap or maybe each line as it is wrapped so that we can replicate the exact same layout?
As mentioned above, if a transformation matrix is applied to a text document or a Text Area, the flow of text and how the text is wrapped within the Text Area itself will not change. Therefore your PDF output will match precisely the output that you see on the screen. However, this is assuming that you are using device-independent text layout. For more info, please see Rendering Great Looking Text With D-Type — Device Dependent or Device Independent?. Also, please review the description of the TargetDeviceID parameter under DT_TX_TEXTFLOW_AREA on the D-Type Unicode Text Module Core Structures page in the manual. Please note that this parameter is equivalent to the pdDeviceMode property in Power Engine API (see e.g. the Text Area object in D-Type Power Engine Manual).
In PDF you need to store each text line separately. To accomplish this, you can use the Frames to find out where each text line ends within a D-Type textarea. We suggest reviewing the Text Flows and Frames document in the manual for more details. Additionally, The Row member of the DT_PD_FRAME_FORMAT1 and DT_PD_FRAME_FORMAT2 structure gives you the row index of each glyph rendered by D-Type Power Engine or D-Type Unicode Text Module and, this way, allows you to figure out where your text lines end.
Q-8-12. If a transformation matrix is applied (for example to skew the text) does the Text Area dimensions change (i.e. bounding box) or does it just effect how the text is wrapped?
If a transformation matrix is applied to a text document or an entire Text Area, the bounding box of the Text Area will change, however, the flow of text and/or how the text is wrapped within the Text Area itself will not.
It's pretty easy to compute the new bounding box: you simply have to transform all four corner points of the Text Area (you can use the formula presented in the Basic Data Types section of the manual, see the DT_TM2X2 or DT_TM3X3 data type) and then calculate the global X and Y minimum and maximum extent for the four transformed corner points.
Q-8-13. I understand that we can pass parameters to draw the selection when the text is rendered. However, is it possible to pass the color of the selection so that it matches with the operating system default?
Yes. See the txTextSetHighlighter function.
Q-8-15. For our text editor to work we obviously need to know the cursor position. Luckily, the function txTextGetSelect returns this for us. However, are the positions 0 are 1 based?
Yes, the positions are 0 based.
Q-8-16. If the cursor position has been set but no selection has been made does first_char and last_char contain the same value?
Correct, if the cursor position has been set but no selection has been made, the first_char and last_char contain the same value.
Q-8-17. Can you give me an example when txTextGetSelect would return more than one entry?
This can happen when the user makes a rectangular (also called block) text selection or makes several non-contiguous selections. However, this multi-selection capability must be explicitly enabled by calling the txTextSetParams function. If it is not enabled, txTextGetSelect will never return a value larger than 1.
Q-8-23. Are we correct in thinking that we can create and format a text document and then call txTextGetPowerDoc to create a PowerDoc from the text document?
Yes. Actually, you are not really creating a PowerDoc, you are simply obtaining your text document's internal reference to the PowerDoc that it already created (when you called txTextIniViaStream). So txTextGetPowerDoc is a simple "getter" function; it will return almost immediately.
Q-8-24. If so, will the PowerDoc have all of the styling/textflows/transformations that the text document has so that we can then call pdDocDraw and pdDocSetGlyphCallback to get all of the positioning data we require or do we have to re-apply all of this once we have our PowerDoc?
Yes, the PowerDoc will have all of the styling/textflows/transformations that the text document has. You can subsequently call pdDocSetGlyphCallback and/or pdDocDraw. You don't need to re-apply any styling/textflows/transformations once you have your PowerDoc. Also, if you call pdDocSetGlyphCallback to set your glyph callback function, you don't need to render your text document via pdDocDraw; you can also render it via txTextDraw and your glyph callback function will still be called correctly.
Q-8-25. If we are correct do we have to create a new PowerDoc if we modify the text document contents (i.e. after pasting new text in) or are the text document and PowerDoc linked?
Yes, the text document and PowerDoc are linked. There is no need to call txTextGetPowerDoc after you modify the contents of the text document. But even if you did, this is not wrong — you will simply get the same pointer to the linked PowerDoc. And, again, txTextGetPowerDoc will return almost immediately. For more information see Q-8-24 above.
Q-8-26. In our label printing software, we need a text editor that will shrink the size of text when the user runs out of room to type any more text. In a normal text editor, text would just scroll off the screen or wrap, but that is not the behavior we want. The main issue is that a label is a fixed size, so text needs to automatically shrink to fit the size of the label. And we want to do this in real time as the user types so they can get a sense of how small their text would look on the label. Is it possible to create a real time shrink-to-fit editor using D-Type Unicode Text Module?
Yes, it is quite easy to create a real time shrink-to-fit editor with D-Type Unicode Text Module. Here is one way this can be done:
Step 1. Initialize D-Type Power Engine (pdEngineIniViaStream)
Step 2. Create a new text document (txTextIniViaStream)
Step 3. Set the text scale to 1.0 (txTextSetScale)
Step 4. Render text to a "DV_NULL" surface (txTextDraw), asking the function to return the flows and frames that it generated during its text layout process. After that, process all the frames to get the global bounding box of your text
Step 5. Now that you have the global bounding box of the text and its width (max_width), the horizontal stretch factor (stretch_factor) can be computed as:
stretch_factor = desired_width / max_width;
where desired_width is the width of your label to which your text must fit.
Alternatively, you can compute this factor as:
stretch_factor = ((max_width > desired_width) ? (desired_width / max_width) : 1.0);
Step 6. Set the scale to use the stretch_factor computed in the previous step:
DT_TM2X2 stretch_scale = {stretch_factor, 0.0, 0.0, 1.0}; txTextSetTransform(text_doc, stretch_scale);
Step 7. Render text again (txTextDraw), but this time to a real memory surface. Copy the memory surface to the screen or window.
Step 8. Process events (i.e. mouse hits and keystrokes as the user types) and change your text accordingly.
Step 9. Go to Step 3.
Q-8-27. Is it possible to have a blinking cursor in the editor using D-Type Unicode Text Module? If so, what is the best approach to create the blinking cursor?
It's quite easy to create a blinking cursor with D-Type Unicode Text Module. To turn the cursor off, call the txTextSetHighlighter function and change the color of the cursor to the same color as your background (or, better, make it transparent). Then call txTextCommand with the TX_CMD_CURRCHAR command and repaint the portion of the text area as indicated by the returned Extent parameter. To turn the cursor back on, call txTextSetHighlighter again and restore the original color of your cursor. Then call txTextCommand with the TX_CMD_CURRCHAR command and repaint the portion of the text area as indicated by the returned Extent parameter.
Note: The TX_CMD_CURRCHAR command "moves" the cursor to the same position where it currently is.
Q-8-28. Is there a way to retrieve text rendered by D-Type Power Engine's pdDocDraw function or D-Type Unicode Text Module's txTextDraw function in the form of outlines (polygons) that can be later rasterized using a general purpose polygon rasterizing function? If so, I would like to make sure that all the transformations (e.g. perspective, rotation etc.), text orientation, direction and other relevant text layout parameters are preserved, so that the bitmap generated using the rasterized polygons looks more or less the same as the bitmap generated using the pdDocDraw or txTextDraw functions.
Yes. First call the pdDocSetGlyphCallback function to set up your own glyph callback function. Then, render the text using the pdDocDraw or txTextDraw function. Render to a null-surface i.e. instruct the engine to perform text layout operations only. To do this, set the Flags member of the DT_PD_DOCDRAW_PARAMS structure to 1 and Flows member of the same structure to 10 or 20 (or, alternatively, 1 or 2). See the Text Flows and Frames document in the Workshop section for more details on this technique. Also, see the description of the pdDocDraw and txTextDraw functions and the DT_PD_DOCDRAW_PARAMS structure for more information.
During rendering, for every glyph generated, your callback function will be called. You will receive the glyph index (the glyph_index parameter) and a pointer to the DT_PD_ORIGIN structure (the glyph_info parameter). This structure looks as follows:
/* Origin point */ typedef struct { DT_SFRAC XA, YA; /* Accurate origin point */ DT_SFRAC XS, YS; /* Snapped origin point */ const DT_PD_ORIGIN_EXTRA* Extra; /* Optional extra info */ } DT_PD_ORIGIN;
The additional pointer to the DT_PD_ORIGIN_EXTRA structure (the Extra parameter) provides the information necessary to convert text to outlines (polygons). This structure looks as follows:
/* Extra information */ typedef struct { DT_UBYTE GlyphFlag; /* Flag to identify the type of glyph */ DT_UBYTE GlyphMisc; /* Reserved for future use and presently set to 0 */ DT_UWORD Reserved; /* Reserved for future use and presently set to 0 */ const DT_TYPE_ATTRIBS* Type; /* Typographical attributes of a glyph or character (will be DV_NULL for PowerFonts) */ DT_TM3X3 Transform; /* A 2D perspective (or projective) transformation matrix */ DT_SLONG XOff, YOff; /* Offset in whole pixels */ } DT_PD_ORIGIN_EXTRA;
With all this information, within your callback function, proceed as following:
1) Retrieve the position of the glyph in pixels (returned in 24.8 signed fractional format) and immediately convert to floating point coordinates, x_float and y_float:
DT_FLOAT x_float = GlyphInfo->XS * 0.00390625; DT_FLOAT y_float = GlyphInfo->YS * 0.00390625;
2) Get glyph's typographical attributes (type), 2D perspective (or projective) transformation matrix (transform) and additional offset in whole pixels (xoff and yoff):
const DT_TYPE_ATTRIBS* type = GlyphInfo->Extra->Type; DT_TM3X3 transform = GlyphInfo->Extra->Transform; DT_SLONG xoff = GlyphInfo->Extra->XOff; DT_SLONG yoff = GlyphInfo->Extra->YOff;
3) Obtain D-Type Standard Engine instance, dt_engine. If using D-Type Power Engine, this can be done as follows:
pdEngineGetDTEngineInst(pd_engine, &dt_engine);
4) Set glyph's typographical attributes to D-Type Standard Engine's Typesetter:
if (type==DV_NULL) return 1; /* this is not an outline font, so exit the glyph callback function */ dtTypesetterSetTypeAttribs(dt_engine, type, 0);
At the same time disable hinting and use fractional positioning for maximum precision:
dtTypesetterSetHinting(dt_engine, DV_HINTING_XOFF_YOFF, 0); dtTypesetterSetPositioning(dt_engine, DV_POSITIONING_FRACX_FRACY, 0);
5) Retrieve glyph's scaled outline description using D-Type Standard Engine's dtGlyphDoTransform function:
#define MAXPOINTS 2048 DT_UBYTE ct[MAXPOINTS]; DT_FLOAT cx_float[MAXPOINTS]; DT_FLOAT cy_float[MAXPOINTS]; DT_BMP bmp; DT_SLONG n = dtGlyphDoTransform(dt_engine, glyph_index, 0, 0, 1, MAXPOINTS, ct, cx_float, cy_float, &bmp); if (n < 0 || n > MAXPOINTS) return 1; /* some error (e.g. MAXPOINTS too small), so exit the glyph callback function */
6) Perform final calculations. Transform the glyph's scaled outline using the 2D perspective (or projective) transformation matrix to the final screen floating point coordinates:
DT_FLOAT bmp_x_float = bmp.x + x_float; DT_FLOAT bmp_y_float = bmp.y - y_float; for (DT_SLONG i = 0; i < n; i++) { cx_float[i] += bmp_x_float; cy_float[i] -= bmp_y_float; TransformPoint(transform, cx[i]_float, cy[i]_float, &cx_float[i], &cy_float[i]); }
where TransformPoint is your own function, defined as follows:
void TransformPoint(DT_TM3X3 tm, DT_FLOAT x, DT_FLOAT y, DT_FLOAT* xt, DT_FLOAT* yt) { DT_FLOAT wi = 1 / (tm[2][0] * x + tm[2][1] * y + tm[2][2]); *xt = (x * tm[0][0] + y * tm[0][1] + tm[0][2]) * wi; *yt = (x * tm[1][0] + y * tm[1][1] + tm[1][2]) * wi; }
7) Finally, set the style (color) and render the glyph as a polygon using the dtsPolyFilled (or dtsPolyDashed) function from dtshapes.cpp:
DT_STYLE_ATTRIBS style = {{0, 0}, {90, 40, 180, 0}, 0, DV_NULL}; dtOutputSetStyleAttribs(dt_engine, &style, 0); dtsPolyFilled(dt_engine, xoff, yoff, ct, cx_float, cy_float, n, DV_NULL, DV_NULL);
Note: The dtsPolyFilled function is declared in dtshapes.h as follows:
DT_SWORD dtsPolyFilled(DT_DTENGINE engine, DT_SLONG refx, DT_SLONG refy, const DT_UBYTE ct[], const DT_FLOAT cx[], const DT_FLOAT cy[], DT_SLONG n, const DT_RECT_SLONG* bound_box, const DT_TM2X2 TM);
Q-8-29. What is the significance of the fontmap.inf file? How is this file used? Is it possible to provide this file from memory (as with dtype.inf)? And what should the content of this file be? Where can I find documentation about this file?
The fontmap.inf file assigns suitable fonts to various Unicode scripts defined within the Unicode Standard. This is necessary as there are very few fonts on the market that support all the characters for all the Unicode scripts. The documentation on this file is within the file itself and the description of the txTextIniViaStream function.
# Font and Attribute Mapping Table (Fontmap) for Unicode Text Output
#
# This font and attribute mapping table (or Fontmap) is read when D-Type
# Unicode Text Module lays out Unicode text. The Fontmap allows D-Type
# clients to explicitly assign various scripts and/or characters defined
# within the Unicode Standard to a default set of text layout attributes
# and fonts. This makes it possible to properly display any user-supplied
# text, in both horizontal and vertical writing mode.
#
# When processing the Fontmap, D-Type Unicode Text Module reads the rows
# with mapping instructions one at a time. As soon as the first matching
# Unicode script or character range is found, D-Type Unicode Text Module
# applies the mapping instructions in that row and stops reading and
# processing any subsequent rows.
#
# Each row in the Fontmap consists of precisely three fields, separated
# by a single vertical bar, i.e. pipe (|):
#
# * 1st Field - Unicode script or character range
# * 2nd Field - Assigned set of text layout attributes
# * 3rd Field - Assigned font(s)
#
# Example:
#
# SCRIPTCODE:latn|ATTRIBS:ro=8,ts=10025|FONTNAME:Times;+FONTNAME:Arial
#
# Any given Unicode script or character range can be assigned a single
# set of text layout attributes and one or more fonts. If multiple fonts
# are assigned, it means they are all suitable for the display of the
# specified Unicode script or character range. The order in which fonts
# are listed is important -- the first suitable font, as determined by
# the instructions described below, is always chosen as the default.
#
# -----------
# First Field
# -----------
#
# Within the first field, the CHARCODE, CHARSPAN or SCRIPTCODE
# instruction specifies a character range or Unicode script:
#
# * CHARCODE selects a single Unicode character using an 8-digit
# hexadecimal integer.
#
# Example: CHARCODE:0000004E
#
# * CHARSPAN selects a range of Unicode characters using two
# 8-digit hexadecimal integers (first and last).
#
# Example: CHARSPAN:0000004E-0000005A
#
# Note: CHARCODE and CHARSPAN have a higher priority than
# SCRIPTCODE described below.
#
# * SCRIPTCODE selects a Unicode script using a 4 character script
# code (e.g. latn, cyrl, arab, kana etc). See ISO 15924 Code Lists
# for a list of available script codes.
#
# Example: SCRIPTCODE:arab
#
# Note 1: Script code 0000 is a special code which means any script.
# Fonts associated with this script are usually fallback fonts, i.e.
# fonts that are used in the absence of a more suitable alternative.
# As such, SCRIPTCODE:0000 should be specified after all other
# SCRIPTCODE instructions.
#
# Note 2: The best fallback fonts are those that are specifically
# designed to support a large number of Unicode characters and
# scripts, such as Arial Unicode MS and Code2000.
#
# ------------
# Second Field
# ------------
#
# Within the second field, the ATTRIBS instruction specifies the
# associated set of text layout attributes. This set is supplied as a
# comma separated list of keyword/value pairs. Currently two attribute
# keywords are supported:
#
# * ro (relative orientation)
#
# The ro attribute keyword corresponds to D-Type Power Engine's
# pdRelativeOrientation property and D-Type Unicode Text Module's
# TX_ATTR_ORIENTATION attribute identifier. This attribute allows
# D-Type clients to set the most appropriate relative text orientation
# (portrait/landscape) and baseline (e.g. default, shifted) for the
# associated Unicode script or character range and font(s), in both
# horizontal and vertical writing mode.
#
# * ts (text shaping)
#
# The ts attribute keyword corresponds to D-Type Power Engine's
# pdTextShaping property and D-Type Unicode Text Module's TX_ATTR_SHAPING
# attribute identifier. When required, this attribute allows D-Type
# clients to explicitly set the text shaping method for the associated
# Unicode script or character range and font(s). If this attribute is
# not specified, the shaping method will be set automatically based on
# the Unicode script.
#
# Examples:
#
# ATTRIBS:ro=2
# ATTRIBS:ro=8,ts=10025
#
# -----------
# Third Field
# -----------
#
# Within the third field, the associated font can be identified by its
# name or Unique Font Identifier (fuid). To accomplish this, one of
# the following four instructions can be used:
#
# * FONTFUID
#
# Specifies the font by its Unique Font Identifier (fuid). This
# instruction also performs some basic validation on the font file
# and attempts to activate it. As a result, missing, inaccessible,
# invalid and/or corrupt fonts are rejected as suitable fonts.
#
# Example: FONTFUID:S001R_ARIAL_001A
#
# * FASTFUID
#
# Same as FONTFUID but noticeably faster since it does not perform any
# validation on the font file and does not attempt to activate it. Thus,
# any specified font is accepted as a suitable font.
#
# Example: FASTFUID:S001R_ARIAL_001A
#
# * FONTNAME
#
# Specifies the font by its name. This instruction also performs some
# basic validation on the font file and attempts to activate it. As a
# result, missing, inaccessible, invalid and/or corrupt fonts are
# rejected as suitable fonts. This instruction is slower than FONTFUID
# and FASTFUID since it must access the font file and parse its header
# to extract the font name.
#
# Example: FONTNAME:Times New Roman
#
# * FASTNAME
#
# Same as FONTNAME but does not perform any validation on the font and
# does not attempt to activate it. Thus, any specified font is accepted
# as a suitable font.
#
# Example: FASTNAME:Times New Roman
#
# Multiple Fonts:
#
# To associate multiple fonts with the same Unicode script or character
# range, two different methods are available:
#
# Method 1: Within the third field, multiple font instructions can be
# concatenated using the ;+ operator, as shown in the following example:
#
# SCRIPTCODE:kana|ATTRIBS:ro=2|FONTNAME:Code2000;+FONTFUID:F0011_ARPLSH_NS0
#
# Method 2: Multiple rows that target the same Unicode script or character
# range, but assign different fonts, can be added to the Fontmap. This is
# shown in the following example:
#
# SCRIPTCODE:kana|ATTRIBS:ro=2|FONTNAME:Code2000
# SCRIPTCODE:kana|ATTRIBS:ro=2|FONTFUID:F0011_ARPLSH_NS0
#
# Note that the first method is more compact as it requires only one row
# per Unicode script or character range. However, the second method is
# slightly more flexible as it provides the ability to specify different
# text layout attributes for different fonts.
#
# ----------------
# Additional Notes
# ----------------
#
# * It is the client's responsibility to ensure that the fonts listed in
# the Fontmap have a sufficient number of glyphs to adequately represent
# all of the Unicode scripts and character ranges they are associated
# with. Only associate a font with a Unicode script or character range
# if you know it provides adequate support for that particular script or
# character range. You can use D-Type Font Viewer to check your font's
# support for the intended Unicode script or character range.
#
# * For more information on the Unique Font Identifiers (fuid),
# see the Configure Initial Font List document.
#
# * For more information on Unicode Scripts and script codes, relative
# orientation and text shaping, see the manual.
#
This file is already configured to support some of the frequently used Unicode scripts, however developers can alter it to better fit their needs.
As with all D-Type files (streams), this file can be loaded from memory. In fact, the manual recommends this. Here is what the description of the txTextIniViaStream function says about loading the font map file from memory:
For best performance, the font map file should reside in memory. The DT_STREAM_DESC structure then describes a memory based stream. Memory based streams can be processed more quickly than file based streams. See the DT_STREAM_MEMORY macro and the How To Use D-Type Streams And Stream Macros section for more information on memory based streams.
Loading this file from memory is no different than loading plain text from memory when calling txTextIniViaStream. For an example, please see one of D-Type sample programs (e.g. the example_text_animation example; see /examples/example_text_animation/classes/engine.cpp).
Q-8-30. If I start my application without a fontmap.inf file nothing is rendered when I call txTextDraw(). Why is that the case? Can you tell me more about the fontmap.inf file.
The font map file is simply a list (or database) of known and available (or likely available) fonts that can be used as the default fonts when D-Type Engine renders various Unicode scripts. The term "default" in this context means that the user did not specify any font, just provided plain text. In that case, D-Type Unicode Text Module chooses the most suitable font for the user based on the fontmap.inf file. This happens when the txTextIniViaStream is called (and only then). The intention is to choose the font that has the characters needed to properly display the script in question.
If the end-user chooses a specific font, then this is a different situation that is not related to the fontmap.inf file. In that case, the chosen font is applied to the selected text by calling txTextSetAttribs. This font will override any font that the engine previously selected as the default font. When txTextSetAttribs is called, D-Type Unicode Text Module does not read the fontmap.inf file in any way. The intention here is to allow the end-user to choose a font that better visually represents his/her final design (but still has the characters needed to properly display his/her script), in other words, override the default font. The assumption is that the end-user knows that the chosen font is the right one for his/her particular script. If not, the text may not display or may appear as a series of boxes, depending on the engine parameters. Your application may optionally check for this and warn the user if the chosen font does not contain some of the glyphs needed to display the selected text. This can be accomplished by calling the dtFontGetGlyphIndex, but again, this is merely an optional step.
In conclusion, applications should never start with an empty fontmap.inf file (otherwise txTextIniViaStream will not be able to get any fonts needed to later display the text). At minimum, the 33 entries provided in the fontmap.inf file that ships with D-Type Engine are needed (in the future additional ones might be added). When shipping the final application, it is also a good idea to provide some or all of the fonts referenced in that file, if possible. This way application developers can be sure that the Unicode scripts that they intend to support will always be displayed properly on the end-user's system. If it's not possible to ship the fonts, then the fontmap.inf file should at least have the entries for the fonts that are likely going to be installed on the end-user's system (e.g. Arial, Arial Unicode, Times, Code 2000 etc.).
Q-8-31. How should I find the first and last character position of all paragraphs that are intersecting a given selection? To be more precise I would like to get indexes of starting and ending position of each intersected paragraph since I would like to use txTextSetAttribs for each paragraph and there I need first_char and last_char.
There are several ways to get this information. Below are presented two possible and quite different solutions.
Please note that D-Type Unicode Text Module can be configured to support multiple text selections. In the manual, please see the txTextSetParams function, the DT_TX_DOC_PARAMS structure, the EnableBits member, Bit 1. This should be kept in mind when implementing one of the solutions below.
Solution A:
This solution is based on using the txTextGetSelect function.
Use the txTextGetSelect function to get the list of first and last character positions of your active text selection(s). If the engine is configured to disable multiple text sections, then you will only get one first and one last character position (first_char and last_char), so the problem is simpler.
So now you know the boundaries of your text selection. The second piece of information comes from the fact that D-Type Unicode Text Module makes paragraph breaks when it encounters the carriage return character (LF or 10 decimal or CR or 13 decimal), just like any other text layout application.
Parse your text to find the position of all your paragraphs (LF/CR character) in it. Store these positions in a temporary array (e.g. temp_paragraph_array).
Intersect the results obtained in step 1 with the results obtained in step 3:
a) The largest value in your temp_paragraph_array array that is before first_char is your first paragraph position
b) The smallest value in your temp_paragraph_array array that is after last_char is your last paragraph position
c) Any other values in your temp_paragraph_array array between the values obtained in a) and b) are your remaining paragraph positions
Solution B:
This solution is based on using the txTextCommand and txTextInfo function.
Use the txTextGetSelect function to get the list of first and last character positions of your active text selection(s). If the engine is configured to disable multiple text sections, then you will only get one first and one last character position (first_char and last_char), so the problem is simpler.
Place the cursor at position first_char obtained in step 1. To do so, call txTextSetSelect and set a single text selection that has its first and last character position both equal first_char from step 1. Note: In D-Type Unicode Text Module API, the cursor is a single text selection with equal start and end position (i.e. the length of the selected character range is zero).
So now you have a cursor at the beginning of what used to be your text selection.
Call txTextCommand and set command to TX_CMD_PREVPARAGRAPH. This will position the cursor right after the end of the previous paragraph, i.e. the start of the current paragraph. Call the txTextGetSelect function or, better, txTextInfo (with info_type set to TX_INFO_CURSOR) to get this cursor position. This is the position of your first paragraph.
Call txTextCommand again, but this time set command to TX_CMD_NEXTPARAGRAPH. This will position the cursor right before the start of the next paragraph, i.e. the end of the current paragraph. Call the txTextGetSelect function or, better, txTextInfo (with info_type set to TX_INFO_CURSOR) to get the cursor position. This is the position of your next paragraph.
Keep performing step 4 until the cursor position returned by txTextInfo exceeds last_char obtained in step 1. When this process is over, you have all the relevant paragraph positions.
Q-8-31. How can we make a full copy of the text document?
The process is much like using a text processing application to copy the contents of one document to another. Let's assume that text_doc_source is your source text document, i.e. the document you are copying from.
Then follow these steps:
Make a new empty text document using txTextIniViaStream or txTextIniViaBuffer. Let's call this document text_doc_copy:
txTextIniViaStream(&text_doc_copy, ...
Then use the txTextPasteViaDoc function to paste the entire contents of the text_doc_source document to the newly created text_doc_copy document:
txTextPasteViaDoc(text_doc_copy, text_doc_source, 0);
Note: Prior to doing this, you may need to ensure that the cursor is located at position 0 in the destination text_doc_copy document. You could call txTextCommand(text_doc_copy, TX_CMD_SELECTTEXT, DV_NULL, 0) to accomplish this.
Use the text_doc_copy document as any other text document. When you no longer need it, destroy it using txTextExt(text_doc_copy). After this, your original text_doc_source document is still available.