OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 Google Inc. All rights reserved. | 2 * Copyright (c) 2012 Google Inc. All rights reserved. |
3 * Copyright (C) 2013 BlackBerry Limited. All rights reserved. | 3 * Copyright (C) 2013 BlackBerry Limited. All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are | 6 * modification, are permitted provided that the following conditions are |
7 * met: | 7 * met: |
8 * | 8 * |
9 * * Redistributions of source code must retain the above copyright | 9 * * Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 } else { | 268 } else { |
269 hb_buffer_add_utf16(buffer, toUint16(normalizedBuffer), | 269 hb_buffer_add_utf16(buffer, toUint16(normalizedBuffer), |
270 normalizedBufferLength, startIndex, numCharacters); | 270 normalizedBufferLength, startIndex, numCharacters); |
271 } | 271 } |
272 } | 272 } |
273 | 273 |
274 inline bool HarfBuzzShaper::shapeRange(hb_buffer_t* harfBuzzBuffer, | 274 inline bool HarfBuzzShaper::shapeRange(hb_buffer_t* harfBuzzBuffer, |
275 unsigned startIndex, | 275 unsigned startIndex, |
276 unsigned numCharacters, | 276 unsigned numCharacters, |
277 const SimpleFontData* currentFont, | 277 const SimpleFontData* currentFont, |
278 PassRefPtr<UnicodeRangeSet> currentFontRangeSet, | 278 unsigned currentFontRangeFrom, |
| 279 unsigned currentFontRangeTo, |
279 UScriptCode currentRunScript, | 280 UScriptCode currentRunScript, |
280 hb_language_t language) | 281 hb_language_t language) |
281 { | 282 { |
282 const FontPlatformData* platformData = &(currentFont->platformData()); | 283 const FontPlatformData* platformData = &(currentFont->platformData()); |
283 HarfBuzzFace* face = platformData->harfBuzzFace(); | 284 HarfBuzzFace* face = platformData->harfBuzzFace(); |
284 if (!face) { | 285 if (!face) { |
285 WTF_LOG_ERROR("Could not create HarfBuzzFace from FontPlatformData."); | 286 WTF_LOG_ERROR("Could not create HarfBuzzFace from FontPlatformData."); |
286 return false; | 287 return false; |
287 } | 288 } |
288 | 289 |
289 hb_buffer_set_language(harfBuzzBuffer, language); | 290 hb_buffer_set_language(harfBuzzBuffer, language); |
290 hb_buffer_set_script(harfBuzzBuffer, ICUScriptToHBScript(currentRunScript)); | 291 hb_buffer_set_script(harfBuzzBuffer, ICUScriptToHBScript(currentRunScript)); |
291 hb_buffer_set_direction(harfBuzzBuffer, TextDirectionToHBDirection(m_textRun
.direction(), | 292 hb_buffer_set_direction(harfBuzzBuffer, TextDirectionToHBDirection(m_textRun
.direction(), |
292 m_font->getFontDescription().orientation(), currentFont)); | 293 m_font->getFontDescription().orientation(), currentFont)); |
293 | 294 |
294 addToHarfBuzzBufferInternal(harfBuzzBuffer, | 295 addToHarfBuzzBufferInternal(harfBuzzBuffer, |
295 m_font->getFontDescription(), m_normalizedBuffer.get(), m_normalizedBuff
erLength, | 296 m_font->getFontDescription(), m_normalizedBuffer.get(), m_normalizedBuff
erLength, |
296 startIndex, numCharacters); | 297 startIndex, numCharacters); |
297 | 298 |
298 HarfBuzzScopedPtr<hb_font_t> harfBuzzFont(face->createFont(currentFontRangeS
et), hb_font_destroy); | 299 HarfBuzzScopedPtr<hb_font_t> harfBuzzFont(face->createFont(currentFontRangeF
rom, currentFontRangeTo), hb_font_destroy); |
299 hb_shape(harfBuzzFont.get(), harfBuzzBuffer, m_features.isEmpty() ? 0 : m_fe
atures.data(), m_features.size()); | 300 hb_shape(harfBuzzFont.get(), harfBuzzBuffer, m_features.isEmpty() ? 0 : m_fe
atures.data(), m_features.size()); |
300 | 301 |
301 return true; | 302 return true; |
302 } | 303 } |
303 | 304 |
304 bool HarfBuzzShaper::extractShapeResults(hb_buffer_t* harfBuzzBuffer, | 305 bool HarfBuzzShaper::extractShapeResults(hb_buffer_t* harfBuzzBuffer, |
305 ShapeResult* shapeResult, | 306 ShapeResult* shapeResult, |
306 bool& fontCycleQueued, const HolesQueueItem& currentQueueItem, | 307 bool& fontCycleQueued, const HolesQueueItem& currentQueueItem, |
307 const SimpleFontData* currentFont, | 308 const SimpleFontData* currentFont, |
308 UScriptCode currentRunScript, | 309 UScriptCode currentRunScript, |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
504 // segmentation plays a role here, does the new scriptRuniterator handle tha
t correctly? | 505 // segmentation plays a role here, does the new scriptRuniterator handle tha
t correctly? |
505 while (runSegmenter.consume(&segmentRange)) { | 506 while (runSegmenter.consume(&segmentRange)) { |
506 RefPtr<FontFallbackIterator> fallbackIterator = | 507 RefPtr<FontFallbackIterator> fallbackIterator = |
507 m_font->createFontFallbackIterator( | 508 m_font->createFontFallbackIterator( |
508 segmentRange.fontFallbackPriority); | 509 segmentRange.fontFallbackPriority); |
509 | 510 |
510 appendToHolesQueue(HolesQueueNextFont, 0, 0); | 511 appendToHolesQueue(HolesQueueNextFont, 0, 0); |
511 appendToHolesQueue(HolesQueueRange, segmentRange.start, segmentRange.end
- segmentRange.start); | 512 appendToHolesQueue(HolesQueueRange, segmentRange.start, segmentRange.end
- segmentRange.start); |
512 | 513 |
513 const SimpleFontData* currentFont = nullptr; | 514 const SimpleFontData* currentFont = nullptr; |
514 RefPtr<UnicodeRangeSet> currentFontRangeSet; | 515 unsigned currentFontRangeFrom = 0; |
| 516 unsigned currentFontRangeTo = 0; |
515 | 517 |
516 bool fontCycleQueued = false; | 518 bool fontCycleQueued = false; |
517 while (m_holesQueue.size()) { | 519 while (m_holesQueue.size()) { |
518 HolesQueueItem currentQueueItem = m_holesQueue.takeFirst(); | 520 HolesQueueItem currentQueueItem = m_holesQueue.takeFirst(); |
519 | 521 |
520 if (currentQueueItem.m_action == HolesQueueNextFont) { | 522 if (currentQueueItem.m_action == HolesQueueNextFont) { |
521 // For now, we're building a character list with which we probe | 523 // For now, we're building a character list with which we probe |
522 // for needed fonts depending on the declared unicode-range of a | 524 // for needed fonts depending on the declared unicode-range of a |
523 // segmented CSS font. Alternatively, we can build a fake font | 525 // segmented CSS font. Alternatively, we can build a fake font |
524 // for the shaper and check whether any glyphs were found, or | 526 // for the shaper and check whether any glyphs were found, or |
525 // define a new API on the shaper which will give us coverage | 527 // define a new API on the shaper which will give us coverage |
526 // information? | 528 // information? |
527 if (!collectFallbackHintChars(fallbackCharsHint, fallbackIterato
r->needsHintList())) { | 529 if (!collectFallbackHintChars(fallbackCharsHint, fallbackIterato
r->needsHintList())) { |
528 // Give up shaping since we cannot retrieve a font fallback | 530 // Give up shaping since we cannot retrieve a font fallback |
529 // font without a hintlist. | 531 // font without a hintlist. |
530 m_holesQueue.clear(); | 532 m_holesQueue.clear(); |
531 break; | 533 break; |
532 } | 534 } |
533 | 535 |
534 FontDataForRangeSet nextFontDataForRangeSet = fallbackIterator->
next(fallbackCharsHint); | 536 FontDataRange nextFontDataRange = fallbackIterator->next(fallbac
kCharsHint); |
535 currentFont = nextFontDataForRangeSet.fontData().get(); | 537 currentFont = nextFontDataRange.fontData().get(); |
536 currentFontRangeSet = nextFontDataForRangeSet.ranges(); | 538 currentFontRangeFrom = nextFontDataRange.from(); |
537 | 539 currentFontRangeTo = nextFontDataRange.to(); |
538 if (!currentFont) { | 540 if (!currentFont) { |
539 ASSERT(!m_holesQueue.size()); | 541 ASSERT(!m_holesQueue.size()); |
540 break; | 542 break; |
541 } | 543 } |
542 fontCycleQueued = false; | 544 fontCycleQueued = false; |
543 continue; | 545 continue; |
544 } | 546 } |
545 | 547 |
546 // TODO crbug.com/522964: Only use smallCapsFontData when the font d
oes not support true smcp. The spec | 548 // TODO crbug.com/522964: Only use smallCapsFontData when the font d
oes not support true smcp. The spec |
547 // says: "To match the surrounding text, a font may provide alternat
e glyphs for caseless characters when | 549 // says: "To match the surrounding text, a font may provide alternat
e glyphs for caseless characters when |
548 // these features are enabled but when a user agent simulates small
capitals, it must not attempt to | 550 // these features are enabled but when a user agent simulates small
capitals, it must not attempt to |
549 // simulate alternates for codepoints which are considered caseless.
" | 551 // simulate alternates for codepoints which are considered caseless.
" |
550 const SimpleFontData* smallcapsAdjustedFont = segmentRange.smallCaps
Behavior == SmallCapsIterator::SmallCapsUppercaseNeeded | 552 const SimpleFontData* smallcapsAdjustedFont = segmentRange.smallCaps
Behavior == SmallCapsIterator::SmallCapsUppercaseNeeded |
551 ? currentFont->smallCapsFontData(fontDescription).get() | 553 ? currentFont->smallCapsFontData(fontDescription).get() |
552 : currentFont; | 554 : currentFont; |
553 | 555 |
554 // Compatibility with SimpleFontData approach of keeping a flag for
overriding drawing direction. | 556 // Compatibility with SimpleFontData approach of keeping a flag for
overriding drawing direction. |
555 // TODO: crbug.com/506224 This should go away in favor of storing th
at information elsewhere, for example in | 557 // TODO: crbug.com/506224 This should go away in favor of storing th
at information elsewhere, for example in |
556 // ShapeResult. | 558 // ShapeResult. |
557 const SimpleFontData* directionAndSmallCapsAdjustedFont = fontDataAd
justedForOrientation(smallcapsAdjustedFont, | 559 const SimpleFontData* directionAndSmallCapsAdjustedFont = fontDataAd
justedForOrientation(smallcapsAdjustedFont, |
558 m_font->getFontDescription().orientation(), | 560 m_font->getFontDescription().orientation(), |
559 segmentRange.renderOrientation); | 561 segmentRange.renderOrientation); |
560 | 562 |
561 if (!shapeRange(harfBuzzBuffer.get(), | 563 if (!shapeRange(harfBuzzBuffer.get(), |
562 currentQueueItem.m_startIndex, | 564 currentQueueItem.m_startIndex, |
563 currentQueueItem.m_numCharacters, | 565 currentQueueItem.m_numCharacters, |
564 directionAndSmallCapsAdjustedFont, | 566 directionAndSmallCapsAdjustedFont, |
565 currentFontRangeSet, | 567 currentFontRangeFrom, |
| 568 currentFontRangeTo, |
566 segmentRange.script, | 569 segmentRange.script, |
567 language)) | 570 language)) |
568 WTF_LOG_ERROR("Shaping range failed."); | 571 WTF_LOG_ERROR("Shaping range failed."); |
569 | 572 |
570 if (!extractShapeResults(harfBuzzBuffer.get(), | 573 if (!extractShapeResults(harfBuzzBuffer.get(), |
571 result.get(), | 574 result.get(), |
572 fontCycleQueued, | 575 fontCycleQueued, |
573 currentQueueItem, | 576 currentQueueItem, |
574 directionAndSmallCapsAdjustedFont, | 577 directionAndSmallCapsAdjustedFont, |
575 segmentRange.script, | 578 segmentRange.script, |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
679 result->m_width = run->m_width; | 682 result->m_width = run->m_width; |
680 result->m_numGlyphs = count; | 683 result->m_numGlyphs = count; |
681 ASSERT(result->m_numGlyphs == count); // no overflow | 684 ASSERT(result->m_numGlyphs == count); // no overflow |
682 result->m_hasVerticalOffsets = fontData->platformData().isVerticalAnyUpright
(); | 685 result->m_hasVerticalOffsets = fontData->platformData().isVerticalAnyUpright
(); |
683 result->m_runs.append(run.release()); | 686 result->m_runs.append(run.release()); |
684 return result.release(); | 687 return result.release(); |
685 } | 688 } |
686 | 689 |
687 | 690 |
688 } // namespace blink | 691 } // namespace blink |
OLD | NEW |