18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 22fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * Copyright (C) 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met: 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer. 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * documentation and/or other materials provided with the distribution. 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 13643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 14643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY 17643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22643ca7872b450ea4efacab6188849e5aac2ba161Steve Block * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 26643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include "ComplexTextController.h" 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2821939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "FloatSize.h" 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Font.h" 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "TextBreakIterator.h" 31ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch#include "TextRun.h" 322fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include <ApplicationServices/ApplicationServices.h> 33d0825bca7fe65beaee391d30da42e937db621564Steve Block#include <wtf/StdLibExtras.h> 342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include <wtf/unicode/CharacterNames.h> 35d0825bca7fe65beaee391d30da42e937db621564Steve Block 36d0825bca7fe65beaee391d30da42e937db621564Steve Block#if defined(BUILDING_ON_LEOPARD) 37d0825bca7fe65beaee391d30da42e937db621564Steve Block// Undefined when compiling agains the 10.5 SDK. 38d0825bca7fe65beaee391d30da42e937db621564Steve Block#define kCTVersionNumber10_6 0x00030000 39d0825bca7fe65beaee391d30da42e937db621564Steve Block#endif 40d0825bca7fe65beaee391d30da42e937db621564Steve Block 418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace std; 428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline CGFloat roundCGFloat(CGFloat f) 468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (sizeof(CGFloat) == sizeof(float)) 488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return roundf(static_cast<float>(f)); 498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return static_cast<CGFloat>(round(f)); 508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 52f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochComplexTextController::ComplexTextController(const Font* font, const TextRun& run, bool mayUseNaturalWritingDirection, HashSet<const SimpleFontData*>* fallbackFonts, bool forTextEmphasis) 538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project : m_font(*font) 548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_run(run) 558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_mayUseNaturalWritingDirection(mayUseNaturalWritingDirection) 56f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch , m_forTextEmphasis(forTextEmphasis) 578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_currentCharacter(0) 588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_end(run.length()) 598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_totalWidth(0) 608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_runWidthSoFar(0) 618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_numGlyphsSoFar(0) 628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_currentRun(0) 638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_glyphInCurrentRun(0) 64643ca7872b450ea4efacab6188849e5aac2ba161Steve Block , m_characterInCurrentGlyph(0) 652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block , m_expansion(run.expansion()) 662bde8e466a4451c7319e3a072d118917957d6554Steve Block , m_leadingExpansion(0) 672bde8e466a4451c7319e3a072d118917957d6554Steve Block , m_afterExpansion(!run.allowsLeadingExpansion()) 685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian , m_fallbackFonts(fallbackFonts) 69dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block , m_minGlyphBoundingBoxX(numeric_limits<float>::max()) 70dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block , m_maxGlyphBoundingBoxX(numeric_limits<float>::min()) 71dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block , m_minGlyphBoundingBoxY(numeric_limits<float>::max()) 72dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block , m_maxGlyphBoundingBoxY(numeric_limits<float>::min()) 738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (!m_expansion) 752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block m_expansionPerOpportunity = 0; 768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else { 772bde8e466a4451c7319e3a072d118917957d6554Steve Block bool isAfterExpansion = m_afterExpansion; 782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block unsigned expansionOpportunityCount = Font::expansionOpportunityCount(m_run.characters(), m_end, m_run.ltr() ? LTR : RTL, isAfterExpansion); 792fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (isAfterExpansion && !m_run.allowsTrailingExpansion()) 802fc2651226baac27029e38c9d6ef883fa32084dbSteve Block expansionOpportunityCount--; 818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (!expansionOpportunityCount) 832fc2651226baac27029e38c9d6ef883fa32084dbSteve Block m_expansionPerOpportunity = 0; 848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 852fc2651226baac27029e38c9d6ef883fa32084dbSteve Block m_expansionPerOpportunity = m_expansion / expansionOpportunityCount; 868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 88643ca7872b450ea4efacab6188849e5aac2ba161Steve Block collectComplexTextRuns(); 898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project adjustGlyphsAndAdvances(); 902bde8e466a4451c7319e3a072d118917957d6554Steve Block 912bde8e466a4451c7319e3a072d118917957d6554Steve Block m_runWidthSoFar = m_leadingExpansion; 928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 9406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenint ComplexTextController::offsetForPosition(float h, bool includePartialGlyphs) 958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (h >= m_totalWidth) 978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_run.ltr() ? m_end : 0; 982bde8e466a4451c7319e3a072d118917957d6554Steve Block 992bde8e466a4451c7319e3a072d118917957d6554Steve Block h -= m_leadingExpansion; 1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (h < 0) 1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_run.ltr() ? 0 : m_end; 1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGFloat x = h; 1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 105643ca7872b450ea4efacab6188849e5aac2ba161Steve Block size_t runCount = m_complexTextRuns.size(); 1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project size_t offsetIntoAdjustedGlyphs = 0; 1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (size_t r = 0; r < runCount; ++r) { 109643ca7872b450ea4efacab6188849e5aac2ba161Steve Block const ComplexTextRun& complexTextRun = *m_complexTextRuns[r]; 110643ca7872b450ea4efacab6188849e5aac2ba161Steve Block for (unsigned j = 0; j < complexTextRun.glyphCount(); ++j) { 1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGFloat adjustedAdvance = m_adjustedAdvances[offsetIntoAdjustedGlyphs + j].width; 112643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (x < adjustedAdvance) { 113643ca7872b450ea4efacab6188849e5aac2ba161Steve Block CFIndex hitGlyphStart = complexTextRun.indexAt(j); 114643ca7872b450ea4efacab6188849e5aac2ba161Steve Block CFIndex hitGlyphEnd; 115643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (m_run.ltr()) 1162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block hitGlyphEnd = max<CFIndex>(hitGlyphStart, j + 1 < complexTextRun.glyphCount() ? complexTextRun.indexAt(j + 1) : static_cast<CFIndex>(complexTextRun.indexEnd())); 117643ca7872b450ea4efacab6188849e5aac2ba161Steve Block else 1182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block hitGlyphEnd = max<CFIndex>(hitGlyphStart, j > 0 ? complexTextRun.indexAt(j - 1) : static_cast<CFIndex>(complexTextRun.indexEnd())); 119643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 120d0825bca7fe65beaee391d30da42e937db621564Steve Block // FIXME: Instead of dividing the glyph's advance equally between the characters, this 121643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // could use the glyph's "ligature carets". However, there is no Core Text API to get the 122643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // ligature carets. 123643ca7872b450ea4efacab6188849e5aac2ba161Steve Block CFIndex hitIndex = hitGlyphStart + (hitGlyphEnd - hitGlyphStart) * (m_run.ltr() ? x / adjustedAdvance : 1 - x / adjustedAdvance); 124643ca7872b450ea4efacab6188849e5aac2ba161Steve Block int stringLength = complexTextRun.stringLength(); 125643ca7872b450ea4efacab6188849e5aac2ba161Steve Block TextBreakIterator* cursorPositionIterator = cursorMovementIterator(complexTextRun.characters(), stringLength); 1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int clusterStart; 1275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (isTextBreak(cursorPositionIterator, hitIndex)) 1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project clusterStart = hitIndex; 1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else { 1305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian clusterStart = textBreakPreceding(cursorPositionIterator, hitIndex); 1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (clusterStart == TextBreakDone) 1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project clusterStart = 0; 1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!includePartialGlyphs) 136643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return complexTextRun.stringLocation() + clusterStart; 1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian int clusterEnd = textBreakFollowing(cursorPositionIterator, hitIndex); 1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (clusterEnd == TextBreakDone) 1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project clusterEnd = stringLength; 1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 142643ca7872b450ea4efacab6188849e5aac2ba161Steve Block CGFloat clusterWidth; 143643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // FIXME: The search stops at the boundaries of complexTextRun. In theory, it should go on into neighboring ComplexTextRuns 1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // derived from the same CTLine. In practice, we do not expect there to be more than one CTRun in a CTLine, as no 1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // reordering and on font fallback should occur within a CTLine. 1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (clusterEnd - clusterStart > 1) { 147643ca7872b450ea4efacab6188849e5aac2ba161Steve Block clusterWidth = adjustedAdvance; 1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int firstGlyphBeforeCluster = j - 1; 149643ca7872b450ea4efacab6188849e5aac2ba161Steve Block while (firstGlyphBeforeCluster >= 0 && complexTextRun.indexAt(firstGlyphBeforeCluster) >= clusterStart && complexTextRun.indexAt(firstGlyphBeforeCluster) < clusterEnd) { 1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGFloat width = m_adjustedAdvances[offsetIntoAdjustedGlyphs + firstGlyphBeforeCluster].width; 1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project clusterWidth += width; 1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project x += width; 1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project firstGlyphBeforeCluster--; 1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned firstGlyphAfterCluster = j + 1; 156643ca7872b450ea4efacab6188849e5aac2ba161Steve Block while (firstGlyphAfterCluster < complexTextRun.glyphCount() && complexTextRun.indexAt(firstGlyphAfterCluster) >= clusterStart && complexTextRun.indexAt(firstGlyphAfterCluster) < clusterEnd) { 1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project clusterWidth += m_adjustedAdvances[offsetIntoAdjustedGlyphs + firstGlyphAfterCluster].width; 1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project firstGlyphAfterCluster++; 1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 160643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } else { 161643ca7872b450ea4efacab6188849e5aac2ba161Steve Block clusterWidth = adjustedAdvance / (hitGlyphEnd - hitGlyphStart); 162643ca7872b450ea4efacab6188849e5aac2ba161Steve Block x -= clusterWidth * (m_run.ltr() ? hitIndex - hitGlyphStart : hitGlyphEnd - hitIndex - 1); 1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (x <= clusterWidth / 2) 165643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return complexTextRun.stringLocation() + (m_run.ltr() ? clusterStart : clusterEnd); 1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 167643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return complexTextRun.stringLocation() + (m_run.ltr() ? clusterEnd : clusterStart); 1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project x -= adjustedAdvance; 1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 171643ca7872b450ea4efacab6188849e5aac2ba161Steve Block offsetIntoAdjustedGlyphs += complexTextRun.glyphCount(); 1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT_NOT_REACHED(); 1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 178643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockvoid ComplexTextController::collectComplexTextRuns() 1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_end) 1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // We break up glyph run generation for the string by FontData and (if needed) the use of small caps. 1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const UChar* cp = m_run.characters(); 1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 186bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if (m_font.isSmallCaps()) 1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_smallCapsBuffer.resize(m_end); 1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned indexOfFontTransition = m_run.rtl() ? m_end - 1 : 0; 1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const UChar* curr = m_run.rtl() ? cp + m_end - 1 : cp; 1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const UChar* end = m_run.rtl() ? cp - 1 : cp + m_end; 1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project GlyphData glyphData; 1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project GlyphData nextGlyphData; 1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool isSurrogate = U16_IS_SURROGATE(*curr); 1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isSurrogate) { 1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_run.ltr()) { 1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!U16_IS_SURROGATE_LEAD(curr[0]) || curr + 1 == end || !U16_IS_TRAIL(curr[1])) 2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project nextGlyphData = m_font.glyphDataForCharacter(U16_GET_SUPPLEMENTARY(curr[0], curr[1]), false); 2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!U16_IS_TRAIL(curr[0]) || curr -1 == end || !U16_IS_SURROGATE_LEAD(curr[-1])) 2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project nextGlyphData = m_font.glyphDataForCharacter(U16_GET_SUPPLEMENTARY(curr[-1], curr[0]), false); 2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project nextGlyphData = m_font.glyphDataForCharacter(*curr, false); 2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UChar newC = 0; 2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool isSmallCaps; 2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool nextIsSmallCaps = !isSurrogate && m_font.isSmallCaps() && !(U_GET_GC_MASK(*curr) & U_GC_M_MASK) && (newC = u_toupper(*curr)) != *curr; 2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (nextIsSmallCaps) 2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_smallCapsBuffer[curr - cp] = newC; 2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (true) { 2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project curr = m_run.rtl() ? curr - (isSurrogate ? 2 : 1) : curr + (isSurrogate ? 2 : 1); 2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (curr == end) 2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project glyphData = nextGlyphData; 2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project isSmallCaps = nextIsSmallCaps; 2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int index = curr - cp; 2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project isSurrogate = U16_IS_SURROGATE(*curr); 2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UChar c = *curr; 2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool forceSmallCaps = !isSurrogate && isSmallCaps && (U_GET_GC_MASK(c) & U_GC_M_MASK); 2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (isSurrogate) { 2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_run.ltr()) { 2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!U16_IS_SURROGATE_LEAD(curr[0]) || curr + 1 == end || !U16_IS_TRAIL(curr[1])) 2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project nextGlyphData = m_font.glyphDataForCharacter(U16_GET_SUPPLEMENTARY(curr[0], curr[1]), false); 2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!U16_IS_TRAIL(curr[0]) || curr -1 == end || !U16_IS_SURROGATE_LEAD(curr[-1])) 2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project nextGlyphData = m_font.glyphDataForCharacter(U16_GET_SUPPLEMENTARY(curr[-1], curr[0]), false); 2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 240f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch nextGlyphData = m_font.glyphDataForCharacter(*curr, false, forceSmallCaps ? SmallCapsVariant : AutoVariant); 2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!isSurrogate && m_font.isSmallCaps()) { 2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project nextIsSmallCaps = forceSmallCaps || (newC = u_toupper(c)) != c; 2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (nextIsSmallCaps) 2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_smallCapsBuffer[index] = forceSmallCaps ? c : newC; 2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (nextGlyphData.fontData != glyphData.fontData || nextIsSmallCaps != isSmallCaps || !nextGlyphData.glyph != !glyphData.glyph) { 24906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen int itemStart = m_run.rtl() ? index + 1 : static_cast<int>(indexOfFontTransition); 2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int itemLength = m_run.rtl() ? indexOfFontTransition - index : index - indexOfFontTransition; 251643ca7872b450ea4efacab6188849e5aac2ba161Steve Block collectComplexTextRunsForCharacters((isSmallCaps ? m_smallCapsBuffer.data() : cp) + itemStart, itemLength, itemStart, glyphData.glyph ? glyphData.fontData : 0); 2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project indexOfFontTransition = index; 2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 256bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen int itemLength = m_run.rtl() ? indexOfFontTransition + 1 : m_end - indexOfFontTransition; 2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (itemLength) { 2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int itemStart = m_run.rtl() ? 0 : indexOfFontTransition; 259643ca7872b450ea4efacab6188849e5aac2ba161Steve Block collectComplexTextRunsForCharacters((nextIsSmallCaps ? m_smallCapsBuffer.data() : cp) + itemStart, itemLength, itemStart, nextGlyphData.glyph ? nextGlyphData.fontData : 0); 2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 263d0825bca7fe65beaee391d30da42e937db621564Steve Block#if USE(CORE_TEXT) && USE(ATSUI) 264d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic inline bool shouldUseATSUIAPI() 265d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 266d0825bca7fe65beaee391d30da42e937db621564Steve Block enum TypeRenderingAPIToUse { UnInitialized, UseATSUI, UseCoreText }; 2676c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen static TypeRenderingAPIToUse apiToUse = UnInitialized; 268d0825bca7fe65beaee391d30da42e937db621564Steve Block 269d0825bca7fe65beaee391d30da42e937db621564Steve Block if (UNLIKELY(apiToUse == UnInitialized)) { 270d0825bca7fe65beaee391d30da42e937db621564Steve Block if (&CTGetCoreTextVersion != 0 && CTGetCoreTextVersion() >= kCTVersionNumber10_6) 271d0825bca7fe65beaee391d30da42e937db621564Steve Block apiToUse = UseCoreText; 272d0825bca7fe65beaee391d30da42e937db621564Steve Block else 273d0825bca7fe65beaee391d30da42e937db621564Steve Block apiToUse = UseATSUI; 274d0825bca7fe65beaee391d30da42e937db621564Steve Block } 275d0825bca7fe65beaee391d30da42e937db621564Steve Block 276d0825bca7fe65beaee391d30da42e937db621564Steve Block return apiToUse == UseATSUI; 277d0825bca7fe65beaee391d30da42e937db621564Steve Block} 278d0825bca7fe65beaee391d30da42e937db621564Steve Block#endif 279d0825bca7fe65beaee391d30da42e937db621564Steve Block 280d0825bca7fe65beaee391d30da42e937db621564Steve BlockCFIndex ComplexTextController::ComplexTextRun::indexAt(size_t i) const 281d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 282d0825bca7fe65beaee391d30da42e937db621564Steve Block#if USE(CORE_TEXT) && USE(ATSUI) 283d0825bca7fe65beaee391d30da42e937db621564Steve Block return shouldUseATSUIAPI() ? m_atsuiIndices[i] : m_coreTextIndices[i]; 284d0825bca7fe65beaee391d30da42e937db621564Steve Block#elif USE(ATSUI) 285d0825bca7fe65beaee391d30da42e937db621564Steve Block return m_atsuiIndices[i]; 286d0825bca7fe65beaee391d30da42e937db621564Steve Block#elif USE(CORE_TEXT) 287d0825bca7fe65beaee391d30da42e937db621564Steve Block return m_coreTextIndices[i]; 288d0825bca7fe65beaee391d30da42e937db621564Steve Block#endif 289d0825bca7fe65beaee391d30da42e937db621564Steve Block} 290d0825bca7fe65beaee391d30da42e937db621564Steve Block 291d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp, unsigned length, unsigned stringLocation, const SimpleFontData* fontData) 292d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 293d0825bca7fe65beaee391d30da42e937db621564Steve Block#if USE(CORE_TEXT) && USE(ATSUI) 294d0825bca7fe65beaee391d30da42e937db621564Steve Block if (shouldUseATSUIAPI()) 295d0825bca7fe65beaee391d30da42e937db621564Steve Block return collectComplexTextRunsForCharactersATSUI(cp, length, stringLocation, fontData); 296d0825bca7fe65beaee391d30da42e937db621564Steve Block return collectComplexTextRunsForCharactersCoreText(cp, length, stringLocation, fontData); 297d0825bca7fe65beaee391d30da42e937db621564Steve Block#elif USE(ATSUI) 298d0825bca7fe65beaee391d30da42e937db621564Steve Block return collectComplexTextRunsForCharactersATSUI(cp, length, stringLocation, fontData); 299d0825bca7fe65beaee391d30da42e937db621564Steve Block#elif USE(CORE_TEXT) 300d0825bca7fe65beaee391d30da42e937db621564Steve Block return collectComplexTextRunsForCharactersCoreText(cp, length, stringLocation, fontData); 301d0825bca7fe65beaee391d30da42e937db621564Steve Block#endif 302d0825bca7fe65beaee391d30da42e937db621564Steve Block} 303d0825bca7fe65beaee391d30da42e937db621564Steve Block 304d0825bca7fe65beaee391d30da42e937db621564Steve BlockComplexTextController::ComplexTextRun::ComplexTextRun(const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr) 305d0825bca7fe65beaee391d30da42e937db621564Steve Block : m_fontData(fontData) 306d0825bca7fe65beaee391d30da42e937db621564Steve Block , m_characters(characters) 307d0825bca7fe65beaee391d30da42e937db621564Steve Block , m_stringLocation(stringLocation) 308d0825bca7fe65beaee391d30da42e937db621564Steve Block , m_stringLength(stringLength) 3092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block , m_indexEnd(stringLength) 3108a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block , m_isMonotonic(true) 311d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 312d0825bca7fe65beaee391d30da42e937db621564Steve Block#if USE(CORE_TEXT) && USE(ATSUI) 313d0825bca7fe65beaee391d30da42e937db621564Steve Block shouldUseATSUIAPI() ? createTextRunFromFontDataATSUI(ltr) : createTextRunFromFontDataCoreText(ltr); 314d0825bca7fe65beaee391d30da42e937db621564Steve Block#elif USE(ATSUI) 315d0825bca7fe65beaee391d30da42e937db621564Steve Block createTextRunFromFontDataATSUI(ltr); 316d0825bca7fe65beaee391d30da42e937db621564Steve Block#elif USE(CORE_TEXT) 317d0825bca7fe65beaee391d30da42e937db621564Steve Block createTextRunFromFontDataCoreText(ltr); 318d0825bca7fe65beaee391d30da42e937db621564Steve Block#endif 319d0825bca7fe65beaee391d30da42e937db621564Steve Block} 320d0825bca7fe65beaee391d30da42e937db621564Steve Block 3218a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Blockvoid ComplexTextController::ComplexTextRun::setIsNonMonotonic() 3228a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block{ 3238a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block ASSERT(m_isMonotonic); 3248a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block m_isMonotonic = false; 3258a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 3268a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block Vector<bool, 64> mappedIndices(m_stringLength); 3278a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block for (size_t i = 0; i < m_glyphCount; ++i) { 3288a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block ASSERT(indexAt(i) < static_cast<CFIndex>(m_stringLength)); 3298a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block mappedIndices[indexAt(i)] = true; 3308a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block } 3318a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 3328a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block m_glyphEndOffsets.grow(m_glyphCount); 3338a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block for (size_t i = 0; i < m_glyphCount; ++i) { 3342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block CFIndex nextMappedIndex = m_indexEnd; 3358a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block for (size_t j = indexAt(i) + 1; j < m_stringLength; ++j) { 3368a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block if (mappedIndices[j]) { 3378a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block nextMappedIndex = j; 3388a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block break; 3398a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block } 3408a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block } 3418a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block m_glyphEndOffsets[i] = nextMappedIndex; 3428a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block } 3438a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block} 3448a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 345643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockvoid ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer) 3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (static_cast<int>(offset) > m_end) 3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project offset = m_end; 3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (offset <= m_currentCharacter) 3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_currentCharacter = offset; 3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 355643ca7872b450ea4efacab6188849e5aac2ba161Steve Block size_t runCount = m_complexTextRuns.size(); 3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool ltr = m_run.ltr(); 3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned k = ltr ? m_numGlyphsSoFar : m_adjustedGlyphs.size() - 1 - m_numGlyphsSoFar; 3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (m_currentRun < runCount) { 361643ca7872b450ea4efacab6188849e5aac2ba161Steve Block const ComplexTextRun& complexTextRun = *m_complexTextRuns[ltr ? m_currentRun : runCount - 1 - m_currentRun]; 362643ca7872b450ea4efacab6188849e5aac2ba161Steve Block size_t glyphCount = complexTextRun.glyphCount(); 3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned g = ltr ? m_glyphInCurrentRun : glyphCount - 1 - m_glyphInCurrentRun; 3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (m_glyphInCurrentRun < glyphCount) { 365643ca7872b450ea4efacab6188849e5aac2ba161Steve Block unsigned glyphStartOffset = complexTextRun.indexAt(g); 366643ca7872b450ea4efacab6188849e5aac2ba161Steve Block unsigned glyphEndOffset; 3678a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block if (complexTextRun.isMonotonic()) { 3688a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block if (ltr) 3692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block glyphEndOffset = max<unsigned>(glyphStartOffset, static_cast<unsigned>(g + 1 < glyphCount ? complexTextRun.indexAt(g + 1) : complexTextRun.indexEnd())); 3708a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block else 3712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block glyphEndOffset = max<unsigned>(glyphStartOffset, static_cast<unsigned>(g > 0 ? complexTextRun.indexAt(g - 1) : complexTextRun.indexEnd())); 3728a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block } else 3738a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block glyphEndOffset = complexTextRun.endOffsetAt(g); 374643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CGSize adjustedAdvance = m_adjustedAdvances[k]; 376643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 377643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (glyphStartOffset + complexTextRun.stringLocation() >= m_currentCharacter) 378643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return; 379643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 380643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (glyphBuffer && !m_characterInCurrentGlyph) 381643ca7872b450ea4efacab6188849e5aac2ba161Steve Block glyphBuffer->add(m_adjustedGlyphs[k], complexTextRun.fontData(), adjustedAdvance); 382643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 383643ca7872b450ea4efacab6188849e5aac2ba161Steve Block unsigned oldCharacterInCurrentGlyph = m_characterInCurrentGlyph; 384643ca7872b450ea4efacab6188849e5aac2ba161Steve Block m_characterInCurrentGlyph = min(m_currentCharacter - complexTextRun.stringLocation(), glyphEndOffset) - glyphStartOffset; 3852fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // FIXME: Instead of dividing the glyph's advance equally between the characters, this 386643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // could use the glyph's "ligature carets". However, there is no Core Text API to get the 387643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // ligature carets. 388dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (glyphStartOffset == glyphEndOffset) { 389dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // When there are multiple glyphs per character we need to advance by the full width of the glyph. 390dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block ASSERT(m_characterInCurrentGlyph == oldCharacterInCurrentGlyph); 391dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_runWidthSoFar += adjustedAdvance.width; 392dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } else 393dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_runWidthSoFar += adjustedAdvance.width * (m_characterInCurrentGlyph - oldCharacterInCurrentGlyph) / (glyphEndOffset - glyphStartOffset); 394643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 395643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (glyphEndOffset + complexTextRun.stringLocation() > m_currentCharacter) 396643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return; 397643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_numGlyphsSoFar++; 3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_glyphInCurrentRun++; 400643ca7872b450ea4efacab6188849e5aac2ba161Steve Block m_characterInCurrentGlyph = 0; 4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (ltr) { 4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project g++; 4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project k++; 4048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 4058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project g--; 4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project k--; 4078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_currentRun++; 4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_glyphInCurrentRun = 0; 4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 414643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockvoid ComplexTextController::adjustGlyphsAndAdvances() 4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 41681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch CGFloat widthSinceLastCommit = 0; 417643ca7872b450ea4efacab6188849e5aac2ba161Steve Block size_t runCount = m_complexTextRuns.size(); 4182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block bool hasExtraSpacing = (m_font.letterSpacing() || m_font.wordSpacing() || m_expansion) && !m_run.spacingDisabled(); 4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (size_t r = 0; r < runCount; ++r) { 4208a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block ComplexTextRun& complexTextRun = *m_complexTextRuns[r]; 421643ca7872b450ea4efacab6188849e5aac2ba161Steve Block unsigned glyphCount = complexTextRun.glyphCount(); 422643ca7872b450ea4efacab6188849e5aac2ba161Steve Block const SimpleFontData* fontData = complexTextRun.fontData(); 4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 424643ca7872b450ea4efacab6188849e5aac2ba161Steve Block const CGGlyph* glyphs = complexTextRun.glyphs(); 425643ca7872b450ea4efacab6188849e5aac2ba161Steve Block const CGSize* advances = complexTextRun.advances(); 4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool lastRun = r + 1 == runCount; 4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool roundsAdvances = !m_font.isPrinterFont() && fontData->platformData().roundsGlyphAdvances(); 42981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch const UChar* cp = complexTextRun.characters(); 430dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block CGPoint glyphOrigin = CGPointZero; 4318a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block CFIndex lastCharacterIndex = m_run.ltr() ? numeric_limits<CFIndex>::min() : numeric_limits<CFIndex>::max(); 4328a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block bool isMonotonic = true; 4338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (unsigned i = 0; i < glyphCount; i++) { 435643ca7872b450ea4efacab6188849e5aac2ba161Steve Block CFIndex characterIndex = complexTextRun.indexAt(i); 4368a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block if (m_run.ltr()) { 4378a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block if (characterIndex < lastCharacterIndex) 4388a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block isMonotonic = false; 4398a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block } else { 4408a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block if (characterIndex > lastCharacterIndex) 4418a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block isMonotonic = false; 4428a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block } 4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UChar ch = *(cp + characterIndex); 4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool lastGlyph = lastRun && i + 1 == glyphCount; 4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UChar nextCh; 4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (lastGlyph) 4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project nextCh = ' '; 4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else if (i + 1 < glyphCount) 449643ca7872b450ea4efacab6188849e5aac2ba161Steve Block nextCh = *(cp + complexTextRun.indexAt(i + 1)); 4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 451643ca7872b450ea4efacab6188849e5aac2ba161Steve Block nextCh = *(m_complexTextRuns[r + 1]->characters() + m_complexTextRuns[r + 1]->indexAt(0)); 4528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool treatAsSpace = Font::treatAsSpace(ch); 4545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian CGGlyph glyph = treatAsSpace ? fontData->spaceGlyph() : glyphs[i]; 4555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian CGSize advance = treatAsSpace ? CGSizeMake(fontData->spaceWidth(), advances[i].height) : advances[i]; 4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (ch == '\t' && m_run.allowTabs()) { 458967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch float tabWidth = m_font.tabWidth(*fontData); 45981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch advance.width = tabWidth - fmodf(m_run.xPos() + m_totalWidth + widthSinceLastCommit, tabWidth); 460f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } else if (ch == zeroWidthSpace || (Font::treatAsZeroWidthSpace(ch) && !treatAsSpace)) { 4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project advance.width = 0; 4625f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian glyph = fontData->spaceGlyph(); 4638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float roundedAdvanceWidth = roundf(advance.width); 4668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (roundsAdvances) 4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project advance.width = roundedAdvanceWidth; 4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian advance.width += fontData->syntheticBoldOffset(); 4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (hasExtraSpacing) { 4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If we're a glyph with an advance, go ahead and add in letter-spacing. 4738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // That way we weed out zero width lurkers. This behavior matches the fast text code path. 4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (advance.width && m_font.letterSpacing()) 4758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project advance.width += m_font.letterSpacing(); 4768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Handle justification and word-spacing. 4782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (treatAsSpace || Font::isCJKIdeographOrSymbol(ch)) { 4792fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // Distribute the run's total expansion evenly over all expansion opportunities in the run. 4802bde8e466a4451c7319e3a072d118917957d6554Steve Block if (m_expansion) { 4812fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (!treatAsSpace && !m_afterExpansion) { 4822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // Take the expansion opportunity before this ideograph. 4832fc2651226baac27029e38c9d6ef883fa32084dbSteve Block m_expansion -= m_expansionPerOpportunity; 48481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch m_totalWidth += m_expansionPerOpportunity; 4852bde8e466a4451c7319e3a072d118917957d6554Steve Block if (m_adjustedAdvances.isEmpty()) 4862bde8e466a4451c7319e3a072d118917957d6554Steve Block m_leadingExpansion = m_expansionPerOpportunity; 4872bde8e466a4451c7319e3a072d118917957d6554Steve Block else 4882bde8e466a4451c7319e3a072d118917957d6554Steve Block m_adjustedAdvances.last().width += m_expansionPerOpportunity; 4892bde8e466a4451c7319e3a072d118917957d6554Steve Block } 4902bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!lastGlyph || m_run.allowsTrailingExpansion()) { 4912bde8e466a4451c7319e3a072d118917957d6554Steve Block m_expansion -= m_expansionPerOpportunity; 4922bde8e466a4451c7319e3a072d118917957d6554Steve Block advance.width += m_expansionPerOpportunity; 4932bde8e466a4451c7319e3a072d118917957d6554Steve Block m_afterExpansion = true; 4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } else 4962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block m_afterExpansion = false; 4978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Account for word-spacing. 4992fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (treatAsSpace && characterIndex > 0 && !Font::treatAsSpace(*m_run.data(characterIndex - 1)) && m_font.wordSpacing()) 5008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project advance.width += m_font.wordSpacing(); 5012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } else 5022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block m_afterExpansion = false; 5038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 50581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch widthSinceLastCommit += advance.width; 5068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 507f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // FIXME: Combining marks should receive a text emphasis mark if they are combine with a space. 508f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (m_forTextEmphasis && (!Font::canReceiveTextEmphasis(ch) || (U_GET_GC_MASK(ch) & U_GC_M_MASK))) 509f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch glyph = 0; 510f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 5118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project advance.height *= -1; 5128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_adjustedAdvances.append(advance); 5138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_adjustedGlyphs.append(glyph); 514dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 51521939df44de1705786c545cd1bf519d47250322dBen Murdoch FloatRect glyphBounds = fontData->boundsForGlyph(glyph); 51621939df44de1705786c545cd1bf519d47250322dBen Murdoch glyphBounds.move(glyphOrigin.x, glyphOrigin.y); 51721939df44de1705786c545cd1bf519d47250322dBen Murdoch m_minGlyphBoundingBoxX = min(m_minGlyphBoundingBoxX, glyphBounds.x()); 5182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block m_maxGlyphBoundingBoxX = max(m_maxGlyphBoundingBoxX, glyphBounds.maxX()); 51921939df44de1705786c545cd1bf519d47250322dBen Murdoch m_minGlyphBoundingBoxY = min(m_minGlyphBoundingBoxY, glyphBounds.y()); 5202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, glyphBounds.maxY()); 521dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block glyphOrigin.x += advance.width; 522dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block glyphOrigin.y += advance.height; 523dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 5248a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block lastCharacterIndex = characterIndex; 5258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5268a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block if (!isMonotonic) 5278a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block complexTextRun.setIsNonMonotonic(); 5288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 52981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch m_totalWidth += widthSinceLastCommit; 5308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace WebCore 533