[wx] Unreviewed build fixes after recent trunk changes.
[WebKit-https.git] / Source / WebCore / platform / graphics / mac / ComplexTextControllerCoreText.cpp
1 /*
2  * Copyright (C) 2007, 2008, 2009 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 #include "config.h"
26
27 #if USE(CORE_TEXT)
28
29 #include "ComplexTextController.h"
30
31 #include "Font.h"
32 #include "TextRun.h"
33 #include "WebCoreSystemInterface.h"
34
35 #if PLATFORM(WX)
36 #include <ApplicationServices/ApplicationServices.h>
37 #else
38 #include <CoreText/CoreText.h>
39 #endif
40
41 #if defined(BUILDING_ON_LEOPARD)
42 // The following symbols are SPI in 10.5.
43 extern "C" {
44 void CTRunGetAdvances(CTRunRef run, CFRange range, CGSize buffer[]);
45 const CGSize* CTRunGetAdvancesPtr(CTRunRef run);
46 extern const CFStringRef kCTTypesetterOptionForcedEmbeddingLevel;
47 }
48 #endif
49
50 namespace WebCore {
51
52 ComplexTextController::ComplexTextRun::ComplexTextRun(CTRunRef ctRun, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, CFRange runRange)
53     : m_fontData(fontData)
54     , m_characters(characters)
55     , m_stringLocation(stringLocation)
56     , m_stringLength(stringLength)
57     , m_indexEnd(runRange.location + runRange.length)
58     , m_isMonotonic(true)
59 {
60     m_glyphCount = CTRunGetGlyphCount(ctRun);
61     m_coreTextIndices = CTRunGetStringIndicesPtr(ctRun);
62     if (!m_coreTextIndices) {
63         m_coreTextIndicesVector.grow(m_glyphCount);
64         CTRunGetStringIndices(ctRun, CFRangeMake(0, 0), m_coreTextIndicesVector.data());
65         m_coreTextIndices = m_coreTextIndicesVector.data();
66     }
67
68     m_glyphs = CTRunGetGlyphsPtr(ctRun);
69     if (!m_glyphs) {
70         m_glyphsVector.grow(m_glyphCount);
71         CTRunGetGlyphs(ctRun, CFRangeMake(0, 0), m_glyphsVector.data());
72         m_glyphs = m_glyphsVector.data();
73     }
74
75     m_advances = CTRunGetAdvancesPtr(ctRun);
76     if (!m_advances) {
77         m_advancesVector.grow(m_glyphCount);
78         CTRunGetAdvances(ctRun, CFRangeMake(0, 0), m_advancesVector.data());
79         m_advances = m_advancesVector.data();
80     }
81 }
82
83 // Missing glyphs run constructor. Core Text will not generate a run of missing glyphs, instead falling back on
84 // glyphs from LastResort. We want to use the primary font's missing glyph in order to match the fast text code path.
85 void ComplexTextController::ComplexTextRun::createTextRunFromFontDataCoreText(bool ltr)
86 {
87     m_coreTextIndicesVector.reserveInitialCapacity(m_stringLength);
88     unsigned r = 0;
89     while (r < m_stringLength) {
90         m_coreTextIndicesVector.uncheckedAppend(r);
91         if (U_IS_SURROGATE(m_characters[r])) {
92             ASSERT(r + 1 < m_stringLength);
93             ASSERT(U_IS_SURROGATE_LEAD(m_characters[r]));
94             ASSERT(U_IS_TRAIL(m_characters[r + 1]));
95             r += 2;
96         } else
97             r++;
98     }
99     m_glyphCount = m_coreTextIndicesVector.size();
100     if (!ltr) {
101         for (unsigned r = 0, end = m_glyphCount - 1; r < m_glyphCount / 2; ++r, --end)
102             std::swap(m_coreTextIndicesVector[r], m_coreTextIndicesVector[end]);
103     }
104     m_coreTextIndices = m_coreTextIndicesVector.data();
105
106     // Synthesize a run of missing glyphs.
107     m_glyphsVector.fill(0, m_glyphCount);
108     m_glyphs = m_glyphsVector.data();
109     m_advancesVector.fill(CGSizeMake(m_fontData->widthForGlyph(0), 0), m_glyphCount);
110     m_advances = m_advancesVector.data();
111 }
112
113 struct ProviderInfo {
114     const UChar* cp;
115     unsigned length;
116     CFDictionaryRef attributes;
117 };
118
119 static const UniChar* provideStringAndAttributes(CFIndex stringIndex, CFIndex* charCount, CFDictionaryRef* attributes, void* refCon)
120 {
121     ProviderInfo* info = static_cast<struct ProviderInfo*>(refCon);
122     if (stringIndex < 0 || static_cast<unsigned>(stringIndex) >= info->length)
123         return 0;
124
125     *charCount = info->length - stringIndex;
126     *attributes = info->attributes;
127     return info->cp + stringIndex;
128 }
129
130 void ComplexTextController::collectComplexTextRunsForCharactersCoreText(const UChar* cp, unsigned length, unsigned stringLocation, const SimpleFontData* fontData)
131 {
132     if (!fontData) {
133         // Create a run of missing glyphs from the primary font.
134         m_complexTextRuns.append(ComplexTextRun::create(m_font.primaryFont(), cp, stringLocation, length, m_run.ltr()));
135         return;
136     }
137
138     if (m_fallbackFonts && fontData != m_font.primaryFont())
139         m_fallbackFonts->add(fontData);
140
141     RetainPtr<CTLineRef> line;
142
143     if (!m_mayUseNaturalWritingDirection || m_run.directionalOverride()) {
144         static const void* optionKeys[] = { kCTTypesetterOptionForcedEmbeddingLevel };
145         const short ltrForcedEmbeddingLevelValue = 0;
146         const short rtlForcedEmbeddingLevelValue = 1;
147         static const void* ltrOptionValues[] = { CFNumberCreate(kCFAllocatorDefault, kCFNumberShortType, &ltrForcedEmbeddingLevelValue) };
148         static const void* rtlOptionValues[] = { CFNumberCreate(kCFAllocatorDefault, kCFNumberShortType, &rtlForcedEmbeddingLevelValue) };
149         static CFDictionaryRef ltrTypesetterOptions = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, ltrOptionValues, WTF_ARRAY_LENGTH(optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
150         static CFDictionaryRef rtlTypesetterOptions = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, rtlOptionValues, WTF_ARRAY_LENGTH(optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
151
152 #if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
153         ProviderInfo info = { cp, length, fontData->getCFStringAttributes(m_font.typesettingFeatures(), fontData->platformData().orientation()) };
154         RetainPtr<CTTypesetterRef> typesetter(AdoptCF, wkCreateCTTypesetterWithUniCharProviderAndOptions(&provideStringAndAttributes, 0, &info, m_run.ltr() ? ltrTypesetterOptions : rtlTypesetterOptions));
155 #else
156         RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, cp, length, kCFAllocatorNull));
157         RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), fontData->getCFStringAttributes(m_font.typesettingFeatures(), fontData->platformData().orientation())));
158         RetainPtr<CTTypesetterRef> typesetter(AdoptCF, CTTypesetterCreateWithAttributedStringAndOptions(attributedString.get(), m_run.ltr() ? ltrTypesetterOptions : rtlTypesetterOptions));
159 #endif
160
161         line.adoptCF(CTTypesetterCreateLine(typesetter.get(), CFRangeMake(0, 0)));
162     } else {
163         ProviderInfo info = { cp, length, fontData->getCFStringAttributes(m_font.typesettingFeatures(), fontData->platformData().orientation()) };
164
165         line.adoptCF(wkCreateCTLineWithUniCharProvider(&provideStringAndAttributes, 0, &info));
166     }
167
168     m_coreTextLines.append(line.get());
169
170     CFArrayRef runArray = CTLineGetGlyphRuns(line.get());
171
172     CFIndex runCount = CFArrayGetCount(runArray);
173
174     for (CFIndex r = 0; r < runCount; r++) {
175         CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r));
176         ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID());
177         CFRange runRange = CTRunGetStringRange(ctRun);
178         m_complexTextRuns.append(ComplexTextRun::create(ctRun, fontData, cp, stringLocation, length, runRange));
179     }
180 }
181
182 } // namespace WebCore
183
184 #endif // USE(CORE_TEXT)