1 /*
2  * Copyright (C) 2007, 2008, 2009, 2011 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24 
25 #ifndef ComplexTextController_h
26 #define ComplexTextController_h
27 
28 #include "GlyphBuffer.h"
29 #include <wtf/HashSet.h>
30 #include <wtf/PassRefPtr.h>
31 #include <wtf/RefCounted.h>
32 #include <wtf/RetainPtr.h>
33 #include <wtf/Vector.h>
34 #include <wtf/unicode/Unicode.h>
35 
36 typedef unsigned short CGGlyph;
37 
38 #if USE(CORE_TEXT)
39 typedef const struct __CTRun * CTRunRef;
40 typedef const struct __CTLine * CTLineRef;
41 #endif
42 #if USE(ATSUI)
43 typedef struct OpaqueATSUTextLayout*    ATSUTextLayout;
44 typedef struct ATSGlyphVector*          ATSULineRef;
45 typedef UInt32 ATSULayoutOperationSelector;
46 typedef UInt32 ATSULayoutOperationCallbackStatus;
47 #endif
48 
49 namespace WebCore {
50 
51 class Font;
52 class SimpleFontData;
53 class TextRun;
54 
55 // ComplexTextController is responsible for rendering and measuring glyphs for
56 // complex scripts on OS X.
57 // The underlying API can be selected at compile time based on USE(ATSUI) and
58 // USE(CORE_TEXT).  If both are defined then the Core Text APIs are used for
59 // OS Versions >= 10.6, ATSUI is used otherwise.
60 class ComplexTextController {
61 public:
62     ComplexTextController(const Font*, const TextRun&, bool mayUseNaturalWritingDirection = false, HashSet<const SimpleFontData*>* fallbackFonts = 0, bool forTextEmphasis = false);
63 
64     // Advance and emit glyphs up to the specified character.
65     void advance(unsigned to, GlyphBuffer* = 0);
66 
67     // Compute the character offset for a given x coordinate.
68     int offsetForPosition(float x, bool includePartialGlyphs);
69 
70     // Returns the width of everything we've consumed so far.
runWidthSoFar()71     float runWidthSoFar() const { return m_runWidthSoFar; }
72 
totalWidth()73     float totalWidth() const { return m_totalWidth; }
74 
minGlyphBoundingBoxX()75     float minGlyphBoundingBoxX() const { return m_minGlyphBoundingBoxX; }
maxGlyphBoundingBoxX()76     float maxGlyphBoundingBoxX() const { return m_maxGlyphBoundingBoxX; }
minGlyphBoundingBoxY()77     float minGlyphBoundingBoxY() const { return m_minGlyphBoundingBoxY; }
maxGlyphBoundingBoxY()78     float maxGlyphBoundingBoxY() const { return m_maxGlyphBoundingBoxY; }
79 
80 private:
81     class ComplexTextRun : public RefCounted<ComplexTextRun> {
82     public:
83 #if USE(CORE_TEXT)
create(CTRunRef ctRun,const SimpleFontData * fontData,const UChar * characters,unsigned stringLocation,size_t stringLength,CFRange runRange)84         static PassRefPtr<ComplexTextRun> create(CTRunRef ctRun, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, CFRange runRange)
85         {
86             return adoptRef(new ComplexTextRun(ctRun, fontData, characters, stringLocation, stringLength, runRange));
87         }
88 #endif
89 #if USE(ATSUI)
create(ATSUTextLayout atsuTextLayout,const SimpleFontData * fontData,const UChar * characters,unsigned stringLocation,size_t stringLength,bool ltr,bool directionalOverride)90         static PassRefPtr<ComplexTextRun> create(ATSUTextLayout atsuTextLayout, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr, bool directionalOverride)
91         {
92             return adoptRef(new ComplexTextRun(atsuTextLayout, fontData, characters, stringLocation, stringLength, ltr, directionalOverride));
93         }
94 #endif
create(const SimpleFontData * fontData,const UChar * characters,unsigned stringLocation,size_t stringLength,bool ltr)95         static PassRefPtr<ComplexTextRun> create(const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr)
96         {
97             return adoptRef(new ComplexTextRun(fontData, characters, stringLocation, stringLength, ltr));
98         }
99 
glyphCount()100         unsigned glyphCount() const { return m_glyphCount; }
fontData()101         const SimpleFontData* fontData() const { return m_fontData; }
characters()102         const UChar* characters() const { return m_characters; }
stringLocation()103         unsigned stringLocation() const { return m_stringLocation; }
stringLength()104         size_t stringLength() const { return m_stringLength; }
105         ALWAYS_INLINE CFIndex indexAt(size_t i) const;
indexEnd()106         CFIndex indexEnd() const { return m_indexEnd; }
endOffsetAt(size_t i)107         CFIndex endOffsetAt(size_t i) const { ASSERT(!m_isMonotonic); return m_glyphEndOffsets[i]; }
glyphs()108         const CGGlyph* glyphs() const { return m_glyphs; }
advances()109         const CGSize* advances() const { return m_advances; }
isMonotonic()110         bool isMonotonic() const { return m_isMonotonic; }
111         void setIsNonMonotonic();
112 
113     private:
114 #if USE(CORE_TEXT)
115         ComplexTextRun(CTRunRef, const SimpleFontData*, const UChar* characters, unsigned stringLocation, size_t stringLength, CFRange runRange);
116         void createTextRunFromFontDataCoreText(bool ltr);
117 #endif
118 #if USE(ATSUI)
119         ComplexTextRun(ATSUTextLayout, const SimpleFontData*, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr, bool directionalOverride);
120         void createTextRunFromFontDataATSUI(bool ltr);
121 #endif
122         ComplexTextRun(const SimpleFontData*, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr);
123 
124 #if USE(ATSUI)
125         static OSStatus overrideLayoutOperation(ATSULayoutOperationSelector, ATSULineRef, URefCon, void*, ATSULayoutOperationCallbackStatus*);
126 #endif
127 
128         unsigned m_glyphCount;
129         const SimpleFontData* m_fontData;
130         const UChar* m_characters;
131         unsigned m_stringLocation;
132         size_t m_stringLength;
133 #if USE(CORE_TEXT)
134         Vector<CFIndex, 64> m_coreTextIndicesVector;
135         const CFIndex* m_coreTextIndices;
136 #endif
137 #if USE(ATSUI)
138         Vector<CFIndex, 64> m_atsuiIndices;
139 #endif
140         CFIndex m_indexEnd;
141         Vector<CFIndex, 64> m_glyphEndOffsets;
142         Vector<CGGlyph, 64> m_glyphsVector;
143         const CGGlyph* m_glyphs;
144         Vector<CGSize, 64> m_advancesVector;
145         const CGSize* m_advances;
146 #if USE(ATSUI)
147         bool m_directionalOverride;
148 #endif
149         bool m_isMonotonic;
150     };
151 
152     void collectComplexTextRuns();
153 
154     // collectComplexTextRunsForCharacters() is a stub function that calls through to the ATSUI or Core Text variants based
155     // on the API in use.
156     void collectComplexTextRunsForCharacters(const UChar*, unsigned length, unsigned stringLocation, const SimpleFontData*);
157     void collectComplexTextRunsForCharactersATSUI(const UChar*, unsigned length, unsigned stringLocation, const SimpleFontData*);
158     void collectComplexTextRunsForCharactersCoreText(const UChar*, unsigned length, unsigned stringLocation, const SimpleFontData*);
159     void adjustGlyphsAndAdvances();
160 
161     const Font& m_font;
162     const TextRun& m_run;
163     bool m_mayUseNaturalWritingDirection;
164     bool m_forTextEmphasis;
165 
166     Vector<UChar, 256> m_smallCapsBuffer;
167 
168 #if USE(CORE_TEXT)
169     // Retain lines rather than their runs for better performance.
170     Vector<RetainPtr<CTLineRef> > m_coreTextLines;
171 #endif
172     Vector<RefPtr<ComplexTextRun>, 16> m_complexTextRuns;
173     Vector<CGSize, 256> m_adjustedAdvances;
174     Vector<CGGlyph, 256> m_adjustedGlyphs;
175 
176     unsigned m_currentCharacter;
177     int m_end;
178 
179     CGFloat m_totalWidth;
180 
181     float m_runWidthSoFar;
182     unsigned m_numGlyphsSoFar;
183     size_t m_currentRun;
184     unsigned m_glyphInCurrentRun;
185     unsigned m_characterInCurrentGlyph;
186     float m_expansion;
187     float m_expansionPerOpportunity;
188     float m_leadingExpansion;
189     bool m_afterExpansion;
190 
191     HashSet<const SimpleFontData*>* m_fallbackFonts;
192 
193     float m_minGlyphBoundingBoxX;
194     float m_maxGlyphBoundingBoxX;
195     float m_minGlyphBoundingBoxY;
196     float m_maxGlyphBoundingBoxY;
197 };
198 
199 } // namespace WebCore
200 
201 #endif // ComplexTextController_h
202