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