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

Side by Side Diff: Source/core/rendering/InlineTextBox.cpp

Issue 414863002: Minimize RenderObject* casting to RenderText* (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rebase Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/rendering/InlineTextBox.h ('k') | Source/core/rendering/RenderBlock.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 int sPos = std::max(startPos - m_start, 0); 198 int sPos = std::max(startPos - m_start, 0);
199 int ePos = std::min(endPos - m_start, (int)m_len); 199 int ePos = std::min(endPos - m_start, (int)m_len);
200 200
201 if (sPos > ePos) 201 if (sPos > ePos)
202 return LayoutRect(); 202 return LayoutRect();
203 203
204 FontCachePurgePreventer fontCachePurgePreventer; 204 FontCachePurgePreventer fontCachePurgePreventer;
205 205
206 LayoutUnit selTop = selectionTop(); 206 LayoutUnit selTop = selectionTop();
207 LayoutUnit selHeight = selectionHeight(); 207 LayoutUnit selHeight = selectionHeight();
208 RenderStyle* styleToUse = textRenderer().style(isFirstLineStyle()); 208 RenderStyle* styleToUse = renderer().style(isFirstLineStyle());
209 const Font& font = styleToUse->font(); 209 const Font& font = styleToUse->font();
210 210
211 StringBuilder charactersWithHyphen; 211 StringBuilder charactersWithHyphen;
212 bool respectHyphen = ePos == m_len && hasHyphen(); 212 bool respectHyphen = ePos == m_len && hasHyphen();
213 TextRun textRun = constructTextRun(styleToUse, font, respectHyphen ? &charac tersWithHyphen : 0); 213 TextRun textRun = constructTextRun(styleToUse, font, respectHyphen ? &charac tersWithHyphen : 0);
214 214
215 FloatPoint startingPoint = FloatPoint(logicalLeft(), selTop.toFloat()); 215 FloatPoint startingPoint = FloatPoint(logicalLeft(), selTop.toFloat());
216 LayoutRect r; 216 LayoutRect r;
217 if (sPos || ePos != static_cast<int>(m_len)) 217 if (sPos || ePos != static_cast<int>(m_len))
218 r = enclosingIntRect(font.selectionRectForText(textRun, startingPoint, s elHeight, sPos, ePos)); 218 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. 219 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.toFloat()))); 220 r = enclosingIntRect(FloatRect(startingPoint, FloatSize(m_logicalWidth, selHeight.toFloat())));
221 221
222 LayoutUnit logicalWidth = r.width(); 222 LayoutUnit logicalWidth = r.width();
223 if (r.x() > logicalRight()) 223 if (r.x() > logicalRight())
224 logicalWidth = 0; 224 logicalWidth = 0;
225 else if (r.maxX() > logicalRight()) 225 else if (r.maxX() > logicalRight())
226 logicalWidth = logicalRight() - r.x(); 226 logicalWidth = logicalRight() - r.x();
227 227
228 LayoutPoint topPoint = isHorizontal() ? LayoutPoint(r.x(), selTop) : LayoutP oint(selTop, r.x()); 228 LayoutPoint topPoint = isHorizontal() ? LayoutPoint(r.x(), selTop) : LayoutP oint(selTop, r.x());
229 LayoutUnit width = isHorizontal() ? logicalWidth : selHeight; 229 LayoutUnit width = isHorizontal() ? logicalWidth : selHeight;
230 LayoutUnit height = isHorizontal() ? selHeight : logicalWidth; 230 LayoutUnit height = isHorizontal() ? selHeight : logicalWidth;
231 231
232 return LayoutRect(topPoint, LayoutSize(width, height)); 232 return LayoutRect(topPoint, LayoutSize(width, height));
233 } 233 }
234 234
235 void InlineTextBox::deleteLine() 235 void InlineTextBox::deleteLine()
236 { 236 {
237 toRenderText(renderer()).removeTextBox(this); 237 renderer().removeTextBox(this);
238 destroy(); 238 destroy();
239 } 239 }
240 240
241 void InlineTextBox::extractLine() 241 void InlineTextBox::extractLine()
242 { 242 {
243 if (extracted()) 243 if (extracted())
244 return; 244 return;
245 245
246 toRenderText(renderer()).extractTextBox(this); 246 renderer().extractTextBox(this);
247 } 247 }
248 248
249 void InlineTextBox::attachLine() 249 void InlineTextBox::attachLine()
250 { 250 {
251 if (!extracted()) 251 if (!extracted())
252 return; 252 return;
253 253
254 toRenderText(renderer()).attachTextBox(this); 254 renderer().attachTextBox(this);
255 } 255 }
256 256
257 float InlineTextBox::placeEllipsisBox(bool flowIsLTR, float visibleLeftEdge, flo at visibleRightEdge, float ellipsisWidth, float &truncatedWidth, bool& foundBox) 257 float InlineTextBox::placeEllipsisBox(bool flowIsLTR, float visibleLeftEdge, flo at visibleRightEdge, float ellipsisWidth, float &truncatedWidth, bool& foundBox)
258 { 258 {
259 if (foundBox) { 259 if (foundBox) {
260 m_truncation = cFullTruncation; 260 m_truncation = cFullTruncation;
261 return -1; 261 return -1;
262 } 262 }
263 263
264 // For LTR this is the left edge of the box, for RTL, the right edge in pare nt coordinates. 264 // 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
298 m_truncation = cFullTruncation; 298 m_truncation = cFullTruncation;
299 truncatedWidth += ellipsisWidth; 299 truncatedWidth += ellipsisWidth;
300 return std::min(ellipsisX, logicalLeft()); 300 return std::min(ellipsisX, logicalLeft());
301 } 301 }
302 302
303 // Set the truncation index on the text run. 303 // Set the truncation index on the text run.
304 m_truncation = offset; 304 m_truncation = offset;
305 305
306 // If we got here that means that we were only partially truncated and w e need to return the pixel offset at which 306 // 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. 307 // to place the ellipsis.
308 float widthOfVisibleText = toRenderText(renderer()).width(m_start, offse t, textPos(), flowIsLTR ? LTR : RTL, isFirstLineStyle()); 308 float widthOfVisibleText = renderer().width(m_start, offset, textPos(), flowIsLTR ? LTR : RTL, isFirstLineStyle());
309 309
310 // The ellipsis needs to be placed just after the last visible character . 310 // The ellipsis needs to be placed just after the last visible character .
311 // Where "after" is defined by the flow directionality, not the inline 311 // Where "after" is defined by the flow directionality, not the inline
312 // box directionality. 312 // box directionality.
313 // e.g. In the case of an LTR inline box truncated in an RTL flow then w e can 313 // 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| 314 // have a situation such as |Hello| -> |...He|
315 truncatedWidth += widthOfVisibleText + ellipsisWidth; 315 truncatedWidth += widthOfVisibleText + ellipsisWidth;
316 if (flowIsLTR) 316 if (flowIsLTR)
317 return logicalLeft() + widthOfVisibleText; 317 return logicalLeft() + widthOfVisibleText;
318 else 318 else
(...skipping 27 matching lines...) Expand all
346 if (mode & TextModeStroke) { 346 if (mode & TextModeStroke) {
347 if (strokeColor != context->strokeColor()) 347 if (strokeColor != context->strokeColor())
348 context->setStrokeColor(strokeColor); 348 context->setStrokeColor(strokeColor);
349 if (strokeThickness != context->strokeThickness()) 349 if (strokeThickness != context->strokeThickness())
350 context->setStrokeThickness(strokeThickness); 350 context->setStrokeThickness(strokeThickness);
351 } 351 }
352 } 352 }
353 353
354 bool InlineTextBox::isLineBreak() const 354 bool InlineTextBox::isLineBreak() const
355 { 355 {
356 return renderer().isBR() || (renderer().style()->preserveNewline() && len() == 1 && (*textRenderer().text().impl())[start()] == '\n'); 356 return renderer().isBR() || (renderer().style()->preserveNewline() && len() == 1 && (*renderer().text().impl())[start()] == '\n');
357 } 357 }
358 358
359 bool InlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re sult, const HitTestLocation& locationInContainer, const LayoutPoint& accumulated Offset, LayoutUnit /* lineTop */, LayoutUnit /*lineBottom*/) 359 bool InlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re sult, const HitTestLocation& locationInContainer, const LayoutPoint& accumulated Offset, LayoutUnit /* lineTop */, LayoutUnit /*lineBottom*/)
360 { 360 {
361 if (isLineBreak()) 361 if (isLineBreak())
362 return false; 362 return false;
363 363
364 FloatPoint boxOrigin = locationIncludingFlipping(); 364 FloatPoint boxOrigin = locationIncludingFlipping();
365 boxOrigin.moveBy(accumulatedOffset); 365 boxOrigin.moveBy(accumulatedOffset);
366 FloatRect rect(boxOrigin, size()); 366 FloatRect rect(boxOrigin, size());
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 // subpixel boundaries on the x-axis and thus there is no reason to 564 // subpixel boundaries on the x-axis and thus there is no reason to
565 // snap the x value. We still round the y-axis to ensure consistent 565 // snap the x value. We still round the y-axis to ensure consistent
566 // line heights. 566 // line heights.
567 LayoutPoint adjustedPaintOffset = RuntimeEnabledFeatures::subpixelFontScalin gEnabled() 567 LayoutPoint adjustedPaintOffset = RuntimeEnabledFeatures::subpixelFontScalin gEnabled()
568 ? LayoutPoint(paintOffset.x(), paintOffset.y().round()) 568 ? LayoutPoint(paintOffset.x(), paintOffset.y().round())
569 : roundedIntPoint(paintOffset); 569 : roundedIntPoint(paintOffset);
570 570
571 if (logicalStart >= paintEnd || logicalStart + logicalExtent <= paintStart) 571 if (logicalStart >= paintEnd || logicalStart + logicalExtent <= paintStart)
572 return; 572 return;
573 573
574 bool isPrinting = textRenderer().document().printing(); 574 bool isPrinting = renderer().document().printing();
575 575
576 // Determine whether or not we're selected. 576 // Determine whether or not we're selected.
577 bool haveSelection = !isPrinting && paintInfo.phase != PaintPhaseTextClip && selectionState() != RenderObject::SelectionNone; 577 bool haveSelection = !isPrinting && paintInfo.phase != PaintPhaseTextClip && selectionState() != RenderObject::SelectionNone;
578 if (!haveSelection && paintInfo.phase == PaintPhaseSelection) 578 if (!haveSelection && paintInfo.phase == PaintPhaseSelection)
579 // When only painting the selection, don't bother to paint if there is n one. 579 // When only painting the selection, don't bother to paint if there is n one.
580 return; 580 return;
581 581
582 if (m_truncation != cNoTruncation) { 582 if (m_truncation != cNoTruncation) {
583 if (renderer().containingBlock()->style()->isLeftToRightDirection() != i sLeftToRightDirection()) { 583 if (renderer().containingBlock()->style()->isLeftToRightDirection() != i sLeftToRightDirection()) {
584 // Make the visible fragment of text hug the edge closest to the res t of the run by moving the origin 584 // Make the visible fragment of text hug the edge closest to the res t of the run by moving the origin
585 // at which we start drawing text. 585 // at which we start drawing text.
586 // e.g. In the case of LTR text truncated in an RTL Context, the cor rect behavior is: 586 // e.g. In the case of LTR text truncated in an RTL Context, the cor rect behavior is:
587 // |Hello|CBA| -> |...He|CBA| 587 // |Hello|CBA| -> |...He|CBA|
588 // In order to draw the fragment "He" aligned to the right edge of i t's box, we need to start drawing 588 // In order to draw the fragment "He" aligned to the right edge of i t's box, we need to start drawing
589 // farther to the right. 589 // farther to the right.
590 // NOTE: WebKit's behavior differs from that of IE which appears to just overlay the ellipsis on top of the 590 // NOTE: WebKit's behavior differs from that of IE which appears to just overlay the ellipsis on top of the
591 // truncated string i.e. |Hello|CBA| -> |...lo|CBA| 591 // truncated string i.e. |Hello|CBA| -> |...lo|CBA|
592 LayoutUnit widthOfVisibleText = toRenderText(renderer()).width(m_sta rt, m_truncation, textPos(), isLeftToRightDirection() ? LTR : RTL, isFirstLineSt yle()); 592 LayoutUnit widthOfVisibleText = renderer().width(m_start, m_truncati on, textPos(), isLeftToRightDirection() ? LTR : RTL, isFirstLineStyle());
593 LayoutUnit widthOfHiddenText = m_logicalWidth - widthOfVisibleText; 593 LayoutUnit widthOfHiddenText = m_logicalWidth - widthOfVisibleText;
594 // FIXME: The hit testing logic also needs to take this translation into account. 594 // FIXME: The hit testing logic also needs to take this translation into account.
595 LayoutSize truncationOffset(isLeftToRightDirection() ? widthOfHidden Text : -widthOfHiddenText, 0); 595 LayoutSize truncationOffset(isLeftToRightDirection() ? widthOfHidden Text : -widthOfHiddenText, 0);
596 adjustedPaintOffset.move(isHorizontal() ? truncationOffset : truncat ionOffset.transposedSize()); 596 adjustedPaintOffset.move(isHorizontal() ? truncationOffset : truncat ionOffset.transposedSize());
597 } 597 }
598 } 598 }
599 599
600 GraphicsContext* context = paintInfo.context; 600 GraphicsContext* context = paintInfo.context;
601 RenderStyle* styleToUse = renderer().style(isFirstLineStyle()); 601 RenderStyle* styleToUse = renderer().style(isFirstLineStyle());
602 602
603 adjustedPaintOffset.move(0, styleToUse->isHorizontalWritingMode() ? 0 : -log icalHeight()); 603 adjustedPaintOffset.move(0, styleToUse->isHorizontalWritingMode() ? 0 : -log icalHeight());
604 604
605 FloatPoint boxOrigin = locationIncludingFlipping(); 605 FloatPoint boxOrigin = locationIncludingFlipping();
606 boxOrigin.move(adjustedPaintOffset.x().toFloat(), adjustedPaintOffset.y().to Float()); 606 boxOrigin.move(adjustedPaintOffset.x().toFloat(), adjustedPaintOffset.y().to Float());
607 FloatRect boxRect(boxOrigin, LayoutSize(logicalWidth(), logicalHeight())); 607 FloatRect boxRect(boxOrigin, LayoutSize(logicalWidth(), logicalHeight()));
608 608
609 RenderCombineText* combinedText = styleToUse->hasTextCombine() && textRender er().isCombineText() && toRenderCombineText(textRenderer()).isCombined() ? &toRe nderCombineText(textRenderer()) : 0; 609 RenderCombineText* combinedText = styleToUse->hasTextCombine() && renderer() .isCombineText() && toRenderCombineText(renderer()).isCombined() ? &toRenderComb ineText(renderer()) : 0;
610 610
611 bool shouldRotate = !isHorizontal() && !combinedText; 611 bool shouldRotate = !isHorizontal() && !combinedText;
612 if (shouldRotate) 612 if (shouldRotate)
613 context->concatCTM(rotation(boxRect, Clockwise)); 613 context->concatCTM(rotation(boxRect, Clockwise));
614 614
615 // Determine whether or not we have composition underlines to draw. 615 // Determine whether or not we have composition underlines to draw.
616 bool containsComposition = renderer().node() && renderer().frame()->inputMet hodController().compositionNode() == renderer().node(); 616 bool containsComposition = renderer().node() && renderer().frame()->inputMet hodController().compositionNode() == renderer().node();
617 bool useCustomUnderlines = containsComposition && renderer().frame()->inputM ethodController().compositionUsesCustomUnderlines(); 617 bool useCustomUnderlines = containsComposition && renderer().frame()->inputM ethodController().compositionUsesCustomUnderlines();
618 618
619 // Determine text colors. 619 // Determine text colors.
620 TextPaintingStyle textStyle = textPaintingStyle(textRenderer(), styleToUse, paintInfo.forceBlackText(), isPrinting); 620 TextPaintingStyle textStyle = textPaintingStyle(renderer(), styleToUse, pain tInfo.forceBlackText(), isPrinting);
621 TextPaintingStyle selectionStyle = selectionPaintingStyle(textRenderer(), ha veSelection, paintInfo.forceBlackText(), isPrinting, textStyle); 621 TextPaintingStyle selectionStyle = selectionPaintingStyle(renderer(), haveSe lection, paintInfo.forceBlackText(), isPrinting, textStyle);
622 bool paintSelectedTextOnly = (paintInfo.phase == PaintPhaseSelection); 622 bool paintSelectedTextOnly = (paintInfo.phase == PaintPhaseSelection);
623 bool paintSelectedTextSeparately = !paintSelectedTextOnly && textStyle != se lectionStyle; 623 bool paintSelectedTextSeparately = !paintSelectedTextOnly && textStyle != se lectionStyle;
624 624
625 // Set our font. 625 // Set our font.
626 const Font& font = styleToUse->font(); 626 const Font& font = styleToUse->font();
627 627
628 FloatPoint textOrigin = FloatPoint(boxOrigin.x(), boxOrigin.y() + font.fontM etrics().ascent()); 628 FloatPoint textOrigin = FloatPoint(boxOrigin.x(), boxOrigin.y() + font.fontM etrics().ascent());
629 if (combinedText) 629 if (combinedText)
630 combinedText->adjustTextOrigin(textOrigin, boxRect); 630 combinedText->adjustTextOrigin(textOrigin, boxRect);
631 631
632 // 1. Paint backgrounds behind text if needed. Examples of such backgrounds include selection 632 // 1. Paint backgrounds behind text if needed. Examples of such backgrounds include selection
633 // and composition highlights. 633 // and composition highlights.
634 if (paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseT extClip && !isPrinting) { 634 if (paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseT extClip && !isPrinting) {
635 if (containsComposition) { 635 if (containsComposition) {
636 paintCompositionBackgrounds(context, boxOrigin, styleToUse, font, us eCustomUnderlines); 636 paintCompositionBackgrounds(context, boxOrigin, styleToUse, font, us eCustomUnderlines);
637 } 637 }
638 638
639 paintDocumentMarkers(context, boxOrigin, styleToUse, font, true); 639 paintDocumentMarkers(context, boxOrigin, styleToUse, font, true);
640 640
641 if (haveSelection && !useCustomUnderlines) 641 if (haveSelection && !useCustomUnderlines)
642 paintSelection(context, boxOrigin, styleToUse, font, selectionStyle. fillColor); 642 paintSelection(context, boxOrigin, styleToUse, font, selectionStyle. fillColor);
643 } 643 }
644 644
645 // 2. Now paint the foreground, including text and decorations like underlin e/overline (in quirks mode only). 645 // 2. Now paint the foreground, including text and decorations like underlin e/overline (in quirks mode only).
646 int length = m_len; 646 int length = m_len;
647 int maximumLength; 647 int maximumLength;
648 StringView string; 648 StringView string;
649 if (!combinedText) { 649 if (!combinedText) {
650 string = textRenderer().text().createView(); 650 string = renderer().text().createView();
651 if (static_cast<unsigned>(length) != string.length() || m_start) 651 if (static_cast<unsigned>(length) != string.length() || m_start)
652 string.narrow(m_start, length); 652 string.narrow(m_start, length);
653 maximumLength = textRenderer().textLength() - m_start; 653 maximumLength = renderer().textLength() - m_start;
654 } else { 654 } else {
655 combinedText->getStringToRender(m_start, string, length); 655 combinedText->getStringToRender(m_start, string, length);
656 maximumLength = length; 656 maximumLength = length;
657 } 657 }
658 658
659 StringBuilder charactersWithHyphen; 659 StringBuilder charactersWithHyphen;
660 TextRun textRun = constructTextRun(styleToUse, font, string, maximumLength, hasHyphen() ? &charactersWithHyphen : 0); 660 TextRun textRun = constructTextRun(styleToUse, font, string, maximumLength, hasHyphen() ? &charactersWithHyphen : 0);
661 if (hasHyphen()) 661 if (hasHyphen())
662 length = textRun.length(); 662 length = textRun.length();
663 663
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
738 738
739 if (shouldRotate) 739 if (shouldRotate)
740 context->concatCTM(rotation(boxRect, Counterclockwise)); 740 context->concatCTM(rotation(boxRect, Counterclockwise));
741 } 741 }
742 742
743 void InlineTextBox::selectionStartEnd(int& sPos, int& ePos) 743 void InlineTextBox::selectionStartEnd(int& sPos, int& ePos)
744 { 744 {
745 int startPos, endPos; 745 int startPos, endPos;
746 if (renderer().selectionState() == RenderObject::SelectionInside) { 746 if (renderer().selectionState() == RenderObject::SelectionInside) {
747 startPos = 0; 747 startPos = 0;
748 endPos = textRenderer().textLength(); 748 endPos = renderer().textLength();
749 } else { 749 } else {
750 textRenderer().selectionStartEnd(startPos, endPos); 750 renderer().selectionStartEnd(startPos, endPos);
751 if (renderer().selectionState() == RenderObject::SelectionStart) 751 if (renderer().selectionState() == RenderObject::SelectionStart)
752 endPos = textRenderer().textLength(); 752 endPos = renderer().textLength();
753 else if (renderer().selectionState() == RenderObject::SelectionEnd) 753 else if (renderer().selectionState() == RenderObject::SelectionEnd)
754 startPos = 0; 754 startPos = 0;
755 } 755 }
756 756
757 sPos = std::max(startPos - m_start, 0); 757 sPos = std::max(startPos - m_start, 0);
758 ePos = std::min(endPos - m_start, (int)m_len); 758 ePos = std::min(endPos - m_start, (int)m_len);
759 } 759 }
760 760
761 void InlineTextBox::paintSelection(GraphicsContext* context, const FloatPoint& b oxOrigin, RenderStyle* style, const Font& font, Color textColor) 761 void InlineTextBox::paintSelection(GraphicsContext* context, const FloatPoint& b oxOrigin, RenderStyle* style, const Font& font, Color textColor)
762 { 762 {
(...skipping 14 matching lines...) Expand all
777 // background. 777 // background.
778 if (textColor == c) 778 if (textColor == c)
779 c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue()); 779 c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue());
780 780
781 GraphicsContextStateSaver stateSaver(*context); 781 GraphicsContextStateSaver stateSaver(*context);
782 updateGraphicsContext(context, c, c, 0); // Don't draw text at all! 782 updateGraphicsContext(context, c, c, 0); // Don't draw text at all!
783 783
784 // If the text is truncated, let the thing being painted in the truncation 784 // If the text is truncated, let the thing being painted in the truncation
785 // draw its own highlight. 785 // draw its own highlight.
786 int length = m_truncation != cNoTruncation ? m_truncation : m_len; 786 int length = m_truncation != cNoTruncation ? m_truncation : m_len;
787 StringView string = textRenderer().text().createView(); 787 StringView string = renderer().text().createView();
788 788
789 if (string.length() != static_cast<unsigned>(length) || m_start) 789 if (string.length() != static_cast<unsigned>(length) || m_start)
790 string.narrow(m_start, length); 790 string.narrow(m_start, length);
791 791
792 StringBuilder charactersWithHyphen; 792 StringBuilder charactersWithHyphen;
793 bool respectHyphen = ePos == length && hasHyphen(); 793 bool respectHyphen = ePos == length && hasHyphen();
794 TextRun textRun = constructTextRun(style, font, string, textRenderer().textL ength() - m_start, respectHyphen ? &charactersWithHyphen : 0); 794 TextRun textRun = constructTextRun(style, font, string, renderer().textLengt h() - m_start, respectHyphen ? &charactersWithHyphen : 0);
795 if (respectHyphen) 795 if (respectHyphen)
796 ePos = textRun.length(); 796 ePos = textRun.length();
797 797
798 LayoutUnit selectionBottom = root().selectionBottom(); 798 LayoutUnit selectionBottom = root().selectionBottom();
799 LayoutUnit selectionTop = root().selectionTopAdjustedForPrecedingBlock(); 799 LayoutUnit selectionTop = root().selectionTopAdjustedForPrecedingBlock();
800 800
801 int deltaY = roundToInt(renderer().style()->isFlippedLinesWritingMode() ? se lectionBottom - logicalBottom() : logicalTop() - selectionTop); 801 int deltaY = roundToInt(renderer().style()->isFlippedLinesWritingMode() ? se lectionBottom - logicalBottom() : logicalTop() - selectionTop);
802 int selHeight = std::max(0, roundToInt(selectionBottom - selectionTop)); 802 int selHeight = std::max(0, roundToInt(selectionBottom - selectionTop));
803 803
804 FloatPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY); 804 FloatPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY);
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
1054 { 1054 {
1055 GraphicsContextStateSaver stateSaver(*context); 1055 GraphicsContextStateSaver stateSaver(*context);
1056 1056
1057 if (m_truncation == cFullTruncation) 1057 if (m_truncation == cFullTruncation)
1058 return; 1058 return;
1059 1059
1060 FloatPoint localOrigin = boxOrigin; 1060 FloatPoint localOrigin = boxOrigin;
1061 1061
1062 float width = m_logicalWidth; 1062 float width = m_logicalWidth;
1063 if (m_truncation != cNoTruncation) { 1063 if (m_truncation != cNoTruncation) {
1064 width = toRenderText(renderer()).width(m_start, m_truncation, textPos(), isLeftToRightDirection() ? LTR : RTL, isFirstLineStyle()); 1064 width = renderer().width(m_start, m_truncation, textPos(), isLeftToRight Direction() ? LTR : RTL, isFirstLineStyle());
1065 if (!isLeftToRightDirection()) 1065 if (!isLeftToRightDirection())
1066 localOrigin.move(m_logicalWidth - width, 0); 1066 localOrigin.move(m_logicalWidth - width, 0);
1067 } 1067 }
1068 1068
1069 // Get the text decoration colors. 1069 // Get the text decoration colors.
1070 RenderObject::AppliedTextDecoration underline, overline, linethrough; 1070 RenderObject::AppliedTextDecoration underline, overline, linethrough;
1071 1071
1072 renderer().getTextDecorations(deco, underline, overline, linethrough, true); 1072 renderer().getTextDecorations(deco, underline, overline, linethrough, true);
1073 if (isFirstLineStyle()) 1073 if (isFirstLineStyle())
1074 renderer().getTextDecorations(deco, underline, overline, linethrough, tr ue, true); 1074 renderer().getTextDecorations(deco, underline, overline, linethrough, tr ue, true);
1075 1075
1076 // Use a special function for underlines to get the positioning exactly righ t. 1076 // Use a special function for underlines to get the positioning exactly righ t.
1077 bool isPrinting = textRenderer().document().printing(); 1077 bool isPrinting = renderer().document().printing();
1078 1078
1079 bool linesAreOpaque = !isPrinting && (!(deco & TextDecorationUnderline) || u nderline.color.alpha() == 255) && (!(deco & TextDecorationOverline) || overline. color.alpha() == 255) && (!(deco & TextDecorationLineThrough) || linethrough.col or.alpha() == 255); 1079 bool linesAreOpaque = !isPrinting && (!(deco & TextDecorationUnderline) || u nderline.color.alpha() == 255) && (!(deco & TextDecorationOverline) || overline. color.alpha() == 255) && (!(deco & TextDecorationLineThrough) || linethrough.col or.alpha() == 255);
1080 1080
1081 RenderStyle* styleToUse = renderer().style(isFirstLineStyle()); 1081 RenderStyle* styleToUse = renderer().style(isFirstLineStyle());
1082 int baseline = styleToUse->fontMetrics().ascent(); 1082 int baseline = styleToUse->fontMetrics().ascent();
1083 1083
1084 size_t shadowCount = shadowList ? shadowList->shadows().size() : 0; 1084 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. 1085 // 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. 1086 // Using computedFontSize should take care of zoom as well.
1087 1087
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1154 return GraphicsContext::DocumentMarkerGrammarLineStyle; 1154 return GraphicsContext::DocumentMarkerGrammarLineStyle;
1155 default: 1155 default:
1156 ASSERT_NOT_REACHED(); 1156 ASSERT_NOT_REACHED();
1157 return GraphicsContext::DocumentMarkerSpellingLineStyle; 1157 return GraphicsContext::DocumentMarkerSpellingLineStyle;
1158 } 1158 }
1159 } 1159 }
1160 1160
1161 void InlineTextBox::paintDocumentMarker(GraphicsContext* pt, const FloatPoint& b oxOrigin, DocumentMarker* marker, RenderStyle* style, const Font& font, bool gra mmar) 1161 void InlineTextBox::paintDocumentMarker(GraphicsContext* pt, const FloatPoint& b oxOrigin, DocumentMarker* marker, RenderStyle* style, const Font& font, bool gra mmar)
1162 { 1162 {
1163 // Never print spelling/grammar markers (5327887) 1163 // Never print spelling/grammar markers (5327887)
1164 if (textRenderer().document().printing()) 1164 if (renderer().document().printing())
1165 return; 1165 return;
1166 1166
1167 if (m_truncation == cFullTruncation) 1167 if (m_truncation == cFullTruncation)
1168 return; 1168 return;
1169 1169
1170 float start = 0; // start of line to draw, relative to tx 1170 float start = 0; // start of line to draw, relative to tx
1171 float width = m_logicalWidth; // how much line to draw 1171 float width = m_logicalWidth; // how much line to draw
1172 1172
1173 // Determine whether we need to measure text 1173 // Determine whether we need to measure text
1174 bool markerSpansWholeBox = true; 1174 bool markerSpansWholeBox = true;
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
1331 void InlineTextBox::paintCompositionUnderline(GraphicsContext* ctx, const FloatP oint& boxOrigin, const CompositionUnderline& underline) 1331 void InlineTextBox::paintCompositionUnderline(GraphicsContext* ctx, const FloatP oint& boxOrigin, const CompositionUnderline& underline)
1332 { 1332 {
1333 if (m_truncation == cFullTruncation) 1333 if (m_truncation == cFullTruncation)
1334 return; 1334 return;
1335 1335
1336 unsigned paintStart = underlinePaintStart(underline); 1336 unsigned paintStart = underlinePaintStart(underline);
1337 unsigned paintEnd = underlinePaintEnd(underline); 1337 unsigned paintEnd = underlinePaintEnd(underline);
1338 1338
1339 // start of line to draw, relative to paintOffset. 1339 // start of line to draw, relative to paintOffset.
1340 float start = paintStart == static_cast<unsigned>(m_start) ? 0 : 1340 float start = paintStart == static_cast<unsigned>(m_start) ? 0 :
1341 toRenderText(renderer()).width(m_start, paintStart - m_start, textPos(), isLeftToRightDirection() ? LTR : RTL, isFirstLineStyle()); 1341 renderer().width(m_start, paintStart - m_start, textPos(), isLeftToRight Direction() ? LTR : RTL, isFirstLineStyle());
1342 // how much line to draw 1342 // how much line to draw
1343 float width = (paintStart == static_cast<unsigned>(m_start) && paintEnd == s tatic_cast<unsigned>(end()) + 1) ? m_logicalWidth : 1343 float width = (paintStart == static_cast<unsigned>(m_start) && paintEnd == s tatic_cast<unsigned>(end()) + 1) ? m_logicalWidth :
1344 toRenderText(renderer()).width(paintStart, paintEnd - paintStart, textPo s() + start, isLeftToRightDirection() ? LTR : RTL, isFirstLineStyle()); 1344 renderer().width(paintStart, paintEnd - paintStart, textPos() + start, i sLeftToRightDirection() ? LTR : RTL, isFirstLineStyle());
1345 1345
1346 // Thick marked text underlines are 2px thick as long as there is room for t he 2px line under the baseline. 1346 // Thick marked text underlines are 2px thick as long as there is room for t he 2px line under the baseline.
1347 // All other marked text underlines are 1px thick. 1347 // All other marked text underlines are 1px thick.
1348 // If there's not enough space the underline will touch or overlap character s. 1348 // If there's not enough space the underline will touch or overlap character s.
1349 int lineThickness = 1; 1349 int lineThickness = 1;
1350 int baseline = renderer().style(isFirstLineStyle())->fontMetrics().ascent(); 1350 int baseline = renderer().style(isFirstLineStyle())->fontMetrics().ascent();
1351 if (underline.thick && logicalHeight() - baseline >= 2) 1351 if (underline.thick && logicalHeight() - baseline >= 2)
1352 lineThickness = 2; 1352 lineThickness = 2;
1353 1353
1354 // We need to have some space between underlines of subsequent clauses, beca use some input methods do not use different underline styles for those. 1354 // We need to have some space between underlines of subsequent clauses, beca use some input methods do not use different underline styles for those.
1355 // We make each line shorter, which has a harmless side effect of shortening the first and last clauses, too. 1355 // We make each line shorter, which has a harmless side effect of shortening the first and last clauses, too.
1356 start += 1; 1356 start += 1;
1357 width -= 2; 1357 width -= 2;
1358 1358
1359 ctx->setStrokeColor(underline.color); 1359 ctx->setStrokeColor(underline.color);
1360 ctx->setStrokeThickness(lineThickness); 1360 ctx->setStrokeThickness(lineThickness);
1361 ctx->drawLineForText(FloatPoint(boxOrigin.x() + start, boxOrigin.y() + logic alHeight() - lineThickness), width, textRenderer().document().printing()); 1361 ctx->drawLineForText(FloatPoint(boxOrigin.x() + start, boxOrigin.y() + logic alHeight() - lineThickness), width, renderer().document().printing());
1362 } 1362 }
1363 1363
1364 int InlineTextBox::caretMinOffset() const 1364 int InlineTextBox::caretMinOffset() const
1365 { 1365 {
1366 return m_start; 1366 return m_start;
1367 } 1367 }
1368 1368
1369 int InlineTextBox::caretMaxOffset() const 1369 int InlineTextBox::caretMaxOffset() const
1370 { 1370 {
1371 return m_start + m_len; 1371 return m_start + m_len;
(...skipping 13 matching lines...) Expand all
1385 if (isLineBreak()) 1385 if (isLineBreak())
1386 return 0; 1386 return 0;
1387 1387
1388 if (lineOffset - logicalLeft() > logicalWidth()) 1388 if (lineOffset - logicalLeft() > logicalWidth())
1389 return isLeftToRightDirection() ? len() : 0; 1389 return isLeftToRightDirection() ? len() : 0;
1390 if (lineOffset - logicalLeft() < 0) 1390 if (lineOffset - logicalLeft() < 0)
1391 return isLeftToRightDirection() ? 0 : len(); 1391 return isLeftToRightDirection() ? 0 : len();
1392 1392
1393 FontCachePurgePreventer fontCachePurgePreventer; 1393 FontCachePurgePreventer fontCachePurgePreventer;
1394 1394
1395 RenderText& text = toRenderText(renderer()); 1395 RenderText& text = renderer();
1396 RenderStyle* style = text.style(isFirstLineStyle()); 1396 RenderStyle* style = text.style(isFirstLineStyle());
1397 const Font& font = style->font(); 1397 const Font& font = style->font();
1398 return font.offsetForPosition(constructTextRun(style, font), lineOffset - lo gicalLeft(), includePartialGlyphs); 1398 return font.offsetForPosition(constructTextRun(style, font), lineOffset - lo gicalLeft(), includePartialGlyphs);
1399 } 1399 }
1400 1400
1401 float InlineTextBox::positionForOffset(int offset) const 1401 float InlineTextBox::positionForOffset(int offset) const
1402 { 1402 {
1403 ASSERT(offset >= m_start); 1403 ASSERT(offset >= m_start);
1404 ASSERT(offset <= m_start + m_len); 1404 ASSERT(offset <= m_start + m_len);
1405 1405
1406 if (isLineBreak()) 1406 if (isLineBreak())
1407 return logicalLeft(); 1407 return logicalLeft();
1408 1408
1409 FontCachePurgePreventer fontCachePurgePreventer; 1409 FontCachePurgePreventer fontCachePurgePreventer;
1410 1410
1411 RenderText& text = toRenderText(renderer()); 1411 RenderText& text = renderer();
1412 RenderStyle* styleToUse = text.style(isFirstLineStyle()); 1412 RenderStyle* styleToUse = text.style(isFirstLineStyle());
1413 ASSERT(styleToUse); 1413 ASSERT(styleToUse);
1414 const Font& font = styleToUse->font(); 1414 const Font& font = styleToUse->font();
1415 int from = !isLeftToRightDirection() ? offset - m_start : 0; 1415 int from = !isLeftToRightDirection() ? offset - m_start : 0;
1416 int to = !isLeftToRightDirection() ? m_len : offset - m_start; 1416 int to = !isLeftToRightDirection() ? m_len : offset - m_start;
1417 // FIXME: Do we need to add rightBearing here? 1417 // FIXME: Do we need to add rightBearing here?
1418 return font.selectionRectForText(constructTextRun(styleToUse, font), IntPoin t(logicalLeft(), 0), 0, from, to).maxX(); 1418 return font.selectionRectForText(constructTextRun(styleToUse, font), IntPoin t(logicalLeft(), 0), 0, from, to).maxX();
1419 } 1419 }
1420 1420
1421 bool InlineTextBox::containsCaretOffset(int offset) const 1421 bool InlineTextBox::containsCaretOffset(int offset) const
(...skipping 17 matching lines...) Expand all
1439 return false; 1439 return false;
1440 1440
1441 // Offsets at the end are "in" for normal boxes (but the caller has to check affinity). 1441 // Offsets at the end are "in" for normal boxes (but the caller has to check affinity).
1442 return true; 1442 return true;
1443 } 1443 }
1444 1444
1445 void InlineTextBox::characterWidths(Vector<float>& widths) const 1445 void InlineTextBox::characterWidths(Vector<float>& widths) const
1446 { 1446 {
1447 FontCachePurgePreventer fontCachePurgePreventer; 1447 FontCachePurgePreventer fontCachePurgePreventer;
1448 1448
1449 RenderStyle* styleToUse = textRenderer().style(isFirstLineStyle()); 1449 RenderStyle* styleToUse = renderer().style(isFirstLineStyle());
1450 const Font& font = styleToUse->font(); 1450 const Font& font = styleToUse->font();
1451 1451
1452 TextRun textRun = constructTextRun(styleToUse, font); 1452 TextRun textRun = constructTextRun(styleToUse, font);
1453 1453
1454 GlyphBuffer glyphBuffer; 1454 GlyphBuffer glyphBuffer;
1455 WidthIterator it(&font, textRun); 1455 WidthIterator it(&font, textRun);
1456 float lastWidth = 0; 1456 float lastWidth = 0;
1457 widths.resize(m_len); 1457 widths.resize(m_len);
1458 for (unsigned i = 0; i < m_len; i++) { 1458 for (unsigned i = 0; i < m_len; i++) {
1459 it.advance(i + 1, &glyphBuffer); 1459 it.advance(i + 1, &glyphBuffer);
1460 widths[i] = it.m_runWidthSoFar - lastWidth; 1460 widths[i] = it.m_runWidthSoFar - lastWidth;
1461 lastWidth = it.m_runWidthSoFar; 1461 lastWidth = it.m_runWidthSoFar;
1462 } 1462 }
1463 } 1463 }
1464 1464
1465 TextRun InlineTextBox::constructTextRun(RenderStyle* style, const Font& font, St ringBuilder* charactersWithHyphen) const 1465 TextRun InlineTextBox::constructTextRun(RenderStyle* style, const Font& font, St ringBuilder* charactersWithHyphen) const
1466 { 1466 {
1467 ASSERT(style); 1467 ASSERT(style);
1468 ASSERT(textRenderer().text()); 1468 ASSERT(renderer().text());
1469 1469
1470 StringView string = textRenderer().text().createView(); 1470 StringView string = renderer().text().createView();
1471 unsigned startPos = start(); 1471 unsigned startPos = start();
1472 unsigned length = len(); 1472 unsigned length = len();
1473 1473
1474 if (string.length() != length || startPos) 1474 if (string.length() != length || startPos)
1475 string.narrow(startPos, length); 1475 string.narrow(startPos, length);
1476 1476
1477 return constructTextRun(style, font, string, textRenderer().textLength() - s tartPos, charactersWithHyphen); 1477 return constructTextRun(style, font, string, renderer().textLength() - start Pos, charactersWithHyphen);
1478 } 1478 }
1479 1479
1480 TextRun InlineTextBox::constructTextRun(RenderStyle* style, const Font& font, St ringView string, int maximumLength, StringBuilder* charactersWithHyphen) const 1480 TextRun InlineTextBox::constructTextRun(RenderStyle* style, const Font& font, St ringView string, int maximumLength, StringBuilder* charactersWithHyphen) const
1481 { 1481 {
1482 ASSERT(style); 1482 ASSERT(style);
1483 1483
1484 if (charactersWithHyphen) { 1484 if (charactersWithHyphen) {
1485 const AtomicString& hyphenString = style->hyphenString(); 1485 const AtomicString& hyphenString = style->hyphenString();
1486 charactersWithHyphen->reserveCapacity(string.length() + hyphenString.len gth()); 1486 charactersWithHyphen->reserveCapacity(string.length() + hyphenString.len gth());
1487 charactersWithHyphen->append(string); 1487 charactersWithHyphen->append(string);
1488 charactersWithHyphen->append(hyphenString); 1488 charactersWithHyphen->append(hyphenString);
1489 string = charactersWithHyphen->toString().createView(); 1489 string = charactersWithHyphen->toString().createView();
1490 maximumLength = string.length(); 1490 maximumLength = string.length();
1491 } 1491 }
1492 1492
1493 ASSERT(maximumLength >= static_cast<int>(string.length())); 1493 ASSERT(maximumLength >= static_cast<int>(string.length()));
1494 1494
1495 TextRun run(string, textPos(), expansion(), expansionBehavior(), direction() , dirOverride() || style->rtlOrdering() == VisualOrder, !textRenderer().canUseSi mpleFontCodePath()); 1495 TextRun run(string, textPos(), expansion(), expansionBehavior(), direction() , dirOverride() || style->rtlOrdering() == VisualOrder, !renderer().canUseSimple FontCodePath());
1496 run.setTabSize(!style->collapseWhiteSpace(), style->tabSize()); 1496 run.setTabSize(!style->collapseWhiteSpace(), style->tabSize());
1497 run.setCharacterScanForCodePath(!textRenderer().canUseSimpleFontCodePath()); 1497 run.setCharacterScanForCodePath(!renderer().canUseSimpleFontCodePath());
1498 if (textRunNeedsRenderingContext(font)) 1498 if (textRunNeedsRenderingContext(font))
1499 run.setRenderingContext(SVGTextRunRenderingContext::create(&textRenderer ())); 1499 run.setRenderingContext(SVGTextRunRenderingContext::create(&renderer())) ;
1500 1500
1501 // Propagate the maximum length of the characters buffer to the TextRun, eve n when we're only processing a substring. 1501 // Propagate the maximum length of the characters buffer to the TextRun, eve n when we're only processing a substring.
1502 run.setCharactersLength(maximumLength); 1502 run.setCharactersLength(maximumLength);
1503 ASSERT(run.charactersLength() >= run.length()); 1503 ASSERT(run.charactersLength() >= run.length());
1504 return run; 1504 return run;
1505 } 1505 }
1506 1506
1507 TextRun InlineTextBox::constructTextRunForInspector(RenderStyle* style, const Fo nt& font) const 1507 TextRun InlineTextBox::constructTextRunForInspector(RenderStyle* style, const Fo nt& font) const
1508 { 1508 {
1509 return InlineTextBox::constructTextRun(style, font); 1509 return InlineTextBox::constructTextRun(style, font);
1510 } 1510 }
1511 1511
1512 #ifndef NDEBUG 1512 #ifndef NDEBUG
1513 1513
1514 const char* InlineTextBox::boxName() const 1514 const char* InlineTextBox::boxName() const
1515 { 1515 {
1516 return "InlineTextBox"; 1516 return "InlineTextBox";
1517 } 1517 }
1518 1518
1519 void InlineTextBox::showBox(int printedCharacters) const 1519 void InlineTextBox::showBox(int printedCharacters) const
1520 { 1520 {
1521 const RenderText& obj = toRenderText(renderer()); 1521 const RenderText& obj = renderer();
1522 String value = obj.text(); 1522 String value = obj.text();
1523 value = value.substring(start(), len()); 1523 value = value.substring(start(), len());
1524 value.replaceWithLiteral('\\', "\\\\"); 1524 value.replaceWithLiteral('\\', "\\\\");
1525 value.replaceWithLiteral('\n', "\\n"); 1525 value.replaceWithLiteral('\n', "\\n");
1526 printedCharacters += fprintf(stderr, "%s\t%p", boxName(), this); 1526 printedCharacters += fprintf(stderr, "%s\t%p", boxName(), this);
1527 for (; printedCharacters < showTreeCharacterOffset; printedCharacters++) 1527 for (; printedCharacters < showTreeCharacterOffset; printedCharacters++)
1528 fputc(' ', stderr); 1528 fputc(' ', stderr);
1529 printedCharacters = fprintf(stderr, "\t%s %p", obj.renderName(), &obj); 1529 printedCharacters = fprintf(stderr, "\t%s %p", obj.renderName(), &obj);
1530 const int rendererCharacterOffset = 24; 1530 const int rendererCharacterOffset = 24;
1531 for (; printedCharacters < rendererCharacterOffset; printedCharacters++) 1531 for (; printedCharacters < rendererCharacterOffset; printedCharacters++)
1532 fputc(' ', stderr); 1532 fputc(' ', stderr);
1533 fprintf(stderr, "(%d,%d) \"%s\"\n", start(), start() + len(), value.utf8().d ata()); 1533 fprintf(stderr, "(%d,%d) \"%s\"\n", start(), start() + len(), value.utf8().d ata());
1534 } 1534 }
1535 1535
1536 #endif 1536 #endif
1537 1537
1538 } // namespace blink 1538 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/rendering/InlineTextBox.h ('k') | Source/core/rendering/RenderBlock.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698