Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(243)

Side by Side Diff: Source/platform/fonts/shaping/HarfBuzzShaper.cpp

Issue 1242213002: Add tab characters support in complex path (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 534 matching lines...) Expand 10 before | Expand all | Expand 10 after
545 stringFor8BitRun = String::make16BitFrom8BitSource(run.characters8(), ru n.length()); 545 stringFor8BitRun = String::make16BitFrom8BitSource(run.characters8(), ru n.length());
546 source = stringFor8BitRun.characters16(); 546 source = stringFor8BitRun.characters16();
547 } else { 547 } else {
548 source = run.characters16(); 548 source = run.characters16();
549 } 549 }
550 550
551 *destinationLength = 0; 551 *destinationLength = 0;
552 while (position < length) { 552 while (position < length) {
553 UChar32 character; 553 UChar32 character;
554 U16_NEXT(source, position, length, character); 554 U16_NEXT(source, position, length, character);
555 // Don't normalize tabs as they are not treated as spaces for word-end. 555 if (!(character == tabulationCharacter && run.allowTabs())) {
556 if (run.normalizeSpace() && Character::isNormalizedCanvasSpaceCharacter( character)) 556 // Don't normalize tabs as they are not treated as spaces for word-e nd.
557 character = spaceCharacter; 557 if (run.normalizeSpace() && Character::isNormalizedCanvasSpaceCharac ter(character))
558 else if (Character::treatAsSpace(character) && character != tabulationCh aracter) 558 character = spaceCharacter;
559 character = spaceCharacter; 559 else if (Character::treatAsSpace(character) && character != tabulati onCharacter)
560 else if (Character::treatAsZeroWidthSpaceInComplexScript(character)) 560 character = spaceCharacter;
561 character = zeroWidthSpaceCharacter; 561 else if (Character::treatAsZeroWidthSpaceInComplexScript(character))
562 character = zeroWidthSpaceCharacter;
563 }
562 564
563 U16_APPEND(destination, *destinationLength, length, character, error); 565 U16_APPEND(destination, *destinationLength, length, character, error);
564 ASSERT_UNUSED(error, !error); 566 ASSERT_UNUSED(error, !error);
565 } 567 }
566 } 568 }
567 569
568 HarfBuzzShaper::HarfBuzzShaper(const Font* font, const TextRun& run, 570 HarfBuzzShaper::HarfBuzzShaper(const Font* font, const TextRun& run,
569 HashSet<const SimpleFontData*>* fallbackFonts) 571 HashSet<const SimpleFontData*>* fallbackFonts)
570 : Shaper(font, run, nullptr, fallbackFonts) 572 : Shaper(font, run, nullptr, fallbackFonts)
571 , m_normalizedBufferLength(0) 573 , m_normalizedBufferLength(0)
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
725 } 727 }
726 728
727 struct CandidateRun { 729 struct CandidateRun {
728 UChar32 character; 730 UChar32 character;
729 unsigned start; 731 unsigned start;
730 unsigned end; 732 unsigned end;
731 const SimpleFontData* fontData; 733 const SimpleFontData* fontData;
732 UScriptCode script; 734 UScriptCode script;
733 }; 735 };
734 736
737 static void collectCandidateRunsForTabulationCharacters(UTF16TextIterator& itera tor,
738 Vector<CandidateRun>* runs, unsigned& startIndexOfCurrentRun,
739 UChar32& character, const SimpleFontData* currentFontData)
740 {
741 ASSERT(character == tabulationCharacter);
742 for (iterator.advance(); iterator.consume(character); iterator.advance()) {
743 if (character != tabulationCharacter)
744 break;
745 }
746 CandidateRun run = { tabulationCharacter, startIndexOfCurrentRun, static_cas t<unsigned>(iterator.offset()), currentFontData, USCRIPT_COMMON };
747 runs->append(run);
748 startIndexOfCurrentRun = iterator.offset();
749 }
750
751 static inline bool updateCharacterInfo(const Font* font, UChar32 character, cons t TextRun& textRun,
eae 2015/07/20 17:39:24 Update makes it sound like it has state, how about
kojii 2015/07/21 01:11:47 Glad you suggested this! I once did this but it ma
752 const SimpleFontData*& fontData, UScriptCode& script)
753 {
754 fontData = font->glyphDataForCharacter(character, false, textRun.normalizeSp ace()).fontData;
755 UErrorCode errorCode = U_ZERO_ERROR;
756 script = uscript_getScript(character, &errorCode);
757 if (U_FAILURE(errorCode))
758 return false;
759 return true;
760 }
761
735 static inline bool collectCandidateRuns(const UChar* normalizedBuffer, 762 static inline bool collectCandidateRuns(const UChar* normalizedBuffer,
736 size_t bufferLength, const Font* font, Vector<CandidateRun>* runs, bool isSp aceNormalize) 763 size_t bufferLength, const Font* font, Vector<CandidateRun>* runs,
764 const TextRun& textRun)
737 { 765 {
738 UTF16TextIterator iterator(normalizedBuffer, bufferLength); 766 UTF16TextIterator iterator(normalizedBuffer, bufferLength);
739 UChar32 character; 767 UChar32 character;
740 unsigned startIndexOfCurrentRun = 0; 768 unsigned startIndexOfCurrentRun = 0;
741 769
742 if (!iterator.consume(character)) 770 if (!iterator.consume(character))
743 return false; 771 return false;
744 772
745 const SimpleFontData* nextFontData = font->glyphDataForCharacter(character, false, isSpaceNormalize).fontData; 773 const SimpleFontData* nextFontData;
746 UErrorCode errorCode = U_ZERO_ERROR; 774 UScriptCode nextScript;
747 UScriptCode nextScript = uscript_getScript(character, &errorCode); 775 if (!updateCharacterInfo(font, character, textRun, nextFontData, nextScript) )
748 if (U_FAILURE(errorCode))
749 return false; 776 return false;
750 777
751 do { 778 do {
779 // Tab characters need to go to its own run because the run doesn't use Harfbuzz.
780 if (character == tabulationCharacter && textRun.allowTabs()) {
eae 2015/07/20 17:39:24 How about adding UNLIKELY macros around the tab ch
kojii 2015/07/21 01:11:47 Thought UNLIKELY() is the past. Thanks, learned on
781 collectCandidateRunsForTabulationCharacters(iterator, runs,
782 startIndexOfCurrentRun, character, nextFontData);
783 if (iterator.atEnd())
784 break;
785 if (!updateCharacterInfo(font, character, textRun, nextFontData, nex tScript))
786 return false;
787 }
788
752 const UChar* currentCharacterPosition = iterator.characters(); 789 const UChar* currentCharacterPosition = iterator.characters();
753 const SimpleFontData* currentFontData = nextFontData; 790 const SimpleFontData* currentFontData = nextFontData;
754 UScriptCode currentScript = nextScript; 791 UScriptCode currentScript = nextScript;
755 792
756 UChar32 lastCharacter = character; 793 UChar32 lastCharacter = character;
757 for (iterator.advance(); iterator.consume(character); iterator.advance() ) { 794 for (iterator.advance(); iterator.consume(character); iterator.advance() ) {
758 if (Character::treatAsZeroWidthSpace(character)) 795 if (Character::treatAsZeroWidthSpace(character)) {
796 if (character == tabulationCharacter && textRun.allowTabs())
eae 2015/07/20 17:39:24 I'd move this check out of the treatAsZeroWidthSpa
kojii 2015/07/21 01:11:47 That's better to read. treatAsZeroWidthSpace() che
797 break;
759 continue; 798 continue;
799 }
760 if ((U_GET_GC_MASK(character) & U_GC_M_MASK) 800 if ((U_GET_GC_MASK(character) & U_GC_M_MASK)
761 && (Character::isUnicodeVariationSelector(character) 801 && (Character::isUnicodeVariationSelector(character)
762 || currentFontData->canRenderCombiningCharacterSequence( 802 || currentFontData->canRenderCombiningCharacterSequence(
763 currentCharacterPosition, 803 currentCharacterPosition,
764 iterator.glyphEnd() - currentCharacterPosition))) 804 iterator.glyphEnd() - currentCharacterPosition)))
765 continue; 805 continue;
766 806
767 nextFontData = font->glyphDataForCharacter(character, false, isSpace Normalize).fontData; 807 if (!updateCharacterInfo(font, character, textRun, nextFontData, nex tScript))
768 nextScript = uscript_getScript(character, &errorCode);
769 if (U_FAILURE(errorCode))
770 return false; 808 return false;
771 if (lastCharacter == zeroWidthJoinerCharacter) 809 if (lastCharacter == zeroWidthJoinerCharacter)
772 currentFontData = nextFontData; 810 currentFontData = nextFontData;
773 if ((nextFontData != currentFontData) || ((currentScript != nextScri pt) && (nextScript != USCRIPT_INHERITED) && (!uscript_hasScript(character, curre ntScript)))) 811 if ((nextFontData != currentFontData) || ((currentScript != nextScri pt) && (nextScript != USCRIPT_INHERITED) && (!uscript_hasScript(character, curre ntScript))))
774 break; 812 break;
775 currentCharacterPosition = iterator.characters(); 813 currentCharacterPosition = iterator.characters();
776 lastCharacter = character; 814 lastCharacter = character;
777 } 815 }
778 816
779 CandidateRun run = { lastCharacter, startIndexOfCurrentRun, static_cast< unsigned>(iterator.offset()), currentFontData, currentScript }; 817 CandidateRun run = { lastCharacter, startIndexOfCurrentRun, static_cast< unsigned>(iterator.offset()), currentFontData, currentScript };
780 runs->append(run); 818 runs->append(run);
781 819
782 startIndexOfCurrentRun = iterator.offset(); 820 startIndexOfCurrentRun = iterator.offset();
783 } while (iterator.consume(character)); 821 } while (!iterator.atEnd());
784 822
785 return true; 823 return true;
786 } 824 }
787 825
788 static inline bool matchesAdjacentRun(UScriptCode* scriptExtensions, int length, 826 static inline bool matchesAdjacentRun(UScriptCode* scriptExtensions, int length,
789 CandidateRun& adjacentRun) 827 CandidateRun& adjacentRun)
790 { 828 {
791 for (int i = 0; i < length; i++) { 829 for (int i = 0; i < length; i++) {
792 if (scriptExtensions[i] == adjacentRun.script) 830 if (scriptExtensions[i] == adjacentRun.script)
793 return true; 831 return true;
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
886 return true; 924 return true;
887 } 925 }
888 926
889 bool HarfBuzzShaper::createHarfBuzzRuns() 927 bool HarfBuzzShaper::createHarfBuzzRuns()
890 { 928 {
891 if (m_normalizedBufferLength == 1) 929 if (m_normalizedBufferLength == 1)
892 return createHarfBuzzRunsForSingleCharacter(); 930 return createHarfBuzzRunsForSingleCharacter();
893 931
894 Vector<CandidateRun> candidateRuns; 932 Vector<CandidateRun> candidateRuns;
895 if (!collectCandidateRuns(m_normalizedBuffer.get(), 933 if (!collectCandidateRuns(m_normalizedBuffer.get(),
896 m_normalizedBufferLength, m_font, &candidateRuns, m_textRun.normalizeSpa ce())) 934 m_normalizedBufferLength, m_font, &candidateRuns, m_textRun))
897 return false; 935 return false;
898 936
899 if (!resolveCandidateRuns(candidateRuns)) 937 if (!resolveCandidateRuns(candidateRuns))
900 return false; 938 return false;
901 939
902 size_t length = candidateRuns.size(); 940 size_t length = candidateRuns.size();
903 for (size_t i = 0; i < length; ) { 941 for (size_t i = 0; i < length; ) {
904 CandidateRun& run = candidateRuns[i]; 942 CandidateRun& run = candidateRuns[i];
943 if (run.character == tabulationCharacter && m_textRun.allowTabs()) {
eae 2015/07/20 17:39:24 Is this really needed? Isn't the extra condition i
kojii 2015/07/21 01:11:47 Yeah, this check is needed if the first run is tab
944 addHarfBuzzRun(run.start, run.end, run.fontData, run.script);
945 ++i;
946 continue;
947 }
905 CandidateRun lastMatchingRun = run; 948 CandidateRun lastMatchingRun = run;
906 for (i++; i < length; i++) { 949 for (i++; i < length; i++) {
907 if (candidateRuns[i].script != run.script 950 if (candidateRuns[i].script != run.script
908 || candidateRuns[i].fontData != run.fontData) 951 || candidateRuns[i].fontData != run.fontData
952 || candidateRuns[i].character == tabulationCharacter)
909 break; 953 break;
910 lastMatchingRun = candidateRuns[i]; 954 lastMatchingRun = candidateRuns[i];
911 } 955 }
912 addHarfBuzzRun(run.start, lastMatchingRun.end, run.fontData, run.script) ; 956 addHarfBuzzRun(run.start, lastMatchingRun.end, run.fontData, run.script) ;
913 } 957 }
914 return !m_harfBuzzRuns.isEmpty(); 958 return !m_harfBuzzRuns.isEmpty();
915 } 959 }
916 960
917 // A port of hb_icu_script_to_script because harfbuzz on CrOS is built 961 // A port of hb_icu_script_to_script because harfbuzz on CrOS is built
918 // without hb-icu. See http://crbug.com/356929 962 // without hb-icu. See http://crbug.com/356929
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
951 static const uint16_t* toUint16(const UChar* src) 995 static const uint16_t* toUint16(const UChar* src)
952 { 996 {
953 // FIXME: This relies on undefined behavior however it works on the 997 // FIXME: This relies on undefined behavior however it works on the
954 // current versions of all compilers we care about and avoids making 998 // current versions of all compilers we care about and avoids making
955 // a copy of the string. 999 // a copy of the string.
956 static_assert(sizeof(UChar) == sizeof(uint16_t), "UChar should be the same s ize as uint16_t"); 1000 static_assert(sizeof(UChar) == sizeof(uint16_t), "UChar should be the same s ize as uint16_t");
957 return reinterpret_cast<const uint16_t*>(src); 1001 return reinterpret_cast<const uint16_t*>(src);
958 } 1002 }
959 1003
960 static inline void addToHarfBuzzBufferInternal(hb_buffer_t* buffer, 1004 static inline void addToHarfBuzzBufferInternal(hb_buffer_t* buffer,
961 const FontDescription& fontDescription, const UChar* normalizedBuffer, 1005 const FontDescription& fontDescription, const UChar* characters,
962 unsigned startIndex, unsigned numCharacters) 1006 unsigned numCharacters)
963 { 1007 {
964 if (fontDescription.variant() == FontVariantSmallCaps 1008 if (fontDescription.variant() == FontVariantSmallCaps
965 && u_islower(normalizedBuffer[startIndex])) { 1009 && u_islower(characters[0])) {
966 String upperText = String(normalizedBuffer + startIndex, numCharacters) 1010 String upperText = String(characters, numCharacters)
967 .upper(); 1011 .upper();
968 // TextRun is 16 bit, therefore upperText is 16 bit, even after we call 1012 // TextRun is 16 bit, therefore upperText is 16 bit, even after we call
969 // makeUpper(). 1013 // makeUpper().
970 ASSERT(!upperText.is8Bit()); 1014 ASSERT(!upperText.is8Bit());
971 hb_buffer_add_utf16(buffer, toUint16(upperText.characters16()), 1015 hb_buffer_add_utf16(buffer, toUint16(upperText.characters16()),
972 numCharacters, 0, numCharacters); 1016 numCharacters, 0, numCharacters);
973 } else { 1017 } else {
974 hb_buffer_add_utf16(buffer, toUint16(normalizedBuffer + startIndex), 1018 hb_buffer_add_utf16(buffer, toUint16(characters),
975 numCharacters, 0, numCharacters); 1019 numCharacters, 0, numCharacters);
976 } 1020 }
977 } 1021 }
978 1022
979 PassRefPtr<ShapeResult> HarfBuzzShaper::shapeHarfBuzzRuns() 1023 PassRefPtr<ShapeResult> HarfBuzzShaper::shapeHarfBuzzRuns()
980 { 1024 {
981 RefPtr<ShapeResult> result = ShapeResult::create( 1025 RefPtr<ShapeResult> result = ShapeResult::create(
982 m_normalizedBufferLength, m_textRun.direction()); 1026 m_normalizedBufferLength, m_textRun.direction());
983 HarfBuzzScopedPtr<hb_buffer_t> harfBuzzBuffer(hb_buffer_create(), hb_buffer_ destroy); 1027 HarfBuzzScopedPtr<hb_buffer_t> harfBuzzBuffer(hb_buffer_create(), hb_buffer_ destroy);
984 1028
985 const FontDescription& fontDescription = m_font->fontDescription(); 1029 const FontDescription& fontDescription = m_font->fontDescription();
986 const String& localeString = fontDescription.locale(); 1030 const String& localeString = fontDescription.locale();
987 CString locale = localeString.latin1(); 1031 CString locale = localeString.latin1();
988 const hb_language_t language = hb_language_from_string(locale.data(), locale .length()); 1032 const hb_language_t language = hb_language_from_string(locale.data(), locale .length());
989 1033
990 result->m_runs.resize(m_harfBuzzRuns.size()); 1034 result->m_runs.resize(m_harfBuzzRuns.size());
991 for (unsigned i = 0; i < m_harfBuzzRuns.size(); ++i) { 1035 for (unsigned i = 0; i < m_harfBuzzRuns.size(); ++i) {
992 unsigned runIndex = m_textRun.rtl() ? m_harfBuzzRuns.size() - i - 1 : i; 1036 unsigned runIndex = m_textRun.rtl() ? m_harfBuzzRuns.size() - i - 1 : i;
993 const HarfBuzzRun* currentRun = &m_harfBuzzRuns[runIndex]; 1037 const HarfBuzzRun* currentRun = &m_harfBuzzRuns[runIndex];
1038 ASSERT(m_normalizedBufferLength >= currentRun->m_startIndex + currentRun ->m_numCharacters);
1039 const UChar* characters = m_normalizedBuffer.get() + currentRun->m_start Index;
1040
1041 if (characters[0] == tabulationCharacter && m_textRun.allowTabs()) {
1042 shapeResultForTabulationCharacters(result.get(), i, currentRun);
1043 continue;
1044 }
994 1045
995 const SimpleFontData* currentFontData = currentRun->m_fontData; 1046 const SimpleFontData* currentFontData = currentRun->m_fontData;
996 FontPlatformData* platformData = const_cast<FontPlatformData*>(&currentF ontData->platformData()); 1047 FontPlatformData* platformData = const_cast<FontPlatformData*>(&currentF ontData->platformData());
997 HarfBuzzFace* face = platformData->harfBuzzFace(); 1048 HarfBuzzFace* face = platformData->harfBuzzFace();
998 if (!face) 1049 if (!face)
999 return nullptr; 1050 return nullptr;
1000 1051
1001 hb_buffer_set_language(harfBuzzBuffer.get(), language); 1052 hb_buffer_set_language(harfBuzzBuffer.get(), language);
1002 hb_buffer_set_script(harfBuzzBuffer.get(), currentRun->m_script); 1053 hb_buffer_set_script(harfBuzzBuffer.get(), currentRun->m_script);
1003 hb_buffer_set_direction(harfBuzzBuffer.get(), currentRun->m_direction); 1054 hb_buffer_set_direction(harfBuzzBuffer.get(), currentRun->m_direction);
1004 1055
1005 // Add a space as pre-context to the buffer. This prevents showing dotte d-circle 1056 // Add a space as pre-context to the buffer. This prevents showing dotte d-circle
1006 // for combining marks at the beginning of runs. 1057 // for combining marks at the beginning of runs.
1007 static const uint16_t preContext = spaceCharacter; 1058 static const uint16_t preContext = spaceCharacter;
1008 hb_buffer_add_utf16(harfBuzzBuffer.get(), &preContext, 1, 1, 0); 1059 hb_buffer_add_utf16(harfBuzzBuffer.get(), &preContext, 1, 1, 0);
1009 1060
1010 addToHarfBuzzBufferInternal(harfBuzzBuffer.get(), 1061 addToHarfBuzzBufferInternal(harfBuzzBuffer.get(),
1011 fontDescription, m_normalizedBuffer.get(), currentRun->m_startIndex, 1062 fontDescription, characters, currentRun->m_numCharacters);
1012 currentRun->m_numCharacters);
1013 1063
1014 if (fontDescription.isVerticalAnyUpright()) 1064 if (fontDescription.isVerticalAnyUpright())
1015 face->setScriptForVerticalGlyphSubstitution(harfBuzzBuffer.get()); 1065 face->setScriptForVerticalGlyphSubstitution(harfBuzzBuffer.get());
1016 1066
1017 HarfBuzzScopedPtr<hb_font_t> harfBuzzFont(face->createFont(), hb_font_de stroy); 1067 HarfBuzzScopedPtr<hb_font_t> harfBuzzFont(face->createFont(), hb_font_de stroy);
1018 hb_shape(harfBuzzFont.get(), harfBuzzBuffer.get(), m_features.isEmpty() ? 0 : m_features.data(), m_features.size()); 1068 hb_shape(harfBuzzFont.get(), harfBuzzBuffer.get(), m_features.isEmpty() ? 0 : m_features.data(), m_features.size());
1019 shapeResult(result.get(), i, currentRun, harfBuzzBuffer.get()); 1069 shapeResult(result.get(), i, currentRun, harfBuzzBuffer.get());
1020 1070
1021 hb_buffer_reset(harfBuzzBuffer.get()); 1071 hb_buffer_reset(harfBuzzBuffer.get());
1022 } 1072 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1060 bool runEnd = i + 1 == numGlyphs; 1110 bool runEnd = i + 1 == numGlyphs;
1061 uint16_t glyph = glyphInfos[i].codepoint; 1111 uint16_t glyph = glyphInfos[i].codepoint;
1062 offsetX = harfBuzzPositionToFloat(glyphPositions[i].x_offset); 1112 offsetX = harfBuzzPositionToFloat(glyphPositions[i].x_offset);
1063 offsetY = -harfBuzzPositionToFloat(glyphPositions[i].y_offset); 1113 offsetY = -harfBuzzPositionToFloat(glyphPositions[i].y_offset);
1064 1114
1065 // One out of x_advance and y_advance is zero, depending on 1115 // One out of x_advance and y_advance is zero, depending on
1066 // whether the buffer direction is horizontal or vertical. 1116 // whether the buffer direction is horizontal or vertical.
1067 float advance = harfBuzzPositionToFloat(glyphPositions[i].x_advance - gl yphPositions[i].y_advance); 1117 float advance = harfBuzzPositionToFloat(glyphPositions[i].x_advance - gl yphPositions[i].y_advance);
1068 unsigned currentCharacterIndex = currentRun->m_startIndex + glyphInfos[i ].cluster; 1118 unsigned currentCharacterIndex = currentRun->m_startIndex + glyphInfos[i ].cluster;
1069 RELEASE_ASSERT(m_normalizedBufferLength > currentCharacterIndex); 1119 RELEASE_ASSERT(m_normalizedBufferLength > currentCharacterIndex);
1120 ASSERT(m_normalizedBuffer[currentCharacterIndex] != tabulationCharacter || !m_textRun.allowTabs());
1070 bool isClusterEnd = runEnd || glyphInfos[i].cluster != glyphInfos[i + 1] .cluster; 1121 bool isClusterEnd = runEnd || glyphInfos[i].cluster != glyphInfos[i + 1] .cluster;
1071 float spacing = 0; 1122 float spacing = 0;
1072 1123
1073 run->m_glyphData[i].characterIndex = glyphInfos[i].cluster; 1124 run->m_glyphData[i].characterIndex = glyphInfos[i].cluster;
1074 1125
1075 if (isClusterEnd) 1126 if (isClusterEnd)
1076 spacing += adjustSpacing(run, i, currentCharacterIndex, *directionOf fset, totalAdvance); 1127 spacing += adjustSpacing(run, i, currentCharacterIndex, *directionOf fset, totalAdvance);
1077 1128
1078 if (currentFontData->isZeroWidthSpaceGlyph(glyph)) { 1129 if (currentFontData->isZeroWidthSpaceGlyph(glyph)) {
1079 run->setGlyphAndPositions(i, glyph, 0, 0, 0); 1130 run->setGlyphAndPositions(i, glyph, 0, 0, 0);
(...skipping 16 matching lines...) Expand all
1096 result->m_glyphBoundingBox.unite(glyphBounds); 1147 result->m_glyphBoundingBox.unite(glyphBounds);
1097 glyphOrigin += FloatSize(advance + offsetX, offsetY); 1148 glyphOrigin += FloatSize(advance + offsetX, offsetY);
1098 } 1149 }
1099 1150
1100 run->m_width = totalAdvance > 0.0 ? totalAdvance : 0.0; 1151 run->m_width = totalAdvance > 0.0 ? totalAdvance : 0.0;
1101 result->m_width += run->m_width; 1152 result->m_width += run->m_width;
1102 for (auto& fallbackFont : *m_fallbackFonts) 1153 for (auto& fallbackFont : *m_fallbackFonts)
1103 result->m_fallbackFonts.add(const_cast<SimpleFontData*>(fallbackFont)); 1154 result->m_fallbackFonts.add(const_cast<SimpleFontData*>(fallbackFont));
1104 } 1155 }
1105 1156
1157 void HarfBuzzShaper::shapeResultForTabulationCharacters(ShapeResult* result, uns igned index, const HarfBuzzRun* currentRun)
1158 {
1159 const SimpleFontData& fontData = *currentRun->m_fontData;
1160 ShapeResult::RunInfo* run = new ShapeResult::RunInfo(currentRun->m_fontData,
1161 currentRun->m_direction, currentRun->m_script, currentRun->m_startIndex,
1162 currentRun->m_numCharacters, currentRun->m_numCharacters);
1163 result->m_runs[index] = run;
1164 result->m_numGlyphs += currentRun->m_numCharacters;
1165 float position = m_textRun.xPos() + result->m_width;
1166 float positionStart = position;
1167 for (size_t i = 0; i < currentRun->m_numCharacters; ++i) {
1168 ASSERT(m_normalizedBuffer[currentRun->m_startIndex + i] == tabulationCha racter);
1169 float advance = m_font->tabWidth(fontData, m_textRun.tabSize(), position );
1170 run->m_glyphData[i].characterIndex = i;
1171 run->setGlyphAndPositions(i, fontData.spaceGlyph(), advance, 0, 0);
1172 position += advance;
1173 }
1174 run->m_width = position - positionStart;
1175 result->m_width += run->m_width;
1176 }
1177
1106 float HarfBuzzShaper::adjustSpacing(ShapeResult::RunInfo* run, size_t glyphIndex , unsigned currentCharacterIndex, float& offset, float& totalAdvance) 1178 float HarfBuzzShaper::adjustSpacing(ShapeResult::RunInfo* run, size_t glyphIndex , unsigned currentCharacterIndex, float& offset, float& totalAdvance)
1107 { 1179 {
1108 float spacing = 0; 1180 float spacing = 0;
1109 UChar32 character = m_normalizedBuffer[currentCharacterIndex]; 1181 UChar32 character = m_normalizedBuffer[currentCharacterIndex];
1110 if (m_letterSpacing && !Character::treatAsZeroWidthSpace(character)) 1182 if (m_letterSpacing && !Character::treatAsZeroWidthSpace(character))
1111 spacing += m_letterSpacing; 1183 spacing += m_letterSpacing;
1112 1184
1113 bool treatAsSpace = Character::treatAsSpace(character); 1185 bool treatAsSpace = Character::treatAsSpace(character);
1114 if (treatAsSpace && currentCharacterIndex && (character != '\t' || !m_textRu n.allowTabs())) 1186 if (treatAsSpace && currentCharacterIndex && (character != '\t' || !m_textRu n.allowTabs()))
1115 spacing += m_wordSpacingAdjustment; 1187 spacing += m_wordSpacingAdjustment;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1153 return spacing; 1225 return spacing;
1154 } 1226 }
1155 1227
1156 // Don't need to check m_textRun.allowsTrailingExpansion() since it's covere d by !m_expansionOpportunityCount above 1228 // Don't need to check m_textRun.allowsTrailingExpansion() since it's covere d by !m_expansionOpportunityCount above
1157 spacing += nextExpansionPerOpportunity(); 1229 spacing += nextExpansionPerOpportunity();
1158 m_isAfterExpansion = true; 1230 m_isAfterExpansion = true;
1159 return spacing; 1231 return spacing;
1160 } 1232 }
1161 1233
1162 } // namespace blink 1234 } // namespace blink
OLDNEW
« no previous file with comments | « Source/platform/fonts/shaping/HarfBuzzShaper.h ('k') | Source/platform/fonts/shaping/HarfBuzzShaperTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698