Download as pdf or txt
Download as pdf or txt
You are on page 1of 1

CHAPTER 2: Text Text composition 86

Scanning text
If you require access to only the character code data of a story, the simplest API to use is the TextIterator
class. There are many code snippets that show how it is used, including
SnpInspectTextModel::ReportCharacters. If you do not want to process character by character, use
IComposeScanner to access the characters in a story in larger chunks. For a fully functional example, see
the TextExportFilter SDK plug-in.

To access styled runs of text, use IComposeScanner. For an example, see “Estimating text width”.

Estimating text width


You can estimate of the width of a character string for a given horizontal font using
IFontInstance::MeasureWText. Code in the FrameLabel SDK sample plug-in
FrmLblAdornment::GetPaintedBBox() demonstrates how to do this.

To apply this estimate to a range of text in a story, use IComposeScanner to access runs of characters with
the same drawing style. The following example, EstimateTextWidth, illustrates this.
/** Returns estimated width of given text range by scanning text using IComposeScanner,
then estimating width using IFontInstance.
@param textModel text model to be scanned.
@param startingIndex of the first character to be measured.
@param span the number of characters to be measured.
@return total estimated width of a given text range.
*/
static PMReal EstimateTextWidth(
ITextModel* textModel, const TextIndex& startingIndex, const int32& span)
{
// Use the story's compose scanner to access the text.
InterfacePtr<IComposeScanner> composeScanner(textModel, UseDefaultIID());
ASSERT(composeScanner);
if (!composeScanner) return PMReal(0.0);
// Width of the given text range.
PMReal totalWidth = ::ToPMReal(0.0);
// Drawing style for the current run.
InterfacePtr<IDrawingStyle> drawingStyle(nil);
// Font for the current run.
InterfacePtr<IFontInstance> fontInstance(nil);
// Current index into the text model.
TextIndex index = startingIndex;
// Number of characters still to be processed
int32 length = span;
// Number of characters returned by the compose scanner.
int32 chunkLength = 0;
// Character buffer.
WideString run;

// The compose scanner may not return all the text


// in one call. So call it in a loop.
while (length > 0) {
        // Drawing style for the next run.
    IDrawingStyle* nextDrawingStyle = nil;
        // Get a chunk of text.
    TextIterator iter = composeScanner->QueryDataAt(
    index, &nextDrawingStyle, &chunkLength);
    if (iter.IsNull() ││ chunkLength == 0) break; // no more text.

You might also like