| /* |
| ********************************************************************** |
| * Copyright (C) 2002-2010, International Business Machines |
| * Corporation and others. All Rights Reserved. |
| ********************************************************************** |
| */ |
| |
| #ifndef __PARAGRAPHLAYOUT_H |
| |
| #define __PARAGRAPHLAYOUT_H |
| |
| /** |
| * \file |
| * \brief C++ API: Paragraph Layout |
| */ |
| |
| /* |
| * ParagraphLayout doesn't make much sense without |
| * BreakIterator... |
| */ |
| #include "unicode/uscript.h" |
| #if ! UCONFIG_NO_BREAK_ITERATION |
| |
| #include "layout/LETypes.h" |
| #include "layout/LEFontInstance.h" |
| #include "layout/LayoutEngine.h" |
| #include "unicode/ubidi.h" |
| #include "unicode/brkiter.h" |
| |
| #include "layout/RunArrays.h" |
| |
| U_NAMESPACE_BEGIN |
| |
| /** |
| * 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 characters into glyph codes in visual order. |
| * |
| * Clients can use this to break a paragraph into lines, and to display the glyphs in each line. |
| * |
| */ |
| class U_LAYOUTEX_API ParagraphLayout : public UObject |
| { |
| public: |
| class VisualRun; |
| |
| /** |
| * This class represents a single line of text in a <code>ParagraphLayout</code>. They |
| * can only be created by calling <code>ParagraphLayout::nextLine()</code>. Each line |
| * consists of multiple visual runs, represented by <code>ParagraphLayout::VisualRun</code> |
| * objects. |
| * |
| * @see ParagraphLayout |
| * @see ParagraphLayout::VisualRun |
| * |
| * @stable ICU 3.2 |
| */ |
| class U_LAYOUTEX_API Line : public UObject |
| { |
| public: |
| /** |
| * The constructor is private since these objects can only be |
| * created by <code>ParagraphLayout</code>. However, it is the |
| * clients responsibility to destroy the objects, so the destructor |
| * is public. |
| * |
| * @stable ICU 3.2 |
| */ |
| ~Line(); |
| |
| /** |
| * Count the number of visual runs in the line. |
| * |
| * @return the number of visual runs. |
| * |
| * @stable ICU 3.2 |
| */ |
| inline le_int32 countRuns() const; |
| |
| /** |
| * Get the ascent of the line. This is the maximum ascent |
| * of all the fonts on the line. |
| * |
| * @return the ascent of the line. |
| * |
| * @stable ICU 3.2 |
| */ |
| le_int32 getAscent() const; |
| |
| /** |
| * Get the descent of the line. This is the maximum descent |
| * of all the fonts on the line. |
| * |
| * @return the descent of the line. |
| * |
| * @stable ICU 3.2 |
| */ |
| le_int32 getDescent() const; |
| |
| /** |
| * Get the leading of the line. This is the maximum leading |
| * of all the fonts on the line. |
| * |
| * @return the leading of the line. |
| * |
| * @stable ICU 3.2 |
| */ |
| le_int32 getLeading() const; |
| |
| /** |
| * Get the width of the line. This is a convenience method |
| * which returns the last X position of the last visual run |
| * in the line. |
| * |
| * @return the width of the line. |
| * |
| * @stable ICU 2.8 |
| */ |
| le_int32 getWidth() const; |
| |
| /** |
| * Get a <code>ParagraphLayout::VisualRun</code> object for a given |
| * visual run in the line. |
| * |
| * @param runIndex is the index of the run, in visual order. |
| * |
| * @return the <code>ParagraphLayout::VisualRun</code> object representing the |
| * visual run. This object is owned by the <code>Line</code> object which |
| * created it, and will remain valid for as long as the <code>Line</code> |
| * object is valid. |
| * |
| * @see ParagraphLayout::VisualRun |
| * |
| * @stable ICU 3.2 |
| */ |
| const VisualRun *getVisualRun(le_int32 runIndex) const; |
| |
| /** |
| * ICU "poor man's RTTI", returns a UClassID for this class. |
| * |
| * @stable ICU 3.2 |
| */ |
| static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; } |
| |
| /** |
| * ICU "poor man's RTTI", returns a UClassID for the actual class. |
| * |
| * @stable ICU 3.2 |
| */ |
| virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); } |
| |
| private: |
| |
| /** |
| * The address of this static class variable serves as this class's ID |
| * for ICU "poor man's RTTI". |
| */ |
| static const char fgClassID; |
| |
| friend class ParagraphLayout; |
| |
| le_int32 fAscent; |
| le_int32 fDescent; |
| le_int32 fLeading; |
| |
| le_int32 fRunCount; |
| le_int32 fRunCapacity; |
| |
| VisualRun **fRuns; |
| |
| inline Line(); |
| inline Line(const Line &other); |
| inline Line &operator=(const Line & /*other*/) { return *this; }; |
| |
| void computeMetrics(); |
| |
| void append(const LEFontInstance *font, UBiDiDirection direction, le_int32 glyphCount, |
| const LEGlyphID glyphs[], const float positions[], const le_int32 glyphToCharMap[]); |
| }; |
| |
| /** |
| * This object represents a single visual run in a line of text in |
| * a paragraph. A visual run is text which is in the same font, |
| * script, and direction. The text is represented by an array of |
| * <code>LEGlyphIDs</code>, an array of (x, y) glyph positions and |
| * a table which maps indices into the glyph array to indices into |
| * the original character array which was used to create the paragraph. |
| * |
| * These objects are only created by <code>ParagraphLayout::Line</code> objects, |
| * so their constructors and destructors are private. |
| * |
| * @see ParagraphLayout::Line |
| * |
| * @stable ICU 3.2 |
| */ |
| class U_LAYOUTEX_API VisualRun : public UObject |
| { |
| public: |
| /** |
| * Get the <code>LEFontInstance</code> object which |
| * represents the font of the visual run. This will always |
| * be a non-composite font. |
| * |
| * @return the <code>LEFontInstance</code> object which represents the |
| * font of the visual run. |
| * |
| * @see LEFontInstance |
| * |
| * @stable ICU 3.2 |
| */ |
| inline const LEFontInstance *getFont() const; |
| |
| /** |
| * Get the direction of the visual run. |
| * |
| * @return the direction of the run. This will be UBIDI_LTR if the |
| * run is left-to-right and UBIDI_RTL if the line is right-to-left. |
| * |
| * @stable ICU 3.2 |
| */ |
| inline UBiDiDirection getDirection() const; |
| |
| /** |
| * Get the number of glyphs in the visual run. |
| * |
| * @return the number of glyphs. |
| * |
| * @stable ICU 3.2 |
| */ |
| inline le_int32 getGlyphCount() const; |
| |
| /** |
| * Get the glyphs in the visual run. Glyphs with the values <code>0xFFFE</code> and |
| * <code>0xFFFF</code> should be ignored. |
| * |
| * @return the address of the array of glyphs for this visual run. The storage |
| * is owned by the <code>VisualRun</code> object and must not be deleted. |
| * It will remain valid as long as the <code>VisualRun</code> object is valid. |
| * |
| * @stable ICU 3.2 |
| */ |
| inline const LEGlyphID *getGlyphs() const; |
| |
| /** |
| * Get the (x, y) positions of the glyphs in the visual run. To simplify storage |
| * management, the x and y positions are stored in a single array with the x positions |
| * at even offsets in the array and the corresponding y position in the following odd offset. |
| * There is an extra (x, y) pair at the end of the array which represents the advance of |
| * the final glyph in the run. |
| * |
| * @return the address of the array of glyph positions for this visual run. The storage |
| * is owned by the <code>VisualRun</code> object and must not be deleted. |
| * It will remain valid as long as the <code>VisualRun</code> object is valid. |
| * |
| * @stable ICU 3.2 |
| */ |
| inline const float *getPositions() const; |
| |
| /** |
| * Get the glyph-to-character map for this visual run. This maps the indices into |
| * the glyph array to indices into the character array used to create the paragraph. |
| * |
| * @return the address of the character-to-glyph map for this visual run. The storage |
| * is owned by the <code>VisualRun</code> object and must not be deleted. |
| * It will remain valid as long as the <code>VisualRun</code> object is valid. |
| * |
| * @stable ICU 3.2 |
| */ |
| inline const le_int32 *getGlyphToCharMap() const; |
| |
| /** |
| * A convenience method which returns the ascent value for the font |
| * associated with this run. |
| * |
| * @return the ascent value of this run's font. |
| * |
| * @stable ICU 3.2 |
| */ |
| inline le_int32 getAscent() const; |
| |
| /** |
| * A convenience method which returns the descent value for the font |
| * associated with this run. |
| * |
| * @return the descent value of this run's font. |
| * |
| * @stable ICU 3.2 |
| */ |
| inline le_int32 getDescent() const; |
| |
| /** |
| * A convenience method which returns the leading value for the font |
| * associated with this run. |
| * |
| * @return the leading value of this run's font. |
| * |
| * @stable ICU 3.2 |
| */ |
| inline le_int32 getLeading() const; |
| |
| /** |
| * ICU "poor man's RTTI", returns a UClassID for this class. |
| * |
| * @stable ICU 3.2 |
| */ |
| static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; } |
| |
| /** |
| * ICU "poor man's RTTI", returns a UClassID for the actual class. |
| * |
| * @stable ICU 3.2 |
| */ |
| virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); } |
| |
| private: |
| |
| /** |
| * The address of this static class variable serves as this class's ID |
| * for ICU "poor man's RTTI". |
| */ |
| static const char fgClassID; |
| |
| const LEFontInstance *fFont; |
| const UBiDiDirection fDirection; |
| |
| const le_int32 fGlyphCount; |
| |
| const LEGlyphID *fGlyphs; |
| const float *fPositions; |
| const le_int32 *fGlyphToCharMap; |
| |
| friend class Line; |
| |
| inline VisualRun(); |
| inline VisualRun(const VisualRun &other); |
| inline VisualRun &operator=(const VisualRun &/*other*/) { return *this; }; |
| |
| inline VisualRun(const LEFontInstance *font, UBiDiDirection direction, le_int32 glyphCount, |
| const LEGlyphID glyphs[], const float positions[], const le_int32 glyphToCharMap[]); |
| |
| ~VisualRun(); |
| }; |
| |
| /** |
| * 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. |
| * |
| * If any errors are encountered during construction, <code>status</code> will be set, and the object |
| * will be set to be empty. |
| * |
| * @param chars is an array of the characters in the paragraph |
| * |
| * @param count is the number of characters in the paragraph. |
| * |
| * @param fontRuns a pointer to a <code>FontRuns</code> object representing the font runs. |
| * |
| * @param levelRuns is a pointer to a <code>ValueRuns</code> object representing the directional levels. |
| * If this pointer in <code>NULL</code> the levels will be determined by running the Unicde |
| * Bidi algorithm. |
| * |
| * @param scriptRuns is a pointer to a <code>ValueRuns</code> object representing script runs. |
| * If this pointer in <code>NULL</code> the script runs will be determined using the |
| * Unicode code points. |
| * |
| * @param localeRuns is a pointer to a <code>LocaleRuns</code> object representing locale runs. |
| * The <code>Locale</code> objects are used to determind the language of the text. If this |
| * pointer is <code>NULL</code> the default locale will be used for all of the text. |
| * |
| * @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. |
| * |
| * @param status will be set to any error code encountered during construction. |
| * |
| * @see ubidi.h |
| * @see LEFontInstance.h |
| * @see LayoutEngine.h |
| * @see RunArrays.h |
| * |
| * @stable ICU 2.8 |
| */ |
| ParagraphLayout(const LEUnicode chars[], le_int32 count, |
| const FontRuns *fontRuns, |
| const ValueRuns *levelRuns, |
| const ValueRuns *scriptRuns, |
| const LocaleRuns *localeRuns, |
| UBiDiLevel paragraphLevel, le_bool vertical, |
| LEErrorCode &status); |
| |
| /** |
| * The destructor. Virtual so that it works correctly with |
| * sublcasses. |
| * |
| * @stable ICU 3.2 |
| */ |
| ~ParagraphLayout(); |
| |
| // Note: the following is #if 0'd out because there's no good |
| // way to implement it without either calling layoutEngineFactory() |
| // or duplicating the logic there... |
| #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 fontRuns is a pointer to a <code>FontRuns</code> object representing the font runs. |
| * |
| * @return <code>TRUE</code> if the paragraph contains complex text. |
| * |
| * @stable ICU 3.2 |
| */ |
| static le_bool isComplex(const LEUnicode chars[], le_int32 count, const FontRuns *fontRuns); |
| #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. |
| * |
| * @stable ICU 3.2 |
| */ |
| 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. |
| * |
| * @stable ICU 3.2 |
| */ |
| inline 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. |
| * |
| * @stable ICU 3.2 |
| */ |
| inline UBiDiDirection getTextDirection(); |
| |
| /** |
| * Return the max ascent value for all the fonts |
| * in the paragraph. |
| * |
| * @return the ascent value. |
| * |
| * @stable ICU 3.2 |
| */ |
| virtual le_int32 getAscent() const; |
| |
| /** |
| * Return the max descent value for all the fonts |
| * in the paragraph. |
| * |
| * @return the decent value. |
| * |
| * @stable ICU 3.2 |
| */ |
| virtual le_int32 getDescent() const; |
| |
| /** |
| * Return the max leading value for all the fonts |
| * in the paragraph. |
| * |
| * @return the leading value. |
| * |
| * @stable ICU 3.2 |
| */ |
| virtual le_int32 getLeading() const; |
| |
| /** |
| * Reset line breaking to start from the beginning of the paragraph. |
| * |
| * |
| * @stable ICU 3.2 |
| */ |
| inline void reflow(); |
| /** |
| * |
| * Convenience method for determining if paragraph layout processing is complete ( i.e. there |
| * are no more lines left to process. ) |
| * |
| * @return true if there are no more lines to be processed |
| * |
| * @internal |
| */ |
| inline le_bool isDone() const; |
| |
| /** |
| * Return a <code>ParagraphLayout::Line</code> object which represents 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. If <code>width</code> is less than or equal |
| * to zero, a <code>ParagraphLayout::Line</code> object representing the |
| * rest of the paragraph will be returned. |
| * |
| * @return a <code>ParagraphLayout::Line</code> object which represents the line. The caller |
| * is responsible for deleting the object. Returns <code>NULL</code> if there are no |
| * more lines in the paragraph. |
| * |
| * @see ParagraphLayout::Line |
| * |
| * @stable ICU 3.2 |
| */ |
| Line *nextLine(float width); |
| |
| /** |
| * ICU "poor man's RTTI", returns a UClassID for this class. |
| * |
| * @stable ICU 3.2 |
| */ |
| static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; } |
| |
| /** |
| * ICU "poor man's RTTI", returns a UClassID for the actual class. |
| * |
| * @stable ICU 3.2 |
| */ |
| virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); } |
| |
| private: |
| |
| |
| /** |
| * The address of this static class variable serves as this class's ID |
| * for ICU "poor man's RTTI". |
| */ |
| static const char fgClassID; |
| |
| struct StyleRunInfo |
| { |
| LayoutEngine *engine; |
| const LEFontInstance *font; |
| const Locale *locale; |
| LEGlyphID *glyphs; |
| float *positions; |
| UScriptCode script; |
| UBiDiLevel level; |
| le_int32 runBase; |
| le_int32 runLimit; |
| le_int32 glyphBase; |
| le_int32 glyphCount; |
| }; |
| |
| ParagraphLayout() {}; |
| ParagraphLayout(const ParagraphLayout & /*other*/) : UObject( ){}; |
| inline ParagraphLayout &operator=(const ParagraphLayout & /*other*/) { return *this; }; |
| |
| void computeLevels(UBiDiLevel paragraphLevel); |
| |
| Line *computeVisualRuns(); |
| void appendRun(Line *line, le_int32 run, le_int32 firstChar, le_int32 lastChar); |
| |
| void computeScripts(); |
| |
| void computeLocales(); |
| |
| void computeSubFonts(const FontRuns *fontRuns, LEErrorCode &status); |
| |
| void computeMetrics(); |
| |
| le_int32 getLanguageCode(const Locale *locale); |
| |
| 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 FontRuns *fFontRuns; |
| const ValueRuns *fLevelRuns; |
| const ValueRuns *fScriptRuns; |
| const LocaleRuns *fLocaleRuns; |
| |
| le_bool fVertical; |
| le_bool fClientLevels; |
| le_bool fClientScripts; |
| le_bool fClientLocales; |
| |
| UBiDiLevel *fEmbeddingLevels; |
| |
| le_int32 fAscent; |
| le_int32 fDescent; |
| le_int32 fLeading; |
| |
| le_int32 *fGlyphToCharMap; |
| le_int32 *fCharToMinGlyphMap; |
| le_int32 *fCharToMaxGlyphMap; |
| 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; |
| |
| le_int32 fFirstVisualRun; |
| le_int32 fLastVisualRun; |
| float fVisualRunLastX; |
| float fVisualRunLastY; |
| }; |
| |
| inline UBiDiLevel ParagraphLayout::getParagraphLevel() |
| { |
| return ubidi_getParaLevel(fParaBidi); |
| } |
| |
| inline UBiDiDirection ParagraphLayout::getTextDirection() |
| { |
| return ubidi_getDirection(fParaBidi); |
| } |
| |
| inline void ParagraphLayout::reflow() |
| { |
| fLineEnd = 0; |
| } |
| |
| inline ParagraphLayout::Line::Line() |
| : UObject(), fAscent(0), fDescent(0), fLeading(0), fRunCount(0), fRunCapacity(0), fRuns(NULL) |
| { |
| // nothing else to do |
| } |
| |
| inline ParagraphLayout::Line::Line(const Line & /*other*/) |
| : UObject(), fAscent(0), fDescent(0), fLeading(0), fRunCount(0), fRunCapacity(0), fRuns(NULL) |
| { |
| // nothing else to do |
| } |
| |
| inline le_int32 ParagraphLayout::Line::countRuns() const |
| { |
| return fRunCount; |
| } |
| |
| inline const LEFontInstance *ParagraphLayout::VisualRun::getFont() const |
| { |
| return fFont; |
| } |
| |
| inline UBiDiDirection ParagraphLayout::VisualRun::getDirection() const |
| { |
| return fDirection; |
| } |
| |
| inline le_int32 ParagraphLayout::VisualRun::getGlyphCount() const |
| { |
| return fGlyphCount; |
| } |
| |
| inline const LEGlyphID *ParagraphLayout::VisualRun::getGlyphs() const |
| { |
| return fGlyphs; |
| } |
| |
| inline const float *ParagraphLayout::VisualRun::getPositions() const |
| { |
| return fPositions; |
| } |
| |
| inline const le_int32 *ParagraphLayout::VisualRun::getGlyphToCharMap() const |
| { |
| return fGlyphToCharMap; |
| } |
| |
| inline le_int32 ParagraphLayout::VisualRun::getAscent() const |
| { |
| return fFont->getAscent(); |
| } |
| |
| inline le_int32 ParagraphLayout::VisualRun::getDescent() const |
| { |
| return fFont->getDescent(); |
| } |
| |
| inline le_int32 ParagraphLayout::VisualRun::getLeading() const |
| { |
| return fFont->getLeading(); |
| } |
| |
| inline ParagraphLayout::VisualRun::VisualRun() |
| : UObject(), fFont(NULL), fDirection(UBIDI_LTR), fGlyphCount(0), fGlyphs(NULL), fPositions(NULL), fGlyphToCharMap(NULL) |
| { |
| // nothing |
| } |
| |
| inline ParagraphLayout::VisualRun::VisualRun(const VisualRun &/*other*/) |
| : UObject(), fFont(NULL), fDirection(UBIDI_LTR), fGlyphCount(0), fGlyphs(NULL), fPositions(NULL), fGlyphToCharMap(NULL) |
| { |
| // nothing |
| } |
| |
| inline ParagraphLayout::VisualRun::VisualRun(const LEFontInstance *font, UBiDiDirection direction, le_int32 glyphCount, |
| const LEGlyphID glyphs[], const float positions[], const le_int32 glyphToCharMap[]) |
| : fFont(font), fDirection(direction), fGlyphCount(glyphCount), |
| fGlyphs(glyphs), fPositions(positions), fGlyphToCharMap(glyphToCharMap) |
| { |
| // nothing else needs to be done! |
| } |
| |
| U_NAMESPACE_END |
| #endif |
| #endif |