blob: eace610a0cf55012b85dd41c816fcc87790dd917 [file] [log] [blame]
/*
**********************************************************************
* Copyright (C) 2002, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
*/
#ifndef __PARAGRAPHLAYOUT_H
#define __PARAGRAPHLAYOUT_H
#include "layout/LETypes.h"
#include "layout/LayoutEngine.h"
#include "layout/LEFontInstance.h"
#include "unicode/ubidi.h"
#include "unicode/brkiter.h"
struct VisualRunInfo;
struct StyleRunInfo;
/**
* ParagraphLayout.
*
* The <code>ParagraphLayout</code> object will analyze the text into runs of text in the
* same font, script and direction, and will create a <code>LayoutEngine</code> object for each run.
* The <code>LayoutEngine</code> will transform the characers into glyph codes in visual order.
*
* Clients can use this to break a paragraph into lines, and to display the glyphs in each line.
*
*/
/*
* NOTES:
* * The documentation needs a *lot* of work...
*
* * Need a usage example, esp. to show that you need to call findLineBreak() before
* countLineRuns() and / or getVisualRun(). (AND, what should happen if you don't??)
* (It treats the whole paragraph as a single line.)
*
* If you don't call countLineRuns() before getVisualRun(), we'll (effectively) call
* it internally.
*
* * Might want to change to a model where a paragraph object iterates over lines objects
* and a line object iterates over runs.
*
* * Add some constructors which don't take all the arguments, so that clients don't have
* to fuss with the full-blown one if they're not doing anything tricky.
*
* * May need to handle composite fonts via LEFontInstance. We'd get a 32-bit glyph ID
* back from mapCharToGlyph() where the high 16 bits identify the physical font. We'd
* need to use this to compute physical font runs. Might want to make some of the high
* bits be client-defined flags, which the LayoutEngine will always ignore. Say 8 bits
* of flags, and 8 bits of font ID. (The flags could be used by clients for whatever they
* want, we wouldn't look at them at all...)
*
* * Might want language (or maybe locale?) runs in the constructor so that language tags
* can be passed to the LayoutEngines.
*/
class ParagraphLayout
{
public:
/**
* Construct a <code>ParagraphLayout</code> object for a styled paragraph. The paragraph is specified
* as runs of text all in the same font. An <code>LEFontInstance</code> object and a limit offset
* are specified for each font run. The limit offset is the offset of the character immediately
* after the font run.
*
* Clients can optionally specify directional runs and / or script runs. If these aren't specified
* they will be computed.
*
* @param chars is an array of the characters in the paragraph
*
* @param count is the number of characters in the paragraph.
*
* @param fonts is an array of the <code>LEFontInstance</code> objects associated
* with each font run.
*
* @param fontRunLimits is an array of the run limits of each font run.
*
* @param fontRunCount is the number of font runs.
*
* @param levels is an array of directional levels. If this pointer in <code>NULL</code>
* the levels will be determined by running the Unicde Bidi algorithm.
*
* @param levelRunLimits is an array of run limits for each level run. If <code>levels</code>
* is <code>NULL</code> this pointer must be <code>NULL</code> too.
*
* @param levelRunCount is the number of directional level runs. If <code>levels</code> is
* <code>NULL</code> this count must be zero.
*
* @param scripts is an array of script codes. If this pointer in <code>NULL</code>
* the script runs will be determined using the Unicode code points.
*
* @param scriptRunLimits is an array of run limits for each script run. If <code>scripts</code>
* is <code>NULL</code> this pointer must be <code>NULL</code> too.
*
* @param scriptRunCount is the number of script runs. If <code>scripts</code> is
* <code>NULL</code> this count must be zero.
*
* @param paragraphLevel is the directionality of the paragraph, as in the UBiDi object.
*
* @param vertical is <code>true</code> if the paragraph should be set vertically.
*
* @see ubidi.h
* @see LEFontInstance.h
* @see LayoutEngine.h
*
* @draft
*/
ParagraphLayout(const LEUnicode chars[], le_int32 count,
const LEFontInstance **fonts, const le_int32 fontRunLimits[], le_int32 fontRunCount,
const UBiDiLevel levels[], const le_int32 levelRunLimits[], le_int32 levelRunCount,
const UScriptCode scripts[], const le_int32 scriptRunLimits[], le_int32 scriptRunCount,
UBiDiLevel paragraphLevel, le_bool vertical);
~ParagraphLayout();
#if 0
/**
* Examine the given styled paragraph and determine if it contains any text which
* requires complex processing. (i.e. that cannot be correctly rendered by
* just mapping the characters to glyphs and rendering them in order)
*
* @param chars is an array of the characters in the paragraph
*
* @param count is the number of characters in the paragraph.
*
* @param fonts is an array of the <code>LEFontInstance</code> objects associated
* with each font run.
*
* @param fontRunLimits is an array of the run limits of each font run.
*
* @param fontRunCount is the number of font runs.
*
* @return <code>true</code> if the paragraph contains complex text.
*/
static le_bool isComplex(const LEUnicode chars[], le_int32 count,
const LEFontInstance *fonts[], const le_int32 fontRunLimits[], le_int32 fontRunCount);
#else
/**
* Examine the given text and determine if it contains characters in any
* script which requires complex processing to be rendered correctly.
*
* @param chars is an array of the characters in the paragraph
*
* @param count is the number of characters in the paragraph.
*
* @return <code>true</code> if any of the text requires complex processing.
*/
static le_bool isComplex(const LEUnicode chars[], le_int32 count);
#endif
/**
* Return the resolved paragraph level. This is useful for those cases
* where the bidi analysis has determined the level based on the first
* strong character in the paragraph.
*
* @return the resolved paragraph level.
*/
UBiDiLevel getParagraphLevel();
/**
* Return the directionality of the text in the paragraph.
*
* @return <code>UBIDI_LTR</code> if the text is all left to right,
* <code>UBIDI_RTL</code> if the text is all right to left,
* or <code>UBIDI_MIXED</code> if the text has mixed direction.
*/
UBiDiDirection getTextDirection();
/**
* Reset line breaking to start from the beginning of the paragraph.
*
*/
void reflow();
/**
* Find the next line in the paragraph. The width of the line is specified
* each time so that it can be varied to support arbitrary paragraph shapes.
*
* @param width is the width of the line.
*
* @return the offset of the first character which will not fit on the line, or -1
* if there are no more lines in the paragraph.
*/
le_int32 nextLineBreak(float width);
/**
* Count the number of runs in the line. Each run will contain glyphs
* in the same font and direction.
*
* @return the number of runs on the line.
*/
le_int32 countLineRuns();
/**
* Get the glyphs in the a visual run of the current line.
*
* @param runIndex is the index of the run.
*
* @param glyphs is an array which will receive the glyphs in the run, in visual order. If this
* is <code>NULL</code>, no glyphs are retreived.
*
* @param positions is an array which will receive the x and y position for
* each glyph in the run. This array will contain two entries for each glyph. The entry
* at the even offset will be the x position of the glyph, and the entry at the following
* odd offset will be the y position. There will be an extra pair of positions at the end
* of the array to specify the position of the glyph following the run. If this is <code>NULL</code>
* no positions are stored.
*
* @param glyphToCharMap is an array which will receive the original character offset for each glyph
* in the run. If this is <code>NULL</code> no character offsets are stored.
*
* @param font will receive the <code>LEFontInstance</code> object associated with this run.
*
* @param runLevel will receive the run direction.
*
* @return the number of glyphs in the run, or -1 if <code>runIndex</code> is out or range.
*
* NOTE: All input arrays are owned by the Caller. You can call this method with <code>glyphs</code>,
* <code>advances</code>, and <code>glyphToCharMap</code> all set to <code>NULL</code> to get the number
* of glyphs in the run, allocate the arrays, and call this method again to fill the arrays.
*/
le_int32 getVisualRun(le_int32 runIndex, LEGlyphID glyphs[], float positions[], le_int32 glyphToCharMap[],
const LEFontInstance **font, UBiDiDirection *runDirection);
private:
void computeLevels(UBiDiLevel paragraphLevel);
void computeVisualRuns();
void computeScripts();
le_int32 getCharRun(le_int32 charIndex);
static le_bool isComplex(UScriptCode script);
le_int32 previousBreak(le_int32 charIndex);
const LEUnicode *fChars;
le_int32 fCharCount;
const LEFontInstance **fFonts;
const le_int32 *fFontRunLimits;
le_int32 fFontRunCount;
const UBiDiLevel *fLevels;
const le_int32 *fLevelRunLimits;
le_int32 fLevelRunCount;
const UScriptCode *fScripts;
const le_int32 *fScriptRunLimits;
le_int32 fScriptRunCount;
le_bool fVertical;
le_bool fClientLevels;
le_bool fClientScripts;
UBiDiLevel *fEmbeddingLevels;
le_int32 *fGlyphToCharMap;
le_int32 *fCharToGlyphMap;
float *fGlyphWidths;
le_int32 fGlyphCount;
UBiDi *fParaBidi;
UBiDi *fLineBidi;
le_int32 *fStyleRunLimits;
le_int32 *fStyleIndices;
StyleRunInfo *fStyleRunInfo;
le_int32 fStyleRunCount;
BreakIterator *fBreakIterator;
le_int32 fLineStart;
le_int32 fLineEnd;
VisualRunInfo *fVisualRuns;
le_int32 fVisualRunCount;
le_int32 fFirstVisualRun;
le_int32 fLastVisualRun;
float fVisualRunLastX;
float fVisualRunLastY;
static le_bool fComplexTable[];
};
inline UBiDiLevel ParagraphLayout::getParagraphLevel()
{
return ubidi_getParaLevel(fParaBidi);
}
inline UBiDiDirection ParagraphLayout::getTextDirection()
{
return ubidi_getDirection(fParaBidi);
}
inline void ParagraphLayout::reflow()
{
fLineEnd = 0;
}
#endif