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

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

Issue 23567004: Fix alignment for bidirectional text. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Trying Again Created 7 years, 3 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
« no previous file with comments | « Source/core/rendering/RenderBlock.h ('k') | no next file » | 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 * Copyright (C) 2000 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r ight reserved. 3 * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r ight reserved.
4 * Copyright (C) 2010 Google Inc. All rights reserved. 4 * Copyright (C) 2010 Google Inc. All rights 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 931 matching lines...) Expand 10 before | Expand all | Expand 10 after
942 textBox->setExpansion(expansion); 942 textBox->setExpansion(expansion);
943 totalLogicalWidth += expansion; 943 totalLogicalWidth += expansion;
944 } 944 }
945 expansionOpportunityCount -= opportunitiesInRun; 945 expansionOpportunityCount -= opportunitiesInRun;
946 if (!expansionOpportunityCount) 946 if (!expansionOpportunityCount)
947 break; 947 break;
948 } 948 }
949 } 949 }
950 } 950 }
951 951
952 void RenderBlock::updateLogicalWidthForAlignment(const ETextAlign& textAlign, Bi diRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& av ailableLogicalWidth, int expansionOpportunityCount) 952 void RenderBlock::updateLogicalWidthForAlignment(const ETextAlign& textAlign, co nst RootInlineBox* rootInlineBox, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& availableLogicalWidth, int expansionOpportunit yCount)
953 { 953 {
954 TextDirection direction;
955 if (rootInlineBox && rootInlineBox->renderer()->style()->unicodeBidi() == Pl aintext)
956 direction = rootInlineBox->direction();
957 else
958 direction = style()->direction();
959
954 // Armed with the total width of the line (without justification), 960 // Armed with the total width of the line (without justification),
955 // we now examine our text-align property in order to determine where to pos ition the 961 // we now examine our text-align property in order to determine where to pos ition the
956 // objects horizontally. The total width of the line can be increased if we end up 962 // objects horizontally. The total width of the line can be increased if we end up
957 // justifying text. 963 // justifying text.
958 switch (textAlign) { 964 switch (textAlign) {
959 case LEFT: 965 case LEFT:
960 case WEBKIT_LEFT: 966 case WEBKIT_LEFT:
961 updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); 967 updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
962 break; 968 break;
963 case RIGHT: 969 case RIGHT:
964 case WEBKIT_RIGHT: 970 case WEBKIT_RIGHT:
965 updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirection() , trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); 971 updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirection() , trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
966 break; 972 break;
967 case CENTER: 973 case CENTER:
968 case WEBKIT_CENTER: 974 case WEBKIT_CENTER:
969 updateLogicalWidthForCenterAlignedBlock(style()->isLeftToRightDirection( ), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); 975 updateLogicalWidthForCenterAlignedBlock(style()->isLeftToRightDirection( ), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
970 break; 976 break;
971 case JUSTIFY: 977 case JUSTIFY:
972 adjustInlineDirectionLineBounds(expansionOpportunityCount, logicalLeft, availableLogicalWidth); 978 adjustInlineDirectionLineBounds(expansionOpportunityCount, logicalLeft, availableLogicalWidth);
973 if (expansionOpportunityCount) { 979 if (expansionOpportunityCount) {
974 if (trailingSpaceRun) { 980 if (trailingSpaceRun) {
975 totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth(); 981 totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth();
976 trailingSpaceRun->m_box->setLogicalWidth(0); 982 trailingSpaceRun->m_box->setLogicalWidth(0);
977 } 983 }
978 break; 984 break;
979 } 985 }
980 // Fall through 986 // Fall through
981 case TASTART: 987 case TASTART:
982 if (style()->isLeftToRightDirection()) 988 if (direction == LTR)
983 updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirectio n(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); 989 updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirectio n(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
984 else 990 else
985 updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirecti on(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); 991 updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirecti on(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
986 break; 992 break;
987 case TAEND: 993 case TAEND:
988 if (style()->isLeftToRightDirection()) 994 if (direction == LTR)
989 updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirecti on(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); 995 updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirecti on(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
990 else 996 else
991 updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirectio n(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth); 997 updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirectio n(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
992 break; 998 break;
993 } 999 }
994 } 1000 }
995 1001
996 static IndentTextOrNot requiresIndent(bool isFirstLine, bool isAfterHardLineBrea k, RenderStyle* style) 1002 static IndentTextOrNot requiresIndent(bool isFirstLine, bool isAfterHardLineBrea k, RenderStyle* style)
997 { 1003 {
998 if (isFirstLine) 1004 if (isFirstLine)
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1125 1131
1126 totalLogicalWidth += r->m_box->logicalWidth(); 1132 totalLogicalWidth += r->m_box->logicalWidth();
1127 previousObject = r->m_object; 1133 previousObject = r->m_object;
1128 } 1134 }
1129 1135
1130 if (isAfterExpansion && !expansionOpportunities.isEmpty()) { 1136 if (isAfterExpansion && !expansionOpportunities.isEmpty()) {
1131 expansionOpportunities.last()--; 1137 expansionOpportunities.last()--;
1132 expansionOpportunityCount--; 1138 expansionOpportunityCount--;
1133 } 1139 }
1134 1140
1135 updateLogicalWidthForAlignment(textAlign, trailingSpaceRun, logicalLeft, tot alLogicalWidth, availableLogicalWidth, expansionOpportunityCount); 1141 updateLogicalWidthForAlignment(textAlign, lineBox, trailingSpaceRun, logical Left, totalLogicalWidth, availableLogicalWidth, expansionOpportunityCount);
1136 1142
1137 computeExpansionForJustifiedText(firstRun, trailingSpaceRun, expansionOpport unities, expansionOpportunityCount, totalLogicalWidth, availableLogicalWidth); 1143 computeExpansionForJustifiedText(firstRun, trailingSpaceRun, expansionOpport unities, expansionOpportunityCount, totalLogicalWidth, availableLogicalWidth);
1138 1144
1139 return r; 1145 return r;
1140 } 1146 }
1141 1147
1142 void RenderBlock::computeBlockDirectionPositionsForLine(RootInlineBox* lineBox, BidiRun* firstRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, 1148 void RenderBlock::computeBlockDirectionPositionsForLine(RootInlineBox* lineBox, BidiRun* firstRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap,
1143 VerticalPositionCache& v erticalPositionCache) 1149 VerticalPositionCache& v erticalPositionCache)
1144 { 1150 {
1145 setLogicalHeight(lineBox->alignBoxesInBlockDirection(logicalHeight(), textBo xDataMap, verticalPositionCache)); 1151 setLogicalHeight(lineBox->alignBoxesInBlockDirection(logicalHeight(), textBo xDataMap, verticalPositionCache));
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
1379 topResolver.midpointState().betweenMidpoints = false; 1385 topResolver.midpointState().betweenMidpoints = false;
1380 } 1386 }
1381 if (!segmentIsEmpty(segmentStart, segmentEnd)) { 1387 if (!segmentIsEmpty(segmentStart, segmentEnd)) {
1382 topResolver.setPosition(segmentStart, numberOfIsolateAncestors(segme ntStart)); 1388 topResolver.setPosition(segmentStart, numberOfIsolateAncestors(segme ntStart));
1383 constructBidiRunsForSegment(topResolver, bidiRuns, segmentEnd, overr ide, previousLineBrokeCleanly); 1389 constructBidiRunsForSegment(topResolver, bidiRuns, segmentEnd, overr ide, previousLineBrokeCleanly);
1384 } 1390 }
1385 } 1391 }
1386 } 1392 }
1387 1393
1388 // This function constructs line boxes for all of the text runs in the resolver and computes their position. 1394 // This function constructs line boxes for all of the text runs in the resolver and computes their position.
1389 RootInlineBox* RenderBlock::createLineBoxesFromBidiRuns(BidiRunList<BidiRun>& bi diRuns, const InlineIterator& end, LineInfo& lineInfo, VerticalPositionCache& ve rticalPositionCache, BidiRun* trailingSpaceRun, WordMeasurements& wordMeasuremen ts) 1395 RootInlineBox* RenderBlock::createLineBoxesFromBidiRuns(unsigned bidiLevel, Bidi RunList<BidiRun>& bidiRuns, const InlineIterator& end, LineInfo& lineInfo, Verti calPositionCache& verticalPositionCache, BidiRun* trailingSpaceRun, WordMeasurem ents& wordMeasurements)
1390 { 1396 {
1391 if (!bidiRuns.runCount()) 1397 if (!bidiRuns.runCount())
1392 return 0; 1398 return 0;
1393 1399
1394 // FIXME: Why is this only done when we had runs? 1400 // FIXME: Why is this only done when we had runs?
1395 lineInfo.setLastLine(!end.m_obj); 1401 lineInfo.setLastLine(!end.m_obj);
1396 1402
1397 RootInlineBox* lineBox = constructLine(bidiRuns, lineInfo); 1403 RootInlineBox* lineBox = constructLine(bidiRuns, lineInfo);
1398 if (!lineBox) 1404 if (!lineBox)
1399 return 0; 1405 return 0;
1400 1406
1407 lineBox->setBidiLevel(bidiLevel);
1401 lineBox->setEndsWithBreak(lineInfo.previousLineBrokeCleanly()); 1408 lineBox->setEndsWithBreak(lineInfo.previousLineBrokeCleanly());
1402 1409
1403 bool isSVGRootInlineBox = lineBox->isSVGRootInlineBox(); 1410 bool isSVGRootInlineBox = lineBox->isSVGRootInlineBox();
1404 1411
1405 GlyphOverflowAndFallbackFontsMap textBoxDataMap; 1412 GlyphOverflowAndFallbackFontsMap textBoxDataMap;
1406 1413
1407 // Now we position all of our text runs horizontally. 1414 // Now we position all of our text runs horizontally.
1408 if (!isSVGRootInlineBox) 1415 if (!isSVGRootInlineBox)
1409 computeInlineDirectionPositionsForLine(lineBox, lineInfo, bidiRuns.first Run(), trailingSpaceRun, end.atEnd(), textBoxDataMap, verticalPositionCache, wor dMeasurements); 1416 computeInlineDirectionPositionsForLine(lineBox, lineInfo, bidiRuns.first Run(), trailingSpaceRun, end.atEnd(), textBoxDataMap, verticalPositionCache, wor dMeasurements);
1410 1417
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after
1853 bidiRuns.logicallyLastRun()->m_hasHyphen = true; 1860 bidiRuns.logicallyLastRun()->m_hasHyphen = true;
1854 consecutiveHyphenatedLines++; 1861 consecutiveHyphenatedLines++;
1855 } else 1862 } else
1856 consecutiveHyphenatedLines = 0; 1863 consecutiveHyphenatedLines = 0;
1857 1864
1858 // Now that the runs have been ordered, we create the line boxes. 1865 // Now that the runs have been ordered, we create the line boxes.
1859 // At the same time we figure out where border/padding/margin should be applied for 1866 // At the same time we figure out where border/padding/margin should be applied for
1860 // inline flow boxes. 1867 // inline flow boxes.
1861 1868
1862 LayoutUnit oldLogicalHeight = logicalHeight(); 1869 LayoutUnit oldLogicalHeight = logicalHeight();
1863 RootInlineBox* lineBox = createLineBoxesFromBidiRuns(bidiRuns, end, layoutState.lineInfo(), verticalPositionCache, trailingSpaceRun, wordMeasurement s); 1870 RootInlineBox* lineBox = createLineBoxesFromBidiRuns(resolver.status ().context->level(), bidiRuns, end, layoutState.lineInfo(), verticalPositionCach e, trailingSpaceRun, wordMeasurements);
1864 1871
1865 bidiRuns.deleteRuns(); 1872 bidiRuns.deleteRuns();
1866 resolver.markCurrentRunEmpty(); // FIXME: This can probably be repla ced by an ASSERT (or just removed). 1873 resolver.markCurrentRunEmpty(); // FIXME: This can probably be repla ced by an ASSERT (or just removed).
1867 1874
1868 if (lineBox) { 1875 if (lineBox) {
1869 lineBox->setLineBreakInfo(end.m_obj, end.m_pos, resolver.status( )); 1876 lineBox->setLineBreakInfo(end.m_obj, end.m_pos, resolver.status( ));
1870 if (layoutState.usesRepaintBounds()) 1877 if (layoutState.usesRepaintBounds())
1871 layoutState.updateRepaintRangeFromBox(lineBox); 1878 layoutState.updateRepaintRangeFromBox(lineBox);
1872 1879
1873 if (paginated) { 1880 if (paginated) {
(...skipping 1486 matching lines...) Expand 10 before | Expand all | Expand 10 after
3360 bool ltr = style()->isLeftToRightDirection(); 3367 bool ltr = style()->isLeftToRightDirection();
3361 bool firstLine = true; 3368 bool firstLine = true;
3362 for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) { 3369 for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
3363 if (curr->hasEllipsisBox()) { 3370 if (curr->hasEllipsisBox()) {
3364 curr->clearTruncation(); 3371 curr->clearTruncation();
3365 3372
3366 // Shift the line back where it belongs if we cannot accomodate an e llipsis. 3373 // Shift the line back where it belongs if we cannot accomodate an e llipsis.
3367 float logicalLeft = pixelSnappedLogicalLeftOffsetForLine(curr->lineT op(), firstLine); 3374 float logicalLeft = pixelSnappedLogicalLeftOffsetForLine(curr->lineT op(), firstLine);
3368 float availableLogicalWidth = logicalRightOffsetForLine(curr->lineTo p(), false) - logicalLeft; 3375 float availableLogicalWidth = logicalRightOffsetForLine(curr->lineTo p(), false) - logicalLeft;
3369 float totalLogicalWidth = curr->logicalWidth(); 3376 float totalLogicalWidth = curr->logicalWidth();
3370 updateLogicalWidthForAlignment(textAlign, 0, logicalLeft, totalLogic alWidth, availableLogicalWidth, 0); 3377 updateLogicalWidthForAlignment(textAlign, curr, 0, logicalLeft, tota lLogicalWidth, availableLogicalWidth, 0);
3371 3378
3372 if (ltr) 3379 if (ltr)
3373 curr->adjustLogicalPosition((logicalLeft - curr->logicalLeft()), 0); 3380 curr->adjustLogicalPosition((logicalLeft - curr->logicalLeft()), 0);
3374 else 3381 else
3375 curr->adjustLogicalPosition(-(curr->logicalLeft() - logicalLeft) , 0); 3382 curr->adjustLogicalPosition(-(curr->logicalLeft() - logicalLeft) , 0);
3376 } 3383 }
3377 firstLine = false; 3384 firstLine = false;
3378 } 3385 }
3379 } 3386 }
3380 3387
(...skipping 26 matching lines...) Expand all
3407 // accommodate our truncation string, and no replaced elements (imag es, tables) can overlap the ellipsis 3414 // accommodate our truncation string, and no replaced elements (imag es, tables) can overlap the ellipsis
3408 // space. 3415 // space.
3409 3416
3410 LayoutUnit width = firstLine ? firstLineEllipsisWidth : ellipsisWidt h; 3417 LayoutUnit width = firstLine ? firstLineEllipsisWidth : ellipsisWidt h;
3411 LayoutUnit blockEdge = ltr ? blockRightEdge : blockLeftEdge; 3418 LayoutUnit blockEdge = ltr ? blockRightEdge : blockLeftEdge;
3412 if (curr->lineCanAccommodateEllipsis(ltr, blockEdge, lineBoxEdge, wi dth)) { 3419 if (curr->lineCanAccommodateEllipsis(ltr, blockEdge, lineBoxEdge, wi dth)) {
3413 float totalLogicalWidth = curr->placeEllipsis(ellipsisStr, ltr, blockLeftEdge, blockRightEdge, width); 3420 float totalLogicalWidth = curr->placeEllipsis(ellipsisStr, ltr, blockLeftEdge, blockRightEdge, width);
3414 3421
3415 float logicalLeft = 0; // We are only intersted in the delta fro m the base position. 3422 float logicalLeft = 0; // We are only intersted in the delta fro m the base position.
3416 float truncatedWidth = pixelSnappedLogicalRightOffsetForLine(cur r->lineTop(), firstLine); 3423 float truncatedWidth = pixelSnappedLogicalRightOffsetForLine(cur r->lineTop(), firstLine);
3417 updateLogicalWidthForAlignment(textAlign, 0, logicalLeft, totalL ogicalWidth, truncatedWidth, 0); 3424 updateLogicalWidthForAlignment(textAlign, curr, 0, logicalLeft, totalLogicalWidth, truncatedWidth, 0);
3418 if (ltr) 3425 if (ltr)
3419 curr->adjustLogicalPosition(logicalLeft, 0); 3426 curr->adjustLogicalPosition(logicalLeft, 0);
3420 else 3427 else
3421 curr->adjustLogicalPosition(-(truncatedWidth - (logicalLeft + totalLogicalWidth)), 0); 3428 curr->adjustLogicalPosition(-(truncatedWidth - (logicalLeft + totalLogicalWidth)), 0);
3422 } 3429 }
3423 } 3430 }
3424 firstLine = false; 3431 firstLine = false;
3425 } 3432 }
3426 } 3433 }
3427 3434
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
3482 { 3489 {
3483 ETextAlign textAlign = style()->textAlign(); 3490 ETextAlign textAlign = style()->textAlign();
3484 3491
3485 if (textAlign == TASTART) // FIXME: Handle TAEND here 3492 if (textAlign == TASTART) // FIXME: Handle TAEND here
3486 return startOffsetForLine(position, firstLine); 3493 return startOffsetForLine(position, firstLine);
3487 3494
3488 // updateLogicalWidthForAlignment() handles the direction of the block so no need to consider it here 3495 // updateLogicalWidthForAlignment() handles the direction of the block so no need to consider it here
3489 float totalLogicalWidth = 0; 3496 float totalLogicalWidth = 0;
3490 float logicalLeft = logicalLeftOffsetForLine(logicalHeight(), false); 3497 float logicalLeft = logicalLeftOffsetForLine(logicalHeight(), false);
3491 float availableLogicalWidth = logicalRightOffsetForLine(logicalHeight(), fal se) - logicalLeft; 3498 float availableLogicalWidth = logicalRightOffsetForLine(logicalHeight(), fal se) - logicalLeft;
3492 updateLogicalWidthForAlignment(textAlign, 0, logicalLeft, totalLogicalWidth, availableLogicalWidth, 0); 3499 updateLogicalWidthForAlignment(textAlign, 0, 0, logicalLeft, totalLogicalWid th, availableLogicalWidth, 0);
3493 3500
3494 if (!style()->isLeftToRightDirection()) 3501 if (!style()->isLeftToRightDirection())
3495 return logicalWidth() - logicalLeft; 3502 return logicalWidth() - logicalLeft;
3496 return logicalLeft; 3503 return logicalLeft;
3497 } 3504 }
3498 3505
3499 3506
3500 void RenderBlock::layoutLineGridBox() 3507 void RenderBlock::layoutLineGridBox()
3501 { 3508 {
3502 if (style()->lineGrid() == RenderStyle::initialLineGrid()) { 3509 if (style()->lineGrid() == RenderStyle::initialLineGrid()) {
(...skipping 11 matching lines...) Expand all
3514 lineGridBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap, ver ticalPositionCache); 3521 lineGridBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap, ver ticalPositionCache);
3515 3522
3516 setLineGridBox(lineGridBox); 3523 setLineGridBox(lineGridBox);
3517 3524
3518 // FIXME: If any of the characteristics of the box change compared to the ol d one, then we need to do a deep dirtying 3525 // FIXME: If any of the characteristics of the box change compared to the ol d one, then we need to do a deep dirtying
3519 // (similar to what happens when the page height changes). Ideally, though, we only do this if someone is actually snapping 3526 // (similar to what happens when the page height changes). Ideally, though, we only do this if someone is actually snapping
3520 // to this grid. 3527 // to this grid.
3521 } 3528 }
3522 3529
3523 } 3530 }
OLDNEW
« no previous file with comments | « Source/core/rendering/RenderBlock.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698