Changeset 70263 in webkit
- Timestamp:
- Oct 21, 2010 2:16:55 PM (14 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r70260 r70263 1 2010-10-21 David Hyatt <hyatt@apple.com> 2 3 Reviewed by Darin Adler. 4 5 https://bugs.webkit.org/show_bug.cgi?id=48085 6 7 Make basic vertical text painting work. This includes the text itself, underlines, overlines, line-throughs and shadows. 8 9 Added fast/blockflow/english-lr-text.html 10 11 * fast/blockflow/english-lr-text.html: Added. 12 * platform/mac/fast/blockflow/english-lr-text-expected.checksum: Added. 13 * platform/mac/fast/blockflow/english-lr-text-expected.png: Added. 14 * platform/mac/fast/blockflow/english-lr-text-expected.txt: Added. 15 1 16 2010-10-21 James Robinson <jamesr@chromium.org> 2 17 -
trunk/LayoutTests/platform/mac/fast/text/international/vertical-text-glyph-test-expected.checksum
r70250 r70263 1 83a57acedeb979e93959cf59fe59cdfc 1 386f323eb617f371186afe888df1ce4e -
trunk/WebCore/ChangeLog
r70262 r70263 1 2010-10-21 David Hyatt <hyatt@apple.com> 2 3 Reviewed by Darin Adler. 4 5 https://bugs.webkit.org/show_bug.cgi?id=48085 6 7 Make basic vertical text painting work. This includes the text itself, underlines, overlines, line-throughs and shadows. 8 9 Added fast/blockflow/english-lr-text.html 10 11 * rendering/InlineFlowBox.cpp: 12 (WebCore::InlineFlowBox::paint): 13 * rendering/InlineFlowBox.h: 14 * rendering/InlineTextBox.cpp: 15 (WebCore::InlineTextBox::applyShadowToGraphicsContext): 16 (WebCore::paintTextWithShadows): 17 (WebCore::InlineTextBox::paint): 18 (WebCore::InlineTextBox::paintDecoration): 19 (WebCore::InlineTextBox::paintTextMatchMarker): 20 * rendering/InlineTextBox.h: 21 * rendering/svg/SVGInlineTextBox.cpp: 22 (WebCore::SVGInlineTextBox::paintTextWithShadows): 23 1 24 2010-10-21 No'am Rosenthal <noam.rosenthal@nokia.com> 2 25 -
trunk/WebCore/WebCore.xcodeproj/project.pbxproj
r70250 r70263 21201 21201 buildConfigurationList = 149C284308902B11008A9EFC /* Build configuration list for PBXProject "WebCore" */; 21202 21202 compatibilityVersion = "Xcode 2.4"; 21203 developmentRegion = English; 21203 21204 hasScannedForEncodings = 1; 21204 21205 knownRegions = ( -
trunk/WebCore/rendering/InlineFlowBox.cpp
r70172 r70263 702 702 return; 703 703 } else { 704 // 1.Paint our background, border and box-shadow.704 // Paint our background, border and box-shadow. 705 705 paintBoxDecorations(paintInfo, tx, ty); 706 707 // 2. Paint our underline and overline.708 paintTextDecorations(paintInfo, tx, ty, false);709 706 } 710 707 } … … 718 715 childInfo.updatePaintingRootForChildren(renderer()); 719 716 720 // 3.Paint our children.717 // Paint our children. 721 718 if (paintPhase != PaintPhaseSelfOutline) { 722 719 for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { … … 725 722 } 726 723 } 727 728 // 4. Paint our strike-through729 if (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection)730 paintTextDecorations(paintInfo, tx, ty, true);731 724 } 732 725 … … 931 924 } 932 925 933 static bool shouldDrawTextDecoration(RenderObject* obj)934 {935 for (RenderObject* curr = obj->firstChild(); curr; curr = curr->nextSibling()) {936 if (curr->isRenderInline())937 return true;938 if (curr->isText() && !curr->isBR()) {939 if (!curr->style()->collapseWhiteSpace())940 return true;941 Node* currElement = curr->node();942 if (!currElement)943 return true;944 if (!currElement->isTextNode())945 return true;946 if (!static_cast<Text*>(currElement)->containsOnlyWhitespace())947 return true;948 }949 }950 return false;951 }952 953 void InlineFlowBox::paintTextDecorations(PaintInfo& paintInfo, int tx, int ty, bool paintedChildren)954 {955 // Paint text decorations like underlines/overlines. We only do this if we aren't in quirks mode (i.e., in956 // almost-strict mode or strict mode).957 if (renderer()->document()->inQuirksMode() || !paintInfo.shouldPaintWithinRoot(renderer()) ||958 renderer()->style()->visibility() != VISIBLE)959 return;960 961 // We don't want underlines or other decorations when we're trying to draw nothing but the selection as white text.962 if (paintInfo.phase == PaintPhaseSelection && paintInfo.forceBlackText)963 return;964 965 GraphicsContext* context = paintInfo.context;966 tx += m_x;967 ty += m_y;968 RenderStyle* styleToUse = renderer()->style(m_firstLine);969 int deco = parent() ? styleToUse->textDecoration() : styleToUse->textDecorationsInEffect();970 if (deco != TDNONE &&971 ((!paintedChildren && ((deco & UNDERLINE) || (deco & OVERLINE))) || (paintedChildren && (deco & LINE_THROUGH))) &&972 shouldDrawTextDecoration(renderer())) {973 int x = m_x + borderLogicalLeft() + paddingLogicalLeft();974 int w = m_logicalWidth - (borderLogicalLeft() + paddingLogicalLeft() + borderLogicalRight() + paddingLogicalRight());975 RootInlineBox* rootLine = root();976 if (rootLine->ellipsisBox()) {977 int ellipsisX = m_x + rootLine->ellipsisBox()->x();978 int ellipsisWidth = rootLine->ellipsisBox()->logicalWidth();979 bool ltr = renderer()->style()->isLeftToRightDirection();980 if (rootLine == this) {981 // Trim w and x so that the underline isn't drawn underneath the ellipsis.982 // ltr: is our right edge farther right than the right edge of the ellipsis.983 // rtl: is the left edge of our box farther left than the left edge of the ellipsis.984 bool ltrTruncation = ltr && (x + w >= ellipsisX + ellipsisWidth);985 bool rtlTruncation = !ltr && (x <= ellipsisX + ellipsisWidth);986 if (ltrTruncation)987 w -= (x + w) - (ellipsisX + ellipsisWidth);988 else if (rtlTruncation) {989 int dx = m_x - ((ellipsisX - m_x) + ellipsisWidth);990 tx -= dx;991 w += dx;992 }993 } else {994 bool ltrPastEllipsis = ltr && x >= ellipsisX;995 bool rtlPastEllipsis = !ltr && (x + w) <= (ellipsisX + ellipsisWidth);996 if (ltrPastEllipsis || rtlPastEllipsis)997 return;998 999 bool ltrTruncation = ltr && x + w >= ellipsisX;1000 bool rtlTruncation = !ltr && x <= ellipsisX;1001 if (ltrTruncation)1002 w -= (x + w - ellipsisX);1003 else if (rtlTruncation) {1004 int dx = m_x - ((ellipsisX - m_x) + ellipsisWidth);1005 tx -= dx;1006 w += dx;1007 }1008 }1009 }1010 1011 // We must have child boxes and have decorations defined.1012 tx += borderLogicalLeft() + paddingLogicalLeft();1013 1014 Color underline, overline, linethrough;1015 underline = overline = linethrough = styleToUse->visitedDependentColor(CSSPropertyColor);1016 if (!parent())1017 renderer()->getTextDecorationColors(deco, underline, overline, linethrough);1018 1019 bool isPrinting = renderer()->document()->printing();1020 context->setStrokeThickness(1.0f); // FIXME: We should improve this rule and not always just assume 1.1021 1022 bool paintUnderline = deco & UNDERLINE && !paintedChildren;1023 bool paintOverline = deco & OVERLINE && !paintedChildren;1024 bool paintLineThrough = deco & LINE_THROUGH && paintedChildren;1025 1026 bool linesAreOpaque = !isPrinting && (!paintUnderline || underline.alpha() == 255) && (!paintOverline || overline.alpha() == 255) && (!paintLineThrough || linethrough.alpha() == 255);1027 1028 int baselinePos = renderer()->style(m_firstLine)->font().ascent();1029 if (!isRootInlineBox())1030 baselinePos += boxModelObject()->borderTop() + boxModelObject()->paddingTop();1031 1032 bool setClip = false;1033 int extraOffset = 0;1034 const ShadowData* shadow = styleToUse->textShadow();1035 if (!linesAreOpaque && shadow && shadow->next()) {1036 IntRect clipRect(tx, ty, w, baselinePos + 2);1037 for (const ShadowData* s = shadow; s; s = s->next()) {1038 IntRect shadowRect(tx, ty, w, baselinePos + 2);1039 shadowRect.inflate(s->blur());1040 shadowRect.move(s->x(), s->y());1041 clipRect.unite(shadowRect);1042 extraOffset = max(extraOffset, max(0, s->y()) + s->blur());1043 }1044 context->save();1045 context->clip(clipRect);1046 extraOffset += baselinePos + 2;1047 ty += extraOffset;1048 setClip = true;1049 }1050 1051 ColorSpace colorSpace = renderer()->style()->colorSpace();1052 bool setShadow = false;1053 do {1054 if (shadow) {1055 if (!shadow->next()) {1056 // The last set of lines paints normally inside the clip.1057 ty -= extraOffset;1058 extraOffset = 0;1059 }1060 context->setShadow(IntSize(shadow->x(), shadow->y() - extraOffset), shadow->blur(), shadow->color(), colorSpace);1061 setShadow = true;1062 shadow = shadow->next();1063 }1064 1065 if (paintUnderline) {1066 context->setStrokeColor(underline, colorSpace);1067 context->setStrokeStyle(SolidStroke);1068 // Leave one pixel of white between the baseline and the underline.1069 context->drawLineForText(IntPoint(tx, ty + baselinePos + 1), w, isPrinting);1070 }1071 if (paintOverline) {1072 context->setStrokeColor(overline, colorSpace);1073 context->setStrokeStyle(SolidStroke);1074 context->drawLineForText(IntPoint(tx, ty), w, isPrinting);1075 }1076 if (paintLineThrough) {1077 context->setStrokeColor(linethrough, colorSpace);1078 context->setStrokeStyle(SolidStroke);1079 context->drawLineForText(IntPoint(tx, ty + 2 * baselinePos / 3), w, isPrinting);1080 }1081 } while (shadow);1082 1083 if (setClip)1084 context->restore();1085 else if (setShadow)1086 context->clearShadow();1087 }1088 }1089 1090 926 InlineBox* InlineFlowBox::firstLeafChild() const 1091 927 { -
trunk/WebCore/rendering/InlineFlowBox.h
r70172 r70263 97 97 void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int w, int h, CompositeOperator = CompositeSourceOver); 98 98 void paintBoxShadow(GraphicsContext*, RenderStyle*, ShadowStyle, int tx, int ty, int w, int h); 99 virtual void paintTextDecorations(PaintInfo&, int tx, int ty, bool paintedChildren = false);100 99 virtual void paint(PaintInfo&, int tx, int ty); 101 100 virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty); -
trunk/WebCore/rendering/InlineTextBox.cpp
r70072 r70263 312 312 } 313 313 314 FloatSize InlineTextBox::applyShadowToGraphicsContext(GraphicsContext* context, const ShadowData* shadow, const FloatRect& textRect, bool stroked, bool opaque )314 FloatSize InlineTextBox::applyShadowToGraphicsContext(GraphicsContext* context, const ShadowData* shadow, const FloatRect& textRect, bool stroked, bool opaque, bool vertical) 315 315 { 316 316 if (!shadow) … … 318 318 319 319 FloatSize extraOffset; 320 FloatSize shadowOffset(shadow->x(), shadow->y()); 320 int shadowX = vertical ? shadow->y() : shadow->x(); 321 int shadowY = vertical ? -shadow->x() : shadow->y(); 322 FloatSize shadowOffset(shadowX, shadowY); 321 323 int shadowBlur = shadow->blur(); 322 324 const Color& shadowColor = shadow->color(); … … 337 339 } 338 340 339 static void paintTextWithShadows(GraphicsContext* context, const Font& font, const TextRun& textRun, int startOffset, int endOffset, int truncationPoint, const IntPoint& textOrigin, int x, int y, int w, int h, const ShadowData* shadow, bool stroked) 341 static void paintTextWithShadows(GraphicsContext* context, const Font& font, const TextRun& textRun, int startOffset, int endOffset, int truncationPoint, const IntPoint& textOrigin, 342 int x, int y, int w, int h, const ShadowData* shadow, bool stroked, bool vertical) 340 343 { 341 344 Color fillColor = context->fillColor(); … … 348 351 IntSize extraOffset; 349 352 if (shadow) 350 extraOffset = roundedIntSize(InlineTextBox::applyShadowToGraphicsContext(context, shadow, FloatRect(x, y, w, h), stroked, opaque ));353 extraOffset = roundedIntSize(InlineTextBox::applyShadowToGraphicsContext(context, shadow, FloatRect(x, y, w, h), stroked, opaque, vertical)); 351 354 else if (!opaque) 352 355 context->setFillColor(fillColor, fillColorSpace); … … 376 379 { 377 380 if (isLineBreak() || !paintInfo.shouldPaintWithinRoot(renderer()) || renderer()->style()->visibility() != VISIBLE || 378 m_truncation == cFullTruncation || paintInfo.phase == PaintPhaseOutline )381 m_truncation == cFullTruncation || paintInfo.phase == PaintPhaseOutline || !m_len) 379 382 return; 380 383 … … 411 414 int widthOfHiddenText = m_logicalWidth - widthOfVisibleText; 412 415 // FIXME: The hit testing logic also needs to take this translation int account. 413 tx += isLeftToRightDirection() ? widthOfHiddenText : -widthOfHiddenText; 416 if (!m_isVertical) 417 tx += isLeftToRightDirection() ? widthOfHiddenText : -widthOfHiddenText; 418 else 419 ty += isLeftToRightDirection() ? widthOfHiddenText : -widthOfHiddenText; 414 420 } 415 421 } … … 417 423 GraphicsContext* context = paintInfo.context; 418 424 425 RenderStyle* styleToUse = renderer()->style(m_firstLine); 426 int baseline = styleToUse->font().ascent(); 427 ty -= styleToUse->isFlippedLinesWritingMode() ? baseline : 0; 428 IntPoint textOrigin(m_x + tx, m_y + ty + baseline); 429 430 if (m_isVertical) { 431 context->save(); 432 context->translate(textOrigin.x(), textOrigin.y()); 433 context->rotate(deg2rad(90.)); 434 context->translate(-textOrigin.x(), -textOrigin.y()); 435 } 436 419 437 // Determine whether or not we have composition underlines to draw. 420 438 bool containsComposition = renderer()->node() && renderer()->frame()->editor()->compositionNode() == renderer()->node(); … … 422 440 423 441 // Set our font. 424 RenderStyle* styleToUse = renderer()->style(m_firstLine);425 442 int d = styleToUse->textDecorationsInEffect(); 426 443 const Font& font = styleToUse->font(); … … 447 464 448 465 // 2. Now paint the foreground, including text and decorations like underline/overline (in quirks mode only). 449 if (m_len <= 0)450 return;451 452 466 Color textFillColor; 453 467 Color textStrokeColor; … … 518 532 adjustCharactersAndLengthForHyphen(charactersWithHyphen, styleToUse, characters, length); 519 533 520 int baseline = renderer()->style(m_firstLine)->font().ascent();521 IntPoint textOrigin(m_x + tx, m_y + ty + baseline);522 534 TextRun textRun(characters, length, textRenderer()->allowTabs(), textPos(), m_toAdd, !isLeftToRightDirection(), m_dirOverride || styleToUse->visuallyOrdered()); 523 535 … … 542 554 if (!paintSelectedTextSeparately || ePos <= sPos) { 543 555 // FIXME: Truncate right-to-left text correctly. 544 paintTextWithShadows(context, font, textRun, 0, length, length, textOrigin, m_x + tx, m_y + ty, logicalWidth(), logicalHeight(), textShadow, textStrokeWidth > 0 );556 paintTextWithShadows(context, font, textRun, 0, length, length, textOrigin, m_x + tx, m_y + ty, logicalWidth(), logicalHeight(), textShadow, textStrokeWidth > 0, m_isVertical); 545 557 } else 546 paintTextWithShadows(context, font, textRun, ePos, sPos, length, textOrigin, m_x + tx, m_y + ty, logicalWidth(), logicalHeight(), textShadow, textStrokeWidth > 0 );558 paintTextWithShadows(context, font, textRun, ePos, sPos, length, textOrigin, m_x + tx, m_y + ty, logicalWidth(), logicalHeight(), textShadow, textStrokeWidth > 0, m_isVertical); 547 559 548 560 if (textStrokeWidth > 0) … … 556 568 557 569 updateGraphicsContext(context, selectionFillColor, selectionStrokeColor, selectionStrokeWidth, styleToUse->colorSpace()); 558 paintTextWithShadows(context, font, textRun, sPos, ePos, length, textOrigin, m_x + tx, m_y + ty, logicalWidth(), logicalHeight(), selectionShadow, selectionStrokeWidth > 0 );570 paintTextWithShadows(context, font, textRun, sPos, ePos, length, textOrigin, m_x + tx, m_y + ty, logicalWidth(), logicalHeight(), selectionShadow, selectionStrokeWidth > 0, m_isVertical); 559 571 560 572 if (selectionStrokeWidth > 0) … … 563 575 564 576 // Paint decorations 565 if (d != TDNONE && paintInfo.phase != PaintPhaseSelection && renderer()->document()->inQuirksMode()) {566 context->setStrokeColor(styleToUse->visitedDependentColor(CSSPropertyColor), styleToUse->colorSpace());577 if (d != TDNONE && paintInfo.phase != PaintPhaseSelection) { 578 updateGraphicsContext(context, textFillColor, textStrokeColor, textStrokeWidth, styleToUse->colorSpace()); 567 579 paintDecoration(context, tx, ty, d, textShadow); 568 580 } … … 596 608 } 597 609 } 610 611 if (m_isVertical) 612 context->restore(); 598 613 } 599 614 … … 724 739 bool linesAreOpaque = !isPrinting && (!(deco & UNDERLINE) || underline.alpha() == 255) && (!(deco & OVERLINE) || overline.alpha() == 255) && (!(deco & LINE_THROUGH) || linethrough.alpha() == 255); 725 740 726 int baseline = renderer()->style(m_firstLine)->font().ascent(); 741 RenderStyle* styleToUse = renderer()->style(m_firstLine); 742 int baseline = styleToUse->font().ascent(); 727 743 728 744 bool setClip = false; … … 734 750 IntRect shadowRect(tx, ty, width, baseline + 2); 735 751 shadowRect.inflate(s->blur()); 736 shadowRect.move(s->x(), s->y()); 752 int shadowX = m_isVertical ? s->y() : s->x(); 753 int shadowY = m_isVertical ? -s->x() : s->y(); 754 shadowRect.move(shadowX, shadowY); 737 755 clipRect.unite(shadowRect); 738 extraOffset = max(extraOffset, max(0, s ->y()) + s->blur());756 extraOffset = max(extraOffset, max(0, shadowY) + s->blur()); 739 757 } 740 758 context->save(); … … 755 773 extraOffset = 0; 756 774 } 757 context->setShadow(IntSize(shadow->x(), shadow->y() - extraOffset), shadow->blur(), shadow->color(), colorSpace); 775 int shadowX = m_isVertical ? shadow->y() : shadow->x(); 776 int shadowY = m_isVertical ? -shadow->x() : shadow->y(); 777 context->setShadow(IntSize(shadowX, shadowY - extraOffset), shadow->blur(), shadow->color(), colorSpace); 758 778 setShadow = true; 759 779 shadow = shadow->next(); … … 880 900 markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox(); 881 901 renderer()->document()->markers()->setRenderedRectForMarker(renderer()->node(), marker, markerRect); 882 902 883 903 // Optionally highlight the text 884 904 if (renderer()->frame()->editor()->markedTextMatchesAreHighlighted()) { -
trunk/WebCore/rendering/InlineTextBox.h
r70072 r70263 128 128 129 129 // Needs to be public, so the static paintTextWithShadows() function can use it. 130 static FloatSize applyShadowToGraphicsContext(GraphicsContext*, const ShadowData*, const FloatRect& textRect, bool stroked, bool opaque );130 static FloatSize applyShadowToGraphicsContext(GraphicsContext*, const ShadowData*, const FloatRect& textRect, bool stroked, bool opaque, bool vertical); 131 131 132 132 private: -
trunk/WebCore/rendering/svg/SVGInlineTextBox.cpp
r70072 r70263 524 524 FloatSize extraOffset; 525 525 if (shadow) 526 extraOffset = applyShadowToGraphicsContext(context, shadow, shadowRect, false /* stroked */, true /* opaque */ );526 extraOffset = applyShadowToGraphicsContext(context, shadow, shadowRect, false /* stroked */, true /* opaque */, false /* vertical */); 527 527 528 528 font.drawText(context, textRun, textOrigin + extraOffset, startPosition, endPosition);
Note: See TracChangeset
for help on using the changeset viewer.