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