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