1643ca7872b450ea4efacab6188849e5aac2ba161Steve Block/*
2643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3643ca7872b450ea4efacab6188849e5aac2ba161Steve Block *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4643ca7872b450ea4efacab6188849e5aac2ba161Steve Block *           (C) 2000 Dirk Mueller (mueller@kde.org)
5643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
6643ca7872b450ea4efacab6188849e5aac2ba161Steve Block *
7643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * This library is free software; you can redistribute it and/or
8643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * modify it under the terms of the GNU Library General Public
9643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * License as published by the Free Software Foundation; either
10643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * version 2 of the License, or (at your option) any later version.
11643ca7872b450ea4efacab6188849e5aac2ba161Steve Block *
12643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * This library is distributed in the hope that it will be useful,
13643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * but WITHOUT ANY WARRANTY; without even the implied warranty of
14643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * Library General Public License for more details.
16643ca7872b450ea4efacab6188849e5aac2ba161Steve Block *
17643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * You should have received a copy of the GNU Library General Public License
18643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * along with this library; see the file COPYING.LIB.  If not, write to
19643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * Boston, MA 02110-1301, USA.
21643ca7872b450ea4efacab6188849e5aac2ba161Steve Block */
22643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
23643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include "config.h"
24643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include "ComplexTextController.h"
25643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
26643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#if USE(ATSUI)
27643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
28643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include "Font.h"
29643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include "ShapeArabic.h"
30ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch#include "TextRun.h"
312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include <wtf/unicode/CharacterNames.h>
32643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
33643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#ifdef __LP64__
34643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// ATSUTextInserted() is SPI in 64-bit.
35643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockextern "C" {
36643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockOSStatus ATSUTextInserted(ATSUTextLayout iTextLayout,  UniCharArrayOffset iInsertionLocation, UniCharCount iInsertionLength);
37643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
38643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#endif
39643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
40643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockusing namespace WTF::Unicode;
41643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
42643ca7872b450ea4efacab6188849e5aac2ba161Steve Blocknamespace WebCore {
43643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
44643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockOSStatus ComplexTextController::ComplexTextRun::overrideLayoutOperation(ATSULayoutOperationSelector, ATSULineRef atsuLineRef, URefCon refCon, void*, ATSULayoutOperationCallbackStatus* callbackStatus)
45643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
46643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    ComplexTextRun* complexTextRun = reinterpret_cast<ComplexTextRun*>(refCon);
47643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    OSStatus status;
48643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    ItemCount count;
49d0825bca7fe65beaee391d30da42e937db621564Steve Block    ATSLayoutRecord* layoutRecords;
50643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
51643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    status = ATSUDirectGetLayoutDataArrayPtrFromLineRef(atsuLineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, true, reinterpret_cast<void**>(&layoutRecords), &count);
52643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (status != noErr) {
53643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        *callbackStatus = kATSULayoutOperationCallbackStatusContinue;
54643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return status;
55643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
56643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
57643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    count--;
58643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    ItemCount j = 0;
59643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    CFIndex indexOffset = 0;
60643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
61643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (complexTextRun->m_directionalOverride) {
62643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        j++;
63643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        count -= 2;
64643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        indexOffset = -1;
65643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
66643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
67643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    complexTextRun->m_glyphCount = count;
68643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    complexTextRun->m_glyphsVector.reserveCapacity(count);
69643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    complexTextRun->m_advancesVector.reserveCapacity(count);
70d0825bca7fe65beaee391d30da42e937db621564Steve Block    complexTextRun->m_atsuiIndices.reserveCapacity(count);
71643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
72643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    bool atBeginning = true;
73643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    CGFloat lastX = 0;
74643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
75643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    for (ItemCount i = 0; i < count; ++i, ++j) {
76643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (layoutRecords[j].glyphID == kATSDeletedGlyphcode) {
77643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            complexTextRun->m_glyphCount--;
78643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            continue;
79643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        }
80643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        complexTextRun->m_glyphsVector.uncheckedAppend(layoutRecords[j].glyphID);
81d0825bca7fe65beaee391d30da42e937db621564Steve Block        complexTextRun->m_atsuiIndices.uncheckedAppend(layoutRecords[j].originalOffset / 2 + indexOffset);
82643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        CGFloat x = FixedToFloat(layoutRecords[j].realPos);
83643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (!atBeginning)
84643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            complexTextRun->m_advancesVector.uncheckedAppend(CGSizeMake(x - lastX, 0));
85643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        lastX = x;
86643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        atBeginning = false;
87643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
88643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
89643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    complexTextRun->m_advancesVector.uncheckedAppend(CGSizeMake(FixedToFloat(layoutRecords[j].realPos) - lastX, 0));
90643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
91643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    complexTextRun->m_glyphs = complexTextRun->m_glyphsVector.data();
92643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    complexTextRun->m_advances = complexTextRun->m_advancesVector.data();
93643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
94643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    status = ATSUDirectReleaseLayoutDataArrayPtr(atsuLineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, reinterpret_cast<void**>(&layoutRecords));
95643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    *callbackStatus = kATSULayoutOperationCallbackStatusContinue;
96643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return noErr;
97643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
98643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
99643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic inline bool isArabicLamWithAlefLigature(UChar c)
100643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
101643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return c >= 0xfef5 && c <= 0xfefc;
102643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
103643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
104643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic void shapeArabic(const UChar* source, UChar* dest, unsigned totalLength)
105643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
106643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    unsigned shapingStart = 0;
107643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    while (shapingStart < totalLength) {
108643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        unsigned shapingEnd;
109643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        // We do not want to pass a Lam with Alef ligature followed by a space to the shaper,
110643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        // since we want to be able to identify this sequence as the result of shaping a Lam
111643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        // followed by an Alef and padding with a space.
112643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        bool foundLigatureSpace = false;
113643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        for (shapingEnd = shapingStart; !foundLigatureSpace && shapingEnd < totalLength - 1; ++shapingEnd)
114643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            foundLigatureSpace = isArabicLamWithAlefLigature(source[shapingEnd]) && source[shapingEnd + 1] == ' ';
115643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        shapingEnd++;
116643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
117643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        UErrorCode shapingError = U_ZERO_ERROR;
118643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        unsigned charsWritten = shapeArabic(source + shapingStart, shapingEnd - shapingStart, dest + shapingStart, shapingEnd - shapingStart, U_SHAPE_LETTERS_SHAPE | U_SHAPE_LENGTH_FIXED_SPACES_NEAR, &shapingError);
119643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
120643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (U_SUCCESS(shapingError) && charsWritten == shapingEnd - shapingStart) {
121643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            for (unsigned j = shapingStart; j < shapingEnd - 1; ++j) {
122643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                if (isArabicLamWithAlefLigature(dest[j]) && dest[j + 1] == ' ')
123643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    dest[++j] = zeroWidthSpace;
124643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            }
125643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            if (foundLigatureSpace) {
126643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                dest[shapingEnd] = ' ';
127643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                shapingEnd++;
128643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            } else if (isArabicLamWithAlefLigature(dest[shapingEnd - 1])) {
129643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                // u_shapeArabic quirk: if the last two characters in the source string are a Lam and an Alef,
130643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                // the space is put at the beginning of the string, despite U_SHAPE_LENGTH_FIXED_SPACES_NEAR.
131643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                ASSERT(dest[shapingStart] == ' ');
132643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                dest[shapingStart] = zeroWidthSpace;
133643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            }
134643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        } else {
135643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            // Something went wrong. Abandon shaping and just copy the rest of the buffer.
136643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            LOG_ERROR("u_shapeArabic failed(%d)", shapingError);
137643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            shapingEnd = totalLength;
138643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            memcpy(dest + shapingStart, source + shapingStart, (shapingEnd - shapingStart) * sizeof(UChar));
139643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        }
140643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        shapingStart = shapingEnd;
141643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
142643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
143643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
144643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockComplexTextController::ComplexTextRun::ComplexTextRun(ATSUTextLayout atsuTextLayout, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr, bool directionalOverride)
145643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    : m_fontData(fontData)
146643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    , m_characters(characters)
147643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    , m_stringLocation(stringLocation)
148643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    , m_stringLength(stringLength)
1492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    , m_indexEnd(stringLength)
150643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    , m_directionalOverride(directionalOverride)
1518a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    , m_isMonotonic(true)
152643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
153643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    OSStatus status;
154643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
155643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    status = ATSUSetTextLayoutRefCon(atsuTextLayout, reinterpret_cast<URefCon>(this));
156643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
157643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    ATSLineLayoutOptions lineLayoutOptions = kATSLineKeepSpacesOutOfMargin | kATSLineHasNoHangers;
158643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
159643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    Boolean rtl = !ltr;
160643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
161643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    Vector<UChar, 256> substituteCharacters;
162643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    bool shouldCheckForMirroring = !ltr && !fontData->m_ATSUMirrors;
163643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    bool shouldCheckForArabic = !fontData->shapesArabic();
164643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    bool shouldShapeArabic = false;
165643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
166643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    bool mirrored = false;
167643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    for (size_t i = 0; i < stringLength; ++i) {
168643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (shouldCheckForMirroring) {
169643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            UChar mirroredChar = u_charMirror(characters[i]);
170643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            if (mirroredChar != characters[i]) {
171643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                if (!mirrored) {
172643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    mirrored = true;
173643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    substituteCharacters.grow(stringLength);
174643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    memcpy(substituteCharacters.data(), characters, stringLength * sizeof(UChar));
175643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                    ATSUTextMoved(atsuTextLayout, substituteCharacters.data());
176643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                }
177643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                substituteCharacters[i] = mirroredChar;
178643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            }
179643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        }
180643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (shouldCheckForArabic && isArabicChar(characters[i])) {
181643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            shouldCheckForArabic = false;
182643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            shouldShapeArabic = true;
183643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        }
184643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
185643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
186643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (shouldShapeArabic) {
187643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        Vector<UChar, 256> shapedArabic(stringLength);
188643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        shapeArabic(substituteCharacters.isEmpty() ? characters : substituteCharacters.data(), shapedArabic.data(), stringLength);
189643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        substituteCharacters.swap(shapedArabic);
190643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        ATSUTextMoved(atsuTextLayout, substituteCharacters.data());
191643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
192643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
193643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (directionalOverride) {
194643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        UChar override = ltr ? leftToRightOverride : rightToLeftOverride;
195643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (substituteCharacters.isEmpty()) {
196643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            substituteCharacters.grow(stringLength + 2);
197643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            substituteCharacters[0] = override;
198643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            memcpy(substituteCharacters.data() + 1, characters, stringLength * sizeof(UChar));
199643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            substituteCharacters[stringLength + 1] = popDirectionalFormatting;
200643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            ATSUTextMoved(atsuTextLayout, substituteCharacters.data());
201643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        } else {
202643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            substituteCharacters.prepend(override);
203643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            substituteCharacters.append(popDirectionalFormatting);
204643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        }
205643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        ATSUTextInserted(atsuTextLayout, 0, 2);
206643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
207643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
208643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    ATSULayoutOperationOverrideSpecifier overrideSpecifier;
209643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    overrideSpecifier.operationSelector = kATSULayoutOperationPostLayoutAdjustment;
210643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    overrideSpecifier.overrideUPP = overrideLayoutOperation;
211643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
212643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    ATSUAttributeTag tags[] = { kATSULineLayoutOptionsTag, kATSULineDirectionTag, kATSULayoutOperationOverrideTag };
213643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    ByteCount sizes[] = { sizeof(ATSLineLayoutOptions), sizeof(Boolean), sizeof(ATSULayoutOperationOverrideSpecifier) };
214643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    ATSUAttributeValuePtr values[] = { &lineLayoutOptions, &rtl, &overrideSpecifier };
215643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
216643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    status = ATSUSetLayoutControls(atsuTextLayout, 3, tags, sizes, values);
217643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
218643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    ItemCount boundsCount;
219643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    status = ATSUGetGlyphBounds(atsuTextLayout, 0, 0, 0, m_stringLength, kATSUseFractionalOrigins, 0, 0, &boundsCount);
220643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
221643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    status = ATSUDisposeTextLayout(atsuTextLayout);
222643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
223643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
224d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid ComplexTextController::ComplexTextRun::createTextRunFromFontDataATSUI(bool ltr)
225643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
226d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_atsuiIndices.reserveCapacity(m_stringLength);
227643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    unsigned r = 0;
228d0825bca7fe65beaee391d30da42e937db621564Steve Block    while (r < m_stringLength) {
229d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_atsuiIndices.uncheckedAppend(r);
230d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (U_IS_SURROGATE(m_characters[r])) {
231d0825bca7fe65beaee391d30da42e937db621564Steve Block            ASSERT(r + 1 < m_stringLength);
232d0825bca7fe65beaee391d30da42e937db621564Steve Block            ASSERT(U_IS_SURROGATE_LEAD(m_characters[r]));
233d0825bca7fe65beaee391d30da42e937db621564Steve Block            ASSERT(U_IS_TRAIL(m_characters[r + 1]));
234643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            r += 2;
235643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        } else
236643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            r++;
237643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
238d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_glyphCount = m_atsuiIndices.size();
239643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (!ltr) {
240643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        for (unsigned r = 0, end = m_glyphCount - 1; r < m_glyphCount / 2; ++r, --end)
241d0825bca7fe65beaee391d30da42e937db621564Steve Block            std::swap(m_atsuiIndices[r], m_atsuiIndices[end]);
242643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
243643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
244643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    m_glyphsVector.fill(0, m_glyphCount);
245643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    m_glyphs = m_glyphsVector.data();
246d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_advancesVector.fill(CGSizeMake(m_fontData->widthForGlyph(0), 0), m_glyphCount);
247643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    m_advances = m_advancesVector.data();
248643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
249643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
250643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockstatic bool fontHasMirroringInfo(ATSUFontID fontID)
251643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
252643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    ByteCount propTableSize;
253643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    OSStatus status = ATSFontGetTable(fontID, 'prop', 0, 0, 0, &propTableSize);
254643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (status == noErr)    // naively assume that if a 'prop' table exists then it contains mirroring info
255643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return true;
256643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    else if (status != kATSInvalidFontTableAccess) // anything other than a missing table is logged as an error
257643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        LOG_ERROR("ATSFontGetTable failed (%d)", static_cast<int>(status));
258643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
259643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return false;
260643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
261643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
262d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic void disableLigatures(const SimpleFontData* fontData, ATSUStyle atsuStyle, TypesettingFeatures typesettingFeatures)
263643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
264643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Don't be too aggressive: if the font doesn't contain 'a', then assume that any ligatures it contains are
265643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // in characters that always go through ATSUI, and therefore allow them. Geeza Pro is an example.
266643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // See bugzilla 5166.
2672bde8e466a4451c7319e3a072d118917957d6554Steve Block    if ((typesettingFeatures & Ligatures) || (fontData->platformData().orientation() == Horizontal && fontData->platformData().allowsLigatures()))
268643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return;
269643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
270643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    ATSUFontFeatureType featureTypes[] = { kLigaturesType };
271643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    ATSUFontFeatureSelector featureSelectors[] = { kCommonLigaturesOffSelector };
272d0825bca7fe65beaee391d30da42e937db621564Steve Block    OSStatus status = ATSUSetFontFeatures(atsuStyle, 1, featureTypes, featureSelectors);
273643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (status != noErr)
274643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        LOG_ERROR("ATSUSetFontFeatures failed (%d) -- ligatures remain enabled", static_cast<int>(status));
275643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
276643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
277d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic ATSUStyle initializeATSUStyle(const SimpleFontData* fontData, TypesettingFeatures typesettingFeatures)
278643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
279d0825bca7fe65beaee391d30da42e937db621564Steve Block    unsigned key = typesettingFeatures + 1;
280d0825bca7fe65beaee391d30da42e937db621564Steve Block    pair<HashMap<unsigned, ATSUStyle>::iterator, bool> addResult = fontData->m_ATSUStyleMap.add(key, 0);
281d0825bca7fe65beaee391d30da42e937db621564Steve Block    ATSUStyle& atsuStyle = addResult.first->second;
282d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!addResult.second)
283d0825bca7fe65beaee391d30da42e937db621564Steve Block        return atsuStyle;
284643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
2854576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    ATSUFontID fontID = fontData->platformData().ctFont() ? CTFontGetPlatformFont(fontData->platformData().ctFont(), 0) : 0;
286643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (!fontID) {
287643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        LOG_ERROR("unable to get ATSUFontID for %p", fontData->platformData().font());
288d0825bca7fe65beaee391d30da42e937db621564Steve Block        fontData->m_ATSUStyleMap.remove(addResult.first);
289d0825bca7fe65beaee391d30da42e937db621564Steve Block        return 0;
290643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
291643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
292d0825bca7fe65beaee391d30da42e937db621564Steve Block    OSStatus status = ATSUCreateStyle(&atsuStyle);
293643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (status != noErr)
294643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        LOG_ERROR("ATSUCreateStyle failed (%d)", static_cast<int>(status));
295643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
296643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    Fixed fontSize = FloatToFixed(fontData->platformData().m_size);
297643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    Fract kerningInhibitFactor = FloatToFract(1);
298643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    static CGAffineTransform verticalFlip = CGAffineTransformMakeScale(1, -1);
299643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
300643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    ByteCount styleSizes[4] = { sizeof(fontSize), sizeof(fontID), sizeof(verticalFlip), sizeof(kerningInhibitFactor) };
301643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    ATSUAttributeTag styleTags[4] = { kATSUSizeTag, kATSUFontTag, kATSUFontMatrixTag, kATSUKerningInhibitFactorTag };
302643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    ATSUAttributeValuePtr styleValues[4] = { &fontSize, &fontID, &verticalFlip, &kerningInhibitFactor };
303643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
304d0825bca7fe65beaee391d30da42e937db621564Steve Block    bool allowKerning = typesettingFeatures & Kerning;
305d0825bca7fe65beaee391d30da42e937db621564Steve Block    status = ATSUSetAttributes(atsuStyle, allowKerning ? 3 : 4, styleTags, styleSizes, styleValues);
306643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (status != noErr)
307643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        LOG_ERROR("ATSUSetAttributes failed (%d)", static_cast<int>(status));
308643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
309643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    fontData->m_ATSUMirrors = fontHasMirroringInfo(fontID);
310643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
311d0825bca7fe65beaee391d30da42e937db621564Steve Block    disableLigatures(fontData, atsuStyle, typesettingFeatures);
312d0825bca7fe65beaee391d30da42e937db621564Steve Block    return atsuStyle;
313643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
314643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
315d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid ComplexTextController::collectComplexTextRunsForCharactersATSUI(const UChar* cp, unsigned length, unsigned stringLocation, const SimpleFontData* fontData)
316643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
317643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (!fontData) {
318643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        // Create a run of missing glyphs from the primary font.
319643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        m_complexTextRuns.append(ComplexTextRun::create(m_font.primaryFont(), cp, stringLocation, length, m_run.ltr()));
320643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return;
321643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
322643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
323643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (m_fallbackFonts && fontData != m_font.primaryFont())
324643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        m_fallbackFonts->add(fontData);
325643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
326d0825bca7fe65beaee391d30da42e937db621564Steve Block    ATSUStyle atsuStyle = initializeATSUStyle(fontData, m_font.typesettingFeatures());
327643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
328643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    OSStatus status;
329643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    ATSUTextLayout atsuTextLayout;
330643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    UniCharCount runLength = length;
331643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
332d0825bca7fe65beaee391d30da42e937db621564Steve Block    status = ATSUCreateTextLayoutWithTextPtr(cp, 0, length, length, 1, &runLength, &atsuStyle, &atsuTextLayout);
333643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (status != noErr) {
334643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        LOG_ERROR("ATSUCreateTextLayoutWithTextPtr failed with error %d", static_cast<int>(status));
335643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return;
336643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
337643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    m_complexTextRuns.append(ComplexTextRun::create(atsuTextLayout, fontData, cp, stringLocation, length, m_run.ltr(), m_run.directionalOverride()));
338643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
339643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
340643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} // namespace WebCore
341643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
342643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#endif // USE(ATSUI)
343