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 931 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
942 glyphBounds.move(glyphOrigin.x(), glyphOrigin.y()); | 942 glyphBounds.move(glyphOrigin.x(), glyphOrigin.y()); |
943 m_glyphBoundingBox.unite(glyphBounds); | 943 m_glyphBoundingBox.unite(glyphBounds); |
944 glyphOrigin += FloatSize(advance + offsetX, offsetY); | 944 glyphOrigin += FloatSize(advance + offsetX, offsetY); |
945 | 945 |
946 totalAdvance += advance; | 946 totalAdvance += advance; |
947 } | 947 } |
948 currentRun->setWidth(totalAdvance > 0.0 ? totalAdvance : 0.0); | 948 currentRun->setWidth(totalAdvance > 0.0 ? totalAdvance : 0.0); |
949 m_totalWidth += currentRun->width(); | 949 m_totalWidth += currentRun->width(); |
950 } | 950 } |
951 | 951 |
952 void HarfBuzzShaper::fillGlyphBufferFromHarfBuzzRun(GlyphBuffer* glyphBuffer, | 952 float HarfBuzzShaper::fillGlyphBufferFromHarfBuzzRun(GlyphBuffer* glyphBuffer, |
953 HarfBuzzRun* currentRun, float& carryAdvance) | 953 HarfBuzzRun* currentRun, float initialAdvance) |
954 { | 954 { |
955 FloatSize* offsets = currentRun->offsets(); | 955 FloatSize* offsets = currentRun->offsets(); |
956 uint16_t* glyphs = currentRun->glyphs(); | 956 uint16_t* glyphs = currentRun->glyphs(); |
957 float* advances = currentRun->advances(); | 957 float* advances = currentRun->advances(); |
958 unsigned numGlyphs = currentRun->numGlyphs(); | 958 unsigned numGlyphs = currentRun->numGlyphs(); |
959 uint16_t* glyphToCharacterIndexes = currentRun->glyphToCharacterIndexes(); | 959 uint16_t* glyphToCharacterIndexes = currentRun->glyphToCharacterIndexes(); |
960 FloatSize runStartOffset = FloatSize(); | 960 float advanceSoFar = initialAdvance; |
961 if (m_run.rtl()) { | 961 if (m_run.rtl()) { |
962 for (unsigned i = 0; i < numGlyphs; ++i) { | 962 for (unsigned i = 0; i < numGlyphs; ++i) { |
963 uint16_t currentCharacterIndex = currentRun->startIndex() + glyphToC
haracterIndexes[i]; | 963 uint16_t currentCharacterIndex = currentRun->startIndex() + glyphToC
haracterIndexes[i]; |
964 if (currentCharacterIndex >= m_toIndex) { | 964 if (currentCharacterIndex >= m_toIndex) { |
965 carryAdvance += advances[i]; | 965 advanceSoFar += advances[i]; |
966 } else if (currentCharacterIndex >= m_fromIndex) { | 966 } else if (currentCharacterIndex >= m_fromIndex) { |
967 runStartOffset = HB_DIRECTION_IS_HORIZONTAL(currentRun->directio
n()) ? FloatSize(carryAdvance, 0) : FloatSize(0, carryAdvance); | 967 FloatPoint runStartOffset = HB_DIRECTION_IS_HORIZONTAL(currentRu
n->direction()) ? |
968 glyphBuffer->add(glyphs[i], currentRun->fontData(), runStartOffs
et + offsets[i], carryAdvance + advances[i]); | 968 FloatPoint(advanceSoFar, 0) : FloatPoint(0, advanceSoFar); |
969 carryAdvance = 0; | 969 glyphBuffer->add(glyphs[i], currentRun->fontData(), runStartOffs
et + offsets[i]); |
| 970 advanceSoFar += advances[i]; |
970 } | 971 } |
971 } | 972 } |
972 } else { | 973 } else { |
973 for (unsigned i = 0; i < numGlyphs; ++i) { | 974 for (unsigned i = 0; i < numGlyphs; ++i) { |
974 uint16_t currentCharacterIndex = currentRun->startIndex() + glyphToC
haracterIndexes[i]; | 975 uint16_t currentCharacterIndex = currentRun->startIndex() + glyphToC
haracterIndexes[i]; |
975 if (currentCharacterIndex < m_fromIndex) { | 976 if (currentCharacterIndex < m_fromIndex) { |
976 carryAdvance += advances[i]; | 977 advanceSoFar += advances[i]; |
977 } else if (currentCharacterIndex < m_toIndex) { | 978 } else if (currentCharacterIndex < m_toIndex) { |
978 runStartOffset = HB_DIRECTION_IS_HORIZONTAL(currentRun->directio
n()) ? FloatSize(carryAdvance, 0) : FloatSize(0, carryAdvance); | 979 FloatPoint runStartOffset = HB_DIRECTION_IS_HORIZONTAL(currentRu
n->direction()) ? |
979 glyphBuffer->add(glyphs[i], currentRun->fontData(), runStartOffs
et + offsets[i], carryAdvance + advances[i]); | 980 FloatPoint(advanceSoFar, 0) : FloatPoint(0, advanceSoFar); |
980 carryAdvance = 0; | 981 glyphBuffer->add(glyphs[i], currentRun->fontData(), runStartOffs
et + offsets[i]); |
| 982 advanceSoFar += advances[i]; |
981 } | 983 } |
982 } | 984 } |
983 } | 985 } |
| 986 |
| 987 return advanceSoFar - initialAdvance; |
984 } | 988 } |
985 | 989 |
986 void HarfBuzzShaper::fillGlyphBufferForTextEmphasis(GlyphBuffer* glyphBuffer, Ha
rfBuzzRun* currentRun) | 990 float HarfBuzzShaper::fillGlyphBufferForTextEmphasis(GlyphBuffer* glyphBuffer, H
arfBuzzRun* currentRun, float initialAdvance) |
987 { | 991 { |
988 // FIXME: Instead of generating a synthetic GlyphBuffer here which is then u
sed by the | 992 // FIXME: Instead of generating a synthetic GlyphBuffer here which is then u
sed by the |
989 // drawEmphasisMarks method of FontFastPath, we should roll our own emphasis
mark drawing function. | 993 // drawEmphasisMarks method of FontFastPath, we should roll our own emphasis
mark drawing function. |
990 | 994 |
991 float* advances = currentRun->advances(); | 995 float* advances = currentRun->advances(); |
992 unsigned numGlyphs = currentRun->numGlyphs(); | 996 unsigned numGlyphs = currentRun->numGlyphs(); |
993 uint16_t* glyphToCharacterIndexes = currentRun->glyphToCharacterIndexes(); | 997 uint16_t* glyphToCharacterIndexes = currentRun->glyphToCharacterIndexes(); |
994 unsigned graphemesInCluster = 1; | 998 unsigned graphemesInCluster = 1; |
995 float clusterAdvance = 0; | 999 float clusterAdvance = 0; |
996 uint16_t clusterStart; | 1000 uint16_t clusterStart; |
997 | 1001 |
998 // A "cluster" in this context means a cluster as it is used by HarfBuzz: | 1002 // A "cluster" in this context means a cluster as it is used by HarfBuzz: |
999 // The minimal group of characters and corresponding glyphs, that cannot be
broken | 1003 // The minimal group of characters and corresponding glyphs, that cannot be
broken |
1000 // down further from a text shaping point of view. | 1004 // down further from a text shaping point of view. |
1001 // A cluster can contain multiple glyphs and grapheme clusters, with mutuall
y | 1005 // A cluster can contain multiple glyphs and grapheme clusters, with mutuall
y |
1002 // overlapping boundaries. Below we count grapheme clusters per HarfBuzz clu
sters, | 1006 // overlapping boundaries. Below we count grapheme clusters per HarfBuzz clu
sters, |
1003 // then linearly split the sum of corresponding glyph advances by the number
of | 1007 // then linearly split the sum of corresponding glyph advances by the number
of |
1004 // grapheme clusters in order to find positions for emphasis mark drawing. | 1008 // grapheme clusters in order to find positions for emphasis mark drawing. |
1005 | 1009 |
1006 if (m_run.rtl()) | 1010 if (m_run.rtl()) |
1007 clusterStart = currentRun->startIndex() + currentRun->numCharacters(); | 1011 clusterStart = currentRun->startIndex() + currentRun->numCharacters(); |
1008 else | 1012 else |
1009 clusterStart = currentRun->startIndex() + glyphToCharacterIndexes[0]; | 1013 clusterStart = currentRun->startIndex() + glyphToCharacterIndexes[0]; |
1010 | 1014 |
| 1015 float advanceSoFar = initialAdvance; |
1011 for (unsigned i = 0; i < numGlyphs; ++i) { | 1016 for (unsigned i = 0; i < numGlyphs; ++i) { |
1012 uint16_t currentCharacterIndex = currentRun->startIndex() + glyphToChara
cterIndexes[i]; | 1017 uint16_t currentCharacterIndex = currentRun->startIndex() + glyphToChara
cterIndexes[i]; |
1013 bool isRunEnd = (i + 1 == numGlyphs); | 1018 bool isRunEnd = (i + 1 == numGlyphs); |
1014 bool isClusterEnd = isRunEnd || (currentRun->startIndex() + glyphToChar
acterIndexes[i + 1] != currentCharacterIndex); | 1019 bool isClusterEnd = isRunEnd || (currentRun->startIndex() + glyphToChar
acterIndexes[i + 1] != currentCharacterIndex); |
1015 clusterAdvance += advances[i]; | 1020 clusterAdvance += advances[i]; |
1016 | 1021 |
1017 if (isClusterEnd) { | 1022 if (isClusterEnd) { |
1018 uint16_t clusterEnd; | 1023 uint16_t clusterEnd; |
1019 if (m_run.rtl()) | 1024 if (m_run.rtl()) |
1020 clusterEnd = currentCharacterIndex; | 1025 clusterEnd = currentCharacterIndex; |
1021 else | 1026 else |
1022 clusterEnd = isRunEnd ? currentRun->startIndex() + currentRun->n
umCharacters() : currentRun->startIndex() + glyphToCharacterIndexes[i + 1]; | 1027 clusterEnd = isRunEnd ? currentRun->startIndex() + currentRun->n
umCharacters() : currentRun->startIndex() + glyphToCharacterIndexes[i + 1]; |
1023 | 1028 |
1024 graphemesInCluster = countGraphemesInCluster(m_normalizedBuffer.get(
), m_normalizedBufferLength, clusterStart, clusterEnd); | 1029 graphemesInCluster = countGraphemesInCluster(m_normalizedBuffer.get(
), m_normalizedBufferLength, clusterStart, clusterEnd); |
1025 if (!graphemesInCluster || !clusterAdvance) | 1030 if (!graphemesInCluster || !clusterAdvance) |
1026 continue; | 1031 continue; |
1027 | 1032 |
1028 float glyphAdvanceX = clusterAdvance / graphemesInCluster; | 1033 float glyphAdvanceX = clusterAdvance / graphemesInCluster; |
1029 for (unsigned j = 0; j < graphemesInCluster; ++j) { | 1034 for (unsigned j = 0; j < graphemesInCluster; ++j) { |
1030 // Do not put emphasis marks on space, separator, and control ch
aracters. | 1035 // Do not put emphasis marks on space, separator, and control ch
aracters. |
1031 Glyph glyphToAdd = Character::canReceiveTextEmphasis(m_run[curre
ntCharacterIndex]) ? 1 : 0; | 1036 Glyph glyphToAdd = Character::canReceiveTextEmphasis(m_run[curre
ntCharacterIndex]) ? 1 : 0; |
1032 glyphBuffer->add(glyphToAdd, currentRun->fontData(), glyphAdvanc
eX); | 1037 // The emphasis code expects mid-glyph offsets. |
| 1038 glyphBuffer->add(glyphToAdd, currentRun->fontData(), advanceSoFa
r + glyphAdvanceX / 2); |
| 1039 advanceSoFar += glyphAdvanceX; |
1033 } | 1040 } |
1034 clusterStart = clusterEnd; | 1041 clusterStart = clusterEnd; |
1035 clusterAdvance = 0; | 1042 clusterAdvance = 0; |
1036 } | 1043 } |
1037 } | 1044 } |
| 1045 |
| 1046 return advanceSoFar - initialAdvance; |
1038 } | 1047 } |
1039 | 1048 |
1040 bool HarfBuzzShaper::fillGlyphBuffer(GlyphBuffer* glyphBuffer) | 1049 bool HarfBuzzShaper::fillGlyphBuffer(GlyphBuffer* glyphBuffer) |
1041 { | 1050 { |
| 1051 ASSERT(glyphBuffer); |
| 1052 |
1042 unsigned numRuns = m_harfBuzzRuns.size(); | 1053 unsigned numRuns = m_harfBuzzRuns.size(); |
1043 float carryAdvance = 0; | 1054 float advanceSoFar = 0; |
1044 if (m_run.rtl()) { | 1055 for (unsigned runIndex = 0; runIndex < numRuns; ++runIndex) { |
1045 for (int runIndex = numRuns - 1; runIndex >= 0; --runIndex) { | 1056 HarfBuzzRun* currentRun = m_harfBuzzRuns[m_run.ltr() ? runIndex : numRun
s - runIndex - 1].get(); |
1046 HarfBuzzRun* currentRun = m_harfBuzzRuns[runIndex].get(); | 1057 if (!currentRun->hasGlyphToCharacterIndexes()) { |
1047 if (!currentRun->hasGlyphToCharacterIndexes()) { | 1058 // FIXME: bug 337886, 359664 |
1048 // FIXME: bug 337886, 359664 | 1059 continue; |
1049 continue; | |
1050 } | |
1051 if (m_forTextEmphasis == ForTextEmphasis) { | |
1052 fillGlyphBufferForTextEmphasis(glyphBuffer, currentRun); | |
1053 } else { | |
1054 fillGlyphBufferFromHarfBuzzRun(glyphBuffer, currentRun, carryAdv
ance); | |
1055 } | |
1056 } | 1060 } |
1057 } else { | 1061 advanceSoFar += (m_forTextEmphasis == ForTextEmphasis) |
1058 for (unsigned runIndex = 0; runIndex < numRuns; ++runIndex) { | 1062 ? fillGlyphBufferForTextEmphasis(glyphBuffer, currentRun, advanceSoF
ar) |
1059 HarfBuzzRun* currentRun = m_harfBuzzRuns[runIndex].get(); | 1063 : fillGlyphBufferFromHarfBuzzRun(glyphBuffer, currentRun, advanceSoF
ar); |
1060 if (!currentRun->hasGlyphToCharacterIndexes()) { | |
1061 // FIXME: bug 337886, 359664 | |
1062 continue; | |
1063 } | |
1064 if (m_forTextEmphasis == ForTextEmphasis) { | |
1065 fillGlyphBufferForTextEmphasis(glyphBuffer, currentRun); | |
1066 } else { | |
1067 fillGlyphBufferFromHarfBuzzRun(glyphBuffer, currentRun, carryAdv
ance); | |
1068 } | |
1069 } | |
1070 } | 1064 } |
1071 return glyphBuffer->size(); | 1065 return glyphBuffer->size(); |
1072 } | 1066 } |
1073 | 1067 |
1074 int HarfBuzzShaper::offsetForPosition(float targetX) | 1068 int HarfBuzzShaper::offsetForPosition(float targetX) |
1075 { | 1069 { |
1076 int charactersSoFar = 0; | 1070 int charactersSoFar = 0; |
1077 float currentX = 0; | 1071 float currentX = 0; |
1078 | 1072 |
1079 if (m_run.rtl()) { | 1073 if (m_run.rtl()) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1144 fromX = 0; | 1138 fromX = 0; |
1145 if (!foundToX) | 1139 if (!foundToX) |
1146 toX = m_run.rtl() ? 0 : m_totalWidth; | 1140 toX = m_run.rtl() ? 0 : m_totalWidth; |
1147 | 1141 |
1148 if (fromX < toX) | 1142 if (fromX < toX) |
1149 return FloatRect(point.x() + fromX, point.y(), toX - fromX, height); | 1143 return FloatRect(point.x() + fromX, point.y(), toX - fromX, height); |
1150 return FloatRect(point.x() + toX, point.y(), fromX - toX, height); | 1144 return FloatRect(point.x() + toX, point.y(), fromX - toX, height); |
1151 } | 1145 } |
1152 | 1146 |
1153 } // namespace blink | 1147 } // namespace blink |
OLD | NEW |