• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   **********************************************************************
3   *   Copyright (C) 2002-2011, International Business Machines
4   *   Corporation and others.  All Rights Reserved.
5   **********************************************************************
6   */
7  
8  #ifndef __PARAGRAPHLAYOUT_H
9  
10  #define __PARAGRAPHLAYOUT_H
11  
12  /**
13   * \file
14   * \brief C++ API: Paragraph Layout
15   */
16  
17  /*
18   * ParagraphLayout doesn't make much sense without
19   * BreakIterator...
20   */
21  #include "unicode/uscript.h"
22  #if ! UCONFIG_NO_BREAK_ITERATION
23  
24  #include "layout/LETypes.h"
25  #include "layout/LEFontInstance.h"
26  #include "layout/LayoutEngine.h"
27  #include "unicode/ubidi.h"
28  #include "unicode/brkiter.h"
29  
30  #include "layout/RunArrays.h"
31  
32  U_NAMESPACE_BEGIN
33  
34  /**
35   * ParagraphLayout.
36   *
37   * The <code>ParagraphLayout</code> object will analyze the text into runs of text in the
38   * same font, script and direction, and will create a <code>LayoutEngine</code> object for each run.
39   * The <code>LayoutEngine</code> will transform the characters into glyph codes in visual order.
40   *
41   * Clients can use this to break a paragraph into lines, and to display the glyphs in each line.
42   *
43   */
44  class U_LAYOUTEX_API ParagraphLayout : public UObject
45  {
46  public:
47      class VisualRun;
48  
49      /**
50       * This class represents a single line of text in a <code>ParagraphLayout</code>. They
51       * can only be created by calling <code>ParagraphLayout::nextLine()</code>. Each line
52       * consists of multiple visual runs, represented by <code>ParagraphLayout::VisualRun</code>
53       * objects.
54       *
55       * @see ParagraphLayout
56       * @see ParagraphLayout::VisualRun
57       *
58       * @stable ICU 3.2
59       */
60      class U_LAYOUTEX_API Line : public UObject
61      {
62      public:
63          /**
64           * The constructor is private since these objects can only be
65           * created by <code>ParagraphLayout</code>. However, it is the
66           * clients responsibility to destroy the objects, so the destructor
67           * is public.
68          *
69          * @stable ICU 3.2
70           */
71          ~Line();
72  
73          /**
74           * Count the number of visual runs in the line.
75           *
76           * @return the number of visual runs.
77           *
78           * @stable ICU 3.2
79           */
80          inline le_int32 countRuns() const;
81  
82          /**
83           * Get the ascent of the line. This is the maximum ascent
84           * of all the fonts on the line.
85           *
86           * @return the ascent of the line.
87           *
88           * @stable ICU 3.2
89           */
90          le_int32 getAscent() const;
91  
92          /**
93           * Get the descent of the line. This is the maximum descent
94           * of all the fonts on the line.
95           *
96           * @return the descent of the line.
97           *
98           * @stable ICU 3.2
99           */
100          le_int32 getDescent() const;
101  
102          /**
103           * Get the leading of the line. This is the maximum leading
104           * of all the fonts on the line.
105           *
106           * @return the leading of the line.
107           *
108           * @stable ICU 3.2
109           */
110          le_int32 getLeading() const;
111  
112          /**
113           * Get the width of the line. This is a convenience method
114           * which returns the last X position of the last visual run
115           * in the line.
116           *
117           * @return the width of the line.
118           *
119           * @stable ICU 2.8
120           */
121          le_int32 getWidth() const;
122  
123          /**
124           * Get a <code>ParagraphLayout::VisualRun</code> object for a given
125           * visual run in the line.
126           *
127           * @param runIndex is the index of the run, in visual order.
128           *
129           * @return the <code>ParagraphLayout::VisualRun</code> object representing the
130           *         visual run. This object is owned by the <code>Line</code> object which
131           *         created it, and will remain valid for as long as the <code>Line</code>
132           *         object is valid.
133           *
134           * @see ParagraphLayout::VisualRun
135           *
136           * @stable ICU 3.2
137           */
138          const VisualRun *getVisualRun(le_int32 runIndex) const;
139  
140          /**
141           * ICU "poor man's RTTI", returns a UClassID for this class.
142           *
143           * @stable ICU 3.2
144           */
getStaticClassID()145          static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }
146  
147          /**
148           * ICU "poor man's RTTI", returns a UClassID for the actual class.
149           *
150           * @stable ICU 3.2
151           */
getDynamicClassID()152          virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }
153  
154      private:
155  
156          /**
157           * The address of this static class variable serves as this class's ID
158           * for ICU "poor man's RTTI".
159           */
160          static const char fgClassID;
161  
162          friend class ParagraphLayout;
163  
164          le_int32 fAscent;
165          le_int32 fDescent;
166          le_int32 fLeading;
167  
168          le_int32 fRunCount;
169          le_int32 fRunCapacity;
170  
171          VisualRun **fRuns;
172  
173          inline Line();
174          inline Line(const Line &other);
175          inline Line &operator=(const Line & /*other*/) { return *this; };
176  
177          void computeMetrics();
178  
179          void append(const LEFontInstance *font, UBiDiDirection direction, le_int32 glyphCount,
180                      const LEGlyphID glyphs[], const float positions[], const le_int32 glyphToCharMap[]);
181      };
182  
183      /**
184       * This object represents a single visual run in a line of text in
185       * a paragraph. A visual run is text which is in the same font,
186       * script, and direction. The text is represented by an array of
187       * <code>LEGlyphIDs</code>, an array of (x, y) glyph positions and
188       * a table which maps indices into the glyph array to indices into
189       * the original character array which was used to create the paragraph.
190       *
191       * These objects are only created by <code>ParagraphLayout::Line</code> objects,
192       * so their constructors and destructors are private.
193       *
194       * @see ParagraphLayout::Line
195       *
196       * @stable ICU 3.2
197       */
198      class U_LAYOUTEX_API VisualRun : public UObject
199      {
200      public:
201          /**
202           * Get the <code>LEFontInstance</code> object which
203           * represents the font of the visual run. This will always
204           * be a non-composite font.
205           *
206           * @return the <code>LEFontInstance</code> object which represents the
207           *         font of the visual run.
208           *
209           * @see LEFontInstance
210           *
211           * @stable ICU 3.2
212           */
213          inline const LEFontInstance *getFont() const;
214  
215          /**
216           * Get the direction of the visual run.
217           *
218           * @return the direction of the run. This will be UBIDI_LTR if the
219           *         run is left-to-right and UBIDI_RTL if the line is right-to-left.
220           *
221           * @stable ICU 3.2
222           */
223          inline UBiDiDirection getDirection() const;
224  
225          /**
226           * Get the number of glyphs in the visual run.
227           *
228           * @return the number of glyphs.
229           *
230           * @stable ICU 3.2
231           */
232          inline le_int32 getGlyphCount() const;
233  
234          /**
235           * Get the glyphs in the visual run. Glyphs with the values <code>0xFFFE</code> and
236           * <code>0xFFFF</code> should be ignored.
237           *
238           * @return the address of the array of glyphs for this visual run. The storage
239           *         is owned by the <code>VisualRun</code> object and must not be deleted.
240           *         It will remain valid as long as the <code>VisualRun</code> object is valid.
241           *
242           * @stable ICU 3.2
243           */
244          inline const LEGlyphID *getGlyphs() const;
245  
246          /**
247           * Get the (x, y) positions of the glyphs in the visual run. To simplify storage
248           * management, the x and y positions are stored in a single array with the x positions
249           * at even offsets in the array and the corresponding y position in the following odd offset.
250           * There is an extra (x, y) pair at the end of the array which represents the advance of
251           * the final glyph in the run.
252           *
253           * @return the address of the array of glyph positions for this visual run. The storage
254           *         is owned by the <code>VisualRun</code> object and must not be deleted.
255           *         It will remain valid as long as the <code>VisualRun</code> object is valid.
256           *
257           * @stable ICU 3.2
258           */
259          inline const float *getPositions() const;
260  
261          /**
262           * Get the glyph-to-character map for this visual run. This maps the indices into
263           * the glyph array to indices into the character array used to create the paragraph.
264           *
265           * @return the address of the character-to-glyph map for this visual run. The storage
266           *         is owned by the <code>VisualRun</code> object and must not be deleted.
267           *         It will remain valid as long as the <code>VisualRun</code> object is valid.
268           *
269           * @stable ICU 3.2
270           */
271          inline const le_int32 *getGlyphToCharMap() const;
272  
273          /**
274           * A convenience method which returns the ascent value for the font
275           * associated with this run.
276           *
277           * @return the ascent value of this run's font.
278           *
279           * @stable ICU 3.2
280           */
281          inline le_int32 getAscent() const;
282  
283          /**
284           * A convenience method which returns the descent value for the font
285           * associated with this run.
286           *
287           * @return the descent value of this run's font.
288           *
289           * @stable ICU 3.2
290           */
291          inline le_int32 getDescent() const;
292  
293          /**
294           * A convenience method which returns the leading value for the font
295           * associated with this run.
296           *
297           * @return the leading value of this run's font.
298           *
299           * @stable ICU 3.2
300           */
301          inline le_int32 getLeading() const;
302  
303          /**
304           * ICU "poor man's RTTI", returns a UClassID for this class.
305           *
306           * @stable ICU 3.2
307           */
getStaticClassID()308          static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }
309  
310          /**
311           * ICU "poor man's RTTI", returns a UClassID for the actual class.
312           *
313           * @stable ICU 3.2
314           */
getDynamicClassID()315          virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }
316  
317      private:
318  
319          /**
320           * The address of this static class variable serves as this class's ID
321           * for ICU "poor man's RTTI".
322           */
323          static const char fgClassID;
324  
325          const LEFontInstance *fFont;
326          const UBiDiDirection  fDirection;
327  
328          const le_int32 fGlyphCount;
329  
330          const LEGlyphID *fGlyphs;
331          const float     *fPositions;
332          const le_int32  *fGlyphToCharMap;
333  
334          friend class Line;
335  
336          inline VisualRun();
337          inline VisualRun(const VisualRun &other);
338          inline VisualRun &operator=(const VisualRun &/*other*/) { return *this; };
339  
340          inline VisualRun(const LEFontInstance *font, UBiDiDirection direction, le_int32 glyphCount,
341                    const LEGlyphID glyphs[], const float positions[], const le_int32 glyphToCharMap[]);
342  
343          ~VisualRun();
344      };
345  
346      /**
347       * Construct a <code>ParagraphLayout</code> object for a styled paragraph. The paragraph is specified
348       * as runs of text all in the same font. An <code>LEFontInstance</code> object and a limit offset
349       * are specified for each font run. The limit offset is the offset of the character immediately
350       * after the font run.
351       *
352       * Clients can optionally specify directional runs and / or script runs. If these aren't specified
353       * they will be computed.
354       *
355       * If any errors are encountered during construction, <code>status</code> will be set, and the object
356       * will be set to be empty.
357       *
358       * @param chars is an array of the characters in the paragraph
359       *
360       * @param count is the number of characters in the paragraph.
361       *
362       * @param fontRuns a pointer to a <code>FontRuns</code> object representing the font runs.
363       *
364       * @param levelRuns is a pointer to a <code>ValueRuns</code> object representing the directional levels.
365       *        If this pointer in <code>NULL</code> the levels will be determined by running the Unicde
366       *        Bidi algorithm.
367       *
368       * @param scriptRuns is a pointer to a <code>ValueRuns</code> object representing script runs.
369       *        If this pointer in <code>NULL</code> the script runs will be determined using the
370       *        Unicode code points.
371       *
372       * @param localeRuns is a pointer to a <code>LocaleRuns</code> object representing locale runs.
373       *        The <code>Locale</code> objects are used to determind the language of the text. If this
374       *        pointer is <code>NULL</code> the default locale will be used for all of the text.
375       *
376       * @param paragraphLevel is the directionality of the paragraph, as in the UBiDi object.
377       *
378       * @param vertical is <code>TRUE</code> if the paragraph should be set vertically.
379       *
380       * @param status will be set to any error code encountered during construction.
381       *
382       * @see ubidi.h
383       * @see LEFontInstance.h
384       * @see LayoutEngine.h
385       * @see RunArrays.h
386       *
387       * @stable ICU 2.8
388       */
389      ParagraphLayout(const LEUnicode chars[], le_int32 count,
390                      const FontRuns *fontRuns,
391                      const ValueRuns *levelRuns,
392                      const ValueRuns *scriptRuns,
393                      const LocaleRuns *localeRuns,
394                      UBiDiLevel paragraphLevel, le_bool vertical,
395                      LEErrorCode &status);
396  
397      /**
398       * The destructor. Virtual so that it works correctly with
399       * sublcasses.
400       *
401       * @stable ICU 3.2
402       */
403      ~ParagraphLayout();
404  
405      // Note: the following is #if 0'd out because there's no good
406      // way to implement it without either calling layoutEngineFactory()
407      // or duplicating the logic there...
408  #if 0
409      /**
410       * Examine the given styled paragraph and determine if it contains any text which
411       * requires complex processing. (i.e. that cannot be correctly rendered by
412       * just mapping the characters to glyphs and rendering them in order)
413       *
414       * @param chars is an array of the characters in the paragraph
415       *
416       * @param count is the number of characters in the paragraph.
417       *
418       * @param fontRuns is a pointer to a <code>FontRuns</code> object representing the font runs.
419       *
420       * @return <code>TRUE</code> if the paragraph contains complex text.
421       *
422       * @stable ICU 3.2
423       */
424      static le_bool isComplex(const LEUnicode chars[], le_int32 count, const FontRuns *fontRuns);
425  #else
426      /**
427       * Examine the given text and determine if it contains characters in any
428       * script which requires complex processing to be rendered correctly.
429       *
430       * @param chars is an array of the characters in the paragraph
431       *
432       * @param count is the number of characters in the paragraph.
433       *
434       * @return <code>TRUE</code> if any of the text requires complex processing.
435       *
436       * @stable ICU 3.2
437       */
438      static le_bool isComplex(const LEUnicode chars[], le_int32 count);
439  
440  #endif
441  
442      /**
443       * Return the resolved paragraph level. This is useful for those cases
444       * where the bidi analysis has determined the level based on the first
445       * strong character in the paragraph.
446       *
447       * @return the resolved paragraph level.
448       *
449       * @stable ICU 3.2
450       */
451      inline UBiDiLevel getParagraphLevel();
452  
453      /**
454       * Return the directionality of the text in the paragraph.
455       *
456       * @return <code>UBIDI_LTR</code> if the text is all left to right,
457       *         <code>UBIDI_RTL</code> if the text is all right to left,
458       *         or <code>UBIDI_MIXED</code> if the text has mixed direction.
459       *
460       * @stable ICU 3.2
461       */
462      inline UBiDiDirection getTextDirection();
463  
464      /**
465       * Return the max ascent value for all the fonts
466       * in the paragraph.
467       *
468       * @return the ascent value.
469       *
470       * @stable ICU 3.2
471       */
472      virtual le_int32 getAscent() const;
473  
474      /**
475       * Return the max descent value for all the fonts
476       * in the paragraph.
477       *
478       * @return the decent value.
479       *
480       * @stable ICU 3.2
481       */
482      virtual le_int32 getDescent() const;
483  
484      /**
485       * Return the max leading value for all the fonts
486       * in the paragraph.
487       *
488       * @return the leading value.
489       *
490       * @stable ICU 3.2
491       */
492      virtual le_int32 getLeading() const;
493  
494      /**
495       * Reset line breaking to start from the beginning of the paragraph.
496       *
497       *
498       * @stable ICU 3.2
499       */
500      inline void reflow();
501  
502  #ifndef U_HIDE_INTERNAL_API
503      /**
504       *
505       * Convenience method for determining if paragraph layout processing is complete ( i.e. there
506       * are no more lines left to process. )
507       *
508       * @return true if there are no more lines to be processed
509       *
510       * @internal
511       */
512      inline le_bool isDone() const;
513  #endif  /* U_HIDE_INTERNAL_API */
514  
515      /**
516       * Return a <code>ParagraphLayout::Line</code> object which represents next line
517       * in the paragraph. The width of the line is specified each time so that it can
518       * be varied to support arbitrary paragraph shapes.
519       *
520       * @param width is the width of the line. If <code>width</code> is less than or equal
521       *              to zero, a <code>ParagraphLayout::Line</code> object representing the
522       *              rest of the paragraph will be returned.
523       *
524       * @return a <code>ParagraphLayout::Line</code> object which represents the line. The caller
525       *         is responsible for deleting the object. Returns <code>NULL</code> if there are no
526       *         more lines in the paragraph.
527       *
528       * @see ParagraphLayout::Line
529       *
530       * @stable ICU 3.2
531       */
532      Line *nextLine(float width);
533  
534      /**
535       * ICU "poor man's RTTI", returns a UClassID for this class.
536       *
537       * @stable ICU 3.2
538       */
getStaticClassID()539      static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }
540  
541      /**
542       * ICU "poor man's RTTI", returns a UClassID for the actual class.
543       *
544       * @stable ICU 3.2
545       */
getDynamicClassID()546      virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }
547  
548  private:
549  
550  
551      /**
552       * The address of this static class variable serves as this class's ID
553       * for ICU "poor man's RTTI".
554       */
555      static const char fgClassID;
556  
557      struct StyleRunInfo
558      {
559            LayoutEngine   *engine;
560      const LEFontInstance *font;
561      const Locale         *locale;
562            LEGlyphID      *glyphs;
563            float          *positions;
564            UScriptCode     script;
565            UBiDiLevel      level;
566            le_int32        runBase;
567            le_int32        runLimit;
568            le_int32        glyphBase;
569            le_int32        glyphCount;
570      };
571  
ParagraphLayout()572      ParagraphLayout() {};
ParagraphLayout(const ParagraphLayout &)573      ParagraphLayout(const ParagraphLayout & /*other*/) : UObject( ){};
574      inline ParagraphLayout &operator=(const ParagraphLayout & /*other*/) { return *this; };
575  
576      void computeLevels(UBiDiLevel paragraphLevel);
577  
578      Line *computeVisualRuns();
579      void appendRun(Line *line, le_int32 run, le_int32 firstChar, le_int32 lastChar);
580  
581      void computeScripts();
582  
583      void computeLocales();
584  
585      void computeSubFonts(const FontRuns *fontRuns, LEErrorCode &status);
586  
587      void computeMetrics();
588  
589      le_int32 getLanguageCode(const Locale *locale);
590  
591      le_int32 getCharRun(le_int32 charIndex);
592  
593      static le_bool isComplex(UScriptCode script);
594  
595      le_int32 previousBreak(le_int32 charIndex);
596  
597  
598      const LEUnicode *fChars;
599            le_int32   fCharCount;
600  
601      const FontRuns   *fFontRuns;
602      const ValueRuns  *fLevelRuns;
603      const ValueRuns  *fScriptRuns;
604      const LocaleRuns *fLocaleRuns;
605  
606            le_bool fVertical;
607            le_bool fClientLevels;
608            le_bool fClientScripts;
609            le_bool fClientLocales;
610  
611            UBiDiLevel *fEmbeddingLevels;
612  
613            le_int32 fAscent;
614            le_int32 fDescent;
615            le_int32 fLeading;
616  
617            le_int32 *fGlyphToCharMap;
618            le_int32 *fCharToMinGlyphMap;
619            le_int32 *fCharToMaxGlyphMap;
620            float    *fGlyphWidths;
621            le_int32  fGlyphCount;
622  
623            UBiDi *fParaBidi;
624            UBiDi *fLineBidi;
625  
626            le_int32     *fStyleRunLimits;
627            le_int32     *fStyleIndices;
628            StyleRunInfo *fStyleRunInfo;
629            le_int32      fStyleRunCount;
630  
631            BreakIterator *fBreakIterator;
632            le_int32       fLineStart;
633            le_int32       fLineEnd;
634  
635            le_int32       fFirstVisualRun;
636            le_int32       fLastVisualRun;
637            float          fVisualRunLastX;
638            float          fVisualRunLastY;
639  };
640  
getParagraphLevel()641  inline UBiDiLevel ParagraphLayout::getParagraphLevel()
642  {
643      return ubidi_getParaLevel(fParaBidi);
644  }
645  
getTextDirection()646  inline UBiDiDirection ParagraphLayout::getTextDirection()
647  {
648      return ubidi_getDirection(fParaBidi);
649  }
650  
reflow()651  inline void ParagraphLayout::reflow()
652  {
653      fLineEnd = 0;
654  }
655  
Line()656  inline ParagraphLayout::Line::Line()
657      : UObject(), fAscent(0), fDescent(0), fLeading(0), fRunCount(0), fRunCapacity(0), fRuns(NULL)
658  {
659      // nothing else to do
660  }
661  
Line(const Line &)662  inline ParagraphLayout::Line::Line(const Line & /*other*/)
663      : UObject(), fAscent(0), fDescent(0), fLeading(0), fRunCount(0), fRunCapacity(0), fRuns(NULL)
664  {
665      // nothing else to do
666  }
667  
countRuns()668  inline le_int32 ParagraphLayout::Line::countRuns() const
669  {
670      return fRunCount;
671  }
672  
getFont()673  inline const LEFontInstance *ParagraphLayout::VisualRun::getFont() const
674  {
675      return fFont;
676  }
677  
getDirection()678  inline UBiDiDirection ParagraphLayout::VisualRun::getDirection() const
679  {
680      return fDirection;
681  }
682  
getGlyphCount()683  inline le_int32 ParagraphLayout::VisualRun::getGlyphCount() const
684  {
685      return fGlyphCount;
686  }
687  
getGlyphs()688  inline const LEGlyphID *ParagraphLayout::VisualRun::getGlyphs() const
689  {
690      return fGlyphs;
691  }
692  
getPositions()693  inline const float *ParagraphLayout::VisualRun::getPositions() const
694  {
695      return fPositions;
696  }
697  
getGlyphToCharMap()698  inline const le_int32 *ParagraphLayout::VisualRun::getGlyphToCharMap() const
699  {
700      return fGlyphToCharMap;
701  }
702  
getAscent()703  inline le_int32 ParagraphLayout::VisualRun::getAscent() const
704  {
705      return fFont->getAscent();
706  }
707  
getDescent()708  inline le_int32 ParagraphLayout::VisualRun::getDescent() const
709  {
710      return fFont->getDescent();
711  }
712  
getLeading()713  inline le_int32 ParagraphLayout::VisualRun::getLeading() const
714  {
715      return fFont->getLeading();
716  }
717  
VisualRun()718  inline ParagraphLayout::VisualRun::VisualRun()
719      : UObject(), fFont(NULL), fDirection(UBIDI_LTR), fGlyphCount(0), fGlyphs(NULL), fPositions(NULL), fGlyphToCharMap(NULL)
720  {
721      // nothing
722  }
723  
VisualRun(const VisualRun &)724  inline ParagraphLayout::VisualRun::VisualRun(const VisualRun &/*other*/)
725      : UObject(), fFont(NULL), fDirection(UBIDI_LTR), fGlyphCount(0), fGlyphs(NULL), fPositions(NULL), fGlyphToCharMap(NULL)
726  {
727      // nothing
728  }
729  
VisualRun(const LEFontInstance * font,UBiDiDirection direction,le_int32 glyphCount,const LEGlyphID glyphs[],const float positions[],const le_int32 glyphToCharMap[])730  inline ParagraphLayout::VisualRun::VisualRun(const LEFontInstance *font, UBiDiDirection direction, le_int32 glyphCount,
731                                               const LEGlyphID glyphs[], const float positions[], const le_int32 glyphToCharMap[])
732      : fFont(font), fDirection(direction), fGlyphCount(glyphCount),
733        fGlyphs(glyphs), fPositions(positions), fGlyphToCharMap(glyphToCharMap)
734  {
735      // nothing else needs to be done!
736  }
737  
738  U_NAMESPACE_END
739  #endif
740  #endif
741