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 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 int sPos = std::max(startPos - m_start, 0); | 199 int sPos = std::max(startPos - m_start, 0); |
200 int ePos = std::min(endPos - m_start, (int)m_len); | 200 int ePos = std::min(endPos - m_start, (int)m_len); |
201 | 201 |
202 if (sPos > ePos) | 202 if (sPos > ePos) |
203 return LayoutRect(); | 203 return LayoutRect(); |
204 | 204 |
205 FontCachePurgePreventer fontCachePurgePreventer; | 205 FontCachePurgePreventer fontCachePurgePreventer; |
206 | 206 |
207 LayoutUnit selTop = selectionTop(); | 207 LayoutUnit selTop = selectionTop(); |
208 LayoutUnit selHeight = selectionHeight(); | 208 LayoutUnit selHeight = selectionHeight(); |
209 RenderStyle* styleToUse = textRenderer().style(isFirstLineStyle()); | 209 RenderStyle* styleToUse = textRenderer().styleOrFirstLineStyle(isFirstLineSt
yle()); |
210 const Font& font = styleToUse->font(); | 210 const Font& font = styleToUse->font(); |
211 | 211 |
212 StringBuilder charactersWithHyphen; | 212 StringBuilder charactersWithHyphen; |
213 bool respectHyphen = ePos == m_len && hasHyphen(); | 213 bool respectHyphen = ePos == m_len && hasHyphen(); |
214 TextRun textRun = constructTextRun(styleToUse, font, respectHyphen ? &charac
tersWithHyphen : 0); | 214 TextRun textRun = constructTextRun(styleToUse, font, respectHyphen ? &charac
tersWithHyphen : 0); |
215 | 215 |
216 FloatPoint startingPoint = FloatPoint(logicalLeft(), selTop.toFloat()); | 216 FloatPoint startingPoint = FloatPoint(logicalLeft(), selTop.toFloat()); |
217 LayoutRect r; | 217 LayoutRect r; |
218 if (sPos || ePos != static_cast<int>(m_len)) | 218 if (sPos || ePos != static_cast<int>(m_len)) |
219 r = enclosingIntRect(font.selectionRectForText(textRun, startingPoint, s
elHeight, sPos, ePos)); | 219 r = enclosingIntRect(font.selectionRectForText(textRun, startingPoint, s
elHeight, sPos, ePos)); |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
514 LayoutUnit widthOfHiddenText = m_logicalWidth - widthOfVisibleText; | 514 LayoutUnit widthOfHiddenText = m_logicalWidth - widthOfVisibleText; |
515 // FIXME: The hit testing logic also needs to take this translation
into account. | 515 // FIXME: The hit testing logic also needs to take this translation
into account. |
516 LayoutSize truncationOffset(isLeftToRightDirection() ? widthOfHidden
Text : -widthOfHiddenText, 0); | 516 LayoutSize truncationOffset(isLeftToRightDirection() ? widthOfHidden
Text : -widthOfHiddenText, 0); |
517 adjustedPaintOffset.move(isHorizontal() ? truncationOffset : truncat
ionOffset.transposedSize()); | 517 adjustedPaintOffset.move(isHorizontal() ? truncationOffset : truncat
ionOffset.transposedSize()); |
518 } | 518 } |
519 } | 519 } |
520 | 520 |
521 GraphicsContext* context = paintInfo.context; | 521 GraphicsContext* context = paintInfo.context; |
522 | 522 |
523 RenderObject& rendererToUse = renderer(); | 523 RenderObject& rendererToUse = renderer(); |
524 RenderStyle* styleToUse = rendererToUse.style(isFirstLineStyle()); | 524 RenderStyle* styleToUse = rendererToUse.styleOrFirstLineStyle(isFirstLineSty
le()); |
525 | 525 |
526 adjustedPaintOffset.move(0, styleToUse->isHorizontalWritingMode() ? 0 : -log
icalHeight()); | 526 adjustedPaintOffset.move(0, styleToUse->isHorizontalWritingMode() ? 0 : -log
icalHeight()); |
527 | 527 |
528 FloatPoint boxOrigin = locationIncludingFlipping(); | 528 FloatPoint boxOrigin = locationIncludingFlipping(); |
529 boxOrigin.move(adjustedPaintOffset.x().toFloat(), adjustedPaintOffset.y().to
Float()); | 529 boxOrigin.move(adjustedPaintOffset.x().toFloat(), adjustedPaintOffset.y().to
Float()); |
530 FloatRect boxRect(boxOrigin, LayoutSize(logicalWidth(), logicalHeight())); | 530 FloatRect boxRect(boxOrigin, LayoutSize(logicalWidth(), logicalHeight())); |
531 | 531 |
532 RenderCombineText* combinedText = styleToUse->hasTextCombine() && textRender
er().isCombineText() && toRenderCombineText(textRenderer()).isCombined() ? &toRe
nderCombineText(textRenderer()) : 0; | 532 RenderCombineText* combinedText = styleToUse->hasTextCombine() && textRender
er().isCombineText() && toRenderCombineText(textRenderer()).isCombined() ? &toRe
nderCombineText(textRenderer()) : 0; |
533 | 533 |
534 bool shouldRotate = !isHorizontal() && !combinedText; | 534 bool shouldRotate = !isHorizontal() && !combinedText; |
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1123 | 1123 |
1124 renderer().getTextDecorations(deco, underline, overline, linethrough, true); | 1124 renderer().getTextDecorations(deco, underline, overline, linethrough, true); |
1125 if (isFirstLineStyle()) | 1125 if (isFirstLineStyle()) |
1126 renderer().getTextDecorations(deco, underline, overline, linethrough, tr
ue, true); | 1126 renderer().getTextDecorations(deco, underline, overline, linethrough, tr
ue, true); |
1127 | 1127 |
1128 // Use a special function for underlines to get the positioning exactly righ
t. | 1128 // Use a special function for underlines to get the positioning exactly righ
t. |
1129 bool isPrinting = textRenderer().document().printing(); | 1129 bool isPrinting = textRenderer().document().printing(); |
1130 | 1130 |
1131 bool linesAreOpaque = !isPrinting && (!(deco & TextDecorationUnderline) || u
nderline.color.alpha() == 255) && (!(deco & TextDecorationOverline) || overline.
color.alpha() == 255) && (!(deco & TextDecorationLineThrough) || linethrough.col
or.alpha() == 255); | 1131 bool linesAreOpaque = !isPrinting && (!(deco & TextDecorationUnderline) || u
nderline.color.alpha() == 255) && (!(deco & TextDecorationOverline) || overline.
color.alpha() == 255) && (!(deco & TextDecorationLineThrough) || linethrough.col
or.alpha() == 255); |
1132 | 1132 |
1133 RenderStyle* styleToUse = renderer().style(isFirstLineStyle()); | 1133 RenderStyle* styleToUse = renderer().styleOrFirstLineStyle(isFirstLineStyle(
)); |
1134 int baseline = styleToUse->fontMetrics().ascent(); | 1134 int baseline = styleToUse->fontMetrics().ascent(); |
1135 | 1135 |
1136 size_t shadowCount = shadowList ? shadowList->shadows().size() : 0; | 1136 size_t shadowCount = shadowList ? shadowList->shadows().size() : 0; |
1137 // Set the thick of the line to be 10% (or something else ?)of the computed
font size and not less than 1px. | 1137 // Set the thick of the line to be 10% (or something else ?)of the computed
font size and not less than 1px. |
1138 // Using computedFontSize should take care of zoom as well. | 1138 // Using computedFontSize should take care of zoom as well. |
1139 | 1139 |
1140 // Update Underline thickness, in case we have Faulty Font Metrics calculati
ng underline thickness by old method. | 1140 // Update Underline thickness, in case we have Faulty Font Metrics calculati
ng underline thickness by old method. |
1141 float textDecorationThickness = styleToUse->fontMetrics().underlineThickness
(); | 1141 float textDecorationThickness = styleToUse->fontMetrics().underlineThickness
(); |
1142 int fontHeightInt = (int)(styleToUse->fontMetrics().floatHeight() + 0.5); | 1142 int fontHeightInt = (int)(styleToUse->fontMetrics().floatHeight() + 0.5); |
1143 if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHei
ghtInt >> 1))) | 1143 if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHei
ghtInt >> 1))) |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1258 } | 1258 } |
1259 } | 1259 } |
1260 | 1260 |
1261 // IMPORTANT: The misspelling underline is not considered when calculating t
he text bounds, so we have to | 1261 // IMPORTANT: The misspelling underline is not considered when calculating t
he text bounds, so we have to |
1262 // make sure to fit within those bounds. This means the top pixel(s) of the
underline will overlap the | 1262 // make sure to fit within those bounds. This means the top pixel(s) of the
underline will overlap the |
1263 // bottom pixel(s) of the glyphs in smaller font sizes. The alternatives ar
e to increase the line spacing (bad!!) | 1263 // bottom pixel(s) of the glyphs in smaller font sizes. The alternatives ar
e to increase the line spacing (bad!!) |
1264 // or decrease the underline thickness. The overlap is actually the most us
eful, and matches what AppKit does. | 1264 // or decrease the underline thickness. The overlap is actually the most us
eful, and matches what AppKit does. |
1265 // So, we generally place the underline at the bottom of the text, but in la
rger fonts that's not so good so | 1265 // So, we generally place the underline at the bottom of the text, but in la
rger fonts that's not so good so |
1266 // we pin to two pixels under the baseline. | 1266 // we pin to two pixels under the baseline. |
1267 int lineThickness = misspellingLineThickness; | 1267 int lineThickness = misspellingLineThickness; |
1268 int baseline = renderer().style(isFirstLineStyle())->fontMetrics().ascent(); | 1268 int baseline = renderer().styleOrFirstLineStyle(isFirstLineStyle())->fontMet
rics().ascent(); |
1269 int descent = logicalHeight() - baseline; | 1269 int descent = logicalHeight() - baseline; |
1270 int underlineOffset; | 1270 int underlineOffset; |
1271 if (descent <= (2 + lineThickness)) { | 1271 if (descent <= (2 + lineThickness)) { |
1272 // Place the underline at the very bottom of the text in small/medium fo
nts. | 1272 // Place the underline at the very bottom of the text in small/medium fo
nts. |
1273 underlineOffset = logicalHeight() - lineThickness; | 1273 underlineOffset = logicalHeight() - lineThickness; |
1274 } else { | 1274 } else { |
1275 // In larger fonts, though, place the underline up near the baseline to
prevent a big gap. | 1275 // In larger fonts, though, place the underline up near the baseline to
prevent a big gap. |
1276 underlineOffset = baseline + 2; | 1276 underlineOffset = baseline + 2; |
1277 } | 1277 } |
1278 pt->drawLineForDocumentMarker(FloatPoint(boxOrigin.x() + start, boxOrigin.y(
) + underlineOffset), width, lineStyleForMarkerType(marker->type())); | 1278 pt->drawLineForDocumentMarker(FloatPoint(boxOrigin.x() + start, boxOrigin.y(
) + underlineOffset), width, lineStyleForMarkerType(marker->type())); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1392 float start = paintStart == static_cast<unsigned>(m_start) ? 0 : | 1392 float start = paintStart == static_cast<unsigned>(m_start) ? 0 : |
1393 toRenderText(renderer()).width(m_start, paintStart - m_start, textPos(),
isLeftToRightDirection() ? LTR : RTL, isFirstLineStyle()); | 1393 toRenderText(renderer()).width(m_start, paintStart - m_start, textPos(),
isLeftToRightDirection() ? LTR : RTL, isFirstLineStyle()); |
1394 // how much line to draw | 1394 // how much line to draw |
1395 float width = (paintStart == static_cast<unsigned>(m_start) && paintEnd == s
tatic_cast<unsigned>(end()) + 1) ? m_logicalWidth : | 1395 float width = (paintStart == static_cast<unsigned>(m_start) && paintEnd == s
tatic_cast<unsigned>(end()) + 1) ? m_logicalWidth : |
1396 toRenderText(renderer()).width(paintStart, paintEnd - paintStart, textPo
s() + start, isLeftToRightDirection() ? LTR : RTL, isFirstLineStyle()); | 1396 toRenderText(renderer()).width(paintStart, paintEnd - paintStart, textPo
s() + start, isLeftToRightDirection() ? LTR : RTL, isFirstLineStyle()); |
1397 | 1397 |
1398 // Thick marked text underlines are 2px thick as long as there is room for t
he 2px line under the baseline. | 1398 // Thick marked text underlines are 2px thick as long as there is room for t
he 2px line under the baseline. |
1399 // All other marked text underlines are 1px thick. | 1399 // All other marked text underlines are 1px thick. |
1400 // If there's not enough space the underline will touch or overlap character
s. | 1400 // If there's not enough space the underline will touch or overlap character
s. |
1401 int lineThickness = 1; | 1401 int lineThickness = 1; |
1402 int baseline = renderer().style(isFirstLineStyle())->fontMetrics().ascent(); | 1402 int baseline = renderer().styleOrFirstLineStyle(isFirstLineStyle())->fontMet
rics().ascent(); |
1403 if (underline.thick && logicalHeight() - baseline >= 2) | 1403 if (underline.thick && logicalHeight() - baseline >= 2) |
1404 lineThickness = 2; | 1404 lineThickness = 2; |
1405 | 1405 |
1406 // We need to have some space between underlines of subsequent clauses, beca
use some input methods do not use different underline styles for those. | 1406 // We need to have some space between underlines of subsequent clauses, beca
use some input methods do not use different underline styles for those. |
1407 // We make each line shorter, which has a harmless side effect of shortening
the first and last clauses, too. | 1407 // We make each line shorter, which has a harmless side effect of shortening
the first and last clauses, too. |
1408 start += 1; | 1408 start += 1; |
1409 width -= 2; | 1409 width -= 2; |
1410 | 1410 |
1411 ctx->setStrokeColor(underline.color); | 1411 ctx->setStrokeColor(underline.color); |
1412 ctx->setStrokeThickness(lineThickness); | 1412 ctx->setStrokeThickness(lineThickness); |
(...skipping 25 matching lines...) Expand all Loading... |
1438 return 0; | 1438 return 0; |
1439 | 1439 |
1440 if (lineOffset - logicalLeft() > logicalWidth()) | 1440 if (lineOffset - logicalLeft() > logicalWidth()) |
1441 return isLeftToRightDirection() ? len() : 0; | 1441 return isLeftToRightDirection() ? len() : 0; |
1442 if (lineOffset - logicalLeft() < 0) | 1442 if (lineOffset - logicalLeft() < 0) |
1443 return isLeftToRightDirection() ? 0 : len(); | 1443 return isLeftToRightDirection() ? 0 : len(); |
1444 | 1444 |
1445 FontCachePurgePreventer fontCachePurgePreventer; | 1445 FontCachePurgePreventer fontCachePurgePreventer; |
1446 | 1446 |
1447 RenderText& text = toRenderText(renderer()); | 1447 RenderText& text = toRenderText(renderer()); |
1448 RenderStyle* style = text.style(isFirstLineStyle()); | 1448 RenderStyle* style = text.styleOrFirstLineStyle(isFirstLineStyle()); |
1449 const Font& font = style->font(); | 1449 const Font& font = style->font(); |
1450 return font.offsetForPosition(constructTextRun(style, font), lineOffset - lo
gicalLeft(), includePartialGlyphs); | 1450 return font.offsetForPosition(constructTextRun(style, font), lineOffset - lo
gicalLeft(), includePartialGlyphs); |
1451 } | 1451 } |
1452 | 1452 |
1453 float InlineTextBox::positionForOffset(int offset) const | 1453 float InlineTextBox::positionForOffset(int offset) const |
1454 { | 1454 { |
1455 ASSERT(offset >= m_start); | 1455 ASSERT(offset >= m_start); |
1456 ASSERT(offset <= m_start + m_len); | 1456 ASSERT(offset <= m_start + m_len); |
1457 | 1457 |
1458 if (isLineBreak()) | 1458 if (isLineBreak()) |
1459 return logicalLeft(); | 1459 return logicalLeft(); |
1460 | 1460 |
1461 FontCachePurgePreventer fontCachePurgePreventer; | 1461 FontCachePurgePreventer fontCachePurgePreventer; |
1462 | 1462 |
1463 RenderText& text = toRenderText(renderer()); | 1463 RenderText& text = toRenderText(renderer()); |
1464 RenderStyle* styleToUse = text.style(isFirstLineStyle()); | 1464 RenderStyle* styleToUse = text.styleOrFirstLineStyle(isFirstLineStyle()); |
1465 ASSERT(styleToUse); | 1465 ASSERT(styleToUse); |
1466 const Font& font = styleToUse->font(); | 1466 const Font& font = styleToUse->font(); |
1467 int from = !isLeftToRightDirection() ? offset - m_start : 0; | 1467 int from = !isLeftToRightDirection() ? offset - m_start : 0; |
1468 int to = !isLeftToRightDirection() ? m_len : offset - m_start; | 1468 int to = !isLeftToRightDirection() ? m_len : offset - m_start; |
1469 // FIXME: Do we need to add rightBearing here? | 1469 // FIXME: Do we need to add rightBearing here? |
1470 return font.selectionRectForText(constructTextRun(styleToUse, font), IntPoin
t(logicalLeft(), 0), 0, from, to).maxX(); | 1470 return font.selectionRectForText(constructTextRun(styleToUse, font), IntPoin
t(logicalLeft(), 0), 0, from, to).maxX(); |
1471 } | 1471 } |
1472 | 1472 |
1473 bool InlineTextBox::containsCaretOffset(int offset) const | 1473 bool InlineTextBox::containsCaretOffset(int offset) const |
1474 { | 1474 { |
(...skipping 16 matching lines...) Expand all Loading... |
1491 return false; | 1491 return false; |
1492 | 1492 |
1493 // Offsets at the end are "in" for normal boxes (but the caller has to check
affinity). | 1493 // Offsets at the end are "in" for normal boxes (but the caller has to check
affinity). |
1494 return true; | 1494 return true; |
1495 } | 1495 } |
1496 | 1496 |
1497 void InlineTextBox::characterWidths(Vector<float>& widths) const | 1497 void InlineTextBox::characterWidths(Vector<float>& widths) const |
1498 { | 1498 { |
1499 FontCachePurgePreventer fontCachePurgePreventer; | 1499 FontCachePurgePreventer fontCachePurgePreventer; |
1500 | 1500 |
1501 RenderStyle* styleToUse = textRenderer().style(isFirstLineStyle()); | 1501 RenderStyle* styleToUse = textRenderer().styleOrFirstLineStyle(isFirstLineSt
yle()); |
1502 const Font& font = styleToUse->font(); | 1502 const Font& font = styleToUse->font(); |
1503 | 1503 |
1504 TextRun textRun = constructTextRun(styleToUse, font); | 1504 TextRun textRun = constructTextRun(styleToUse, font); |
1505 | 1505 |
1506 GlyphBuffer glyphBuffer; | 1506 GlyphBuffer glyphBuffer; |
1507 WidthIterator it(&font, textRun); | 1507 WidthIterator it(&font, textRun); |
1508 float lastWidth = 0; | 1508 float lastWidth = 0; |
1509 widths.resize(m_len); | 1509 widths.resize(m_len); |
1510 for (unsigned i = 0; i < m_len; i++) { | 1510 for (unsigned i = 0; i < m_len; i++) { |
1511 it.advance(i + 1, &glyphBuffer); | 1511 it.advance(i + 1, &glyphBuffer); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1581 printedCharacters = fprintf(stderr, "\t%s %p", obj.renderName(), &obj); | 1581 printedCharacters = fprintf(stderr, "\t%s %p", obj.renderName(), &obj); |
1582 const int rendererCharacterOffset = 24; | 1582 const int rendererCharacterOffset = 24; |
1583 for (; printedCharacters < rendererCharacterOffset; printedCharacters++) | 1583 for (; printedCharacters < rendererCharacterOffset; printedCharacters++) |
1584 fputc(' ', stderr); | 1584 fputc(' ', stderr); |
1585 fprintf(stderr, "(%d,%d) \"%s\"\n", start(), start() + len(), value.utf8().d
ata()); | 1585 fprintf(stderr, "(%d,%d) \"%s\"\n", start(), start() + len(), value.utf8().d
ata()); |
1586 } | 1586 } |
1587 | 1587 |
1588 #endif | 1588 #endif |
1589 | 1589 |
1590 } // namespace WebCore | 1590 } // namespace WebCore |
OLD | NEW |