Changeset 122562 in webkit
- Timestamp:
- Jul 13, 2012 4:16:50 AM (12 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r122558 r122562 1 2012-07-13 Kenichi Ishibashi <bashi@chromium.org> 2 3 [Chromium] Fix bugs in HarfBuzzShaper 4 https://bugs.webkit.org/show_bug.cgi?id=90951 5 6 Reviewed by Tony Chang. 7 8 Add tests for harfbuzz-ng shaper. I tried to use -expected.html style expectations, 9 but it didn't work because there are very slight difference between CoreText and HarfBuzz in 10 rendering result. 11 12 * fast/text/shaping/shaping-script-order.html: Added. 13 * fast/text/shaping/shaping-selection-rect.html: Added. 14 * platform/chromium/TestExpectations: Need rebaseline. 15 * platform/efl/TestExpectations: Skip added tests because the port doesn't use harfbuzz. 16 * platform/gtk/TestExpectations: Ditto. 17 * platform/mac/TestExpectations: Ditto. 18 * platform/qt/TestExpectations: Ditto. 19 * platform/win/Skipped: Ditto. 20 * platform/wincairo/Skipped: Ditto. 21 * platform/wk2/Skipped: Ditto. 22 1 23 2012-07-13 Kent Tamura <tkent@chromium.org> 2 24 -
trunk/LayoutTests/platform/chromium/TestExpectations
r122558 r122562 3749 3749 // Started crashing after 122286 3750 3750 BUGWK91133 WIN : storage/indexeddb/constants.html = PASS CRASH 3751 3752 // Need rebaseline 3753 BUGWK90951 : fast/text/shaping/shaping-selection-rect.html = MISSING 3754 BUGWK90951 : fast/text/shaping/shaping-script-order.html = MISSING -
trunk/LayoutTests/platform/efl/TestExpectations
r122420 r122562 739 739 // Looks like missing multipart/x-mixed-replace support in libsoup. Failing on both GTK and EFL. 740 740 BUGWK68979 : http/tests/multipart/multipart-replace-non-html-content.php = TEXT 741 742 // Skip tests in fast/text/shaping 743 BUGWK90951 SKIP : fast/text/shaping = PASS -
trunk/LayoutTests/platform/gtk/TestExpectations
r122467 r122562 1255 1255 BUGWK91009 DEBUG : fast/xsl/xslt-missing-namespace-in-xslt.xml = TEXT 1256 1256 1257 // Skip tests in fast/text/shaping 1258 BUGWK90951 SKIP : fast/text/shaping = PASS 1259 1257 1260 ////////////////////////////////////////////////////////////////////////////////////////// 1258 1261 // End of Tests failing -
trunk/LayoutTests/platform/mac/TestExpectations
r122495 r122562 296 296 // INPUT_TYPE_DATE is not enabled on the Mac 297 297 BUGWK90987 : fast/forms/input-in-table-cell-no-value.html = IMAGE 298 299 // Skip tests in fast/text/shaping 300 BUGWK90951 SKIP : fast/text/shaping = PASS -
trunk/LayoutTests/platform/qt/TestExpectations
r122420 r122562 114 114 // Dialog element is not yet enabled. 115 115 BUGWK84635 SKIP : fast/dom/HTMLDialogElement = TEXT 116 117 // Skip tests in fast/text/shaping 118 BUGWK90951 SKIP : fast/text/shaping = PASS -
trunk/LayoutTests/platform/win/Skipped
r122528 r122562 1945 1945 # https://bugs.webkit.org/show_bug.cgi?id=85558 1946 1946 http/tests/security/contentSecurityPolicy/1.1 1947 1948 # Skip tests in fast/text/shaping 1949 fast/text/shaping -
trunk/LayoutTests/platform/wincairo/Skipped
r122528 r122562 2127 2127 # https://bugs.webkit.org/show_bug.cgi?id=85558 2128 2128 http/tests/security/contentSecurityPolicy/1.1 2129 2130 # Skip tests in fast/text/shaping 2131 fast/text/shaping -
trunk/LayoutTests/platform/wk2/Skipped
r122473 r122562 1420 1420 fast/events/drag-display-none-element.html 1421 1421 1422 # Skip tests in fast/text/shaping 1423 fast/text/shaping 1424 1422 1425 ### END OF (4) Features that are not supported in WebKit2 and likely never will be 1423 1426 ######################################## -
trunk/Source/WebCore/ChangeLog
r122561 r122562 1 2012-07-13 Kenichi Ishibashi <bashi@chromium.org> 2 3 [Chromium] Fix bugs in HarfBuzzShaper 4 https://bugs.webkit.org/show_bug.cgi?id=90951 5 6 Reviewed by Tony Chang. 7 8 The current implementation has following problems: 9 - Cannot render RTL text if the TextRun is divided into more than two 10 HarfBuzzRun. 11 - Script handling in TextRun partitioning is incorrect. 12 - Inaccurate calculation of selection rect. 13 - Wrong rendering position when the first glyph of the TextRun have 14 non-zero offsets in terms of HarfBuzz. 15 16 To fix these problems I rewrote HarfBuzzShaper class. Here is the summary: 17 - Divide the whole range of TextRun first, then shape them in visual 18 order. 19 - Divide TextRun in the same way of old-harfbuzz's 20 hb_utf16_script_run_next(). 21 - Prefer float than int when calculating selection. 22 - Adjust the drawing point after shaping. 23 24 Added tests covers the fix except for the last problem. The last problem will be covered 25 by fast/text/international/complex-joining-using-gpos.html after chromium linux port switches 26 to use HarfBuzzShaper. 27 28 Tests: fast/text/shaping/shaping-script-order.html 29 fast/text/shaping/shaping-selection-rect.html 30 31 * platform/graphics/harfbuzz/FontHarfBuzz.cpp: 32 (WebCore::Font::drawComplexText): Adjusts point after shaping. 33 * platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp: 34 (WebCore::HarfBuzzShaper::HarfBuzzRun::HarfBuzzRun): 35 (WebCore): 36 (WebCore::HarfBuzzShaper::HarfBuzzRun::applyShapeResult): Added. 37 (WebCore::HarfBuzzShaper::HarfBuzzRun::setGlyphAndAdvance): Offsets are no longer needed. 38 (WebCore::HarfBuzzShaper::HarfBuzzRun::xPositionForOffset): Calculates character offset based on advance. 39 (WebCore::normalizeCharacters): Added. 40 (WebCore::HarfBuzzShaper::HarfBuzzShaper): 41 (WebCore::HarfBuzzShaper::~HarfBuzzShaper): 42 (WebCore::HarfBuzzShaper::shape): Divides TextRun first, then shapes them. 43 (WebCore::HarfBuzzShaper::adjustStartPoint): Added. 44 (WebCore::HarfBuzzShaper::collectHarfBuzzRuns): Added. 45 (WebCore::HarfBuzzShaper::shapeHarfBuzzRuns): Added. 46 (WebCore::HarfBuzzShaper::setGlyphPositionsForHarfBuzzRun): Followed other changes. 47 (WebCore::HarfBuzzShaper::selectionRect): Use float for calculating selection. 48 * platform/graphics/harfbuzz/ng/HarfBuzzShaper.h: 49 (HarfBuzzShaper): Holds the start index of character. Removed unnecessary variables. 50 (WebCore::HarfBuzzShaper::HarfBuzzRun::create): Ditto. 51 (HarfBuzzRun): 52 (WebCore::HarfBuzzShaper::HarfBuzzRun::fontData): Added. 53 (WebCore::HarfBuzzShaper::HarfBuzzRun::startIndex): Ditto. 54 (WebCore::HarfBuzzShaper::HarfBuzzRun::glyphs): Ditto. 55 (WebCore::HarfBuzzShaper::HarfBuzzRun::advances): Ditto. 56 1 57 2012-07-13 Kentaro Hara <haraken@chromium.org> 2 58 -
trunk/Source/WebCore/platform/graphics/harfbuzz/FontHarfBuzz.cpp
r122310 r122562 188 188 if (!shaper.shape(&glyphBuffer)) 189 189 return; 190 drawGlyphBuffer(gc, run, glyphBuffer, point); 190 FloatPoint adjustedPoint = shaper.adjustStartPoint(point); 191 drawGlyphBuffer(gc, run, glyphBuffer, adjustedPoint); 191 192 #else 192 193 SkCanvas* canvas = gc->platformContext()->canvas(); -
trunk/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp
r120156 r122562 33 33 34 34 #include "Font.h" 35 #include "HarfBuzzFace.h" 35 36 #include "SurrogatePairAwareTextIterator.h" 36 37 #include "TextRun.h" … … 44 45 namespace WebCore { 45 46 47 template<typename T> 48 class HarfBuzzScopedPtr { 49 public: 50 typedef void (*DestroyFunction)(T*); 51 52 HarfBuzzScopedPtr(T* ptr, DestroyFunction destroy) 53 : m_ptr(ptr) 54 , m_destroy(destroy) 55 { 56 ASSERT(m_destroy); 57 } 58 ~HarfBuzzScopedPtr() 59 { 60 if (m_ptr) 61 (*m_destroy)(m_ptr); 62 } 63 64 T* get() { return m_ptr; } 65 private: 66 T* m_ptr; 67 DestroyFunction m_destroy; 68 }; 69 46 70 static inline float harfbuzzPositionToFloat(hb_position_t value) 47 71 { … … 49 73 } 50 74 51 HarfBuzzShaper::HarfBuzzRun::HarfBuzzRun(unsigned numCharacters, TextDirection direction, hb_buffer_t* harfbuzzBuffer) 52 : m_numCharacters(numCharacters) 75 HarfBuzzShaper::HarfBuzzRun::HarfBuzzRun(const SimpleFontData* fontData, unsigned startIndex, unsigned numCharacters, TextDirection direction) 76 : m_fontData(fontData) 77 , m_startIndex(startIndex) 78 , m_numCharacters(numCharacters) 53 79 , m_direction(direction) 80 { 81 } 82 83 void HarfBuzzShaper::HarfBuzzRun::applyShapeResult(hb_buffer_t* harfbuzzBuffer) 54 84 { 55 85 m_numGlyphs = hb_buffer_get_length(harfbuzzBuffer); 56 86 m_glyphs.resize(m_numGlyphs); 57 87 m_advances.resize(m_numGlyphs); 58 m_offsets.resize(m_numGlyphs);59 88 m_glyphToCharacterIndex.resize(m_numGlyphs); 60 89 m_logClusters.resize(m_numCharacters); … … 83 112 } 84 113 85 void HarfBuzzShaper::HarfBuzzRun::setGlyphAnd Positions(unsigned index, uint16_t glyphId, float x, float y, float advance)114 void HarfBuzzShaper::HarfBuzzRun::setGlyphAndAdvance(unsigned index, uint16_t glyphId, float advance) 86 115 { 87 116 m_glyphs[index] = glyphId; 88 m_offsets[index].set(x, y);89 117 m_advances[index] = advance; 90 118 } … … 107 135 } 108 136 109 int HarfBuzzShaper::HarfBuzzRun::xPositionForOffset(unsigned offset)137 float HarfBuzzShaper::HarfBuzzRun::xPositionForOffset(unsigned offset) 110 138 { 111 139 ASSERT(offset < m_numCharacters); 112 140 unsigned glyphIndex = m_logClusters[offset]; 113 ASSERT(glyphIndex < m_numGlyphs); 114 float position = m_offsets[glyphIndex].x(); 141 ASSERT(glyphIndex <= m_numGlyphs); 142 float position = 0; 143 for (unsigned i = 0; i < glyphIndex; ++i) 144 position += m_advances[i]; 115 145 if (rtl()) 116 146 position += m_advances[glyphIndex]; 117 return roundf(position); 147 return position; 148 } 149 150 static void normalizeCharacters(const UChar* source, UChar* destination, int length) 151 { 152 int position = 0; 153 bool error = false; 154 while (position < length) { 155 UChar32 character; 156 int nextPosition = position; 157 U16_NEXT(source, nextPosition, length, character); 158 if (Font::treatAsSpace(character)) 159 character = ' '; 160 else if (Font::treatAsZeroWidthSpaceInComplexScript(character)) 161 character = zeroWidthSpace; 162 U16_APPEND(destination, position, length, character, error); 163 ASSERT_UNUSED(error, !error); 164 position = nextPosition; 165 } 118 166 } 119 167 120 168 HarfBuzzShaper::HarfBuzzShaper(const Font* font, const TextRun& run) 121 169 : HarfBuzzShaperBase(font, run) 122 , m_startIndexOfCurrentRun(0) 123 , m_numCharactersOfCurrentRun(0)124 , m_harfbuzzBuffer(0)125 { 126 set NormalizedBuffer();170 { 171 m_normalizedBuffer = adoptArrayPtr(new UChar[m_run.length() + 1]); 172 m_normalizedBufferLength = m_run.length(); 173 normalizeCharacters(m_run.characters(), m_normalizedBuffer.get(), m_normalizedBufferLength); 174 setPadding(m_run.expansion()); 127 175 setFontFeatures(); 128 176 } … … 130 178 HarfBuzzShaper::~HarfBuzzShaper() 131 179 { 132 if (m_harfbuzzBuffer)133 hb_buffer_destroy(m_harfbuzzBuffer);134 180 } 135 181 … … 153 199 bool HarfBuzzShaper::shape(GlyphBuffer* glyphBuffer) 154 200 { 201 if (!collectHarfBuzzRuns()) 202 return false; 203 155 204 m_totalWidth = 0; 156 while (setupHarfBuzzRun()) { 157 if (!shapeHarfBuzzRun()) 158 return false; 159 setGlyphPositionsForHarfBuzzRun(glyphBuffer); 160 } 161 162 if (!m_harfbuzzRuns.size()) 205 if (!shapeHarfBuzzRuns(glyphBuffer)) 163 206 return false; 164 207 m_totalWidth = roundf(m_totalWidth); 165 208 return true; 166 209 } 167 210 168 bool HarfBuzzShaper::setupHarfBuzzRun()169 { 170 m_startIndexOfCurrentRun += m_numCharactersOfCurrentRun;171 172 // Iterate through the text to take the largest range that stays within 173 // a single font. 174 int endOfRunIndex = m_normalizedBufferLength - m_startIndexOfCurrentRun; 175 SurrogatePairAwareTextIterator iterator(m_normalizedBuffer.get() + m_startIndexOfCurrentRun, 0, endOfRunIndex, endOfRunIndex);211 FloatPoint HarfBuzzShaper::adjustStartPoint(const FloatPoint& point) 212 { 213 return point + m_startOffset; 214 } 215 216 bool HarfBuzzShaper::collectHarfBuzzRuns() 217 { 218 SurrogatePairAwareTextIterator iterator(m_normalizedBuffer.get(), 0, m_normalizedBufferLength, m_normalizedBufferLength); 176 219 UChar32 character; 177 220 unsigned clusterLength = 0; 221 unsigned startIndexOfCurrentRun = 0; 178 222 if (!iterator.consume(character, clusterLength)) 179 223 return false; 180 224 181 m_currentFontData = m_font->glyphDataForCharacter(character, false).fontData;225 const SimpleFontData* nextFontData = m_font->glyphDataForCharacter(character, false).fontData; 182 226 UErrorCode errorCode = U_ZERO_ERROR; 183 UScriptCode currentScript = uscript_getScript(character, &errorCode);227 UScriptCode nextScript = uscript_getScript(character, &errorCode); 184 228 if (U_FAILURE(errorCode)) 185 229 return false; 186 if (currentScript == USCRIPT_INHERITED) 187 currentScript = USCRIPT_COMMON; 188 for (iterator.advance(clusterLength); iterator.consume(character, clusterLength); iterator.advance(clusterLength)) { 189 const SimpleFontData* nextFontData = m_font->glyphDataForCharacter(character, false).fontData; 190 if (nextFontData != m_currentFontData) 191 break; 192 UScriptCode nextScript = uscript_getScript(character, &errorCode); 193 if (U_FAILURE(errorCode)) 230 231 do { 232 const SimpleFontData* currentFontData = nextFontData; 233 UScriptCode currentScript = nextScript; 234 235 for (iterator.advance(clusterLength); iterator.consume(character, clusterLength); iterator.advance(clusterLength)) { 236 nextFontData = m_font->glyphDataForCharacter(character, false).fontData; 237 if (nextFontData != currentFontData) 238 break; 239 nextScript = uscript_getScript(character, &errorCode); 240 if (U_FAILURE(errorCode)) 241 return false; 242 if ((currentScript != nextScript) && (currentScript != USCRIPT_INHERITED)) 243 break; 244 } 245 unsigned numCharactersOfCurrentRun = iterator.currentCharacter() - startIndexOfCurrentRun; 246 m_harfbuzzRuns.append(HarfBuzzRun::create(currentFontData, startIndexOfCurrentRun, numCharactersOfCurrentRun, m_run.direction())); 247 currentFontData = nextFontData; 248 startIndexOfCurrentRun = iterator.currentCharacter(); 249 } while (iterator.consume(character, clusterLength)); 250 251 return !m_harfbuzzRuns.isEmpty(); 252 } 253 254 bool HarfBuzzShaper::shapeHarfBuzzRuns(GlyphBuffer* glyphBuffer) 255 { 256 HarfBuzzScopedPtr<hb_buffer_t> harfbuzzBuffer(hb_buffer_create(), hb_buffer_destroy); 257 hb_buffer_set_unicode_funcs(harfbuzzBuffer.get(), hb_icu_get_unicode_funcs()); 258 if (m_run.directionalOverride()) 259 hb_buffer_set_direction(harfbuzzBuffer.get(), m_run.rtl() ? HB_DIRECTION_RTL : HB_DIRECTION_LTR); 260 261 for (unsigned i = 0; i < m_harfbuzzRuns.size(); ++i) { 262 unsigned runIndex = m_run.rtl() ? m_harfbuzzRuns.size() - i - 1 : i; 263 HarfBuzzRun* currentRun = m_harfbuzzRuns[runIndex].get(); 264 const SimpleFontData* currentFontData = currentRun->fontData(); 265 266 if (m_font->isSmallCaps() && u_islower(m_normalizedBuffer[currentRun->startIndex()])) { 267 String upperText = String(m_normalizedBuffer.get() + currentRun->startIndex(), currentRun->numCharacters()); 268 upperText.makeUpper(); 269 currentFontData = m_font->glyphDataForCharacter(upperText[0], false, SmallCapsVariant).fontData; 270 hb_buffer_add_utf16(harfbuzzBuffer.get(), upperText.characters(), currentRun->numCharacters(), 0, currentRun->numCharacters()); 271 } else 272 hb_buffer_add_utf16(harfbuzzBuffer.get(), m_normalizedBuffer.get() + currentRun->startIndex(), currentRun->numCharacters(), 0, currentRun->numCharacters()); 273 274 FontPlatformData* platformData = const_cast<FontPlatformData*>(¤tFontData->platformData()); 275 HarfBuzzFace* face = platformData->harfbuzzFace(); 276 if (!face) 194 277 return false; 195 if (currentScript == nextScript || nextScript == USCRIPT_INHERITED || nextScript == USCRIPT_COMMON) 196 continue; 197 if (currentScript == USCRIPT_COMMON) 198 currentScript = nextScript; 199 else 200 break; 201 } 202 m_numCharactersOfCurrentRun = iterator.currentCharacter(); 203 204 if (!m_harfbuzzBuffer) { 205 m_harfbuzzBuffer = hb_buffer_create(); 206 hb_buffer_set_unicode_funcs(m_harfbuzzBuffer, hb_icu_get_unicode_funcs()); 207 } else 208 hb_buffer_reset(m_harfbuzzBuffer); 209 hb_buffer_set_script(m_harfbuzzBuffer, hb_icu_script_to_script(currentScript)); 210 211 // WebKit always sets direction to LTR during width calculation. 212 // We only set direction when direction is explicitly set to RTL so that 213 // preventng wrong width calculation. 214 if (m_run.rtl()) 215 hb_buffer_set_direction(m_harfbuzzBuffer, HB_DIRECTION_RTL); 216 217 // Determine whether this run needs to be converted to small caps. 218 // nextScriptRun() will always send us a run of the same case, because a 219 // case change while in small-caps mode always results in different 220 // FontData, so we only need to check the first character's case. 221 if (m_font->isSmallCaps() && u_islower(m_normalizedBuffer[m_startIndexOfCurrentRun])) { 222 String upperText = String(m_normalizedBuffer.get() + m_startIndexOfCurrentRun, m_numCharactersOfCurrentRun); 223 upperText.makeUpper(); 224 m_currentFontData = m_font->glyphDataForCharacter(upperText[0], false, SmallCapsVariant).fontData; 225 hb_buffer_add_utf16(m_harfbuzzBuffer, upperText.characters(), m_numCharactersOfCurrentRun, 0, m_numCharactersOfCurrentRun); 226 } else 227 hb_buffer_add_utf16(m_harfbuzzBuffer, m_normalizedBuffer.get() + m_startIndexOfCurrentRun, m_numCharactersOfCurrentRun, 0, m_numCharactersOfCurrentRun); 228 278 HarfBuzzScopedPtr<hb_font_t> harfbuzzFont(face->createFont(), hb_font_destroy); 279 hb_shape(harfbuzzFont.get(), harfbuzzBuffer.get(), m_features.isEmpty() ? 0 : m_features.data(), m_features.size()); 280 281 currentRun->applyShapeResult(harfbuzzBuffer.get()); 282 setGlyphPositionsForHarfBuzzRun(currentRun, i, harfbuzzBuffer.get(), glyphBuffer); 283 284 hb_buffer_reset(harfbuzzBuffer.get()); 285 if (m_run.directionalOverride()) 286 hb_buffer_set_direction(harfbuzzBuffer.get(), m_run.rtl() ? HB_DIRECTION_RTL : HB_DIRECTION_LTR); 287 } 229 288 return true; 230 289 } 231 290 232 bool HarfBuzzShaper::shapeHarfBuzzRun() 233 { 234 FontPlatformData* platformData = const_cast<FontPlatformData*>(&m_currentFontData->platformData()); 235 HarfBuzzFace* face = platformData->harfbuzzFace(); 236 if (!face) 237 return false; 238 hb_font_t* harfbuzzFont = face->createFont(); 239 hb_shape(harfbuzzFont, m_harfbuzzBuffer, m_features.size() > 0 ? m_features.data() : 0, m_features.size()); 240 hb_font_destroy(harfbuzzFont); 241 m_harfbuzzRuns.append(HarfBuzzRun::create(m_numCharactersOfCurrentRun, m_run.direction(), m_harfbuzzBuffer)); 242 return true; 243 } 244 245 void HarfBuzzShaper::setGlyphPositionsForHarfBuzzRun(GlyphBuffer* glyphBuffer) 246 { 247 hb_glyph_info_t* glyphInfos = hb_buffer_get_glyph_infos(m_harfbuzzBuffer, 0); 248 hb_glyph_position_t* glyphPositions = hb_buffer_get_glyph_positions(m_harfbuzzBuffer, 0); 249 HarfBuzzRun* currentRun = m_harfbuzzRuns.last().get(); 291 void HarfBuzzShaper::setGlyphPositionsForHarfBuzzRun(HarfBuzzRun* currentRun, unsigned runIndexInVisualOrder, hb_buffer_t* harfbuzzBuffer, GlyphBuffer* glyphBuffer) 292 { 293 const SimpleFontData* currentFontData = currentRun->fontData(); 294 hb_glyph_info_t* glyphInfos = hb_buffer_get_glyph_infos(harfbuzzBuffer, 0); 295 hb_glyph_position_t* glyphPositions = hb_buffer_get_glyph_positions(harfbuzzBuffer, 0); 250 296 251 297 unsigned numGlyphs = currentRun->numGlyphs(); … … 263 309 nextOffsetY = runEnd ? 0 : -harfbuzzPositionToFloat(glyphPositions[i + 1].y_offset); 264 310 265 unsigned currentCharacterIndex = m_startIndexOfCurrentRun+ glyphInfos[i].cluster;311 unsigned currentCharacterIndex = currentRun->startIndex() + glyphInfos[i].cluster; 266 312 bool isClusterEnd = runEnd || glyphInfos[i].cluster != glyphInfos[i + 1].cluster; 267 313 float spacing = isClusterEnd ? m_letterSpacing : 0; … … 270 316 spacing += determineWordBreakSpacing(); 271 317 272 if ( m_currentFontData->isZeroWidthSpaceGlyph(glyph)) {273 currentRun->setGlyphAnd Positions(i, glyph, 0, 0, 0);318 if (currentFontData->isZeroWidthSpaceGlyph(glyph)) { 319 currentRun->setGlyphAndAdvance(i, glyph, 0); 274 320 if (glyphBuffer) 275 glyphBuffer->add(glyph, m_currentFontData, createGlyphBufferAdvance(0, 0));321 glyphBuffer->add(glyph, currentFontData, createGlyphBufferAdvance(0, 0)); 276 322 continue; 277 323 } 278 324 279 325 advance += spacing; 280 currentRun->setGlyphAndPositions(i, glyph, totalAdvance + offsetX, offsetY, advance); 326 327 currentRun->setGlyphAndAdvance(i, glyph, advance); 281 328 if (glyphBuffer) { 329 if (!i && !runIndexInVisualOrder) 330 m_startOffset.set(offsetX, offsetY); 282 331 float glyphAdvanceX = advance + nextOffsetX - offsetX; 283 332 float glyphAdvanceY = nextOffsetY - offsetY; 284 glyphBuffer->add(glyph, m_currentFontData, createGlyphBufferAdvance(glyphAdvanceX, glyphAdvanceY));333 glyphBuffer->add(glyph, currentFontData, createGlyphBufferAdvance(glyphAdvanceX, glyphAdvanceY)); 285 334 } 286 335 … … 325 374 FloatRect HarfBuzzShaper::selectionRect(const FloatPoint& point, int height, int from, int to) 326 375 { 327 int fromX = -1, toX = -1; 328 int currentX = 0; 329 // Iterate through the script runs in logical order, searching for the run covering the positions of interest. 376 float currentX = 0; 377 float fromX; 378 float toX; 379 bool foundFromX = false; 380 bool foundToX = false; 381 382 if (m_run.rtl()) 383 currentX = m_totalWidth; 330 384 for (unsigned i = 0; i < m_harfbuzzRuns.size(); ++i) { 385 if (m_run.rtl()) 386 currentX -= m_harfbuzzRuns[i]->width(); 331 387 int numCharacters = m_harfbuzzRuns[i]->numCharacters(); 332 if ( fromX == -1 && from >= 0 && from < numCharacters)388 if (!foundFromX && from >= 0 && from < numCharacters) { 333 389 fromX = m_harfbuzzRuns[i]->xPositionForOffset(from) + currentX; 334 else 390 foundFromX = true; 391 } else 335 392 from -= numCharacters; 336 393 337 if ( toX == -1 && to >= 0 && to < numCharacters)394 if (!foundToX && to >= 0 && to < numCharacters) { 338 395 toX = m_harfbuzzRuns[i]->xPositionForOffset(to) + currentX; 339 else 396 foundToX = true; 397 } else 340 398 to -= numCharacters; 341 399 342 if (f romX != -1 && toX != -1)400 if (foundFromX && foundToX) 343 401 break; 344 currentX += m_harfbuzzRuns[i]->width(); 402 if (!m_run.rtl()) 403 currentX += m_harfbuzzRuns[i]->width(); 345 404 } 346 405 347 406 // The position in question might be just after the text. 348 if ( fromX == -1)407 if (!foundFromX) 349 408 fromX = 0; 350 if ( toX == -1)409 if (!foundToX) 351 410 toX = m_run.rtl() ? 0 : m_totalWidth; 352 411 353 ASSERT(fromX != -1 && toX != -1); 354 412 // Using floorf() and roundf() as the same as mac port. 355 413 if (fromX < toX) 356 return FloatRect( point.x() + fromX, point.y(), toX - fromX, height);357 return FloatRect( point.x() + toX, point.y(), fromX - toX, height);414 return FloatRect(floorf(point.x() + fromX), point.y(), roundf(toX - fromX), height); 415 return FloatRect(floorf(point.x() + toX), point.y(), roundf(fromX - toX), height); 358 416 } 359 417 -
trunk/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.h
r120156 r122562 53 53 54 54 bool shape(GlyphBuffer* = 0); 55 FloatPoint adjustStartPoint(const FloatPoint&); 55 56 float totalWidth() { return m_totalWidth; } 56 57 int offsetForPosition(float targetX); … … 60 61 class HarfBuzzRun { 61 62 public: 62 static PassOwnPtr<HarfBuzzRun> create( unsigned numCharacters, TextDirection direction, hb_buffer_t* buffer)63 static PassOwnPtr<HarfBuzzRun> create(const SimpleFontData* fontData, unsigned startIndex, unsigned numCharacters, TextDirection direction) 63 64 { 64 return adoptPtr(new HarfBuzzRun( numCharacters, direction, buffer));65 return adoptPtr(new HarfBuzzRun(fontData, startIndex, numCharacters, direction)); 65 66 } 66 67 67 void setGlyphAndPositions(unsigned index, uint16_t glyphId, float x, float y, float); 68 void applyShapeResult(hb_buffer_t*); 69 void setGlyphAndAdvance(unsigned index, uint16_t glyphId, float advance); 68 70 void setWidth(float width) { m_width = width; } 69 71 70 72 int characterIndexForXPosition(int targetX); 71 int xPositionForOffset(unsigned offset);73 float xPositionForOffset(unsigned offset); 72 74 75 const SimpleFontData* fontData() { return m_fontData; } 76 unsigned startIndex() const { return m_startIndex; } 73 77 unsigned numCharacters() const { return m_numCharacters; } 74 78 unsigned numGlyphs() const { return m_numGlyphs; } 79 uint16_t* glyphs() { return &m_glyphs[0]; } 80 float* advances() { return &m_advances[0]; } 75 81 float width() { return m_width; } 76 82 77 83 private: 78 HarfBuzzRun( unsigned numCharacters, TextDirection, hb_buffer_t*);84 HarfBuzzRun(const SimpleFontData*, unsigned startIndex, unsigned numCharacters, TextDirection); 79 85 bool rtl() { return m_direction == RTL; } 80 86 87 const SimpleFontData* m_fontData; 88 unsigned m_startIndex; 81 89 size_t m_numCharacters; 82 90 unsigned m_numGlyphs; … … 84 92 Vector<uint16_t, 256> m_glyphs; 85 93 Vector<float, 256> m_advances; 86 Vector<FloatPoint, 256> m_offsets;87 94 Vector<uint16_t, 256> m_logClusters; 88 95 Vector<uint16_t, 256> m_glyphToCharacterIndex; … … 92 99 void setFontFeatures(); 93 100 94 bool setupHarfBuzzRun();95 bool shapeHarfBuzzRun ();96 void setGlyphPositionsForHarfBuzzRun( GlyphBuffer*);101 bool collectHarfBuzzRuns(); 102 bool shapeHarfBuzzRuns(GlyphBuffer*); 103 void setGlyphPositionsForHarfBuzzRun(HarfBuzzRun*, unsigned runIndexInVisualOrder, hb_buffer_t*, GlyphBuffer*); 97 104 98 105 GlyphBufferAdvance createGlyphBufferAdvance(float, float); 99 106 100 107 Vector<hb_feature_t, 4> m_features; 101 unsigned m_startIndexOfCurrentRun;102 unsigned m_numCharactersOfCurrentRun;103 const SimpleFontData* m_currentFontData;104 hb_buffer_t* m_harfbuzzBuffer;105 108 Vector<OwnPtr<HarfBuzzRun>, 16> m_harfbuzzRuns; 109 110 FloatPoint m_startOffset; 106 111 107 112 float m_totalWidth;
Note: See TracChangeset
for help on using the changeset viewer.