OLD | NEW |
---|---|
1 /* | 1 /* |
2 * (C) 1999 Lars Knoll (knoll@kde.org) | 2 * (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 2000 Dirk Mueller (mueller@kde.org) | 3 * (C) 2000 Dirk Mueller (mueller@kde.org) |
4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r ights reserved. | 4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r ights reserved. |
5 * | 5 * |
6 * This library is free software; you can redistribute it and/or | 6 * This library is free software; you can redistribute it and/or |
7 * modify it under the terms of the GNU Library General Public | 7 * modify it under the terms of the GNU Library General Public |
8 * License as published by the Free Software Foundation; either | 8 * License as published by the Free Software Foundation; either |
9 * version 2 of the License, or (at your option) any later version. | 9 * version 2 of the License, or (at your option) any later version. |
10 * | 10 * |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
53 #include "wtf/text/StringBuilder.h" | 53 #include "wtf/text/StringBuilder.h" |
54 | 54 |
55 using namespace std; | 55 using namespace std; |
56 | 56 |
57 namespace WebCore { | 57 namespace WebCore { |
58 | 58 |
59 struct SameSizeAsInlineTextBox : public InlineBox { | 59 struct SameSizeAsInlineTextBox : public InlineBox { |
60 unsigned variables[1]; | 60 unsigned variables[1]; |
61 unsigned short variables2[2]; | 61 unsigned short variables2[2]; |
62 void* pointers[2]; | 62 void* pointers[2]; |
63 float u; | |
63 }; | 64 }; |
64 | 65 |
65 COMPILE_ASSERT(sizeof(InlineTextBox) == sizeof(SameSizeAsInlineTextBox), InlineT extBox_should_stay_small); | 66 COMPILE_ASSERT(sizeof(InlineTextBox) == sizeof(SameSizeAsInlineTextBox), InlineT extBox_should_stay_small); |
66 | 67 |
67 typedef WTF::HashMap<const InlineTextBox*, LayoutRect> InlineTextBoxOverflowMap; | 68 typedef WTF::HashMap<const InlineTextBox*, LayoutRect> InlineTextBoxOverflowMap; |
68 static InlineTextBoxOverflowMap* gTextBoxesWithOverflow; | 69 static InlineTextBoxOverflowMap* gTextBoxesWithOverflow; |
69 | 70 |
70 static const int misspellingLineThickness = 3; | 71 static const int misspellingLineThickness = 3; |
71 | 72 |
72 void InlineTextBox::destroy() | 73 void InlineTextBox::destroy() |
(...skipping 670 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
743 int startOffset = combinedText ? 0 : sPos; | 744 int startOffset = combinedText ? 0 : sPos; |
744 int endOffset = combinedText ? objectReplacementCharacterTextRun.len gth() : ePos; | 745 int endOffset = combinedText ? objectReplacementCharacterTextRun.len gth() : ePos; |
745 int paintRunLength = combinedText ? endOffset : length; | 746 int paintRunLength = combinedText ? endOffset : length; |
746 paintTextWithShadows(context, rendererToUse, combinedText ? combined Text->originalFont() : font, emphasisMarkTextRun, emphasisMark, emphasisMarkOffs et, startOffset, endOffset, paintRunLength, emphasisMarkTextOrigin, boxRect, sel ectionShadow, selectionStrokeWidth > 0, isHorizontal()); | 747 paintTextWithShadows(context, rendererToUse, combinedText ? combined Text->originalFont() : font, emphasisMarkTextRun, emphasisMark, emphasisMarkOffs et, startOffset, endOffset, paintRunLength, emphasisMarkTextOrigin, boxRect, sel ectionShadow, selectionStrokeWidth > 0, isHorizontal()); |
747 | 748 |
748 if (combinedText) | 749 if (combinedText) |
749 context->concatCTM(rotation(boxRect, Counterclockwise)); | 750 context->concatCTM(rotation(boxRect, Counterclockwise)); |
750 } | 751 } |
751 } | 752 } |
752 | 753 |
753 // Paint decorations | 754 // lets only store decorations style and underline thickness, painting of de coration style will be done later |
754 TextDecoration textDecorations = styleToUse->textDecorationsInEffect(); | 755 TextDecoration textDecorations = styleToUse->textDecorationsInEffect(); |
755 if (textDecorations != TextDecorationNone && paintInfo.phase != PaintPhaseSe lection) { | 756 if (textDecorations != TextDecorationNone && paintInfo.phase != PaintPhaseSe lection) { |
756 updateGraphicsContext(context, textFillColor, textStrokeColor, textStrok eWidth); | 757 float textDecorationThickness = styleToUse->fontMetrics().underlineThick ness(); |
leviw_travelin_and_unemployed
2014/03/21 20:43:08
Don't copy and paste this block of code. If you ne
| |
757 if (combinedText) | 758 int fontHeightInt = (int)(styleToUse->fontMetrics().floatHeight() + 0.5) ; |
758 context->concatCTM(rotation(boxRect, Clockwise)); | 759 if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fon tHeightInt >> 1))) |
759 paintDecoration(context, boxOrigin, textDecorations, textShadow); | 760 textDecorationThickness = std::max(1.f, styleToUse->computedFontSize () / 10.f); |
760 if (combinedText) | |
761 context->concatCTM(rotation(boxRect, Counterclockwise)); | |
762 } | |
763 | 761 |
764 if (paintInfo.phase == PaintPhaseForeground) { | 762 setDecorationThickness(textDecorationThickness); |
765 paintDocumentMarkers(context, boxOrigin, styleToUse, font, false); | |
766 | |
767 if (useCustomUnderlines) { | |
768 const Vector<CompositionUnderline>& underlines = renderer().frame()- >inputMethodController().customCompositionUnderlines(); | |
769 size_t numUnderlines = underlines.size(); | |
770 | |
771 for (size_t index = 0; index < numUnderlines; ++index) { | |
772 const CompositionUnderline& underline = underlines[index]; | |
773 | |
774 if (underline.endOffset <= start()) | |
775 // underline is completely before this run. This might be a n underline that sits | |
776 // before the first run we draw, or underlines that were wit hin runs we skipped | |
777 // due to truncation. | |
778 continue; | |
779 | |
780 if (underline.startOffset <= end()) { | |
781 // underline intersects this run. Paint it. | |
782 paintCompositionUnderline(context, boxOrigin, underline); | |
783 if (underline.endOffset > end() + 1) | |
784 // underline also runs into the next run. Bail now, no m ore marker advancement. | |
785 break; | |
786 } else | |
787 // underline is completely after this run, bail. A later ru n will paint it. | |
788 break; | |
789 } | |
790 } | |
791 } | 763 } |
792 | 764 |
793 if (shouldRotate) | 765 if (shouldRotate) |
794 context->concatCTM(rotation(boxRect, Counterclockwise)); | 766 context->concatCTM(rotation(boxRect, Counterclockwise)); |
795 } | 767 } |
796 | 768 |
797 void InlineTextBox::selectionStartEnd(int& sPos, int& ePos) | 769 void InlineTextBox::selectionStartEnd(int& sPos, int& ePos) |
798 { | 770 { |
799 int startPos, endPos; | 771 int startPos, endPos; |
800 if (renderer().selectionState() == RenderObject::SelectionInside) { | 772 if (renderer().selectionState() == RenderObject::SelectionInside) { |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1086 context->setShouldAntialias(antialiasDecoration); | 1058 context->setShouldAntialias(antialiasDecoration); |
1087 // Fall through | 1059 // Fall through |
1088 default: | 1060 default: |
1089 context->drawLineForText(start, width, isPrinting); | 1061 context->drawLineForText(start, width, isPrinting); |
1090 | 1062 |
1091 if (decoration.style == TextDecorationStyleDouble) | 1063 if (decoration.style == TextDecorationStyleDouble) |
1092 context->drawLineForText(start + FloatPoint(0, doubleOffset), width, isPrinting); | 1064 context->drawLineForText(start + FloatPoint(0, doubleOffset), width, isPrinting); |
1093 } | 1065 } |
1094 } | 1066 } |
1095 | 1067 |
1096 void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint& boxOrigin, TextDecoration deco, const ShadowList* shadowList) | 1068 void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint& boxOrigin, TextDecoration deco, const ShadowList* shadowList, float decorationTh ickness) |
1097 { | 1069 { |
1098 GraphicsContextStateSaver stateSaver(*context); | 1070 GraphicsContextStateSaver stateSaver(*context); |
1099 | 1071 |
1100 if (m_truncation == cFullTruncation) | 1072 if (m_truncation == cFullTruncation) |
1101 return; | 1073 return; |
1102 | 1074 |
1103 FloatPoint localOrigin = boxOrigin; | 1075 FloatPoint localOrigin = boxOrigin; |
1104 | 1076 |
1105 float width = m_logicalWidth; | 1077 float width = m_logicalWidth; |
1106 if (m_truncation != cNoTruncation) { | 1078 if (m_truncation != cNoTruncation) { |
(...skipping 15 matching lines...) Expand all Loading... | |
1122 bool linesAreOpaque = !isPrinting && (!(deco & TextDecorationUnderline) || u nderline.color.alpha() == 255) && (!(deco & TextDecorationOverline) || overline. color.alpha() == 255) && (!(deco & TextDecorationLineThrough) || linethrough.col or.alpha() == 255); | 1094 bool linesAreOpaque = !isPrinting && (!(deco & TextDecorationUnderline) || u nderline.color.alpha() == 255) && (!(deco & TextDecorationOverline) || overline. color.alpha() == 255) && (!(deco & TextDecorationLineThrough) || linethrough.col or.alpha() == 255); |
1123 | 1095 |
1124 RenderStyle* styleToUse = renderer().style(isFirstLineStyle()); | 1096 RenderStyle* styleToUse = renderer().style(isFirstLineStyle()); |
1125 int baseline = styleToUse->fontMetrics().ascent(); | 1097 int baseline = styleToUse->fontMetrics().ascent(); |
1126 | 1098 |
1127 size_t shadowCount = shadowList ? shadowList->shadows().size() : 0; | 1099 size_t shadowCount = shadowList ? shadowList->shadows().size() : 0; |
1128 // Set the thick of the line to be 10% (or something else ?)of the computed font size and not less than 1px. | 1100 // Set the thick of the line to be 10% (or something else ?)of the computed font size and not less than 1px. |
1129 // Using computedFontSize should take care of zoom as well. | 1101 // Using computedFontSize should take care of zoom as well. |
1130 | 1102 |
1131 // Update Underline thickness, in case we have Faulty Font Metrics calculati ng underline thickness by old method. | 1103 // Update Underline thickness, in case we have Faulty Font Metrics calculati ng underline thickness by old method. |
1132 float textDecorationThickness = styleToUse->fontMetrics().underlineThickness (); | 1104 float textDecorationThickness = 0; |
1133 int fontHeightInt = (int)(styleToUse->fontMetrics().floatHeight() + 0.5); | 1105 if (!decorationThickness) { |
leviw_travelin_and_unemployed
2014/03/21 20:43:08
I don't fully understand the case when we have to
| |
1134 if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHei ghtInt >> 1))) | 1106 textDecorationThickness = styleToUse->fontMetrics().underlineThickness() ; |
1135 textDecorationThickness = std::max(1.f, styleToUse->computedFontSize() / 10.f); | 1107 int fontHeightInt = (int)(styleToUse->fontMetrics().floatHeight() + 0.5) ; |
1108 if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fon tHeightInt >> 1))) | |
1109 textDecorationThickness = std::max(1.f, styleToUse->computedFontSize () / 10.f); | |
1110 } else { | |
1111 textDecorationThickness = decorationThickness; | |
1112 } | |
1136 | 1113 |
1137 context->setStrokeThickness(textDecorationThickness); | 1114 context->setStrokeThickness(textDecorationThickness); |
1138 | 1115 |
1139 bool antialiasDecoration = shouldSetDecorationAntialias(overline.style, unde rline.style, linethrough.style) | 1116 bool antialiasDecoration = shouldSetDecorationAntialias(overline.style, unde rline.style, linethrough.style) |
1140 && RenderBoxModelObject::shouldAntialiasLines(context); | 1117 && RenderBoxModelObject::shouldAntialiasLines(context); |
1141 | 1118 |
1142 float extraOffset = 0; | 1119 float extraOffset = 0; |
1143 if (!linesAreOpaque && shadowCount > 1) { | 1120 if (!linesAreOpaque && shadowCount > 1) { |
1144 FloatRect clipRect(localOrigin, FloatSize(width, baseline + 2)); | 1121 FloatRect clipRect(localOrigin, FloatSize(width, baseline + 2)); |
1145 for (size_t i = shadowCount; i--; ) { | 1122 for (size_t i = shadowCount; i--; ) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1181 if (deco & TextDecorationOverline) { | 1158 if (deco & TextDecorationOverline) { |
1182 paintAppliedDecoration(context, localOrigin, width, -doubleOffset, 1 , overline, textDecorationThickness, antialiasDecoration, isPrinting); | 1159 paintAppliedDecoration(context, localOrigin, width, -doubleOffset, 1 , overline, textDecorationThickness, antialiasDecoration, isPrinting); |
1183 } | 1160 } |
1184 if (deco & TextDecorationLineThrough) { | 1161 if (deco & TextDecorationLineThrough) { |
1185 const float lineThroughOffset = 2 * baseline / 3; | 1162 const float lineThroughOffset = 2 * baseline / 3; |
1186 paintAppliedDecoration(context, localOrigin + FloatPoint(0, lineThro ughOffset), width, doubleOffset, 0, linethrough, textDecorationThickness, antial iasDecoration, isPrinting); | 1163 paintAppliedDecoration(context, localOrigin + FloatPoint(0, lineThro ughOffset), width, doubleOffset, 0, linethrough, textDecorationThickness, antial iasDecoration, isPrinting); |
1187 } | 1164 } |
1188 } | 1165 } |
1189 } | 1166 } |
1190 | 1167 |
1168 void InlineTextBox::paintDecorationStyle(PaintInfo& paintInfo, const LayoutPoint & paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom, float decorationThickn ess) | |
leviw_travelin_and_unemployed
2014/03/21 20:43:08
Whoa... This is a *ton* of code duplication, no?
| |
1169 { | |
1170 if (isLineBreak() || !paintInfo.shouldPaintWithinRoot(&renderer()) || render er().style()->visibility() != VISIBLE | |
1171 || m_truncation == cFullTruncation || paintInfo.phase == PaintPhaseOutli ne || !m_len) | |
1172 return; | |
1173 | |
1174 ASSERT(paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintP haseChildOutlines); | |
1175 | |
1176 LayoutUnit logicalLeftSide = logicalLeftVisualOverflow(); | |
1177 LayoutUnit logicalRightSide = logicalRightVisualOverflow(); | |
1178 LayoutUnit logicalStart = logicalLeftSide + (isHorizontal() ? paintOffset.x( ) : paintOffset.y()); | |
1179 LayoutUnit logicalExtent = logicalRightSide - logicalLeftSide; | |
1180 | |
1181 LayoutUnit paintEnd = isHorizontal() ? paintInfo.rect.maxX() : paintInfo.rec t.maxY(); | |
1182 LayoutUnit paintStart = isHorizontal() ? paintInfo.rect.x() : paintInfo.rect .y(); | |
1183 | |
1184 LayoutPoint adjustedPaintOffset = roundedIntPoint(paintOffset); | |
1185 bool isPrinting = textRenderer().document().printing(); | |
1186 | |
1187 if (logicalStart >= paintEnd || logicalStart + logicalExtent <= paintStart) | |
1188 return; | |
1189 | |
1190 // Determine whether or not we have composition underlines to draw. | |
1191 bool containsComposition = renderer().node() && renderer().frame()->inputMet hodController().compositionNode() == renderer().node(); | |
1192 bool useCustomUnderlines = containsComposition && renderer().frame()->inputM ethodController().compositionUsesCustomUnderlines(); | |
1193 | |
1194 // Determine whether or not we're selected. | |
1195 bool haveSelection = !isPrinting && paintInfo.phase != PaintPhaseTextClip && selectionState() != RenderObject::SelectionNone; | |
1196 if (!haveSelection && paintInfo.phase == PaintPhaseSelection) { | |
1197 // When only painting the selection, don't bother to paint if there is n one. | |
1198 return; | |
1199 } | |
1200 | |
1201 GraphicsContext* context = paintInfo.context; | |
1202 RenderObject& rendererToUse = renderer(); | |
1203 RenderStyle* styleToUse = rendererToUse.style(isFirstLineStyle()); | |
1204 | |
1205 // Set our font. | |
1206 const Font& font = styleToUse->font(); | |
1207 FloatPoint boxOrigin = locationIncludingFlipping(); | |
1208 // FIXME: Shouldn't these offsets be rounded? | |
1209 boxOrigin.move(adjustedPaintOffset.x().toFloat(), adjustedPaintOffset.y().to Float()); | |
1210 FloatRect boxRect(boxOrigin, LayoutSize(logicalWidth(), logicalHeight())); | |
1211 | |
1212 TextDecoration deco = styleToUse->textDecorationsInEffect(); | |
1213 const ShadowList* textShadow = (context->printing() || paintInfo.forceBlackT ext()) ? 0 : styleToUse->textShadow(); | |
1214 | |
1215 // Determine the text colors and selection colors. | |
1216 Color textFillColor; | |
1217 Color textStrokeColor; | |
1218 Color emphasisMarkColor; | |
1219 float textStrokeWidth = styleToUse->textStrokeWidth(); | |
1220 | |
1221 if (paintInfo.forceBlackText()) { | |
1222 textFillColor = Color::black; | |
1223 textStrokeColor = Color::black; | |
1224 emphasisMarkColor = Color::black; | |
1225 } else { | |
1226 textFillColor = rendererToUse.resolveColor(styleToUse, CSSPropertyWebkit TextFillColor); | |
1227 | |
1228 bool forceBackgroundToWhite = false; | |
1229 if (isPrinting) { | |
1230 if (styleToUse->printColorAdjust() == PrintColorAdjustEconomy) | |
1231 forceBackgroundToWhite = true; | |
1232 if (textRenderer().document().settings() && textRenderer().document( ).settings()->shouldPrintBackgrounds()) | |
1233 forceBackgroundToWhite = false; | |
1234 } | |
1235 | |
1236 // Make the text fill color legible against a white background | |
1237 if (forceBackgroundToWhite) | |
1238 textFillColor = correctedTextColor(textFillColor, Color::white); | |
1239 | |
1240 textStrokeColor = rendererToUse.resolveColor(styleToUse, CSSPropertyWebk itTextStrokeColor); | |
1241 | |
1242 // Make the text stroke color legible against a white background | |
1243 if (forceBackgroundToWhite) | |
1244 textStrokeColor = correctedTextColor(textStrokeColor, Color::white); | |
1245 | |
1246 emphasisMarkColor = rendererToUse.resolveColor(styleToUse, CSSPropertyWe bkitTextEmphasisColor); | |
1247 | |
1248 // Make the text stroke color legible against a white background | |
1249 if (forceBackgroundToWhite) | |
1250 emphasisMarkColor = correctedTextColor(emphasisMarkColor, Color::whi te); | |
1251 } | |
1252 updateGraphicsContext(context, textFillColor, textStrokeColor, textStrokeWid th); | |
1253 paintDecoration(context, boxOrigin, deco, textShadow, decorationThickness); | |
1254 | |
1255 if (paintInfo.phase == PaintPhaseForeground) { | |
1256 paintDocumentMarkers(context, boxOrigin, styleToUse, font, false); | |
1257 | |
1258 if (useCustomUnderlines) { | |
1259 const Vector<CompositionUnderline>& underlines = renderer().frame()- >inputMethodController().customCompositionUnderlines(); | |
1260 size_t numUnderlines = underlines.size(); | |
1261 | |
1262 for (size_t index = 0; index < numUnderlines; ++index) { | |
1263 const CompositionUnderline& underline = underlines[index]; | |
1264 | |
1265 if (underline.endOffset <= start()) { | |
1266 // underline is completely before this run. This might be an underline that sits | |
1267 // before the first run we draw, or underlines that were wit hin runs we skipped | |
1268 // due to truncation. | |
1269 continue; | |
1270 } | |
1271 | |
1272 if (underline.startOffset <= end()) { | |
1273 // underline intersects this run. Paint it. | |
1274 paintCompositionUnderline(context, boxOrigin, underline); | |
1275 if (underline.endOffset > end() + 1) { | |
1276 // underline also runs into the next run. Bail now, no m ore marker advancement. | |
1277 break; | |
1278 } | |
1279 } else { | |
1280 // underline is completely after this run, bail. A later run will paint it. | |
1281 break; | |
1282 } | |
1283 } | |
1284 } | |
1285 } | |
1286 } | |
1287 | |
1288 void InlineTextBox::getPaintDecorationSyle(PaintInfo& paintInfo, const LayoutPoi nt& paintOffset, float * decorationThickness) | |
1289 { | |
1290 *decorationThickness = 0; | |
1291 if (isLineBreak() || !paintInfo.shouldPaintWithinRoot(&renderer()) || render er().style()->visibility() != VISIBLE | |
1292 || m_truncation == cFullTruncation || paintInfo.phase == PaintPhaseOutli ne || !m_len) | |
1293 return; | |
1294 | |
1295 *decorationThickness = getDecorationThickness(); | |
1296 } | |
1297 | |
1191 static GraphicsContext::DocumentMarkerLineStyle lineStyleForMarkerType(DocumentM arker::MarkerType markerType) | 1298 static GraphicsContext::DocumentMarkerLineStyle lineStyleForMarkerType(DocumentM arker::MarkerType markerType) |
1192 { | 1299 { |
1193 switch (markerType) { | 1300 switch (markerType) { |
1194 case DocumentMarker::Spelling: | 1301 case DocumentMarker::Spelling: |
1195 return GraphicsContext::DocumentMarkerSpellingLineStyle; | 1302 return GraphicsContext::DocumentMarkerSpellingLineStyle; |
1196 case DocumentMarker::Grammar: | 1303 case DocumentMarker::Grammar: |
1197 return GraphicsContext::DocumentMarkerGrammarLineStyle; | 1304 return GraphicsContext::DocumentMarkerGrammarLineStyle; |
1198 default: | 1305 default: |
1199 ASSERT_NOT_REACHED(); | 1306 ASSERT_NOT_REACHED(); |
1200 return GraphicsContext::DocumentMarkerSpellingLineStyle; | 1307 return GraphicsContext::DocumentMarkerSpellingLineStyle; |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1565 printedCharacters = fprintf(stderr, "\t%s %p", obj.renderName(), &obj); | 1672 printedCharacters = fprintf(stderr, "\t%s %p", obj.renderName(), &obj); |
1566 const int rendererCharacterOffset = 24; | 1673 const int rendererCharacterOffset = 24; |
1567 for (; printedCharacters < rendererCharacterOffset; printedCharacters++) | 1674 for (; printedCharacters < rendererCharacterOffset; printedCharacters++) |
1568 fputc(' ', stderr); | 1675 fputc(' ', stderr); |
1569 fprintf(stderr, "(%d,%d) \"%s\"\n", start(), start() + len(), value.utf8().d ata()); | 1676 fprintf(stderr, "(%d,%d) \"%s\"\n", start(), start() + len(), value.utf8().d ata()); |
1570 } | 1677 } |
1571 | 1678 |
1572 #endif | 1679 #endif |
1573 | 1680 |
1574 } // namespace WebCore | 1681 } // namespace WebCore |
OLD | NEW |