summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics/WidthIterator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/platform/graphics/WidthIterator.cpp')
-rw-r--r--Source/WebCore/platform/graphics/WidthIterator.cpp83
1 files changed, 75 insertions, 8 deletions
diff --git a/Source/WebCore/platform/graphics/WidthIterator.cpp b/Source/WebCore/platform/graphics/WidthIterator.cpp
index f061ec470..15ca61773 100644
--- a/Source/WebCore/platform/graphics/WidthIterator.cpp
+++ b/Source/WebCore/platform/graphics/WidthIterator.cpp
@@ -27,7 +27,6 @@
#include "Latin1TextIterator.h"
#include "SimpleFontData.h"
#include "SurrogatePairAwareTextIterator.h"
-#include "TextRun.h"
#include <wtf/MathExtras.h>
using namespace WTF;
@@ -43,6 +42,7 @@ WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const
, m_runWidthSoFar(0)
, m_isAfterExpansion(!run.allowsLeadingExpansion())
, m_finalRoundingWidth(0)
+ , m_typesettingFeatures(font->typesettingFeatures())
, m_fallbackFonts(fallbackFonts)
, m_accountForGlyphBounds(accountForGlyphBounds)
, m_maxGlyphBoundingBoxY(numeric_limits<float>::min())
@@ -84,6 +84,62 @@ GlyphData WidthIterator::glyphDataForCharacter(UChar32 character, bool mirror, i
return m_font->glyphDataForCharacter(character, mirror);
}
+struct OriginalAdvancesForCharacterTreatedAsSpace {
+public:
+ OriginalAdvancesForCharacterTreatedAsSpace(bool isSpace, float advanceBefore, float advanceAt)
+ : characterIsSpace(isSpace)
+ , advanceBeforeCharacter(advanceBefore)
+ , advanceAtCharacter(advanceAt)
+ {
+ }
+
+ bool characterIsSpace;
+ float advanceBeforeCharacter;
+ float advanceAtCharacter;
+};
+
+typedef Vector<pair<int, OriginalAdvancesForCharacterTreatedAsSpace>, 64> CharactersTreatedAsSpace;
+
+static inline float applyFontTransforms(GlyphBuffer* glyphBuffer, bool ltr, int& lastGlyphCount, const SimpleFontData* fontData, TypesettingFeatures typesettingFeatures, CharactersTreatedAsSpace& charactersTreatedAsSpace)
+{
+ ASSERT(typesettingFeatures & (Kerning | Ligatures));
+
+ if (!glyphBuffer)
+ return 0;
+
+ int glyphBufferSize = glyphBuffer->size();
+ if (glyphBuffer->size() <= lastGlyphCount + 1)
+ return 0;
+
+ GlyphBufferAdvance* advances = glyphBuffer->advances(0);
+ float widthDifference = 0;
+ for (int i = lastGlyphCount; i < glyphBufferSize; ++i)
+ widthDifference -= advances[i].width();
+
+ if (!ltr)
+ glyphBuffer->reverse(lastGlyphCount, glyphBufferSize - lastGlyphCount);
+
+ fontData->applyTransforms(glyphBuffer->glyphs(lastGlyphCount), advances + lastGlyphCount, glyphBufferSize - lastGlyphCount, typesettingFeatures);
+
+ if (!ltr)
+ glyphBuffer->reverse(lastGlyphCount, glyphBufferSize - lastGlyphCount);
+
+ for (size_t i = 0; i < charactersTreatedAsSpace.size(); ++i) {
+ int spaceOffset = charactersTreatedAsSpace[i].first;
+ const OriginalAdvancesForCharacterTreatedAsSpace& originalAdvances = charactersTreatedAsSpace[i].second;
+ if (spaceOffset && !originalAdvances.characterIsSpace)
+ glyphBuffer->advances(spaceOffset - 1)->setWidth(originalAdvances.advanceBeforeCharacter);
+ glyphBuffer->advances(spaceOffset)->setWidth(originalAdvances.advanceAtCharacter);
+ }
+ charactersTreatedAsSpace.clear();
+
+ for (int i = lastGlyphCount; i < glyphBufferSize; ++i)
+ widthDifference += advances[i].width();
+
+ lastGlyphCount = glyphBufferSize;
+ return widthDifference;
+}
+
template <typename TextIterator>
inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, GlyphBuffer* glyphBuffer)
{
@@ -99,10 +155,11 @@ inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, Glyph
const SimpleFontData* primaryFont = m_font->primaryFont();
const SimpleFontData* lastFontData = primaryFont;
+ int lastGlyphCount = glyphBuffer ? glyphBuffer->size() : 0;
UChar32 character = 0;
unsigned clusterLength = 0;
-
+ CharactersTreatedAsSpace charactersTreatedAsSpace;
while (textIterator.consume(character, clusterLength)) {
unsigned advanceLength = clusterLength;
const GlyphData& glyphData = glyphDataForCharacter(character, rtl, textIterator.currentCharacter(), advanceLength);
@@ -132,6 +189,9 @@ inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, Glyph
}
if (fontData != lastFontData && width) {
+ if (shouldApplyFontTransforms())
+ m_runWidthSoFar += applyFontTransforms(glyphBuffer, m_run.ltr(), lastGlyphCount, lastFontData, m_typesettingFeatures, charactersTreatedAsSpace);
+
lastFontData = fontData;
if (m_fallbackFonts && fontData != primaryFont) {
// FIXME: This does a little extra work that could be avoided if
@@ -187,6 +247,10 @@ inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, Glyph
m_isAfterExpansion = false;
}
+ if (shouldApplyFontTransforms() && glyphBuffer && Font::treatAsSpace(character))
+ charactersTreatedAsSpace.append(make_pair(glyphBuffer->size(),
+ OriginalAdvancesForCharacterTreatedAsSpace(character == ' ', glyphBuffer->size() ? glyphBuffer->advanceAt(glyphBuffer->size() - 1) : 0, width)));
+
if (m_accountForGlyphBounds) {
bounds = fontData->boundsForGlyph(glyph);
if (!textIterator.currentCharacter())
@@ -239,6 +303,9 @@ inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, Glyph
}
}
+ if (shouldApplyFontTransforms())
+ m_runWidthSoFar += applyFontTransforms(glyphBuffer, m_run.ltr(), lastGlyphCount, lastFontData, m_typesettingFeatures, charactersTreatedAsSpace);
+
unsigned consumedCharacters = textIterator.currentCharacter() - m_currentCharacter;
m_currentCharacter = textIterator.currentCharacter();
m_runWidthSoFar += widthSinceLastRounding;
@@ -265,15 +332,15 @@ unsigned WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
return advanceInternal(textIterator, glyphBuffer);
}
-bool WidthIterator::advanceOneCharacter(float& width, GlyphBuffer* glyphBuffer)
+bool WidthIterator::advanceOneCharacter(float& width, GlyphBuffer& glyphBuffer)
{
- int oldSize = glyphBuffer->size();
- advance(m_currentCharacter + 1, glyphBuffer);
+ int oldSize = glyphBuffer.size();
+ advance(m_currentCharacter + 1, &glyphBuffer);
float w = 0;
- for (int i = oldSize; i < glyphBuffer->size(); ++i)
- w += glyphBuffer->advanceAt(i);
+ for (int i = oldSize; i < glyphBuffer.size(); ++i)
+ w += glyphBuffer.advanceAt(i);
width = w;
- return glyphBuffer->size() > oldSize;
+ return glyphBuffer.size() > oldSize;
}
}