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