|
Lines 175-235
unsigned ComplexTextController::offsetForPosition(float h, bool includePartialGl
a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp_sec1
|
| 175 |
if (h < 0) |
175 |
if (h < 0) |
| 176 |
return m_run.ltr() ? 0 : m_end; |
176 |
return m_run.ltr() ? 0 : m_end; |
| 177 |
|
177 |
|
| 178 |
CGFloat x = h; |
178 |
float x = h; |
| 179 |
|
179 |
|
| 180 |
size_t runCount = m_complexTextRuns.size(); |
180 |
size_t runCount = m_complexTextRuns.size(); |
| 181 |
size_t offsetIntoAdjustedGlyphs = 0; |
181 |
unsigned offsetIntoAdjustedGlyphs = 0; |
| 182 |
|
182 |
|
| 183 |
for (size_t r = 0; r < runCount; ++r) { |
183 |
for (size_t r = 0; r < runCount; ++r) { |
| 184 |
const ComplexTextRun& complexTextRun = *m_complexTextRuns[r]; |
184 |
const ComplexTextRun& complexTextRun = *m_complexTextRuns[r]; |
| 185 |
for (unsigned j = 0; j < complexTextRun.glyphCount(); ++j) { |
185 |
for (unsigned j = 0; j < complexTextRun.glyphCount(); ++j) { |
| 186 |
size_t index = offsetIntoAdjustedGlyphs + j; |
186 |
unsigned index = offsetIntoAdjustedGlyphs + j; |
| 187 |
CGFloat adjustedAdvance = m_adjustedBaseAdvances[index].width; |
187 |
float adjustedAdvance = m_adjustedBaseAdvances[index].width(); |
| 188 |
if (x < adjustedAdvance) { |
188 |
if (x < adjustedAdvance) { |
| 189 |
CFIndex hitGlyphStart = complexTextRun.indexAt(j); |
189 |
unsigned hitGlyphStart = complexTextRun.indexAt(j); |
| 190 |
CFIndex hitGlyphEnd; |
190 |
unsigned hitGlyphEnd; |
| 191 |
if (m_run.ltr()) |
191 |
if (m_run.ltr()) |
| 192 |
hitGlyphEnd = std::max<CFIndex>(hitGlyphStart, j + 1 < complexTextRun.glyphCount() ? complexTextRun.indexAt(j + 1) : static_cast<CFIndex>(complexTextRun.indexEnd())); |
192 |
hitGlyphEnd = std::max(hitGlyphStart, j + 1 < complexTextRun.glyphCount() ? complexTextRun.indexAt(j + 1) : complexTextRun.indexEnd()); |
| 193 |
else |
193 |
else |
| 194 |
hitGlyphEnd = std::max<CFIndex>(hitGlyphStart, j > 0 ? complexTextRun.indexAt(j - 1) : static_cast<CFIndex>(complexTextRun.indexEnd())); |
194 |
hitGlyphEnd = std::max(hitGlyphStart, j > 0 ? complexTextRun.indexAt(j - 1) : complexTextRun.indexEnd()); |
| 195 |
|
195 |
|
| 196 |
// FIXME: Instead of dividing the glyph's advance equally between the characters, this |
196 |
// FIXME: Instead of dividing the glyph's advance equally between the characters, this |
| 197 |
// could use the glyph's "ligature carets". This is available in CoreText via CTFontGetLigatureCaretPositions(). |
197 |
// could use the glyph's "ligature carets". This is available in CoreText via CTFontGetLigatureCaretPositions(). |
| 198 |
CFIndex hitIndex = hitGlyphStart + (hitGlyphEnd - hitGlyphStart) * (m_run.ltr() ? x / adjustedAdvance : 1 - x / adjustedAdvance); |
198 |
unsigned hitIndex = hitGlyphStart + (hitGlyphEnd - hitGlyphStart) * (m_run.ltr() ? x / adjustedAdvance : 1 - x / adjustedAdvance); |
| 199 |
int stringLength = complexTextRun.stringLength(); |
199 |
unsigned stringLength = complexTextRun.stringLength(); |
| 200 |
UBreakIterator* cursorPositionIterator = cursorMovementIterator(StringView(complexTextRun.characters(), stringLength)); |
200 |
UBreakIterator* cursorPositionIterator = cursorMovementIterator(StringView(complexTextRun.characters(), stringLength)); |
| 201 |
int clusterStart; |
201 |
unsigned clusterStart; |
| 202 |
if (ubrk_isBoundary(cursorPositionIterator, hitIndex)) |
202 |
if (ubrk_isBoundary(cursorPositionIterator, hitIndex)) |
| 203 |
clusterStart = hitIndex; |
203 |
clusterStart = hitIndex; |
| 204 |
else { |
204 |
else { |
| 205 |
clusterStart = ubrk_preceding(cursorPositionIterator, hitIndex); |
205 |
int preceeding = ubrk_preceding(cursorPositionIterator, hitIndex); |
| 206 |
if (clusterStart == UBRK_DONE) |
206 |
clusterStart = preceeding == UBRK_DONE ? 0 : preceeding; |
| 207 |
clusterStart = 0; |
|
|
| 208 |
} |
207 |
} |
| 209 |
|
208 |
|
| 210 |
if (!includePartialGlyphs) |
209 |
if (!includePartialGlyphs) |
| 211 |
return complexTextRun.stringLocation() + clusterStart; |
210 |
return complexTextRun.stringLocation() + clusterStart; |
| 212 |
|
211 |
|
| 213 |
int clusterEnd = ubrk_following(cursorPositionIterator, hitIndex); |
212 |
int following = ubrk_following(cursorPositionIterator, hitIndex); |
| 214 |
if (clusterEnd == UBRK_DONE) |
213 |
unsigned clusterEnd = following == UBRK_DONE ? stringLength : following; |
| 215 |
clusterEnd = stringLength; |
|
|
| 216 |
|
214 |
|
| 217 |
CGFloat clusterWidth; |
215 |
float clusterWidth; |
| 218 |
// FIXME: The search stops at the boundaries of complexTextRun. In theory, it should go on into neighboring ComplexTextRuns |
216 |
// FIXME: The search stops at the boundaries of complexTextRun. In theory, it should go on into neighboring ComplexTextRuns |
| 219 |
// derived from the same CTLine. In practice, we do not expect there to be more than one CTRun in a CTLine, as no |
217 |
// derived from the same CTLine. In practice, we do not expect there to be more than one CTRun in a CTLine, as no |
| 220 |
// reordering and no font fallback should occur within a CTLine. |
218 |
// reordering and no font fallback should occur within a CTLine. |
| 221 |
if (clusterEnd - clusterStart > 1) { |
219 |
if (clusterEnd - clusterStart > 1) { |
| 222 |
clusterWidth = adjustedAdvance; |
220 |
clusterWidth = adjustedAdvance; |
| 223 |
int firstGlyphBeforeCluster = j - 1; |
221 |
if (j) { |
| 224 |
while (firstGlyphBeforeCluster >= 0 && complexTextRun.indexAt(firstGlyphBeforeCluster) >= clusterStart && complexTextRun.indexAt(firstGlyphBeforeCluster) < clusterEnd) { |
222 |
unsigned firstGlyphBeforeCluster = j - 1; |
| 225 |
CGFloat width = m_adjustedBaseAdvances[offsetIntoAdjustedGlyphs + firstGlyphBeforeCluster].width; |
223 |
while (complexTextRun.indexAt(firstGlyphBeforeCluster) >= clusterStart && complexTextRun.indexAt(firstGlyphBeforeCluster) < clusterEnd) { |
| 226 |
clusterWidth += width; |
224 |
float width = m_adjustedBaseAdvances[offsetIntoAdjustedGlyphs + firstGlyphBeforeCluster].width(); |
| 227 |
x += width; |
225 |
clusterWidth += width; |
| 228 |
firstGlyphBeforeCluster--; |
226 |
x += width; |
|
|
227 |
if (!firstGlyphBeforeCluster) |
| 228 |
break; |
| 229 |
firstGlyphBeforeCluster--; |
| 230 |
} |
| 229 |
} |
231 |
} |
| 230 |
unsigned firstGlyphAfterCluster = j + 1; |
232 |
unsigned firstGlyphAfterCluster = j + 1; |
| 231 |
while (firstGlyphAfterCluster < complexTextRun.glyphCount() && complexTextRun.indexAt(firstGlyphAfterCluster) >= clusterStart && complexTextRun.indexAt(firstGlyphAfterCluster) < clusterEnd) { |
233 |
while (firstGlyphAfterCluster < complexTextRun.glyphCount() && complexTextRun.indexAt(firstGlyphAfterCluster) >= clusterStart && complexTextRun.indexAt(firstGlyphAfterCluster) < clusterEnd) { |
| 232 |
clusterWidth += m_adjustedBaseAdvances[offsetIntoAdjustedGlyphs + firstGlyphAfterCluster].width; |
234 |
clusterWidth += m_adjustedBaseAdvances[offsetIntoAdjustedGlyphs + firstGlyphAfterCluster].width(); |
| 233 |
firstGlyphAfterCluster++; |
235 |
firstGlyphAfterCluster++; |
| 234 |
} |
236 |
} |
| 235 |
} else { |
237 |
} else { |
|
Lines 238-245
unsigned ComplexTextController::offsetForPosition(float h, bool includePartialGl
a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp_sec2
|
| 238 |
} |
240 |
} |
| 239 |
if (x <= clusterWidth / 2) |
241 |
if (x <= clusterWidth / 2) |
| 240 |
return complexTextRun.stringLocation() + (m_run.ltr() ? clusterStart : clusterEnd); |
242 |
return complexTextRun.stringLocation() + (m_run.ltr() ? clusterStart : clusterEnd); |
| 241 |
else |
243 |
return complexTextRun.stringLocation() + (m_run.ltr() ? clusterEnd : clusterStart); |
| 242 |
return complexTextRun.stringLocation() + (m_run.ltr() ? clusterEnd : clusterStart); |
|
|
| 243 |
} |
244 |
} |
| 244 |
x -= adjustedAdvance; |
245 |
x -= adjustedAdvance; |
| 245 |
} |
246 |
} |
|
Lines 270-278
static bool advanceByCombiningCharacterSequence(const UChar*& iterator, const UC
a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp_sec3
|
| 270 |
bool sawJoiner = false; |
271 |
bool sawJoiner = false; |
| 271 |
while (iterator < end) { |
272 |
while (iterator < end) { |
| 272 |
UChar32 nextCharacter; |
273 |
UChar32 nextCharacter; |
| 273 |
int markLength = 0; |
274 |
unsigned markLength = 0; |
| 274 |
bool shouldContinue = false; |
275 |
bool shouldContinue = false; |
| 275 |
U16_NEXT(iterator, markLength, end - iterator, nextCharacter); |
276 |
ASSERT(end >= iterator); |
|
|
277 |
U16_NEXT(iterator, markLength, static_cast<unsigned>(end - iterator), nextCharacter); |
| 276 |
|
278 |
|
| 277 |
if (isVariationSelector(nextCharacter) || isEmojiFitzpatrickModifier(nextCharacter)) |
279 |
if (isVariationSelector(nextCharacter) || isEmojiFitzpatrickModifier(nextCharacter)) |
| 278 |
shouldContinue = true; |
280 |
shouldContinue = true; |
|
Lines 453-459
void ComplexTextController::collectComplexTextRuns()
a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp_sec4
|
| 453 |
m_complexTextRuns.reverse(); |
455 |
m_complexTextRuns.reverse(); |
| 454 |
} |
456 |
} |
| 455 |
|
457 |
|
| 456 |
CFIndex ComplexTextController::ComplexTextRun::indexAt(size_t i) const |
458 |
unsigned ComplexTextController::ComplexTextRun::indexAt(unsigned i) const |
| 457 |
{ |
459 |
{ |
| 458 |
ASSERT(i < m_glyphCount); |
460 |
ASSERT(i < m_glyphCount); |
| 459 |
|
461 |
|
|
Lines 466-480
void ComplexTextController::ComplexTextRun::setIsNonMonotonic()
a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp_sec5
|
| 466 |
m_isMonotonic = false; |
468 |
m_isMonotonic = false; |
| 467 |
|
469 |
|
| 468 |
Vector<bool, 64> mappedIndices(m_stringLength, false); |
470 |
Vector<bool, 64> mappedIndices(m_stringLength, false); |
| 469 |
for (size_t i = 0; i < m_glyphCount; ++i) { |
471 |
for (unsigned i = 0; i < m_glyphCount; ++i) { |
| 470 |
ASSERT(indexAt(i) < static_cast<CFIndex>(m_stringLength)); |
472 |
ASSERT(indexAt(i) < m_stringLength); |
| 471 |
mappedIndices[indexAt(i)] = true; |
473 |
mappedIndices[indexAt(i)] = true; |
| 472 |
} |
474 |
} |
| 473 |
|
475 |
|
| 474 |
m_glyphEndOffsets.grow(m_glyphCount); |
476 |
m_glyphEndOffsets.grow(m_glyphCount); |
| 475 |
for (unsigned i = 0; i < m_glyphCount; ++i) { |
477 |
for (unsigned i = 0; i < m_glyphCount; ++i) { |
| 476 |
CFIndex nextMappedIndex = m_indexEnd; |
478 |
unsigned nextMappedIndex = m_indexEnd; |
| 477 |
for (size_t j = indexAt(i) + 1; j < m_stringLength; ++j) { |
479 |
for (unsigned j = indexAt(i) + 1; j < m_stringLength; ++j) { |
| 478 |
if (mappedIndices[j]) { |
480 |
if (mappedIndices[j]) { |
| 479 |
nextMappedIndex = j; |
481 |
nextMappedIndex = j; |
| 480 |
break; |
482 |
break; |
|
Lines 580-586
void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer, G
a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp_sec6
|
| 580 |
while (m_currentRun < runCount) { |
582 |
while (m_currentRun < runCount) { |
| 581 |
const ComplexTextRun& complexTextRun = *m_complexTextRuns[currentRunIndex]; |
583 |
const ComplexTextRun& complexTextRun = *m_complexTextRuns[currentRunIndex]; |
| 582 |
bool ltr = complexTextRun.isLTR(); |
584 |
bool ltr = complexTextRun.isLTR(); |
| 583 |
size_t glyphCount = complexTextRun.glyphCount(); |
585 |
unsigned glyphCount = complexTextRun.glyphCount(); |
| 584 |
unsigned glyphIndexIntoCurrentRun = ltr ? m_glyphInCurrentRun : glyphCount - 1 - m_glyphInCurrentRun; |
586 |
unsigned glyphIndexIntoCurrentRun = ltr ? m_glyphInCurrentRun : glyphCount - 1 - m_glyphInCurrentRun; |
| 585 |
unsigned glyphIndexIntoComplexTextController = indexOfLeftmostGlyphInCurrentRun + glyphIndexIntoCurrentRun; |
587 |
unsigned glyphIndexIntoComplexTextController = indexOfLeftmostGlyphInCurrentRun + glyphIndexIntoCurrentRun; |
| 586 |
if (fallbackFonts && &complexTextRun.font() != &m_font.primaryFont()) |
588 |
if (fallbackFonts && &complexTextRun.font() != &m_font.primaryFont()) |
|
Lines 590-630
void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer, G
a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp_sec7
|
| 590 |
// When leftmostGlyph is 0, it represents the first glyph to draw, taking into |
592 |
// When leftmostGlyph is 0, it represents the first glyph to draw, taking into |
| 591 |
// account the text direction. |
593 |
// account the text direction. |
| 592 |
if (!indexOfLeftmostGlyphInCurrentRun && glyphBuffer) |
594 |
if (!indexOfLeftmostGlyphInCurrentRun && glyphBuffer) |
| 593 |
glyphBuffer->setInitialAdvance(complexTextRun.initialAdvance()); |
595 |
glyphBuffer->setInitialAdvance(GlyphBufferAdvance(complexTextRun.initialAdvance().width(), complexTextRun.initialAdvance().height())); |
| 594 |
|
596 |
|
| 595 |
while (m_glyphInCurrentRun < glyphCount) { |
597 |
while (m_glyphInCurrentRun < glyphCount) { |
| 596 |
unsigned glyphStartOffset = complexTextRun.indexAt(glyphIndexIntoCurrentRun); |
598 |
unsigned glyphStartOffset = complexTextRun.indexAt(glyphIndexIntoCurrentRun); |
| 597 |
unsigned glyphEndOffset; |
599 |
unsigned glyphEndOffset; |
| 598 |
if (complexTextRun.isMonotonic()) { |
600 |
if (complexTextRun.isMonotonic()) { |
| 599 |
if (ltr) |
601 |
if (ltr) |
| 600 |
glyphEndOffset = std::max<unsigned>(glyphStartOffset, static_cast<unsigned>(glyphIndexIntoCurrentRun + 1 < glyphCount ? complexTextRun.indexAt(glyphIndexIntoCurrentRun + 1) : complexTextRun.indexEnd())); |
602 |
glyphEndOffset = std::max(glyphStartOffset, glyphIndexIntoCurrentRun + 1 < glyphCount ? complexTextRun.indexAt(glyphIndexIntoCurrentRun + 1) : complexTextRun.indexEnd()); |
| 601 |
else |
603 |
else |
| 602 |
glyphEndOffset = std::max<unsigned>(glyphStartOffset, static_cast<unsigned>(glyphIndexIntoCurrentRun > 0 ? complexTextRun.indexAt(glyphIndexIntoCurrentRun - 1) : complexTextRun.indexEnd())); |
604 |
glyphEndOffset = std::max(glyphStartOffset, glyphIndexIntoCurrentRun > 0 ? complexTextRun.indexAt(glyphIndexIntoCurrentRun - 1) : complexTextRun.indexEnd()); |
| 603 |
} else |
605 |
} else |
| 604 |
glyphEndOffset = complexTextRun.endOffsetAt(glyphIndexIntoCurrentRun); |
606 |
glyphEndOffset = complexTextRun.endOffsetAt(glyphIndexIntoCurrentRun); |
| 605 |
|
607 |
|
| 606 |
CGSize adjustedBaseAdvance = m_adjustedBaseAdvances[glyphIndexIntoComplexTextController]; |
608 |
FloatSize adjustedBaseAdvance = m_adjustedBaseAdvances[glyphIndexIntoComplexTextController]; |
| 607 |
|
609 |
|
| 608 |
if (glyphStartOffset + complexTextRun.stringLocation() >= m_currentCharacter) |
610 |
if (glyphStartOffset + complexTextRun.stringLocation() >= m_currentCharacter) |
| 609 |
return; |
611 |
return; |
| 610 |
|
612 |
|
| 611 |
if (glyphBuffer && !m_characterInCurrentGlyph) { |
613 |
if (glyphBuffer && !m_characterInCurrentGlyph) { |
| 612 |
auto currentGlyphOrigin = glyphOrigin(glyphIndexIntoComplexTextController); |
614 |
auto currentGlyphOrigin = glyphOrigin(glyphIndexIntoComplexTextController); |
| 613 |
GlyphBufferAdvance paintAdvance = adjustedBaseAdvance; |
615 |
GlyphBufferAdvance paintAdvance(adjustedBaseAdvance); |
| 614 |
if (!glyphIndexIntoCurrentRun) { |
616 |
if (!glyphIndexIntoCurrentRun) { |
| 615 |
// The first layout advance of every run includes the "initial layout advance." However, here, we need |
617 |
// The first layout advance of every run includes the "initial layout advance." However, here, we need |
| 616 |
// paint advances, so subtract it out before transforming the layout advance into a paint advance. |
618 |
// paint advances, so subtract it out before transforming the layout advance into a paint advance. |
| 617 |
paintAdvance.setWidth(paintAdvance.width() - (complexTextRun.initialAdvance().width - currentGlyphOrigin.x)); |
619 |
paintAdvance.setWidth(paintAdvance.width() - (complexTextRun.initialAdvance().width() - currentGlyphOrigin.x())); |
| 618 |
paintAdvance.setHeight(paintAdvance.height() - (complexTextRun.initialAdvance().height - currentGlyphOrigin.y)); |
620 |
paintAdvance.setHeight(paintAdvance.height() - (complexTextRun.initialAdvance().height() - currentGlyphOrigin.y())); |
| 619 |
} |
621 |
} |
| 620 |
paintAdvance.setWidth(paintAdvance.width() + glyphOrigin(glyphIndexIntoComplexTextController + 1).x - currentGlyphOrigin.x); |
622 |
paintAdvance.setWidth(paintAdvance.width() + glyphOrigin(glyphIndexIntoComplexTextController + 1).x() - currentGlyphOrigin.x()); |
| 621 |
paintAdvance.setHeight(paintAdvance.height() + glyphOrigin(glyphIndexIntoComplexTextController + 1).y - currentGlyphOrigin.y); |
623 |
paintAdvance.setHeight(paintAdvance.height() + glyphOrigin(glyphIndexIntoComplexTextController + 1).y() - currentGlyphOrigin.y()); |
| 622 |
if (glyphIndexIntoCurrentRun == glyphCount - 1 && currentRunIndex + 1 < runCount) { |
624 |
if (glyphIndexIntoCurrentRun == glyphCount - 1 && currentRunIndex + 1 < runCount) { |
| 623 |
// Our paint advance points to the end of the run. However, the next run may have an |
625 |
// Our paint advance points to the end of the run. However, the next run may have an |
| 624 |
// initial advance, and our paint advance needs to point to the location of the next |
626 |
// initial advance, and our paint advance needs to point to the location of the next |
| 625 |
// glyph. So, we need to add in the next run's initial advance. |
627 |
// glyph. So, we need to add in the next run's initial advance. |
| 626 |
paintAdvance.setWidth(paintAdvance.width() - glyphOrigin(glyphIndexIntoComplexTextController + 1).x + m_complexTextRuns[currentRunIndex + 1]->initialAdvance().width); |
628 |
paintAdvance.setWidth(paintAdvance.width() - glyphOrigin(glyphIndexIntoComplexTextController + 1).x() + m_complexTextRuns[currentRunIndex + 1]->initialAdvance().width()); |
| 627 |
paintAdvance.setHeight(paintAdvance.height() - glyphOrigin(glyphIndexIntoComplexTextController + 1).y + m_complexTextRuns[currentRunIndex + 1]->initialAdvance().height); |
629 |
paintAdvance.setHeight(paintAdvance.height() - glyphOrigin(glyphIndexIntoComplexTextController + 1).y() + m_complexTextRuns[currentRunIndex + 1]->initialAdvance().height()); |
| 628 |
} |
630 |
} |
| 629 |
paintAdvance.setHeight(-paintAdvance.height()); // Increasing y points down |
631 |
paintAdvance.setHeight(-paintAdvance.height()); // Increasing y points down |
| 630 |
glyphBuffer->add(m_adjustedGlyphs[glyphIndexIntoComplexTextController], &complexTextRun.font(), paintAdvance, complexTextRun.indexAt(m_glyphInCurrentRun)); |
632 |
glyphBuffer->add(m_adjustedGlyphs[glyphIndexIntoComplexTextController], &complexTextRun.font(), paintAdvance, complexTextRun.indexAt(m_glyphInCurrentRun)); |
|
Lines 632-638
void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer, G
a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp_sec8
|
| 632 |
|
634 |
|
| 633 |
unsigned oldCharacterInCurrentGlyph = m_characterInCurrentGlyph; |
635 |
unsigned oldCharacterInCurrentGlyph = m_characterInCurrentGlyph; |
| 634 |
m_characterInCurrentGlyph = std::min(m_currentCharacter - complexTextRun.stringLocation(), glyphEndOffset) - glyphStartOffset; |
636 |
m_characterInCurrentGlyph = std::min(m_currentCharacter - complexTextRun.stringLocation(), glyphEndOffset) - glyphStartOffset; |
| 635 |
m_runWidthSoFar += adjustedBaseAdvance.width * runWidthSoFarFraction(glyphStartOffset, glyphEndOffset, oldCharacterInCurrentGlyph, iterationStyle); |
637 |
m_runWidthSoFar += adjustedBaseAdvance.width() * runWidthSoFarFraction(glyphStartOffset, glyphEndOffset, oldCharacterInCurrentGlyph, iterationStyle); |
| 636 |
|
638 |
|
| 637 |
if (glyphEndOffset + complexTextRun.stringLocation() > m_currentCharacter) |
639 |
if (glyphEndOffset + complexTextRun.stringLocation() > m_currentCharacter) |
| 638 |
return; |
640 |
return; |
|
Lines 681-687
static inline std::pair<bool, bool> expansionLocation(bool ideograph, bool treat
a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp_sec9
|
| 681 |
void ComplexTextController::adjustGlyphsAndAdvances() |
683 |
void ComplexTextController::adjustGlyphsAndAdvances() |
| 682 |
{ |
684 |
{ |
| 683 |
bool afterExpansion = (m_run.expansionBehavior() & LeadingExpansionMask) == ForbidLeadingExpansion; |
685 |
bool afterExpansion = (m_run.expansionBehavior() & LeadingExpansionMask) == ForbidLeadingExpansion; |
| 684 |
CGFloat widthSinceLastCommit = 0; |
686 |
float widthSinceLastCommit = 0; |
| 685 |
size_t runCount = m_complexTextRuns.size(); |
687 |
size_t runCount = m_complexTextRuns.size(); |
| 686 |
bool hasExtraSpacing = (m_font.letterSpacing() || m_font.wordSpacing() || m_expansion) && !m_run.spacingDisabled(); |
688 |
bool hasExtraSpacing = (m_font.letterSpacing() || m_font.wordSpacing() || m_expansion) && !m_run.spacingDisabled(); |
| 687 |
bool runForcesLeadingExpansion = (m_run.expansionBehavior() & LeadingExpansionMask) == ForceLeadingExpansion; |
689 |
bool runForcesLeadingExpansion = (m_run.expansionBehavior() & LeadingExpansionMask) == ForceLeadingExpansion; |
|
Lines 699-715
void ComplexTextController::adjustGlyphsAndAdvances()
a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp_sec10
|
| 699 |
m_isLTROnly = false; |
701 |
m_isLTROnly = false; |
| 700 |
|
702 |
|
| 701 |
const CGGlyph* glyphs = complexTextRun.glyphs(); |
703 |
const CGGlyph* glyphs = complexTextRun.glyphs(); |
| 702 |
const CGSize* advances = complexTextRun.baseAdvances(); |
704 |
const FloatSize* advances = complexTextRun.baseAdvances(); |
| 703 |
|
705 |
|
| 704 |
bool lastRun = runIndex + 1 == runCount; |
706 |
bool lastRun = runIndex + 1 == runCount; |
| 705 |
float spaceWidth = font.spaceWidth() - font.syntheticBoldOffset(); |
707 |
float spaceWidth = font.spaceWidth() - font.syntheticBoldOffset(); |
| 706 |
const UChar* cp = complexTextRun.characters(); |
708 |
const UChar* cp = complexTextRun.characters(); |
| 707 |
CGPoint glyphOrigin = CGPointZero; |
709 |
FloatPoint glyphOrigin; |
| 708 |
CFIndex lastCharacterIndex = m_run.ltr() ? std::numeric_limits<CFIndex>::min() : std::numeric_limits<CFIndex>::max(); |
710 |
unsigned lastCharacterIndex = m_run.ltr() ? std::numeric_limits<unsigned>::min() : std::numeric_limits<unsigned>::max(); |
| 709 |
bool isMonotonic = true; |
711 |
bool isMonotonic = true; |
| 710 |
|
712 |
|
| 711 |
for (unsigned i = 0; i < glyphCount; i++) { |
713 |
for (unsigned i = 0; i < glyphCount; i++) { |
| 712 |
CFIndex characterIndex = complexTextRun.indexAt(i); |
714 |
unsigned characterIndex = complexTextRun.indexAt(i); |
| 713 |
if (m_run.ltr()) { |
715 |
if (m_run.ltr()) { |
| 714 |
if (characterIndex < lastCharacterIndex) |
716 |
if (characterIndex < lastCharacterIndex) |
| 715 |
isMonotonic = false; |
717 |
isMonotonic = false; |
|
Lines 729-763
void ComplexTextController::adjustGlyphsAndAdvances()
a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp_sec11
|
| 729 |
|
731 |
|
| 730 |
bool treatAsSpace = FontCascade::treatAsSpace(ch); |
732 |
bool treatAsSpace = FontCascade::treatAsSpace(ch); |
| 731 |
CGGlyph glyph = treatAsSpace ? font.spaceGlyph() : glyphs[i]; |
733 |
CGGlyph glyph = treatAsSpace ? font.spaceGlyph() : glyphs[i]; |
| 732 |
CGSize advance = treatAsSpace ? CGSizeMake(spaceWidth, advances[i].height) : advances[i]; |
734 |
FloatSize advance = treatAsSpace ? FloatSize(spaceWidth, advances[i].height()) : advances[i]; |
| 733 |
|
735 |
|
| 734 |
if (ch == '\t' && m_run.allowTabs()) |
736 |
if (ch == '\t' && m_run.allowTabs()) |
| 735 |
advance.width = m_font.tabWidth(font, m_run.tabSize(), m_run.xPos() + m_totalWidth + widthSinceLastCommit); |
737 |
advance.setWidth(m_font.tabWidth(font, m_run.tabSize(), m_run.xPos() + m_totalWidth + widthSinceLastCommit)); |
| 736 |
else if (FontCascade::treatAsZeroWidthSpace(ch) && !treatAsSpace) { |
738 |
else if (FontCascade::treatAsZeroWidthSpace(ch) && !treatAsSpace) { |
| 737 |
advance.width = 0; |
739 |
advance.setWidth(0); |
| 738 |
glyph = font.spaceGlyph(); |
740 |
glyph = font.spaceGlyph(); |
| 739 |
} |
741 |
} |
| 740 |
|
742 |
|
| 741 |
if (!i) { |
743 |
if (!i) { |
| 742 |
advance.width += complexTextRun.initialAdvance().width; |
744 |
advance.expand(complexTextRun.initialAdvance().width(), complexTextRun.initialAdvance().height()); |
| 743 |
advance.height += complexTextRun.initialAdvance().height; |
745 |
if (auto* origins = complexTextRun.glyphOrigins()) |
| 744 |
if (auto* origins = complexTextRun.glyphOrigins()) { |
746 |
advance.expand(-origins[0].x(), -origins[0].y()); |
| 745 |
advance.width -= origins[0].x; |
|
|
| 746 |
advance.height -= origins[0].y; |
| 747 |
} |
| 748 |
} |
747 |
} |
| 749 |
|
748 |
|
| 750 |
advance.width += font.syntheticBoldOffset(); |
749 |
advance.expand(font.syntheticBoldOffset(), 0); |
| 751 |
|
750 |
|
| 752 |
if (hasExtraSpacing) { |
751 |
if (hasExtraSpacing) { |
| 753 |
// If we're a glyph with an advance, add in letter-spacing. |
752 |
// If we're a glyph with an advance, add in letter-spacing. |
| 754 |
// That way we weed out zero width lurkers. This behavior matches the fast text code path. |
753 |
// That way we weed out zero width lurkers. This behavior matches the fast text code path. |
| 755 |
if (advance.width) |
754 |
if (advance.width()) |
| 756 |
advance.width += m_font.letterSpacing(); |
755 |
advance.expand(m_font.letterSpacing(), 0); |
| 757 |
|
756 |
|
| 758 |
unsigned characterIndexInRun = characterIndex + complexTextRun.stringLocation(); |
757 |
unsigned characterIndexInRun = characterIndex + complexTextRun.stringLocation(); |
| 759 |
bool isFirstCharacter = !(characterIndex + complexTextRun.stringLocation()); |
758 |
bool isFirstCharacter = !(characterIndex + complexTextRun.stringLocation()); |
| 760 |
bool isLastCharacter = static_cast<unsigned>(characterIndexInRun + 1) == m_run.length() || (U16_IS_LEAD(ch) && static_cast<unsigned>(characterIndexInRun + 2) == m_run.length() && U16_IS_TRAIL(*(cp + characterIndex + 1))); |
759 |
bool isLastCharacter = characterIndexInRun + 1 == m_run.length() || (U16_IS_LEAD(ch) && characterIndexInRun + 2 == m_run.length() && U16_IS_TRAIL(*(cp + characterIndex + 1))); |
| 761 |
|
760 |
|
| 762 |
bool forceLeadingExpansion = false; // On the left, regardless of m_run.ltr() |
761 |
bool forceLeadingExpansion = false; // On the left, regardless of m_run.ltr() |
| 763 |
bool forceTrailingExpansion = false; // On the right, regardless of m_run.ltr() |
762 |
bool forceTrailingExpansion = false; // On the right, regardless of m_run.ltr() |
|
Lines 779-791
void ComplexTextController::adjustGlyphsAndAdvances()
a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp_sec12
|
| 779 |
bool expandLeft, expandRight; |
778 |
bool expandLeft, expandRight; |
| 780 |
std::tie(expandLeft, expandRight) = expansionLocation(ideograph, treatAsSpace, m_run.ltr(), afterExpansion, forbidLeadingExpansion, forbidTrailingExpansion, forceLeadingExpansion, forceTrailingExpansion); |
779 |
std::tie(expandLeft, expandRight) = expansionLocation(ideograph, treatAsSpace, m_run.ltr(), afterExpansion, forbidLeadingExpansion, forbidTrailingExpansion, forceLeadingExpansion, forceTrailingExpansion); |
| 781 |
m_expansion -= m_expansionPerOpportunity; |
780 |
m_expansion -= m_expansionPerOpportunity; |
| 782 |
advance.width += m_expansionPerOpportunity; |
781 |
advance.expand(m_expansionPerOpportunity, 0); |
| 783 |
if (expandLeft) { |
782 |
if (expandLeft) { |
| 784 |
// Increase previous width |
783 |
// Increase previous width |
| 785 |
if (m_adjustedBaseAdvances.isEmpty()) |
784 |
if (m_adjustedBaseAdvances.isEmpty()) |
| 786 |
complexTextRun.growInitialAdvanceHorizontally(m_expansionPerOpportunity); |
785 |
complexTextRun.growInitialAdvanceHorizontally(m_expansionPerOpportunity); |
| 787 |
else |
786 |
else |
| 788 |
m_adjustedBaseAdvances.last().width += m_expansionPerOpportunity; |
787 |
m_adjustedBaseAdvances.last().expand(m_expansionPerOpportunity, 0); |
| 789 |
} |
788 |
} |
| 790 |
if (expandRight) |
789 |
if (expandRight) |
| 791 |
afterExpansion = true; |
790 |
afterExpansion = true; |
|
Lines 794-805
void ComplexTextController::adjustGlyphsAndAdvances()
a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp_sec13
|
| 794 |
|
793 |
|
| 795 |
// Account for word-spacing. |
794 |
// Account for word-spacing. |
| 796 |
if (treatAsSpace && (ch != '\t' || !m_run.allowTabs()) && (characterIndex > 0 || runIndex > 0) && m_font.wordSpacing()) |
795 |
if (treatAsSpace && (ch != '\t' || !m_run.allowTabs()) && (characterIndex > 0 || runIndex > 0) && m_font.wordSpacing()) |
| 797 |
advance.width += m_font.wordSpacing(); |
796 |
advance.expand(m_font.wordSpacing(), 0); |
| 798 |
} else |
797 |
} else |
| 799 |
afterExpansion = false; |
798 |
afterExpansion = false; |
| 800 |
} |
799 |
} |
| 801 |
|
800 |
|
| 802 |
widthSinceLastCommit += advance.width; |
801 |
widthSinceLastCommit += advance.width(); |
| 803 |
|
802 |
|
| 804 |
// FIXME: Combining marks should receive a text emphasis mark if they are combine with a space. |
803 |
// FIXME: Combining marks should receive a text emphasis mark if they are combine with a space. |
| 805 |
if (m_forTextEmphasis && (!FontCascade::canReceiveTextEmphasis(ch) || (U_GET_GC_MASK(ch) & U_GC_M_MASK))) |
804 |
if (m_forTextEmphasis && (!FontCascade::canReceiveTextEmphasis(ch) || (U_GET_GC_MASK(ch) & U_GC_M_MASK))) |
|
Lines 815-827
void ComplexTextController::adjustGlyphsAndAdvances()
a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp_sec14
|
| 815 |
m_adjustedGlyphs.append(glyph); |
814 |
m_adjustedGlyphs.append(glyph); |
| 816 |
|
815 |
|
| 817 |
FloatRect glyphBounds = font.boundsForGlyph(glyph); |
816 |
FloatRect glyphBounds = font.boundsForGlyph(glyph); |
| 818 |
glyphBounds.move(glyphOrigin.x, glyphOrigin.y); |
817 |
glyphBounds.move(glyphOrigin.x(), glyphOrigin.y()); |
| 819 |
m_minGlyphBoundingBoxX = std::min(m_minGlyphBoundingBoxX, glyphBounds.x()); |
818 |
m_minGlyphBoundingBoxX = std::min(m_minGlyphBoundingBoxX, glyphBounds.x()); |
| 820 |
m_maxGlyphBoundingBoxX = std::max(m_maxGlyphBoundingBoxX, glyphBounds.maxX()); |
819 |
m_maxGlyphBoundingBoxX = std::max(m_maxGlyphBoundingBoxX, glyphBounds.maxX()); |
| 821 |
m_minGlyphBoundingBoxY = std::min(m_minGlyphBoundingBoxY, glyphBounds.y()); |
820 |
m_minGlyphBoundingBoxY = std::min(m_minGlyphBoundingBoxY, glyphBounds.y()); |
| 822 |
m_maxGlyphBoundingBoxY = std::max(m_maxGlyphBoundingBoxY, glyphBounds.maxY()); |
821 |
m_maxGlyphBoundingBoxY = std::max(m_maxGlyphBoundingBoxY, glyphBounds.maxY()); |
| 823 |
glyphOrigin.x += advance.width; |
822 |
glyphOrigin.move(advance); |
| 824 |
glyphOrigin.y += advance.height; |
|
|
| 825 |
|
823 |
|
| 826 |
lastCharacterIndex = characterIndex; |
824 |
lastCharacterIndex = characterIndex; |
| 827 |
} |
825 |
} |