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 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 ASSERT(!knownToHaveNoOverflow()); | 99 ASSERT(!knownToHaveNoOverflow()); |
100 if (!gTextBoxesWithOverflow) | 100 if (!gTextBoxesWithOverflow) |
101 gTextBoxesWithOverflow = new InlineTextBoxOverflowMap; | 101 gTextBoxesWithOverflow = new InlineTextBoxOverflowMap; |
102 gTextBoxesWithOverflow->add(this, rect); | 102 gTextBoxesWithOverflow->add(this, rect); |
103 } | 103 } |
104 | 104 |
105 int InlineTextBox::baselinePosition(FontBaseline baselineType) const | 105 int InlineTextBox::baselinePosition(FontBaseline baselineType) const |
106 { | 106 { |
107 if (!isText() || !parent()) | 107 if (!isText() || !parent()) |
108 return 0; | 108 return 0; |
109 if (parent()->renderer() == renderer()->parent()) | 109 if (parent()->renderer() == renderer().parent()) |
110 return parent()->baselinePosition(baselineType); | 110 return parent()->baselinePosition(baselineType); |
111 return toRenderBoxModelObject(renderer()->parent())->baselinePosition(baseli
neType, isFirstLineStyle(), isHorizontal() ? HorizontalLine : VerticalLine, Posi
tionOnContainingLine); | 111 return toRenderBoxModelObject(renderer().parent())->baselinePosition(baselin
eType, isFirstLineStyle(), isHorizontal() ? HorizontalLine : VerticalLine, Posit
ionOnContainingLine); |
112 } | 112 } |
113 | 113 |
114 LayoutUnit InlineTextBox::lineHeight() const | 114 LayoutUnit InlineTextBox::lineHeight() const |
115 { | 115 { |
116 if (!isText() || !renderer()->parent()) | 116 if (!isText() || !renderer().parent()) |
117 return 0; | 117 return 0; |
118 if (m_renderer->isBR()) | 118 if (renderer().isBR()) |
119 return toRenderBR(m_renderer)->lineHeight(isFirstLineStyle()); | 119 return toRenderBR(renderer()).lineHeight(isFirstLineStyle()); |
120 if (parent()->renderer() == renderer()->parent()) | 120 if (parent()->renderer() == renderer().parent()) |
121 return parent()->lineHeight(); | 121 return parent()->lineHeight(); |
122 return toRenderBoxModelObject(renderer()->parent())->lineHeight(isFirstLineS
tyle(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine
); | 122 return toRenderBoxModelObject(renderer().parent())->lineHeight(isFirstLineSt
yle(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine)
; |
123 } | 123 } |
124 | 124 |
125 LayoutUnit InlineTextBox::selectionTop() | 125 LayoutUnit InlineTextBox::selectionTop() |
126 { | 126 { |
127 return root()->selectionTop(); | 127 return root()->selectionTop(); |
128 } | 128 } |
129 | 129 |
130 LayoutUnit InlineTextBox::selectionBottom() | 130 LayoutUnit InlineTextBox::selectionBottom() |
131 { | 131 { |
132 return root()->selectionBottom(); | 132 return root()->selectionBottom(); |
133 } | 133 } |
134 | 134 |
135 LayoutUnit InlineTextBox::selectionHeight() | 135 LayoutUnit InlineTextBox::selectionHeight() |
136 { | 136 { |
137 return root()->selectionHeight(); | 137 return root()->selectionHeight(); |
138 } | 138 } |
139 | 139 |
140 bool InlineTextBox::isSelected(int startPos, int endPos) const | 140 bool InlineTextBox::isSelected(int startPos, int endPos) const |
141 { | 141 { |
142 int sPos = max(startPos - m_start, 0); | 142 int sPos = max(startPos - m_start, 0); |
143 // The position after a hard line break is considered to be past its end. | 143 // The position after a hard line break is considered to be past its end. |
144 // See the corresponding code in InlineTextBox::selectionState. | 144 // See the corresponding code in InlineTextBox::selectionState. |
145 int ePos = min(endPos - m_start, int(m_len) + (isLineBreak() ? 0 : 1)); | 145 int ePos = min(endPos - m_start, int(m_len) + (isLineBreak() ? 0 : 1)); |
146 return (sPos < ePos); | 146 return (sPos < ePos); |
147 } | 147 } |
148 | 148 |
149 RenderObject::SelectionState InlineTextBox::selectionState() | 149 RenderObject::SelectionState InlineTextBox::selectionState() |
150 { | 150 { |
151 RenderObject::SelectionState state = renderer()->selectionState(); | 151 RenderObject::SelectionState state = renderer().selectionState(); |
152 if (state == RenderObject::SelectionStart || state == RenderObject::Selectio
nEnd || state == RenderObject::SelectionBoth) { | 152 if (state == RenderObject::SelectionStart || state == RenderObject::Selectio
nEnd || state == RenderObject::SelectionBoth) { |
153 int startPos, endPos; | 153 int startPos, endPos; |
154 renderer()->selectionStartEnd(startPos, endPos); | 154 renderer().selectionStartEnd(startPos, endPos); |
155 // The position after a hard line break is considered to be past its end
. | 155 // The position after a hard line break is considered to be past its end
. |
156 // See the corresponding code in InlineTextBox::isSelected. | 156 // See the corresponding code in InlineTextBox::isSelected. |
157 int lastSelectable = start() + len() - (isLineBreak() ? 1 : 0); | 157 int lastSelectable = start() + len() - (isLineBreak() ? 1 : 0); |
158 | 158 |
159 // FIXME: Remove -webkit-line-break: LineBreakAfterWhiteSpace. | 159 // FIXME: Remove -webkit-line-break: LineBreakAfterWhiteSpace. |
160 int endOfLineAdjustmentForCSSLineBreak = renderer()->style()->lineBreak(
) == LineBreakAfterWhiteSpace ? -1 : 0; | 160 int endOfLineAdjustmentForCSSLineBreak = renderer().style()->lineBreak()
== LineBreakAfterWhiteSpace ? -1 : 0; |
161 bool start = (state != RenderObject::SelectionEnd && startPos >= m_start
&& startPos <= m_start + m_len + endOfLineAdjustmentForCSSLineBreak); | 161 bool start = (state != RenderObject::SelectionEnd && startPos >= m_start
&& startPos <= m_start + m_len + endOfLineAdjustmentForCSSLineBreak); |
162 bool end = (state != RenderObject::SelectionStart && endPos > m_start &&
endPos <= lastSelectable); | 162 bool end = (state != RenderObject::SelectionStart && endPos > m_start &&
endPos <= lastSelectable); |
163 if (start && end) | 163 if (start && end) |
164 state = RenderObject::SelectionBoth; | 164 state = RenderObject::SelectionBoth; |
165 else if (start) | 165 else if (start) |
166 state = RenderObject::SelectionStart; | 166 state = RenderObject::SelectionStart; |
167 else if (end) | 167 else if (end) |
168 state = RenderObject::SelectionEnd; | 168 state = RenderObject::SelectionEnd; |
169 else if ((state == RenderObject::SelectionEnd || startPos < m_start) && | 169 else if ((state == RenderObject::SelectionEnd || startPos < m_start) && |
170 (state == RenderObject::SelectionStart || endPos > lastSelectab
le)) | 170 (state == RenderObject::SelectionStart || endPos > lastSelectab
le)) |
(...skipping 24 matching lines...) Expand all Loading... |
195 LayoutRect InlineTextBox::localSelectionRect(int startPos, int endPos) | 195 LayoutRect InlineTextBox::localSelectionRect(int startPos, int endPos) |
196 { | 196 { |
197 int sPos = max(startPos - m_start, 0); | 197 int sPos = max(startPos - m_start, 0); |
198 int ePos = min(endPos - m_start, (int)m_len); | 198 int ePos = min(endPos - m_start, (int)m_len); |
199 | 199 |
200 if (sPos > ePos) | 200 if (sPos > ePos) |
201 return LayoutRect(); | 201 return LayoutRect(); |
202 | 202 |
203 FontCachePurgePreventer fontCachePurgePreventer; | 203 FontCachePurgePreventer fontCachePurgePreventer; |
204 | 204 |
205 RenderText* textObj = textRenderer(); | |
206 LayoutUnit selTop = selectionTop(); | 205 LayoutUnit selTop = selectionTop(); |
207 LayoutUnit selHeight = selectionHeight(); | 206 LayoutUnit selHeight = selectionHeight(); |
208 RenderStyle* styleToUse = textObj->style(isFirstLineStyle()); | 207 RenderStyle* styleToUse = textRenderer().style(isFirstLineStyle()); |
209 const Font& font = styleToUse->font(); | 208 const Font& font = styleToUse->font(); |
210 | 209 |
211 StringBuilder charactersWithHyphen; | 210 StringBuilder charactersWithHyphen; |
212 bool respectHyphen = ePos == m_len && hasHyphen(); | 211 bool respectHyphen = ePos == m_len && hasHyphen(); |
213 TextRun textRun = constructTextRun(styleToUse, font, respectHyphen ? &charac
tersWithHyphen : 0); | 212 TextRun textRun = constructTextRun(styleToUse, font, respectHyphen ? &charac
tersWithHyphen : 0); |
214 | 213 |
215 FloatPoint startingPoint = FloatPoint(logicalLeft(), selTop); | 214 FloatPoint startingPoint = FloatPoint(logicalLeft(), selTop); |
216 LayoutRect r; | 215 LayoutRect r; |
217 if (sPos || ePos != static_cast<int>(m_len)) | 216 if (sPos || ePos != static_cast<int>(m_len)) |
218 r = enclosingIntRect(font.selectionRectForText(textRun, startingPoint, s
elHeight, sPos, ePos)); | 217 r = enclosingIntRect(font.selectionRectForText(textRun, startingPoint, s
elHeight, sPos, ePos)); |
219 else // Avoid computing the font width when the entire line box is selected
as an optimization. | 218 else // Avoid computing the font width when the entire line box is selected
as an optimization. |
220 r = enclosingIntRect(FloatRect(startingPoint, FloatSize(m_logicalWidth,
selHeight))); | 219 r = enclosingIntRect(FloatRect(startingPoint, FloatSize(m_logicalWidth,
selHeight))); |
221 | 220 |
222 LayoutUnit logicalWidth = r.width(); | 221 LayoutUnit logicalWidth = r.width(); |
223 if (r.x() > logicalRight()) | 222 if (r.x() > logicalRight()) |
224 logicalWidth = 0; | 223 logicalWidth = 0; |
225 else if (r.maxX() > logicalRight()) | 224 else if (r.maxX() > logicalRight()) |
226 logicalWidth = logicalRight() - r.x(); | 225 logicalWidth = logicalRight() - r.x(); |
227 | 226 |
228 LayoutPoint topPoint = isHorizontal() ? LayoutPoint(r.x(), selTop) : LayoutP
oint(selTop, r.x()); | 227 LayoutPoint topPoint = isHorizontal() ? LayoutPoint(r.x(), selTop) : LayoutP
oint(selTop, r.x()); |
229 LayoutUnit width = isHorizontal() ? logicalWidth : selHeight; | 228 LayoutUnit width = isHorizontal() ? logicalWidth : selHeight; |
230 LayoutUnit height = isHorizontal() ? selHeight : logicalWidth; | 229 LayoutUnit height = isHorizontal() ? selHeight : logicalWidth; |
231 | 230 |
232 return LayoutRect(topPoint, LayoutSize(width, height)); | 231 return LayoutRect(topPoint, LayoutSize(width, height)); |
233 } | 232 } |
234 | 233 |
235 void InlineTextBox::deleteLine() | 234 void InlineTextBox::deleteLine() |
236 { | 235 { |
237 toRenderText(renderer())->removeTextBox(this); | 236 toRenderText(renderer()).removeTextBox(this); |
238 destroy(); | 237 destroy(); |
239 } | 238 } |
240 | 239 |
241 void InlineTextBox::extractLine() | 240 void InlineTextBox::extractLine() |
242 { | 241 { |
243 if (extracted()) | 242 if (extracted()) |
244 return; | 243 return; |
245 | 244 |
246 toRenderText(renderer())->extractTextBox(this); | 245 toRenderText(renderer()).extractTextBox(this); |
247 } | 246 } |
248 | 247 |
249 void InlineTextBox::attachLine() | 248 void InlineTextBox::attachLine() |
250 { | 249 { |
251 if (!extracted()) | 250 if (!extracted()) |
252 return; | 251 return; |
253 | 252 |
254 toRenderText(renderer())->attachTextBox(this); | 253 toRenderText(renderer()).attachTextBox(this); |
255 } | 254 } |
256 | 255 |
257 float InlineTextBox::placeEllipsisBox(bool flowIsLTR, float visibleLeftEdge, flo
at visibleRightEdge, float ellipsisWidth, float &truncatedWidth, bool& foundBox) | 256 float InlineTextBox::placeEllipsisBox(bool flowIsLTR, float visibleLeftEdge, flo
at visibleRightEdge, float ellipsisWidth, float &truncatedWidth, bool& foundBox) |
258 { | 257 { |
259 if (foundBox) { | 258 if (foundBox) { |
260 m_truncation = cFullTruncation; | 259 m_truncation = cFullTruncation; |
261 return -1; | 260 return -1; |
262 } | 261 } |
263 | 262 |
264 // For LTR this is the left edge of the box, for RTL, the right edge in pare
nt coordinates. | 263 // For LTR this is the left edge of the box, for RTL, the right edge in pare
nt coordinates. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 m_truncation = cFullTruncation; | 297 m_truncation = cFullTruncation; |
299 truncatedWidth += ellipsisWidth; | 298 truncatedWidth += ellipsisWidth; |
300 return min(ellipsisX, logicalLeft()); | 299 return min(ellipsisX, logicalLeft()); |
301 } | 300 } |
302 | 301 |
303 // Set the truncation index on the text run. | 302 // Set the truncation index on the text run. |
304 m_truncation = offset; | 303 m_truncation = offset; |
305 | 304 |
306 // If we got here that means that we were only partially truncated and w
e need to return the pixel offset at which | 305 // If we got here that means that we were only partially truncated and w
e need to return the pixel offset at which |
307 // to place the ellipsis. | 306 // to place the ellipsis. |
308 float widthOfVisibleText = toRenderText(renderer())->width(m_start, offs
et, textPos(), flowIsLTR ? LTR : RTL, isFirstLineStyle()); | 307 float widthOfVisibleText = toRenderText(renderer()).width(m_start, offse
t, textPos(), flowIsLTR ? LTR : RTL, isFirstLineStyle()); |
309 | 308 |
310 // The ellipsis needs to be placed just after the last visible character
. | 309 // The ellipsis needs to be placed just after the last visible character
. |
311 // Where "after" is defined by the flow directionality, not the inline | 310 // Where "after" is defined by the flow directionality, not the inline |
312 // box directionality. | 311 // box directionality. |
313 // e.g. In the case of an LTR inline box truncated in an RTL flow then w
e can | 312 // e.g. In the case of an LTR inline box truncated in an RTL flow then w
e can |
314 // have a situation such as |Hello| -> |...He| | 313 // have a situation such as |Hello| -> |...He| |
315 truncatedWidth += widthOfVisibleText + ellipsisWidth; | 314 truncatedWidth += widthOfVisibleText + ellipsisWidth; |
316 if (flowIsLTR) | 315 if (flowIsLTR) |
317 return logicalLeft() + widthOfVisibleText; | 316 return logicalLeft() + widthOfVisibleText; |
318 else | 317 else |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
360 if (mode & TextModeStroke) { | 359 if (mode & TextModeStroke) { |
361 if (strokeColor != context->strokeColor()) | 360 if (strokeColor != context->strokeColor()) |
362 context->setStrokeColor(strokeColor); | 361 context->setStrokeColor(strokeColor); |
363 if (strokeThickness != context->strokeThickness()) | 362 if (strokeThickness != context->strokeThickness()) |
364 context->setStrokeThickness(strokeThickness); | 363 context->setStrokeThickness(strokeThickness); |
365 } | 364 } |
366 } | 365 } |
367 | 366 |
368 bool InlineTextBox::isLineBreak() const | 367 bool InlineTextBox::isLineBreak() const |
369 { | 368 { |
370 return renderer()->isBR() || (renderer()->style()->preserveNewline() && len(
) == 1 && (*textRenderer()->text().impl())[start()] == '\n'); | 369 return renderer().isBR() || (renderer().style()->preserveNewline() && len()
== 1 && (*textRenderer().text().impl())[start()] == '\n'); |
371 } | 370 } |
372 | 371 |
373 bool InlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
sult, const HitTestLocation& locationInContainer, const LayoutPoint& accumulated
Offset, LayoutUnit /* lineTop */, LayoutUnit /*lineBottom*/) | 372 bool InlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
sult, const HitTestLocation& locationInContainer, const LayoutPoint& accumulated
Offset, LayoutUnit /* lineTop */, LayoutUnit /*lineBottom*/) |
374 { | 373 { |
375 if (isLineBreak()) | 374 if (isLineBreak()) |
376 return false; | 375 return false; |
377 | 376 |
378 FloatPoint boxOrigin = locationIncludingFlipping(); | 377 FloatPoint boxOrigin = locationIncludingFlipping(); |
379 boxOrigin.moveBy(accumulatedOffset); | 378 boxOrigin.moveBy(accumulatedOffset); |
380 FloatRect rect(boxOrigin, size()); | 379 FloatRect rect(boxOrigin, size()); |
381 if (m_truncation != cFullTruncation && visibleToHitTestRequest(request) && l
ocationInContainer.intersects(rect)) { | 380 if (m_truncation != cFullTruncation && visibleToHitTestRequest(request) && l
ocationInContainer.intersects(rect)) { |
382 renderer()->updateHitTestResult(result, flipForWritingMode(locationInCon
tainer.point() - toLayoutSize(accumulatedOffset))); | 381 renderer().updateHitTestResult(result, flipForWritingMode(locationInCont
ainer.point() - toLayoutSize(accumulatedOffset))); |
383 if (!result.addNodeToRectBasedTestResult(renderer()->node(), request, lo
cationInContainer, rect)) | 382 if (!result.addNodeToRectBasedTestResult(renderer().node(), request, loc
ationInContainer, rect)) |
384 return true; | 383 return true; |
385 } | 384 } |
386 return false; | 385 return false; |
387 } | 386 } |
388 | 387 |
389 static void paintTextWithShadows(GraphicsContext* context, | 388 static void paintTextWithShadows(GraphicsContext* context, |
390 const RenderObject* renderer, const Font& font, const TextRun& textRun, | 389 const RenderObject& renderer, const Font& font, const TextRun& textRun, |
391 const AtomicString& emphasisMark, int emphasisMarkOffset, | 390 const AtomicString& emphasisMark, int emphasisMarkOffset, |
392 int startOffset, int endOffset, int truncationPoint, | 391 int startOffset, int endOffset, int truncationPoint, |
393 const FloatPoint& textOrigin, const FloatRect& boxRect, | 392 const FloatPoint& textOrigin, const FloatRect& boxRect, |
394 const ShadowList* shadowList, bool stroked, bool horizontal) | 393 const ShadowList* shadowList, bool stroked, bool horizontal) |
395 { | 394 { |
396 // Text shadows are disabled when printing. http://crbug.com/258321 | 395 // Text shadows are disabled when printing. http://crbug.com/258321 |
397 bool hasShadow = shadowList && !context->printing(); | 396 bool hasShadow = shadowList && !context->printing(); |
398 | 397 |
399 if (hasShadow) { | 398 if (hasShadow) { |
400 OwnPtr<DrawLooperBuilder> drawLooperBuilder = DrawLooperBuilder::create(
); | 399 OwnPtr<DrawLooperBuilder> drawLooperBuilder = DrawLooperBuilder::create(
); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 bool InlineTextBox::getEmphasisMarkPosition(RenderStyle* style, TextEmphasisPosi
tion& emphasisPosition) const | 444 bool InlineTextBox::getEmphasisMarkPosition(RenderStyle* style, TextEmphasisPosi
tion& emphasisPosition) const |
446 { | 445 { |
447 // This function returns true if there are text emphasis marks and they are
suppressed by ruby text. | 446 // This function returns true if there are text emphasis marks and they are
suppressed by ruby text. |
448 if (style->textEmphasisMark() == TextEmphasisMarkNone) | 447 if (style->textEmphasisMark() == TextEmphasisMarkNone) |
449 return false; | 448 return false; |
450 | 449 |
451 emphasisPosition = style->textEmphasisPosition(); | 450 emphasisPosition = style->textEmphasisPosition(); |
452 if (emphasisPosition == TextEmphasisPositionUnder) | 451 if (emphasisPosition == TextEmphasisPositionUnder) |
453 return true; // Ruby text is always over, so it cannot suppress emphasis
marks under. | 452 return true; // Ruby text is always over, so it cannot suppress emphasis
marks under. |
454 | 453 |
455 RenderBlock* containingBlock = renderer()->containingBlock(); | 454 RenderBlock* containingBlock = renderer().containingBlock(); |
456 if (!containingBlock->isRubyBase()) | 455 if (!containingBlock->isRubyBase()) |
457 return true; // This text is not inside a ruby base, so it does not have
ruby text over it. | 456 return true; // This text is not inside a ruby base, so it does not have
ruby text over it. |
458 | 457 |
459 if (!containingBlock->parent()->isRubyRun()) | 458 if (!containingBlock->parent()->isRubyRun()) |
460 return true; // Cannot get the ruby text. | 459 return true; // Cannot get the ruby text. |
461 | 460 |
462 RenderRubyText* rubyText = toRenderRubyRun(containingBlock->parent())->rubyT
ext(); | 461 RenderRubyText* rubyText = toRenderRubyRun(containingBlock->parent())->rubyT
ext(); |
463 | 462 |
464 // The emphasis marks over are suppressed only if there is a ruby text box a
nd it not empty. | 463 // The emphasis marks over are suppressed only if there is a ruby text box a
nd it not empty. |
465 return !rubyText || !rubyText->firstLineBox(); | 464 return !rubyText || !rubyText->firstLineBox(); |
466 } | 465 } |
467 | 466 |
468 void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
LayoutUnit /*lineTop*/, LayoutUnit /*lineBottom*/) | 467 void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
LayoutUnit /*lineTop*/, LayoutUnit /*lineBottom*/) |
469 { | 468 { |
470 if (isLineBreak() || !paintInfo.shouldPaintWithinRoot(renderer()) || rendere
r()->style()->visibility() != VISIBLE || | 469 if (isLineBreak() || !paintInfo.shouldPaintWithinRoot(&renderer()) || render
er().style()->visibility() != VISIBLE |
471 m_truncation == cFullTruncation || paintInfo.phase == PaintPhaseOutline
|| !m_len) | 470 || m_truncation == cFullTruncation || paintInfo.phase == PaintPhaseOutli
ne || !m_len) |
472 return; | 471 return; |
473 | 472 |
474 ASSERT(paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintP
haseChildOutlines); | 473 ASSERT(paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintP
haseChildOutlines); |
475 | 474 |
476 LayoutUnit logicalLeftSide = logicalLeftVisualOverflow(); | 475 LayoutUnit logicalLeftSide = logicalLeftVisualOverflow(); |
477 LayoutUnit logicalRightSide = logicalRightVisualOverflow(); | 476 LayoutUnit logicalRightSide = logicalRightVisualOverflow(); |
478 LayoutUnit logicalStart = logicalLeftSide + (isHorizontal() ? paintOffset.x(
) : paintOffset.y()); | 477 LayoutUnit logicalStart = logicalLeftSide + (isHorizontal() ? paintOffset.x(
) : paintOffset.y()); |
479 LayoutUnit logicalExtent = logicalRightSide - logicalLeftSide; | 478 LayoutUnit logicalExtent = logicalRightSide - logicalLeftSide; |
480 | 479 |
481 LayoutUnit paintEnd = isHorizontal() ? paintInfo.rect.maxX() : paintInfo.rec
t.maxY(); | 480 LayoutUnit paintEnd = isHorizontal() ? paintInfo.rect.maxX() : paintInfo.rec
t.maxY(); |
482 LayoutUnit paintStart = isHorizontal() ? paintInfo.rect.x() : paintInfo.rect
.y(); | 481 LayoutUnit paintStart = isHorizontal() ? paintInfo.rect.x() : paintInfo.rect
.y(); |
483 | 482 |
484 LayoutPoint adjustedPaintOffset = roundedIntPoint(paintOffset); | 483 LayoutPoint adjustedPaintOffset = roundedIntPoint(paintOffset); |
485 | 484 |
486 if (logicalStart >= paintEnd || logicalStart + logicalExtent <= paintStart) | 485 if (logicalStart >= paintEnd || logicalStart + logicalExtent <= paintStart) |
487 return; | 486 return; |
488 | 487 |
489 bool isPrinting = textRenderer()->document().printing(); | 488 bool isPrinting = textRenderer().document().printing(); |
490 | 489 |
491 // Determine whether or not we're selected. | 490 // Determine whether or not we're selected. |
492 bool haveSelection = !isPrinting && paintInfo.phase != PaintPhaseTextClip &&
selectionState() != RenderObject::SelectionNone; | 491 bool haveSelection = !isPrinting && paintInfo.phase != PaintPhaseTextClip &&
selectionState() != RenderObject::SelectionNone; |
493 if (!haveSelection && paintInfo.phase == PaintPhaseSelection) | 492 if (!haveSelection && paintInfo.phase == PaintPhaseSelection) |
494 // When only painting the selection, don't bother to paint if there is n
one. | 493 // When only painting the selection, don't bother to paint if there is n
one. |
495 return; | 494 return; |
496 | 495 |
497 if (m_truncation != cNoTruncation) { | 496 if (m_truncation != cNoTruncation) { |
498 if (renderer()->containingBlock()->style()->isLeftToRightDirection() !=
isLeftToRightDirection()) { | 497 if (renderer().containingBlock()->style()->isLeftToRightDirection() != i
sLeftToRightDirection()) { |
499 // Make the visible fragment of text hug the edge closest to the res
t of the run by moving the origin | 498 // Make the visible fragment of text hug the edge closest to the res
t of the run by moving the origin |
500 // at which we start drawing text. | 499 // at which we start drawing text. |
501 // e.g. In the case of LTR text truncated in an RTL Context, the cor
rect behavior is: | 500 // e.g. In the case of LTR text truncated in an RTL Context, the cor
rect behavior is: |
502 // |Hello|CBA| -> |...He|CBA| | 501 // |Hello|CBA| -> |...He|CBA| |
503 // In order to draw the fragment "He" aligned to the right edge of i
t's box, we need to start drawing | 502 // In order to draw the fragment "He" aligned to the right edge of i
t's box, we need to start drawing |
504 // farther to the right. | 503 // farther to the right. |
505 // NOTE: WebKit's behavior differs from that of IE which appears to
just overlay the ellipsis on top of the | 504 // NOTE: WebKit's behavior differs from that of IE which appears to
just overlay the ellipsis on top of the |
506 // truncated string i.e. |Hello|CBA| -> |...lo|CBA| | 505 // truncated string i.e. |Hello|CBA| -> |...lo|CBA| |
507 LayoutUnit widthOfVisibleText = toRenderText(renderer())->width(m_st
art, m_truncation, textPos(), isLeftToRightDirection() ? LTR : RTL, isFirstLineS
tyle()); | 506 LayoutUnit widthOfVisibleText = toRenderText(renderer()).width(m_sta
rt, m_truncation, textPos(), isLeftToRightDirection() ? LTR : RTL, isFirstLineSt
yle()); |
508 LayoutUnit widthOfHiddenText = m_logicalWidth - widthOfVisibleText; | 507 LayoutUnit widthOfHiddenText = m_logicalWidth - widthOfVisibleText; |
509 // FIXME: The hit testing logic also needs to take this translation
into account. | 508 // FIXME: The hit testing logic also needs to take this translation
into account. |
510 LayoutSize truncationOffset(isLeftToRightDirection() ? widthOfHidden
Text : -widthOfHiddenText, 0); | 509 LayoutSize truncationOffset(isLeftToRightDirection() ? widthOfHidden
Text : -widthOfHiddenText, 0); |
511 adjustedPaintOffset.move(isHorizontal() ? truncationOffset : truncat
ionOffset.transposedSize()); | 510 adjustedPaintOffset.move(isHorizontal() ? truncationOffset : truncat
ionOffset.transposedSize()); |
512 } | 511 } |
513 } | 512 } |
514 | 513 |
515 GraphicsContext* context = paintInfo.context; | 514 GraphicsContext* context = paintInfo.context; |
516 | 515 |
517 RenderObject* rendererToUse = renderer(); | 516 RenderObject& rendererToUse = renderer(); |
518 RenderStyle* styleToUse = rendererToUse->style(isFirstLineStyle()); | 517 RenderStyle* styleToUse = rendererToUse.style(isFirstLineStyle()); |
519 | 518 |
520 adjustedPaintOffset.move(0, styleToUse->isHorizontalWritingMode() ? 0 : -log
icalHeight()); | 519 adjustedPaintOffset.move(0, styleToUse->isHorizontalWritingMode() ? 0 : -log
icalHeight()); |
521 | 520 |
522 FloatPoint boxOrigin = locationIncludingFlipping(); | 521 FloatPoint boxOrigin = locationIncludingFlipping(); |
523 boxOrigin.move(adjustedPaintOffset.x(), adjustedPaintOffset.y()); | 522 boxOrigin.move(adjustedPaintOffset.x(), adjustedPaintOffset.y()); |
524 FloatRect boxRect(boxOrigin, LayoutSize(logicalWidth(), logicalHeight())); | 523 FloatRect boxRect(boxOrigin, LayoutSize(logicalWidth(), logicalHeight())); |
525 | 524 |
526 RenderCombineText* combinedText = styleToUse->hasTextCombine() && textRender
er()->isCombineText() && toRenderCombineText(textRenderer())->isCombined() ? toR
enderCombineText(textRenderer()) : 0; | 525 RenderCombineText* combinedText = styleToUse->hasTextCombine() && textRender
er().isCombineText() && toRenderCombineText(textRenderer()).isCombined() ? &toRe
nderCombineText(textRenderer()) : 0; |
527 | 526 |
528 bool shouldRotate = !isHorizontal() && !combinedText; | 527 bool shouldRotate = !isHorizontal() && !combinedText; |
529 if (shouldRotate) | 528 if (shouldRotate) |
530 context->concatCTM(rotation(boxRect, Clockwise)); | 529 context->concatCTM(rotation(boxRect, Clockwise)); |
531 | 530 |
532 // Determine whether or not we have composition underlines to draw. | 531 // Determine whether or not we have composition underlines to draw. |
533 bool containsComposition = renderer()->node() && renderer()->frame()->inputM
ethodController().compositionNode() == renderer()->node(); | 532 bool containsComposition = renderer().node() && renderer().frame()->inputMet
hodController().compositionNode() == renderer().node(); |
534 bool useCustomUnderlines = containsComposition && renderer()->frame()->input
MethodController().compositionUsesCustomUnderlines(); | 533 bool useCustomUnderlines = containsComposition && renderer().frame()->inputM
ethodController().compositionUsesCustomUnderlines(); |
535 | 534 |
536 // Determine the text colors and selection colors. | 535 // Determine the text colors and selection colors. |
537 Color textFillColor; | 536 Color textFillColor; |
538 Color textStrokeColor; | 537 Color textStrokeColor; |
539 Color emphasisMarkColor; | 538 Color emphasisMarkColor; |
540 float textStrokeWidth = styleToUse->textStrokeWidth(); | 539 float textStrokeWidth = styleToUse->textStrokeWidth(); |
541 | 540 |
542 // Text shadows are disabled when printing. http://crbug.com/258321 | 541 // Text shadows are disabled when printing. http://crbug.com/258321 |
543 const ShadowList* textShadow = (context->printing() || paintInfo.forceBlackT
ext()) ? 0 : styleToUse->textShadow(); | 542 const ShadowList* textShadow = (context->printing() || paintInfo.forceBlackT
ext()) ? 0 : styleToUse->textShadow(); |
544 | 543 |
545 if (paintInfo.forceBlackText()) { | 544 if (paintInfo.forceBlackText()) { |
546 textFillColor = Color::black; | 545 textFillColor = Color::black; |
547 textStrokeColor = Color::black; | 546 textStrokeColor = Color::black; |
548 emphasisMarkColor = Color::black; | 547 emphasisMarkColor = Color::black; |
549 } else { | 548 } else { |
550 textFillColor = rendererToUse->resolveColor(styleToUse, CSSPropertyWebki
tTextFillColor); | 549 textFillColor = rendererToUse.resolveColor(styleToUse, CSSPropertyWebkit
TextFillColor); |
551 | 550 |
552 bool forceBackgroundToWhite = false; | 551 bool forceBackgroundToWhite = false; |
553 if (isPrinting) { | 552 if (isPrinting) { |
554 if (styleToUse->printColorAdjust() == PrintColorAdjustEconomy) | 553 if (styleToUse->printColorAdjust() == PrintColorAdjustEconomy) |
555 forceBackgroundToWhite = true; | 554 forceBackgroundToWhite = true; |
556 if (textRenderer()->document().settings() && textRenderer()->documen
t().settings()->shouldPrintBackgrounds()) | 555 if (textRenderer().document().settings() && textRenderer().document(
).settings()->shouldPrintBackgrounds()) |
557 forceBackgroundToWhite = false; | 556 forceBackgroundToWhite = false; |
558 } | 557 } |
559 | 558 |
560 // Make the text fill color legible against a white background | 559 // Make the text fill color legible against a white background |
561 if (forceBackgroundToWhite) | 560 if (forceBackgroundToWhite) |
562 textFillColor = correctedTextColor(textFillColor, Color::white); | 561 textFillColor = correctedTextColor(textFillColor, Color::white); |
563 | 562 |
564 textStrokeColor = rendererToUse->resolveColor(styleToUse, CSSPropertyWeb
kitTextStrokeColor); | 563 textStrokeColor = rendererToUse.resolveColor(styleToUse, CSSPropertyWebk
itTextStrokeColor); |
565 | 564 |
566 // Make the text stroke color legible against a white background | 565 // Make the text stroke color legible against a white background |
567 if (forceBackgroundToWhite) | 566 if (forceBackgroundToWhite) |
568 textStrokeColor = correctedTextColor(textStrokeColor, Color::white); | 567 textStrokeColor = correctedTextColor(textStrokeColor, Color::white); |
569 | 568 |
570 emphasisMarkColor = rendererToUse->resolveColor(styleToUse, CSSPropertyW
ebkitTextEmphasisColor); | 569 emphasisMarkColor = rendererToUse.resolveColor(styleToUse, CSSPropertyWe
bkitTextEmphasisColor); |
571 | 570 |
572 // Make the text stroke color legible against a white background | 571 // Make the text stroke color legible against a white background |
573 if (forceBackgroundToWhite) | 572 if (forceBackgroundToWhite) |
574 emphasisMarkColor = correctedTextColor(emphasisMarkColor, Color::whi
te); | 573 emphasisMarkColor = correctedTextColor(emphasisMarkColor, Color::whi
te); |
575 } | 574 } |
576 | 575 |
577 bool paintSelectedTextOnly = (paintInfo.phase == PaintPhaseSelection); | 576 bool paintSelectedTextOnly = (paintInfo.phase == PaintPhaseSelection); |
578 bool paintSelectedTextSeparately = false; | 577 bool paintSelectedTextSeparately = false; |
579 | 578 |
580 Color selectionFillColor = textFillColor; | 579 Color selectionFillColor = textFillColor; |
581 Color selectionStrokeColor = textStrokeColor; | 580 Color selectionStrokeColor = textStrokeColor; |
582 Color selectionEmphasisMarkColor = emphasisMarkColor; | 581 Color selectionEmphasisMarkColor = emphasisMarkColor; |
583 float selectionStrokeWidth = textStrokeWidth; | 582 float selectionStrokeWidth = textStrokeWidth; |
584 const ShadowList* selectionShadow = textShadow; | 583 const ShadowList* selectionShadow = textShadow; |
585 if (haveSelection) { | 584 if (haveSelection) { |
586 // Check foreground color first. | 585 // Check foreground color first. |
587 Color foreground = paintInfo.forceBlackText() ? Color::black : renderer(
)->selectionForegroundColor(); | 586 Color foreground = paintInfo.forceBlackText() ? Color::black : renderer(
).selectionForegroundColor(); |
588 if (foreground != selectionFillColor) { | 587 if (foreground != selectionFillColor) { |
589 if (!paintSelectedTextOnly) | 588 if (!paintSelectedTextOnly) |
590 paintSelectedTextSeparately = true; | 589 paintSelectedTextSeparately = true; |
591 selectionFillColor = foreground; | 590 selectionFillColor = foreground; |
592 } | 591 } |
593 | 592 |
594 Color emphasisMarkForeground = paintInfo.forceBlackText() ? Color::black
: renderer()->selectionEmphasisMarkColor(); | 593 Color emphasisMarkForeground = paintInfo.forceBlackText() ? Color::black
: renderer().selectionEmphasisMarkColor(); |
595 if (emphasisMarkForeground != selectionEmphasisMarkColor) { | 594 if (emphasisMarkForeground != selectionEmphasisMarkColor) { |
596 if (!paintSelectedTextOnly) | 595 if (!paintSelectedTextOnly) |
597 paintSelectedTextSeparately = true; | 596 paintSelectedTextSeparately = true; |
598 selectionEmphasisMarkColor = emphasisMarkForeground; | 597 selectionEmphasisMarkColor = emphasisMarkForeground; |
599 } | 598 } |
600 | 599 |
601 if (RenderStyle* pseudoStyle = renderer()->getCachedPseudoStyle(SELECTIO
N)) { | 600 if (RenderStyle* pseudoStyle = renderer().getCachedPseudoStyle(SELECTION
)) { |
602 // Text shadows are disabled when printing. http://crbug.com/258321 | 601 // Text shadows are disabled when printing. http://crbug.com/258321 |
603 const ShadowList* shadow = (context->printing() || paintInfo.forceBl
ackText()) ? 0 : pseudoStyle->textShadow(); | 602 const ShadowList* shadow = (context->printing() || paintInfo.forceBl
ackText()) ? 0 : pseudoStyle->textShadow(); |
604 if (shadow != selectionShadow) { | 603 if (shadow != selectionShadow) { |
605 if (!paintSelectedTextOnly) | 604 if (!paintSelectedTextOnly) |
606 paintSelectedTextSeparately = true; | 605 paintSelectedTextSeparately = true; |
607 selectionShadow = shadow; | 606 selectionShadow = shadow; |
608 } | 607 } |
609 | 608 |
610 float strokeWidth = pseudoStyle->textStrokeWidth(); | 609 float strokeWidth = pseudoStyle->textStrokeWidth(); |
611 if (strokeWidth != selectionStrokeWidth) { | 610 if (strokeWidth != selectionStrokeWidth) { |
612 if (!paintSelectedTextOnly) | 611 if (!paintSelectedTextOnly) |
613 paintSelectedTextSeparately = true; | 612 paintSelectedTextSeparately = true; |
614 selectionStrokeWidth = strokeWidth; | 613 selectionStrokeWidth = strokeWidth; |
615 } | 614 } |
616 | 615 |
617 Color stroke = paintInfo.forceBlackText() ? Color::black : rendererT
oUse->resolveColor(pseudoStyle, CSSPropertyWebkitTextStrokeColor); | 616 Color stroke = paintInfo.forceBlackText() ? Color::black : rendererT
oUse.resolveColor(pseudoStyle, CSSPropertyWebkitTextStrokeColor); |
618 if (stroke != selectionStrokeColor) { | 617 if (stroke != selectionStrokeColor) { |
619 if (!paintSelectedTextOnly) | 618 if (!paintSelectedTextOnly) |
620 paintSelectedTextSeparately = true; | 619 paintSelectedTextSeparately = true; |
621 selectionStrokeColor = stroke; | 620 selectionStrokeColor = stroke; |
622 } | 621 } |
623 } | 622 } |
624 } | 623 } |
625 | 624 |
626 // Set our font. | 625 // Set our font. |
627 const Font& font = styleToUse->font(); | 626 const Font& font = styleToUse->font(); |
628 | 627 |
629 FloatPoint textOrigin = FloatPoint(boxOrigin.x(), boxOrigin.y() + font.fontM
etrics().ascent()); | 628 FloatPoint textOrigin = FloatPoint(boxOrigin.x(), boxOrigin.y() + font.fontM
etrics().ascent()); |
630 | 629 |
631 if (combinedText) | 630 if (combinedText) |
632 combinedText->adjustTextOrigin(textOrigin, boxRect); | 631 combinedText->adjustTextOrigin(textOrigin, boxRect); |
633 | 632 |
634 // 1. Paint backgrounds behind text if needed. Examples of such backgrounds
include selection | 633 // 1. Paint backgrounds behind text if needed. Examples of such backgrounds
include selection |
635 // and composition underlines. | 634 // and composition underlines. |
636 if (paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseT
extClip && !isPrinting) { | 635 if (paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseT
extClip && !isPrinting) { |
637 | 636 |
638 if (containsComposition && !useCustomUnderlines) { | 637 if (containsComposition && !useCustomUnderlines) { |
639 paintCompositionBackground(context, boxOrigin, styleToUse, font, | 638 paintCompositionBackground(context, boxOrigin, styleToUse, font, |
640 renderer()->frame()->inputMethodController().compositionStart(), | 639 renderer().frame()->inputMethodController().compositionStart(), |
641 renderer()->frame()->inputMethodController().compositionEnd()); | 640 renderer().frame()->inputMethodController().compositionEnd()); |
642 } | 641 } |
643 | 642 |
644 paintDocumentMarkers(context, boxOrigin, styleToUse, font, true); | 643 paintDocumentMarkers(context, boxOrigin, styleToUse, font, true); |
645 | 644 |
646 if (haveSelection && !useCustomUnderlines) | 645 if (haveSelection && !useCustomUnderlines) |
647 paintSelection(context, boxOrigin, styleToUse, font, selectionFillCo
lor); | 646 paintSelection(context, boxOrigin, styleToUse, font, selectionFillCo
lor); |
648 } | 647 } |
649 | 648 |
650 // 2. Now paint the foreground, including text and decorations like underlin
e/overline (in quirks mode only). | 649 // 2. Now paint the foreground, including text and decorations like underlin
e/overline (in quirks mode only). |
651 int length = m_len; | 650 int length = m_len; |
652 int maximumLength; | 651 int maximumLength; |
653 StringView string; | 652 StringView string; |
654 if (!combinedText) { | 653 if (!combinedText) { |
655 string = textRenderer()->text().createView(); | 654 string = textRenderer().text().createView(); |
656 if (static_cast<unsigned>(length) != string.length() || m_start) | 655 if (static_cast<unsigned>(length) != string.length() || m_start) |
657 string.narrow(m_start, length); | 656 string.narrow(m_start, length); |
658 maximumLength = textRenderer()->textLength() - m_start; | 657 maximumLength = textRenderer().textLength() - m_start; |
659 } else { | 658 } else { |
660 combinedText->getStringToRender(m_start, string, length); | 659 combinedText->getStringToRender(m_start, string, length); |
661 maximumLength = length; | 660 maximumLength = length; |
662 } | 661 } |
663 | 662 |
664 StringBuilder charactersWithHyphen; | 663 StringBuilder charactersWithHyphen; |
665 TextRun textRun = constructTextRun(styleToUse, font, string, maximumLength,
hasHyphen() ? &charactersWithHyphen : 0); | 664 TextRun textRun = constructTextRun(styleToUse, font, string, maximumLength,
hasHyphen() ? &charactersWithHyphen : 0); |
666 if (hasHyphen()) | 665 if (hasHyphen()) |
667 length = textRun.length(); | 666 length = textRun.length(); |
668 | 667 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
748 context->concatCTM(rotation(boxRect, Clockwise)); | 747 context->concatCTM(rotation(boxRect, Clockwise)); |
749 paintDecoration(context, boxOrigin, textDecorations, styleToUse->textDec
orationStyle(), textShadow); | 748 paintDecoration(context, boxOrigin, textDecorations, styleToUse->textDec
orationStyle(), textShadow); |
750 if (combinedText) | 749 if (combinedText) |
751 context->concatCTM(rotation(boxRect, Counterclockwise)); | 750 context->concatCTM(rotation(boxRect, Counterclockwise)); |
752 } | 751 } |
753 | 752 |
754 if (paintInfo.phase == PaintPhaseForeground) { | 753 if (paintInfo.phase == PaintPhaseForeground) { |
755 paintDocumentMarkers(context, boxOrigin, styleToUse, font, false); | 754 paintDocumentMarkers(context, boxOrigin, styleToUse, font, false); |
756 | 755 |
757 if (useCustomUnderlines) { | 756 if (useCustomUnderlines) { |
758 const Vector<CompositionUnderline>& underlines = renderer()->frame()
->inputMethodController().customCompositionUnderlines(); | 757 const Vector<CompositionUnderline>& underlines = renderer().frame()-
>inputMethodController().customCompositionUnderlines(); |
759 size_t numUnderlines = underlines.size(); | 758 size_t numUnderlines = underlines.size(); |
760 | 759 |
761 for (size_t index = 0; index < numUnderlines; ++index) { | 760 for (size_t index = 0; index < numUnderlines; ++index) { |
762 const CompositionUnderline& underline = underlines[index]; | 761 const CompositionUnderline& underline = underlines[index]; |
763 | 762 |
764 if (underline.endOffset <= start()) | 763 if (underline.endOffset <= start()) |
765 // underline is completely before this run. This might be a
n underline that sits | 764 // underline is completely before this run. This might be a
n underline that sits |
766 // before the first run we draw, or underlines that were wit
hin runs we skipped | 765 // before the first run we draw, or underlines that were wit
hin runs we skipped |
767 // due to truncation. | 766 // due to truncation. |
768 continue; | 767 continue; |
(...skipping 11 matching lines...) Expand all Loading... |
780 } | 779 } |
781 } | 780 } |
782 | 781 |
783 if (shouldRotate) | 782 if (shouldRotate) |
784 context->concatCTM(rotation(boxRect, Counterclockwise)); | 783 context->concatCTM(rotation(boxRect, Counterclockwise)); |
785 } | 784 } |
786 | 785 |
787 void InlineTextBox::selectionStartEnd(int& sPos, int& ePos) | 786 void InlineTextBox::selectionStartEnd(int& sPos, int& ePos) |
788 { | 787 { |
789 int startPos, endPos; | 788 int startPos, endPos; |
790 if (renderer()->selectionState() == RenderObject::SelectionInside) { | 789 if (renderer().selectionState() == RenderObject::SelectionInside) { |
791 startPos = 0; | 790 startPos = 0; |
792 endPos = textRenderer()->textLength(); | 791 endPos = textRenderer().textLength(); |
793 } else { | 792 } else { |
794 textRenderer()->selectionStartEnd(startPos, endPos); | 793 textRenderer().selectionStartEnd(startPos, endPos); |
795 if (renderer()->selectionState() == RenderObject::SelectionStart) | 794 if (renderer().selectionState() == RenderObject::SelectionStart) |
796 endPos = textRenderer()->textLength(); | 795 endPos = textRenderer().textLength(); |
797 else if (renderer()->selectionState() == RenderObject::SelectionEnd) | 796 else if (renderer().selectionState() == RenderObject::SelectionEnd) |
798 startPos = 0; | 797 startPos = 0; |
799 } | 798 } |
800 | 799 |
801 sPos = max(startPos - m_start, 0); | 800 sPos = max(startPos - m_start, 0); |
802 ePos = min(endPos - m_start, (int)m_len); | 801 ePos = min(endPos - m_start, (int)m_len); |
803 } | 802 } |
804 | 803 |
805 void alignSelectionRectToDevicePixels(FloatRect& rect) | 804 void alignSelectionRectToDevicePixels(FloatRect& rect) |
806 { | 805 { |
807 float maxX = floorf(rect.maxX()); | 806 float maxX = floorf(rect.maxX()); |
808 rect.setX(floorf(rect.x())); | 807 rect.setX(floorf(rect.x())); |
809 rect.setWidth(roundf(maxX - rect.x())); | 808 rect.setWidth(roundf(maxX - rect.x())); |
810 } | 809 } |
811 | 810 |
812 void InlineTextBox::paintSelection(GraphicsContext* context, const FloatPoint& b
oxOrigin, RenderStyle* style, const Font& font, Color textColor) | 811 void InlineTextBox::paintSelection(GraphicsContext* context, const FloatPoint& b
oxOrigin, RenderStyle* style, const Font& font, Color textColor) |
813 { | 812 { |
814 if (context->paintingDisabled()) | 813 if (context->paintingDisabled()) |
815 return; | 814 return; |
816 | 815 |
817 // See if we have a selection to paint at all. | 816 // See if we have a selection to paint at all. |
818 int sPos, ePos; | 817 int sPos, ePos; |
819 selectionStartEnd(sPos, ePos); | 818 selectionStartEnd(sPos, ePos); |
820 if (sPos >= ePos) | 819 if (sPos >= ePos) |
821 return; | 820 return; |
822 | 821 |
823 Color c = renderer()->selectionBackgroundColor(); | 822 Color c = renderer().selectionBackgroundColor(); |
824 if (!c.alpha()) | 823 if (!c.alpha()) |
825 return; | 824 return; |
826 | 825 |
827 // If the text color ends up being the same as the selection background, inv
ert the selection | 826 // If the text color ends up being the same as the selection background, inv
ert the selection |
828 // background. | 827 // background. |
829 if (textColor == c) | 828 if (textColor == c) |
830 c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue()); | 829 c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue()); |
831 | 830 |
832 GraphicsContextStateSaver stateSaver(*context); | 831 GraphicsContextStateSaver stateSaver(*context); |
833 updateGraphicsContext(context, c, c, 0); // Don't draw text at all! | 832 updateGraphicsContext(context, c, c, 0); // Don't draw text at all! |
834 | 833 |
835 // If the text is truncated, let the thing being painted in the truncation | 834 // If the text is truncated, let the thing being painted in the truncation |
836 // draw its own highlight. | 835 // draw its own highlight. |
837 int length = m_truncation != cNoTruncation ? m_truncation : m_len; | 836 int length = m_truncation != cNoTruncation ? m_truncation : m_len; |
838 StringView string = textRenderer()->text().createView(); | 837 StringView string = textRenderer().text().createView(); |
839 | 838 |
840 if (string.length() != static_cast<unsigned>(length) || m_start) | 839 if (string.length() != static_cast<unsigned>(length) || m_start) |
841 string.narrow(m_start, length); | 840 string.narrow(m_start, length); |
842 | 841 |
843 StringBuilder charactersWithHyphen; | 842 StringBuilder charactersWithHyphen; |
844 bool respectHyphen = ePos == length && hasHyphen(); | 843 bool respectHyphen = ePos == length && hasHyphen(); |
845 TextRun textRun = constructTextRun(style, font, string, textRenderer()->text
Length() - m_start, respectHyphen ? &charactersWithHyphen : 0); | 844 TextRun textRun = constructTextRun(style, font, string, textRenderer().textL
ength() - m_start, respectHyphen ? &charactersWithHyphen : 0); |
846 if (respectHyphen) | 845 if (respectHyphen) |
847 ePos = textRun.length(); | 846 ePos = textRun.length(); |
848 | 847 |
849 LayoutUnit selectionBottom = root()->selectionBottom(); | 848 LayoutUnit selectionBottom = root()->selectionBottom(); |
850 LayoutUnit selectionTop = root()->selectionTopAdjustedForPrecedingBlock(); | 849 LayoutUnit selectionTop = root()->selectionTopAdjustedForPrecedingBlock(); |
851 | 850 |
852 int deltaY = roundToInt(renderer()->style()->isFlippedLinesWritingMode() ? s
electionBottom - logicalBottom() : logicalTop() - selectionTop); | 851 int deltaY = roundToInt(renderer().style()->isFlippedLinesWritingMode() ? se
lectionBottom - logicalBottom() : logicalTop() - selectionTop); |
853 int selHeight = max(0, roundToInt(selectionBottom - selectionTop)); | 852 int selHeight = max(0, roundToInt(selectionBottom - selectionTop)); |
854 | 853 |
855 FloatPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY); | 854 FloatPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY); |
856 FloatRect clipRect(localOrigin, FloatSize(m_logicalWidth, selHeight)); | 855 FloatRect clipRect(localOrigin, FloatSize(m_logicalWidth, selHeight)); |
857 alignSelectionRectToDevicePixels(clipRect); | 856 alignSelectionRectToDevicePixels(clipRect); |
858 | 857 |
859 context->clip(clipRect); | 858 context->clip(clipRect); |
860 | 859 |
861 context->drawHighlightForText(font, textRun, localOrigin, selHeight, c, sPos
, ePos); | 860 context->drawHighlightForText(font, textRun, localOrigin, selHeight, c, sPos
, ePos); |
862 } | 861 } |
863 | 862 |
864 void InlineTextBox::paintCompositionBackground(GraphicsContext* context, const F
loatPoint& boxOrigin, RenderStyle* style, const Font& font, int startPos, int en
dPos) | 863 void InlineTextBox::paintCompositionBackground(GraphicsContext* context, const F
loatPoint& boxOrigin, RenderStyle* style, const Font& font, int startPos, int en
dPos) |
865 { | 864 { |
866 int offset = m_start; | 865 int offset = m_start; |
867 int sPos = max(startPos - offset, 0); | 866 int sPos = max(startPos - offset, 0); |
868 int ePos = min(endPos - offset, (int)m_len); | 867 int ePos = min(endPos - offset, (int)m_len); |
869 | 868 |
870 if (sPos >= ePos) | 869 if (sPos >= ePos) |
871 return; | 870 return; |
872 | 871 |
873 GraphicsContextStateSaver stateSaver(*context); | 872 GraphicsContextStateSaver stateSaver(*context); |
874 | 873 |
875 Color c = Color(225, 221, 85); | 874 Color c = Color(225, 221, 85); |
876 | 875 |
877 updateGraphicsContext(context, c, c, 0); // Don't draw text at all! | 876 updateGraphicsContext(context, c, c, 0); // Don't draw text at all! |
878 | 877 |
879 int deltaY = renderer()->style()->isFlippedLinesWritingMode() ? selectionBot
tom() - logicalBottom() : logicalTop() - selectionTop(); | 878 int deltaY = renderer().style()->isFlippedLinesWritingMode() ? selectionBott
om() - logicalBottom() : logicalTop() - selectionTop(); |
880 int selHeight = selectionHeight(); | 879 int selHeight = selectionHeight(); |
881 FloatPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY); | 880 FloatPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY); |
882 context->drawHighlightForText(font, constructTextRun(style, font), localOrig
in, selHeight, c, sPos, ePos); | 881 context->drawHighlightForText(font, constructTextRun(style, font), localOrig
in, selHeight, c, sPos, ePos); |
883 } | 882 } |
884 | 883 |
885 static StrokeStyle textDecorationStyleToStrokeStyle(TextDecorationStyle decorati
onStyle) | 884 static StrokeStyle textDecorationStyleToStrokeStyle(TextDecorationStyle decorati
onStyle) |
886 { | 885 { |
887 StrokeStyle strokeStyle = SolidStroke; | 886 StrokeStyle strokeStyle = SolidStroke; |
888 switch (decorationStyle) { | 887 switch (decorationStyle) { |
889 case TextDecorationStyleSolid: | 888 case TextDecorationStyleSolid: |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1055 { | 1054 { |
1056 GraphicsContextStateSaver stateSaver(*context); | 1055 GraphicsContextStateSaver stateSaver(*context); |
1057 | 1056 |
1058 if (m_truncation == cFullTruncation) | 1057 if (m_truncation == cFullTruncation) |
1059 return; | 1058 return; |
1060 | 1059 |
1061 FloatPoint localOrigin = boxOrigin; | 1060 FloatPoint localOrigin = boxOrigin; |
1062 | 1061 |
1063 float width = m_logicalWidth; | 1062 float width = m_logicalWidth; |
1064 if (m_truncation != cNoTruncation) { | 1063 if (m_truncation != cNoTruncation) { |
1065 width = toRenderText(renderer())->width(m_start, m_truncation, textPos()
, isLeftToRightDirection() ? LTR : RTL, isFirstLineStyle()); | 1064 width = toRenderText(renderer()).width(m_start, m_truncation, textPos(),
isLeftToRightDirection() ? LTR : RTL, isFirstLineStyle()); |
1066 if (!isLeftToRightDirection()) | 1065 if (!isLeftToRightDirection()) |
1067 localOrigin.move(m_logicalWidth - width, 0); | 1066 localOrigin.move(m_logicalWidth - width, 0); |
1068 } | 1067 } |
1069 | 1068 |
1070 // Get the text decoration colors. | 1069 // Get the text decoration colors. |
1071 Color underline(Color::transparent), overline(Color::transparent), linethrou
gh(Color::transparent); | 1070 Color underline(Color::transparent), overline(Color::transparent), linethrou
gh(Color::transparent); |
1072 renderer()->getTextDecorationColors(deco, underline, overline, linethrough,
true); | 1071 renderer().getTextDecorationColors(deco, underline, overline, linethrough, t
rue); |
1073 if (isFirstLineStyle()) | 1072 if (isFirstLineStyle()) |
1074 renderer()->getTextDecorationColors(deco, underline, overline, linethrou
gh, true, true); | 1073 renderer().getTextDecorationColors(deco, underline, overline, linethroug
h, true, true); |
1075 | 1074 |
1076 // Use a special function for underlines to get the positioning exactly righ
t. | 1075 // Use a special function for underlines to get the positioning exactly righ
t. |
1077 bool isPrinting = textRenderer()->document().printing(); | 1076 bool isPrinting = textRenderer().document().printing(); |
1078 | 1077 |
1079 bool linesAreOpaque = !isPrinting && (!(deco & TextDecorationUnderline) || u
nderline.alpha() == 255) && (!(deco & TextDecorationOverline) || overline.alpha(
) == 255) && (!(deco & TextDecorationLineThrough) || linethrough.alpha() == 255)
; | 1078 bool linesAreOpaque = !isPrinting && (!(deco & TextDecorationUnderline) || u
nderline.alpha() == 255) && (!(deco & TextDecorationOverline) || overline.alpha(
) == 255) && (!(deco & TextDecorationLineThrough) || linethrough.alpha() == 255)
; |
1080 | 1079 |
1081 RenderStyle* styleToUse = renderer()->style(isFirstLineStyle()); | 1080 RenderStyle* styleToUse = renderer().style(isFirstLineStyle()); |
1082 int baseline = styleToUse->fontMetrics().ascent(); | 1081 int baseline = styleToUse->fontMetrics().ascent(); |
1083 | 1082 |
1084 size_t shadowCount = shadowList ? shadowList->shadows().size() : 0; | 1083 size_t shadowCount = shadowList ? shadowList->shadows().size() : 0; |
1085 // Set the thick of the line to be 10% (or something else ?)of the computed
font size and not less than 1px. | 1084 // Set the thick of the line to be 10% (or something else ?)of the computed
font size and not less than 1px. |
1086 // Using computedFontSize should take care of zoom as well. | 1085 // Using computedFontSize should take care of zoom as well. |
1087 | 1086 |
1088 // Update Underline thickness, in case we have Faulty Font Metrics calculati
ng underline thickness by old method. | 1087 // Update Underline thickness, in case we have Faulty Font Metrics calculati
ng underline thickness by old method. |
1089 float textDecorationThickness = styleToUse->fontMetrics().underlineThickness
(); | 1088 float textDecorationThickness = styleToUse->fontMetrics().underlineThickness
(); |
1090 int fontHeightInt = (int)(styleToUse->fontMetrics().floatHeight() + 0.5); | 1089 int fontHeightInt = (int)(styleToUse->fontMetrics().floatHeight() + 0.5); |
1091 if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHei
ghtInt >> 1))) | 1090 if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHei
ghtInt >> 1))) |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1187 return GraphicsContext::DocumentMarkerGrammarLineStyle; | 1186 return GraphicsContext::DocumentMarkerGrammarLineStyle; |
1188 default: | 1187 default: |
1189 ASSERT_NOT_REACHED(); | 1188 ASSERT_NOT_REACHED(); |
1190 return GraphicsContext::DocumentMarkerSpellingLineStyle; | 1189 return GraphicsContext::DocumentMarkerSpellingLineStyle; |
1191 } | 1190 } |
1192 } | 1191 } |
1193 | 1192 |
1194 void InlineTextBox::paintDocumentMarker(GraphicsContext* pt, const FloatPoint& b
oxOrigin, DocumentMarker* marker, RenderStyle* style, const Font& font, bool gra
mmar) | 1193 void InlineTextBox::paintDocumentMarker(GraphicsContext* pt, const FloatPoint& b
oxOrigin, DocumentMarker* marker, RenderStyle* style, const Font& font, bool gra
mmar) |
1195 { | 1194 { |
1196 // Never print spelling/grammar markers (5327887) | 1195 // Never print spelling/grammar markers (5327887) |
1197 if (textRenderer()->document().printing()) | 1196 if (textRenderer().document().printing()) |
1198 return; | 1197 return; |
1199 | 1198 |
1200 if (m_truncation == cFullTruncation) | 1199 if (m_truncation == cFullTruncation) |
1201 return; | 1200 return; |
1202 | 1201 |
1203 float start = 0; // start of line to draw, relative to tx | 1202 float start = 0; // start of line to draw, relative to tx |
1204 float width = m_logicalWidth; // how much line to draw | 1203 float width = m_logicalWidth; // how much line to draw |
1205 | 1204 |
1206 // Determine whether we need to measure text | 1205 // Determine whether we need to measure text |
1207 bool markerSpansWholeBox = true; | 1206 bool markerSpansWholeBox = true; |
1208 if (m_start <= (int)marker->startOffset()) | 1207 if (m_start <= (int)marker->startOffset()) |
1209 markerSpansWholeBox = false; | 1208 markerSpansWholeBox = false; |
1210 if ((end() + 1) != marker->endOffset()) // end points at the last char, not
past it | 1209 if ((end() + 1) != marker->endOffset()) // end points at the last char, not
past it |
1211 markerSpansWholeBox = false; | 1210 markerSpansWholeBox = false; |
1212 if (m_truncation != cNoTruncation) | 1211 if (m_truncation != cNoTruncation) |
1213 markerSpansWholeBox = false; | 1212 markerSpansWholeBox = false; |
1214 | 1213 |
1215 if (!markerSpansWholeBox || grammar) { | 1214 if (!markerSpansWholeBox || grammar) { |
1216 int startPosition = max<int>(marker->startOffset() - m_start, 0); | 1215 int startPosition = max<int>(marker->startOffset() - m_start, 0); |
1217 int endPosition = min<int>(marker->endOffset() - m_start, m_len); | 1216 int endPosition = min<int>(marker->endOffset() - m_start, m_len); |
1218 | 1217 |
1219 if (m_truncation != cNoTruncation) | 1218 if (m_truncation != cNoTruncation) |
1220 endPosition = min<int>(endPosition, m_truncation); | 1219 endPosition = min<int>(endPosition, m_truncation); |
1221 | 1220 |
1222 // Calculate start & width | 1221 // Calculate start & width |
1223 int deltaY = renderer()->style()->isFlippedLinesWritingMode() ? selectio
nBottom() - logicalBottom() : logicalTop() - selectionTop(); | 1222 int deltaY = renderer().style()->isFlippedLinesWritingMode() ? selection
Bottom() - logicalBottom() : logicalTop() - selectionTop(); |
1224 int selHeight = selectionHeight(); | 1223 int selHeight = selectionHeight(); |
1225 FloatPoint startPoint(boxOrigin.x(), boxOrigin.y() - deltaY); | 1224 FloatPoint startPoint(boxOrigin.x(), boxOrigin.y() - deltaY); |
1226 TextRun run = constructTextRun(style, font); | 1225 TextRun run = constructTextRun(style, font); |
1227 | 1226 |
1228 // FIXME: Convert the document markers to float rects. | 1227 // FIXME: Convert the document markers to float rects. |
1229 IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, sta
rtPoint, selHeight, startPosition, endPosition)); | 1228 IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, sta
rtPoint, selHeight, startPosition, endPosition)); |
1230 start = markerRect.x() - startPoint.x(); | 1229 start = markerRect.x() - startPoint.x(); |
1231 width = markerRect.width(); | 1230 width = markerRect.width(); |
1232 | 1231 |
1233 // Store rendered rects for bad grammar markers, so we can hit-test agai
nst it elsewhere in order to | 1232 // Store rendered rects for bad grammar markers, so we can hit-test agai
nst it elsewhere in order to |
1234 // display a toolTip. We don't do this for misspelling markers. | 1233 // display a toolTip. We don't do this for misspelling markers. |
1235 if (grammar) { | 1234 if (grammar) { |
1236 markerRect.move(-boxOrigin.x(), -boxOrigin.y()); | 1235 markerRect.move(-boxOrigin.x(), -boxOrigin.y()); |
1237 markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect)).
enclosingBoundingBox(); | 1236 markerRect = renderer().localToAbsoluteQuad(FloatRect(markerRect)).e
nclosingBoundingBox(); |
1238 toRenderedDocumentMarker(marker)->setRenderedRect(markerRect); | 1237 toRenderedDocumentMarker(marker)->setRenderedRect(markerRect); |
1239 } | 1238 } |
1240 } | 1239 } |
1241 | 1240 |
1242 // IMPORTANT: The misspelling underline is not considered when calculating t
he text bounds, so we have to | 1241 // IMPORTANT: The misspelling underline is not considered when calculating t
he text bounds, so we have to |
1243 // make sure to fit within those bounds. This means the top pixel(s) of the
underline will overlap the | 1242 // make sure to fit within those bounds. This means the top pixel(s) of the
underline will overlap the |
1244 // bottom pixel(s) of the glyphs in smaller font sizes. The alternatives ar
e to increase the line spacing (bad!!) | 1243 // bottom pixel(s) of the glyphs in smaller font sizes. The alternatives ar
e to increase the line spacing (bad!!) |
1245 // or decrease the underline thickness. The overlap is actually the most us
eful, and matches what AppKit does. | 1244 // or decrease the underline thickness. The overlap is actually the most us
eful, and matches what AppKit does. |
1246 // So, we generally place the underline at the bottom of the text, but in la
rger fonts that's not so good so | 1245 // So, we generally place the underline at the bottom of the text, but in la
rger fonts that's not so good so |
1247 // we pin to two pixels under the baseline. | 1246 // we pin to two pixels under the baseline. |
1248 int lineThickness = misspellingLineThickness; | 1247 int lineThickness = misspellingLineThickness; |
1249 int baseline = renderer()->style(isFirstLineStyle())->fontMetrics().ascent()
; | 1248 int baseline = renderer().style(isFirstLineStyle())->fontMetrics().ascent(); |
1250 int descent = logicalHeight() - baseline; | 1249 int descent = logicalHeight() - baseline; |
1251 int underlineOffset; | 1250 int underlineOffset; |
1252 if (descent <= (2 + lineThickness)) { | 1251 if (descent <= (2 + lineThickness)) { |
1253 // Place the underline at the very bottom of the text in small/medium fo
nts. | 1252 // Place the underline at the very bottom of the text in small/medium fo
nts. |
1254 underlineOffset = logicalHeight() - lineThickness; | 1253 underlineOffset = logicalHeight() - lineThickness; |
1255 } else { | 1254 } else { |
1256 // In larger fonts, though, place the underline up near the baseline to
prevent a big gap. | 1255 // In larger fonts, though, place the underline up near the baseline to
prevent a big gap. |
1257 underlineOffset = baseline + 2; | 1256 underlineOffset = baseline + 2; |
1258 } | 1257 } |
1259 pt->drawLineForDocumentMarker(FloatPoint(boxOrigin.x() + start, boxOrigin.y(
) + underlineOffset), width, lineStyleForMarkerType(marker->type())); | 1258 pt->drawLineForDocumentMarker(FloatPoint(boxOrigin.x() + start, boxOrigin.y(
) + underlineOffset), width, lineStyleForMarkerType(marker->type())); |
1260 } | 1259 } |
1261 | 1260 |
1262 void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, const FloatPoint&
boxOrigin, DocumentMarker* marker, RenderStyle* style, const Font& font) | 1261 void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, const FloatPoint&
boxOrigin, DocumentMarker* marker, RenderStyle* style, const Font& font) |
1263 { | 1262 { |
1264 // Use same y positioning and height as for selection, so that when the sele
ction and this highlight are on | 1263 // Use same y positioning and height as for selection, so that when the sele
ction and this highlight are on |
1265 // the same word there are no pieces sticking out. | 1264 // the same word there are no pieces sticking out. |
1266 int deltaY = renderer()->style()->isFlippedLinesWritingMode() ? selectionBot
tom() - logicalBottom() : logicalTop() - selectionTop(); | 1265 int deltaY = renderer().style()->isFlippedLinesWritingMode() ? selectionBott
om() - logicalBottom() : logicalTop() - selectionTop(); |
1267 int selHeight = selectionHeight(); | 1266 int selHeight = selectionHeight(); |
1268 | 1267 |
1269 int sPos = max(marker->startOffset() - m_start, (unsigned)0); | 1268 int sPos = max(marker->startOffset() - m_start, (unsigned)0); |
1270 int ePos = min(marker->endOffset() - m_start, (unsigned)m_len); | 1269 int ePos = min(marker->endOffset() - m_start, (unsigned)m_len); |
1271 TextRun run = constructTextRun(style, font); | 1270 TextRun run = constructTextRun(style, font); |
1272 | 1271 |
1273 // Always compute and store the rect associated with this marker. The comput
ed rect is in absolute coordinates. | 1272 // Always compute and store the rect associated with this marker. The comput
ed rect is in absolute coordinates. |
1274 IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, IntPoin
t(x(), selectionTop()), selHeight, sPos, ePos)); | 1273 IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, IntPoin
t(x(), selectionTop()), selHeight, sPos, ePos)); |
1275 markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect)).enclosin
gBoundingBox(); | 1274 markerRect = renderer().localToAbsoluteQuad(FloatRect(markerRect)).enclosing
BoundingBox(); |
1276 toRenderedDocumentMarker(marker)->setRenderedRect(markerRect); | 1275 toRenderedDocumentMarker(marker)->setRenderedRect(markerRect); |
1277 | 1276 |
1278 // Optionally highlight the text | 1277 // Optionally highlight the text |
1279 if (renderer()->frame()->editor().markedTextMatchesAreHighlighted()) { | 1278 if (renderer().frame()->editor().markedTextMatchesAreHighlighted()) { |
1280 Color color = marker->activeMatch() ? | 1279 Color color = marker->activeMatch() ? |
1281 RenderTheme::theme().platformActiveTextSearchHighlightColor() : | 1280 RenderTheme::theme().platformActiveTextSearchHighlightColor() : |
1282 RenderTheme::theme().platformInactiveTextSearchHighlightColor(); | 1281 RenderTheme::theme().platformInactiveTextSearchHighlightColor(); |
1283 GraphicsContextStateSaver stateSaver(*pt); | 1282 GraphicsContextStateSaver stateSaver(*pt); |
1284 updateGraphicsContext(pt, color, color, 0); // Don't draw text at all! | 1283 updateGraphicsContext(pt, color, color, 0); // Don't draw text at all! |
1285 pt->clip(FloatRect(boxOrigin.x(), boxOrigin.y() - deltaY, m_logicalWidth
, selHeight)); | 1284 pt->clip(FloatRect(boxOrigin.x(), boxOrigin.y() - deltaY, m_logicalWidth
, selHeight)); |
1286 pt->drawHighlightForText(font, run, FloatPoint(boxOrigin.x(), boxOrigin.
y() - deltaY), selHeight, color, sPos, ePos); | 1285 pt->drawHighlightForText(font, run, FloatPoint(boxOrigin.x(), boxOrigin.
y() - deltaY), selHeight, color, sPos, ePos); |
1287 } | 1286 } |
1288 } | 1287 } |
1289 | 1288 |
1290 void InlineTextBox::paintDocumentMarkers(GraphicsContext* pt, const FloatPoint&
boxOrigin, RenderStyle* style, const Font& font, bool background) | 1289 void InlineTextBox::paintDocumentMarkers(GraphicsContext* pt, const FloatPoint&
boxOrigin, RenderStyle* style, const Font& font, bool background) |
1291 { | 1290 { |
1292 if (!renderer()->node()) | 1291 if (!renderer().node()) |
1293 return; | 1292 return; |
1294 | 1293 |
1295 Vector<DocumentMarker*> markers = renderer()->document().markers().markersFo
r(renderer()->node()); | 1294 Vector<DocumentMarker*> markers = renderer().document().markers().markersFor
(renderer().node()); |
1296 Vector<DocumentMarker*>::const_iterator markerIt = markers.begin(); | 1295 Vector<DocumentMarker*>::const_iterator markerIt = markers.begin(); |
1297 | 1296 |
1298 // Give any document markers that touch this run a chance to draw before the
text has been drawn. | 1297 // Give any document markers that touch this run a chance to draw before the
text has been drawn. |
1299 // Note end() points at the last char, not one past it like endOffset and ra
nges do. | 1298 // Note end() points at the last char, not one past it like endOffset and ra
nges do. |
1300 for ( ; markerIt != markers.end(); ++markerIt) { | 1299 for ( ; markerIt != markers.end(); ++markerIt) { |
1301 DocumentMarker* marker = *markerIt; | 1300 DocumentMarker* marker = *markerIt; |
1302 | 1301 |
1303 // Paint either the background markers or the foreground markers, but no
t both | 1302 // Paint either the background markers or the foreground markers, but no
t both |
1304 switch (marker->type()) { | 1303 switch (marker->type()) { |
1305 case DocumentMarker::Grammar: | 1304 case DocumentMarker::Grammar: |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1348 return; | 1347 return; |
1349 | 1348 |
1350 float start = 0; // start of line to draw, relative to tx | 1349 float start = 0; // start of line to draw, relative to tx |
1351 float width = m_logicalWidth; // how much line to draw | 1350 float width = m_logicalWidth; // how much line to draw |
1352 bool useWholeWidth = true; | 1351 bool useWholeWidth = true; |
1353 unsigned paintStart = m_start; | 1352 unsigned paintStart = m_start; |
1354 unsigned paintEnd = end() + 1; // end points at the last char, not past it | 1353 unsigned paintEnd = end() + 1; // end points at the last char, not past it |
1355 if (paintStart <= underline.startOffset) { | 1354 if (paintStart <= underline.startOffset) { |
1356 paintStart = underline.startOffset; | 1355 paintStart = underline.startOffset; |
1357 useWholeWidth = false; | 1356 useWholeWidth = false; |
1358 start = toRenderText(renderer())->width(m_start, paintStart - m_start, t
extPos(), isLeftToRightDirection() ? LTR : RTL, isFirstLineStyle()); | 1357 start = toRenderText(renderer()).width(m_start, paintStart - m_start, te
xtPos(), isLeftToRightDirection() ? LTR : RTL, isFirstLineStyle()); |
1359 } | 1358 } |
1360 if (paintEnd != underline.endOffset) { // end points at the last char,
not past it | 1359 if (paintEnd != underline.endOffset) { // end points at the last char,
not past it |
1361 paintEnd = min(paintEnd, (unsigned)underline.endOffset); | 1360 paintEnd = min(paintEnd, (unsigned)underline.endOffset); |
1362 useWholeWidth = false; | 1361 useWholeWidth = false; |
1363 } | 1362 } |
1364 if (m_truncation != cNoTruncation) { | 1363 if (m_truncation != cNoTruncation) { |
1365 paintEnd = min(paintEnd, (unsigned)m_start + m_truncation); | 1364 paintEnd = min(paintEnd, (unsigned)m_start + m_truncation); |
1366 useWholeWidth = false; | 1365 useWholeWidth = false; |
1367 } | 1366 } |
1368 if (!useWholeWidth) { | 1367 if (!useWholeWidth) { |
1369 width = toRenderText(renderer())->width(paintStart, paintEnd - paintStar
t, textPos() + start, isLeftToRightDirection() ? LTR : RTL, isFirstLineStyle()); | 1368 width = toRenderText(renderer()).width(paintStart, paintEnd - paintStart
, textPos() + start, isLeftToRightDirection() ? LTR : RTL, isFirstLineStyle()); |
1370 } | 1369 } |
1371 | 1370 |
1372 // Thick marked text underlines are 2px thick as long as there is room for t
he 2px line under the baseline. | 1371 // Thick marked text underlines are 2px thick as long as there is room for t
he 2px line under the baseline. |
1373 // All other marked text underlines are 1px thick. | 1372 // All other marked text underlines are 1px thick. |
1374 // If there's not enough space the underline will touch or overlap character
s. | 1373 // If there's not enough space the underline will touch or overlap character
s. |
1375 int lineThickness = 1; | 1374 int lineThickness = 1; |
1376 int baseline = renderer()->style(isFirstLineStyle())->fontMetrics().ascent()
; | 1375 int baseline = renderer().style(isFirstLineStyle())->fontMetrics().ascent(); |
1377 if (underline.thick && logicalHeight() - baseline >= 2) | 1376 if (underline.thick && logicalHeight() - baseline >= 2) |
1378 lineThickness = 2; | 1377 lineThickness = 2; |
1379 | 1378 |
1380 // We need to have some space between underlines of subsequent clauses, beca
use some input methods do not use different underline styles for those. | 1379 // We need to have some space between underlines of subsequent clauses, beca
use some input methods do not use different underline styles for those. |
1381 // We make each line shorter, which has a harmless side effect of shortening
the first and last clauses, too. | 1380 // We make each line shorter, which has a harmless side effect of shortening
the first and last clauses, too. |
1382 start += 1; | 1381 start += 1; |
1383 width -= 2; | 1382 width -= 2; |
1384 | 1383 |
1385 ctx->setStrokeColor(underline.color); | 1384 ctx->setStrokeColor(underline.color); |
1386 ctx->setStrokeThickness(lineThickness); | 1385 ctx->setStrokeThickness(lineThickness); |
1387 ctx->drawLineForText(FloatPoint(boxOrigin.x() + start, boxOrigin.y() + logic
alHeight() - lineThickness), width, textRenderer()->document().printing()); | 1386 ctx->drawLineForText(FloatPoint(boxOrigin.x() + start, boxOrigin.y() + logic
alHeight() - lineThickness), width, textRenderer().document().printing()); |
1388 } | 1387 } |
1389 | 1388 |
1390 int InlineTextBox::caretMinOffset() const | 1389 int InlineTextBox::caretMinOffset() const |
1391 { | 1390 { |
1392 return m_start; | 1391 return m_start; |
1393 } | 1392 } |
1394 | 1393 |
1395 int InlineTextBox::caretMaxOffset() const | 1394 int InlineTextBox::caretMaxOffset() const |
1396 { | 1395 { |
1397 return m_start + m_len; | 1396 return m_start + m_len; |
(...skipping 13 matching lines...) Expand all Loading... |
1411 if (isLineBreak()) | 1410 if (isLineBreak()) |
1412 return 0; | 1411 return 0; |
1413 | 1412 |
1414 if (lineOffset - logicalLeft() > logicalWidth()) | 1413 if (lineOffset - logicalLeft() > logicalWidth()) |
1415 return isLeftToRightDirection() ? len() : 0; | 1414 return isLeftToRightDirection() ? len() : 0; |
1416 if (lineOffset - logicalLeft() < 0) | 1415 if (lineOffset - logicalLeft() < 0) |
1417 return isLeftToRightDirection() ? 0 : len(); | 1416 return isLeftToRightDirection() ? 0 : len(); |
1418 | 1417 |
1419 FontCachePurgePreventer fontCachePurgePreventer; | 1418 FontCachePurgePreventer fontCachePurgePreventer; |
1420 | 1419 |
1421 RenderText* text = toRenderText(renderer()); | 1420 RenderText& text = toRenderText(renderer()); |
1422 RenderStyle* style = text->style(isFirstLineStyle()); | 1421 RenderStyle* style = text.style(isFirstLineStyle()); |
1423 const Font& font = style->font(); | 1422 const Font& font = style->font(); |
1424 return font.offsetForPosition(constructTextRun(style, font), lineOffset - lo
gicalLeft(), includePartialGlyphs); | 1423 return font.offsetForPosition(constructTextRun(style, font), lineOffset - lo
gicalLeft(), includePartialGlyphs); |
1425 } | 1424 } |
1426 | 1425 |
1427 float InlineTextBox::positionForOffset(int offset) const | 1426 float InlineTextBox::positionForOffset(int offset) const |
1428 { | 1427 { |
1429 ASSERT(offset >= m_start); | 1428 ASSERT(offset >= m_start); |
1430 ASSERT(offset <= m_start + m_len); | 1429 ASSERT(offset <= m_start + m_len); |
1431 | 1430 |
1432 if (isLineBreak()) | 1431 if (isLineBreak()) |
1433 return logicalLeft(); | 1432 return logicalLeft(); |
1434 | 1433 |
1435 FontCachePurgePreventer fontCachePurgePreventer; | 1434 FontCachePurgePreventer fontCachePurgePreventer; |
1436 | 1435 |
1437 RenderText* text = toRenderText(renderer()); | 1436 RenderText& text = toRenderText(renderer()); |
1438 RenderStyle* styleToUse = text->style(isFirstLineStyle()); | 1437 RenderStyle* styleToUse = text.style(isFirstLineStyle()); |
1439 ASSERT(styleToUse); | 1438 ASSERT(styleToUse); |
1440 const Font& font = styleToUse->font(); | 1439 const Font& font = styleToUse->font(); |
1441 int from = !isLeftToRightDirection() ? offset - m_start : 0; | 1440 int from = !isLeftToRightDirection() ? offset - m_start : 0; |
1442 int to = !isLeftToRightDirection() ? m_len : offset - m_start; | 1441 int to = !isLeftToRightDirection() ? m_len : offset - m_start; |
1443 // FIXME: Do we need to add rightBearing here? | 1442 // FIXME: Do we need to add rightBearing here? |
1444 return font.selectionRectForText(constructTextRun(styleToUse, font), IntPoin
t(logicalLeft(), 0), 0, from, to).maxX(); | 1443 return font.selectionRectForText(constructTextRun(styleToUse, font), IntPoin
t(logicalLeft(), 0), 0, from, to).maxX(); |
1445 } | 1444 } |
1446 | 1445 |
1447 bool InlineTextBox::containsCaretOffset(int offset) const | 1446 bool InlineTextBox::containsCaretOffset(int offset) const |
1448 { | 1447 { |
(...skipping 16 matching lines...) Expand all Loading... |
1465 return false; | 1464 return false; |
1466 | 1465 |
1467 // Offsets at the end are "in" for normal boxes (but the caller has to check
affinity). | 1466 // Offsets at the end are "in" for normal boxes (but the caller has to check
affinity). |
1468 return true; | 1467 return true; |
1469 } | 1468 } |
1470 | 1469 |
1471 void InlineTextBox::characterWidths(Vector<float>& widths) const | 1470 void InlineTextBox::characterWidths(Vector<float>& widths) const |
1472 { | 1471 { |
1473 FontCachePurgePreventer fontCachePurgePreventer; | 1472 FontCachePurgePreventer fontCachePurgePreventer; |
1474 | 1473 |
1475 RenderText* textObj = textRenderer(); | 1474 RenderStyle* styleToUse = textRenderer().style(isFirstLineStyle()); |
1476 RenderStyle* styleToUse = textObj->style(isFirstLineStyle()); | |
1477 const Font& font = styleToUse->font(); | 1475 const Font& font = styleToUse->font(); |
1478 | 1476 |
1479 TextRun textRun = constructTextRun(styleToUse, font); | 1477 TextRun textRun = constructTextRun(styleToUse, font); |
1480 | 1478 |
1481 GlyphBuffer glyphBuffer; | 1479 GlyphBuffer glyphBuffer; |
1482 WidthIterator it(&font, textRun); | 1480 WidthIterator it(&font, textRun); |
1483 float lastWidth = 0; | 1481 float lastWidth = 0; |
1484 widths.resize(m_len); | 1482 widths.resize(m_len); |
1485 for (unsigned i = 0; i < m_len; i++) { | 1483 for (unsigned i = 0; i < m_len; i++) { |
1486 it.advance(i + 1, &glyphBuffer); | 1484 it.advance(i + 1, &glyphBuffer); |
1487 widths[i] = it.m_runWidthSoFar - lastWidth; | 1485 widths[i] = it.m_runWidthSoFar - lastWidth; |
1488 lastWidth = it.m_runWidthSoFar; | 1486 lastWidth = it.m_runWidthSoFar; |
1489 } | 1487 } |
1490 } | 1488 } |
1491 | 1489 |
1492 TextRun InlineTextBox::constructTextRun(RenderStyle* style, const Font& font, St
ringBuilder* charactersWithHyphen) const | 1490 TextRun InlineTextBox::constructTextRun(RenderStyle* style, const Font& font, St
ringBuilder* charactersWithHyphen) const |
1493 { | 1491 { |
1494 ASSERT(style); | 1492 ASSERT(style); |
| 1493 ASSERT(textRenderer().text()); |
1495 | 1494 |
1496 RenderText* textRenderer = this->textRenderer(); | 1495 StringView string = textRenderer().text().createView(); |
1497 ASSERT(textRenderer); | |
1498 ASSERT(textRenderer->text()); | |
1499 | |
1500 StringView string = textRenderer->text().createView(); | |
1501 unsigned startPos = start(); | 1496 unsigned startPos = start(); |
1502 unsigned length = len(); | 1497 unsigned length = len(); |
1503 | 1498 |
1504 if (string.length() != length || startPos) | 1499 if (string.length() != length || startPos) |
1505 string.narrow(startPos, length); | 1500 string.narrow(startPos, length); |
1506 | 1501 |
1507 return constructTextRun(style, font, string, textRenderer->textLength() - st
artPos, charactersWithHyphen); | 1502 return constructTextRun(style, font, string, textRenderer().textLength() - s
tartPos, charactersWithHyphen); |
1508 } | 1503 } |
1509 | 1504 |
1510 TextRun InlineTextBox::constructTextRun(RenderStyle* style, const Font& font, St
ringView string, int maximumLength, StringBuilder* charactersWithHyphen) const | 1505 TextRun InlineTextBox::constructTextRun(RenderStyle* style, const Font& font, St
ringView string, int maximumLength, StringBuilder* charactersWithHyphen) const |
1511 { | 1506 { |
1512 ASSERT(style); | 1507 ASSERT(style); |
1513 | 1508 |
1514 RenderText* textRenderer = this->textRenderer(); | |
1515 ASSERT(textRenderer); | |
1516 | |
1517 if (charactersWithHyphen) { | 1509 if (charactersWithHyphen) { |
1518 const AtomicString& hyphenString = style->hyphenString(); | 1510 const AtomicString& hyphenString = style->hyphenString(); |
1519 charactersWithHyphen->reserveCapacity(string.length() + hyphenString.len
gth()); | 1511 charactersWithHyphen->reserveCapacity(string.length() + hyphenString.len
gth()); |
1520 charactersWithHyphen->append(string); | 1512 charactersWithHyphen->append(string); |
1521 charactersWithHyphen->append(hyphenString); | 1513 charactersWithHyphen->append(hyphenString); |
1522 string = charactersWithHyphen->toString().createView(); | 1514 string = charactersWithHyphen->toString().createView(); |
1523 maximumLength = string.length(); | 1515 maximumLength = string.length(); |
1524 } | 1516 } |
1525 | 1517 |
1526 ASSERT(maximumLength >= static_cast<int>(string.length())); | 1518 ASSERT(maximumLength >= static_cast<int>(string.length())); |
1527 | 1519 |
1528 TextRun run(string, textPos(), expansion(), expansionBehavior(), direction()
, dirOverride() || style->rtlOrdering() == VisualOrder, !textRenderer->canUseSim
pleFontCodePath()); | 1520 TextRun run(string, textPos(), expansion(), expansionBehavior(), direction()
, dirOverride() || style->rtlOrdering() == VisualOrder, !textRenderer().canUseSi
mpleFontCodePath()); |
1529 run.setTabSize(!style->collapseWhiteSpace(), style->tabSize()); | 1521 run.setTabSize(!style->collapseWhiteSpace(), style->tabSize()); |
1530 run.setCharacterScanForCodePath(!textRenderer->canUseSimpleFontCodePath()); | 1522 run.setCharacterScanForCodePath(!textRenderer().canUseSimpleFontCodePath()); |
1531 if (textRunNeedsRenderingContext(font)) | 1523 if (textRunNeedsRenderingContext(font)) |
1532 run.setRenderingContext(SVGTextRunRenderingContext::create(textRenderer)
); | 1524 run.setRenderingContext(SVGTextRunRenderingContext::create(&textRenderer
())); |
1533 | 1525 |
1534 // Propagate the maximum length of the characters buffer to the TextRun, eve
n when we're only processing a substring. | 1526 // Propagate the maximum length of the characters buffer to the TextRun, eve
n when we're only processing a substring. |
1535 run.setCharactersLength(maximumLength); | 1527 run.setCharactersLength(maximumLength); |
1536 ASSERT(run.charactersLength() >= run.length()); | 1528 ASSERT(run.charactersLength() >= run.length()); |
1537 return run; | 1529 return run; |
1538 } | 1530 } |
1539 | 1531 |
1540 TextRun InlineTextBox::constructTextRunForInspector(RenderStyle* style, const Fo
nt& font) const | 1532 TextRun InlineTextBox::constructTextRunForInspector(RenderStyle* style, const Fo
nt& font) const |
1541 { | 1533 { |
1542 return InlineTextBox::constructTextRun(style, font); | 1534 return InlineTextBox::constructTextRun(style, font); |
1543 } | 1535 } |
1544 | 1536 |
1545 #ifndef NDEBUG | 1537 #ifndef NDEBUG |
1546 | 1538 |
1547 const char* InlineTextBox::boxName() const | 1539 const char* InlineTextBox::boxName() const |
1548 { | 1540 { |
1549 return "InlineTextBox"; | 1541 return "InlineTextBox"; |
1550 } | 1542 } |
1551 | 1543 |
1552 void InlineTextBox::showBox(int printedCharacters) const | 1544 void InlineTextBox::showBox(int printedCharacters) const |
1553 { | 1545 { |
1554 const RenderText* obj = toRenderText(renderer()); | 1546 const RenderText& obj = toRenderText(renderer()); |
1555 String value = obj->text(); | 1547 String value = obj.text(); |
1556 value = value.substring(start(), len()); | 1548 value = value.substring(start(), len()); |
1557 value.replaceWithLiteral('\\', "\\\\"); | 1549 value.replaceWithLiteral('\\', "\\\\"); |
1558 value.replaceWithLiteral('\n', "\\n"); | 1550 value.replaceWithLiteral('\n', "\\n"); |
1559 printedCharacters += fprintf(stderr, "%s\t%p", boxName(), this); | 1551 printedCharacters += fprintf(stderr, "%s\t%p", boxName(), this); |
1560 for (; printedCharacters < showTreeCharacterOffset; printedCharacters++) | 1552 for (; printedCharacters < showTreeCharacterOffset; printedCharacters++) |
1561 fputc(' ', stderr); | 1553 fputc(' ', stderr); |
1562 printedCharacters = fprintf(stderr, "\t%s %p", obj->renderName(), obj); | 1554 printedCharacters = fprintf(stderr, "\t%s %p", obj.renderName(), &obj); |
1563 const int rendererCharacterOffset = 24; | 1555 const int rendererCharacterOffset = 24; |
1564 for (; printedCharacters < rendererCharacterOffset; printedCharacters++) | 1556 for (; printedCharacters < rendererCharacterOffset; printedCharacters++) |
1565 fputc(' ', stderr); | 1557 fputc(' ', stderr); |
1566 fprintf(stderr, "(%d,%d) \"%s\"\n", start(), start() + len(), value.utf8().d
ata()); | 1558 fprintf(stderr, "(%d,%d) \"%s\"\n", start(), start() + len(), value.utf8().d
ata()); |
1567 } | 1559 } |
1568 | 1560 |
1569 #endif | 1561 #endif |
1570 | 1562 |
1571 } // namespace WebCore | 1563 } // namespace WebCore |
OLD | NEW |