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

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

Issue 46393003: BidiResolver should not append an isolated run if it is in a other line. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Proposed patch Created 7 years, 1 month 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
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 1257 matching lines...) Expand 10 before | Expand all | Expand 10 after
1268 } 1268 }
1269 isolatedResolver.setStatus(statusWithDirection(direction, isOverride(uni codeBidi))); 1269 isolatedResolver.setStatus(statusWithDirection(direction, isOverride(uni codeBidi)));
1270 1270
1271 setupResolverToResumeInIsolate(isolatedResolver, isolatedInline, startOb j); 1271 setupResolverToResumeInIsolate(isolatedResolver, isolatedInline, startOb j);
1272 1272
1273 // The starting position is the beginning of the first run within the is olate that was identified 1273 // The starting position is the beginning of the first run within the is olate that was identified
1274 // during the earlier call to createBidiRunsForLine. This can be but is not necessarily the 1274 // during the earlier call to createBidiRunsForLine. This can be but is not necessarily the
1275 // first run within the isolate. 1275 // first run within the isolate.
1276 InlineIterator iter = InlineIterator(isolatedInline, startObj, isolatedR un->m_start); 1276 InlineIterator iter = InlineIterator(isolatedInline, startObj, isolatedR un->m_start);
1277 isolatedResolver.setPositionIgnoringNestedIsolates(iter); 1277 isolatedResolver.setPositionIgnoringNestedIsolates(iter);
1278
1279 // We stop at the next end of line; we may re-enter this isolate in the next call to constructBidiRuns(). 1278 // We stop at the next end of line; we may re-enter this isolate in the next call to constructBidiRuns().
1280 // FIXME: What should end and previousLineBrokeCleanly be? 1279 // FIXME: What should end and previousLineBrokeCleanly be?
1281 // rniwa says previousLineBrokeCleanly is just a WinIE hack and could al ways be false here? 1280 // rniwa says previousLineBrokeCleanly is just a WinIE hack and could al ways be false here?
1282 isolatedResolver.createBidiRunsForLine(endOfRuns, NoVisualOverride, prev iousLineBrokeCleanly); 1281 isolatedResolver.createBidiRunsForLine(endOfRuns, NoVisualOverride, prev iousLineBrokeCleanly);
1282
1283 // Note that we do not delete the runs from the resolver. 1283 // Note that we do not delete the runs from the resolver.
1284 // We're not guaranteed to get any BidiRuns in the previous step. If we don't, we allow the placeholder 1284 // We're not guaranteed to get any BidiRuns in the previous step. If we don't, we allow the placeholder
1285 // itself to be turned into an InlineBox. We can't remove it here withou t potentially losing track of 1285 // itself to be turned into an InlineBox. We can't remove it here withou t potentially losing track of
1286 // the logically last run. 1286 // the logically last run.
1287 if (isolatedResolver.runs().runCount()) 1287 if (isolatedResolver.runs().runCount())
1288 bidiRuns.replaceRunWithRuns(isolatedRun, isolatedResolver.runs()); 1288 bidiRuns.replaceRunWithRuns(isolatedRun, isolatedResolver.runs());
1289 1289
1290 // If we encountered any nested isolate runs, just move them 1290 // If we encountered any nested isolate runs, just move them
1291 // to the top resolver's list for later processing. 1291 // to the top resolver's list for later processing.
1292 if (!isolatedResolver.isolatedRuns().isEmpty()) { 1292 if (!isolatedResolver.isolatedRuns().isEmpty()) {
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after
1720 1720
1721 end = restartLayoutRunsAndFloatsInRange(logicalHeight(), newLogicalHeight, l astFloatFromPreviousLine, resolver, end); 1721 end = restartLayoutRunsAndFloatsInRange(logicalHeight(), newLogicalHeight, l astFloatFromPreviousLine, resolver, end);
1722 return true; 1722 return true;
1723 } 1723 }
1724 1724
1725 void RenderBlockFlow::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, I nlineBidiResolver& resolver, const InlineIterator& cleanLineStart, const BidiSta tus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines) 1725 void RenderBlockFlow::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, I nlineBidiResolver& resolver, const InlineIterator& cleanLineStart, const BidiSta tus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines)
1726 { 1726 {
1727 RenderStyle* styleToUse = style(); 1727 RenderStyle* styleToUse = style();
1728 bool paginated = view()->layoutState() && view()->layoutState()->isPaginated (); 1728 bool paginated = view()->layoutState() && view()->layoutState()->isPaginated ();
1729 LineMidpointState& lineMidpointState = resolver.midpointState(); 1729 LineMidpointState& lineMidpointState = resolver.midpointState();
1730 InlineIterator end = resolver.position(); 1730 InlineIterator endOfLine = resolver.position();
1731 bool checkForEndLineMatch = layoutState.endLine(); 1731 bool checkForEndLineMatch = layoutState.endLine();
1732 RenderTextInfo renderTextInfo; 1732 RenderTextInfo renderTextInfo;
1733 VerticalPositionCache verticalPositionCache; 1733 VerticalPositionCache verticalPositionCache;
1734 1734
1735 LineBreaker lineBreaker(this); 1735 LineBreaker lineBreaker(this);
1736 1736
1737 LayoutSize logicalOffsetFromShapeContainer; 1737 LayoutSize logicalOffsetFromShapeContainer;
1738 ShapeInsideInfo* shapeInsideInfo = layoutShapeInsideInfo(); 1738 ShapeInsideInfo* shapeInsideInfo = layoutShapeInsideInfo();
1739 if (shapeInsideInfo) { 1739 if (shapeInsideInfo) {
1740 ASSERT(shapeInsideInfo->owner() == this || allowsShapeInsideInfoSharing( )); 1740 ASSERT(shapeInsideInfo->owner() == this || allowsShapeInsideInfoSharing( ));
1741 if (shapeInsideInfo != this->shapeInsideInfo()) { 1741 if (shapeInsideInfo != this->shapeInsideInfo()) {
1742 // FIXME Bug 100284: If subsequent LayoutStates are pushed, we will have to add 1742 // FIXME Bug 100284: If subsequent LayoutStates are pushed, we will have to add
1743 // their offsets from the original shape-inside container. 1743 // their offsets from the original shape-inside container.
1744 logicalOffsetFromShapeContainer = logicalOffsetFromShapeAncestorCont ainer(shapeInsideInfo->owner()); 1744 logicalOffsetFromShapeContainer = logicalOffsetFromShapeAncestorCont ainer(shapeInsideInfo->owner());
1745 } 1745 }
1746 // Begin layout at the logical top of our shape inside. 1746 // Begin layout at the logical top of our shape inside.
1747 if (logicalHeight() + logicalOffsetFromShapeContainer.height() < shapeIn sideInfo->shapeLogicalTop()) { 1747 if (logicalHeight() + logicalOffsetFromShapeContainer.height() < shapeIn sideInfo->shapeLogicalTop()) {
1748 LayoutUnit logicalHeight = shapeInsideInfo->shapeLogicalTop() - logi calOffsetFromShapeContainer.height(); 1748 LayoutUnit logicalHeight = shapeInsideInfo->shapeLogicalTop() - logi calOffsetFromShapeContainer.height();
1749 if (layoutState.flowThread()) 1749 if (layoutState.flowThread())
1750 logicalHeight -= shapeInsideInfo->owner()->borderAndPaddingBefor e(); 1750 logicalHeight -= shapeInsideInfo->owner()->borderAndPaddingBefor e();
1751 setLogicalHeight(logicalHeight); 1751 setLogicalHeight(logicalHeight);
1752 } 1752 }
1753 } 1753 }
1754 1754
1755 while (!end.atEnd()) { 1755 while (!endOfLine.atEnd()) {
1756 // FIXME: Is this check necessary before the first iteration or can it b e moved to the end? 1756 // FIXME: Is this check necessary before the first iteration or can it b e moved to the end?
1757 if (checkForEndLineMatch) { 1757 if (checkForEndLineMatch) {
1758 layoutState.setEndLineMatched(matchedEndLine(layoutState, resolver, cleanLineStart, cleanLineBidiStatus)); 1758 layoutState.setEndLineMatched(matchedEndLine(layoutState, resolver, cleanLineStart, cleanLineBidiStatus));
1759 if (layoutState.endLineMatched()) { 1759 if (layoutState.endLineMatched()) {
1760 resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0), 0); 1760 resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0), 0);
1761 break; 1761 break;
1762 } 1762 }
1763 } 1763 }
1764 1764
1765 lineMidpointState.reset(); 1765 lineMidpointState.reset();
1766 1766
1767 layoutState.lineInfo().setEmpty(true); 1767 layoutState.lineInfo().setEmpty(true);
1768 layoutState.lineInfo().resetRunsFromLeadingWhitespace(); 1768 layoutState.lineInfo().resetRunsFromLeadingWhitespace();
1769 1769
1770 const InlineIterator oldEnd = end; 1770 const InlineIterator previousEndofLine = endOfLine;
1771 bool isNewUBAParagraph = layoutState.lineInfo().previousLineBrokeCleanly (); 1771 bool isNewUBAParagraph = layoutState.lineInfo().previousLineBrokeCleanly ();
1772 FloatingObject* lastFloatFromPreviousLine = (containsFloats()) ? m_float ingObjects->set().last() : 0; 1772 FloatingObject* lastFloatFromPreviousLine = (containsFloats()) ? m_float ingObjects->set().last() : 0;
1773 1773
1774 updateShapeAndSegmentsForCurrentLine(shapeInsideInfo, logicalOffsetFromS hapeContainer, layoutState); 1774 updateShapeAndSegmentsForCurrentLine(shapeInsideInfo, logicalOffsetFromS hapeContainer, layoutState);
1775 1775
1776 WordMeasurements wordMeasurements; 1776 WordMeasurements wordMeasurements;
1777 end = lineBreaker.nextLineBreak(resolver, layoutState.lineInfo(), render TextInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines, wordMeasurement s); 1777 endOfLine = lineBreaker.nextLineBreak(resolver, layoutState.lineInfo(), renderTextInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines, wordMeasu rements);
1778 renderTextInfo.m_lineBreakIterator.resetPriorContext(); 1778 renderTextInfo.m_lineBreakIterator.resetPriorContext();
1779 if (resolver.position().atEnd()) { 1779 if (resolver.position().atEnd()) {
1780 // FIXME: We shouldn't be creating any runs in nextLineBreak to begi n with! 1780 // FIXME: We shouldn't be creating any runs in nextLineBreak to begi n with!
1781 // Once BidiRunList is separated from BidiResolver this will not be needed. 1781 // Once BidiRunList is separated from BidiResolver this will not be needed.
1782 resolver.runs().deleteRuns(); 1782 resolver.runs().deleteRuns();
1783 resolver.markCurrentRunEmpty(); // FIXME: This can probably be repla ced by an ASSERT (or just removed). 1783 resolver.markCurrentRunEmpty(); // FIXME: This can probably be repla ced by an ASSERT (or just removed).
1784 layoutState.setCheckForFloatsFromLastLine(true); 1784 layoutState.setCheckForFloatsFromLastLine(true);
1785 resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0 ), 0); 1785 resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0 ), 0);
1786 break; 1786 break;
1787 } 1787 }
1788 1788
1789 if (adjustLogicalLineTopAndLogicalHeightIfNeeded(shapeInsideInfo, logica lOffsetFromShapeContainer.height(), layoutState, resolver, lastFloatFromPrevious Line, end, wordMeasurements)) 1789 if (adjustLogicalLineTopAndLogicalHeightIfNeeded(shapeInsideInfo, logica lOffsetFromShapeContainer.height(), layoutState, resolver, lastFloatFromPrevious Line, endOfLine, wordMeasurements))
1790 continue; 1790 continue;
1791 1791
1792 ASSERT(end != resolver.position()); 1792 ASSERT(endOfLine != resolver.position());
1793 1793
1794 // This is a short-cut for empty lines. 1794 // This is a short-cut for empty lines.
1795 if (layoutState.lineInfo().isEmpty()) { 1795 if (layoutState.lineInfo().isEmpty()) {
1796 if (lastRootBox()) 1796 if (lastRootBox())
1797 lastRootBox()->setLineBreakInfo(end.m_obj, end.m_pos, resolver.s tatus()); 1797 lastRootBox()->setLineBreakInfo(endOfLine.m_obj, endOfLine.m_pos , resolver.status());
1798 } else { 1798 } else {
1799 VisualDirectionOverride override = (styleToUse->rtlOrdering() == Vis ualOrder ? (styleToUse->direction() == LTR ? VisualLeftToRightOverride : VisualR ightToLeftOverride) : NoVisualOverride); 1799 VisualDirectionOverride override = (styleToUse->rtlOrdering() == Vis ualOrder ? (styleToUse->direction() == LTR ? VisualLeftToRightOverride : VisualR ightToLeftOverride) : NoVisualOverride);
1800 1800
1801 if (isNewUBAParagraph && styleToUse->unicodeBidi() == Plaintext && ! resolver.context()->parent()) { 1801 if (isNewUBAParagraph && styleToUse->unicodeBidi() == Plaintext && ! resolver.context()->parent()) {
1802 TextDirection direction = determinePlaintextDirectionality(resol ver.position().root(), resolver.position().object(), resolver.position().offset( )); 1802 TextDirection direction = determinePlaintextDirectionality(resol ver.position().root(), resolver.position().object(), resolver.position().offset( ));
1803 resolver.setStatus(BidiStatus(direction, isOverride(styleToUse-> unicodeBidi()))); 1803 resolver.setStatus(BidiStatus(direction, isOverride(styleToUse-> unicodeBidi())));
1804 } 1804 }
1805 // FIXME: This ownership is reversed. We should own the BidiRunList and pass it to createBidiRunsForLine. 1805 // FIXME: This ownership is reversed. We should own the BidiRunList and pass it to createBidiRunsForLine.
1806 BidiRunList<BidiRun>& bidiRuns = resolver.runs(); 1806 BidiRunList<BidiRun>& bidiRuns = resolver.runs();
1807 constructBidiRunsForLine(this, resolver, bidiRuns, end, override, la youtState.lineInfo().previousLineBrokeCleanly(), isNewUBAParagraph); 1807 constructBidiRunsForLine(this, resolver, bidiRuns, endOfLine, overri de, layoutState.lineInfo().previousLineBrokeCleanly(), isNewUBAParagraph);
1808 ASSERT(resolver.position() == end); 1808 ASSERT(resolver.position() == endOfLine);
1809 1809
1810 BidiRun* trailingSpaceRun = !layoutState.lineInfo().previousLineBrok eCleanly() ? handleTrailingSpaces(bidiRuns, resolver.context()) : 0; 1810 BidiRun* trailingSpaceRun = !layoutState.lineInfo().previousLineBrok eCleanly() ? handleTrailingSpaces(bidiRuns, resolver.context()) : 0;
1811 1811
1812 if (bidiRuns.runCount() && lineBreaker.lineWasHyphenated()) { 1812 if (bidiRuns.runCount() && lineBreaker.lineWasHyphenated()) {
1813 bidiRuns.logicallyLastRun()->m_hasHyphen = true; 1813 bidiRuns.logicallyLastRun()->m_hasHyphen = true;
1814 consecutiveHyphenatedLines++; 1814 consecutiveHyphenatedLines++;
1815 } else 1815 } else
1816 consecutiveHyphenatedLines = 0; 1816 consecutiveHyphenatedLines = 0;
1817 1817
1818 // Now that the runs have been ordered, we create the line boxes. 1818 // Now that the runs have been ordered, we create the line boxes.
1819 // At the same time we figure out where border/padding/margin should be applied for 1819 // At the same time we figure out where border/padding/margin should be applied for
1820 // inline flow boxes. 1820 // inline flow boxes.
1821 1821
1822 LayoutUnit oldLogicalHeight = logicalHeight(); 1822 LayoutUnit oldLogicalHeight = logicalHeight();
1823 RootInlineBox* lineBox = createLineBoxesFromBidiRuns(resolver.status ().context->level(), bidiRuns, end, layoutState.lineInfo(), verticalPositionCach e, trailingSpaceRun, wordMeasurements); 1823 RootInlineBox* lineBox = createLineBoxesFromBidiRuns(resolver.status ().context->level(), bidiRuns, endOfLine, layoutState.lineInfo(), verticalPositi onCache, trailingSpaceRun, wordMeasurements);
1824 1824
1825 bidiRuns.deleteRuns(); 1825 bidiRuns.deleteRuns();
1826 resolver.markCurrentRunEmpty(); // FIXME: This can probably be repla ced by an ASSERT (or just removed). 1826 resolver.markCurrentRunEmpty(); // FIXME: This can probably be repla ced by an ASSERT (or just removed).
1827 1827
1828 if (lineBox) { 1828 if (lineBox) {
1829 lineBox->setLineBreakInfo(end.m_obj, end.m_pos, resolver.status( )); 1829 lineBox->setLineBreakInfo(endOfLine.m_obj, endOfLine.m_pos, reso lver.status());
1830 if (layoutState.usesRepaintBounds()) 1830 if (layoutState.usesRepaintBounds())
1831 layoutState.updateRepaintRangeFromBox(lineBox); 1831 layoutState.updateRepaintRangeFromBox(lineBox);
1832 1832
1833 if (paginated) { 1833 if (paginated) {
1834 LayoutUnit adjustment = 0; 1834 LayoutUnit adjustment = 0;
1835 adjustLinePositionForPagination(lineBox, adjustment, layoutS tate.flowThread()); 1835 adjustLinePositionForPagination(lineBox, adjustment, layoutS tate.flowThread());
1836 if (adjustment) { 1836 if (adjustment) {
1837 LayoutUnit oldLineWidth = availableLogicalWidthForLine(o ldLogicalHeight, layoutState.lineInfo().isFirstLine()); 1837 LayoutUnit oldLineWidth = availableLogicalWidthForLine(o ldLogicalHeight, layoutState.lineInfo().isFirstLine());
1838 lineBox->adjustBlockDirectionPosition(adjustment); 1838 lineBox->adjustBlockDirectionPosition(adjustment);
1839 if (layoutState.usesRepaintBounds()) 1839 if (layoutState.usesRepaintBounds())
1840 layoutState.updateRepaintRangeFromBox(lineBox); 1840 layoutState.updateRepaintRangeFromBox(lineBox);
1841 1841
1842 if (availableLogicalWidthForLine(oldLogicalHeight + adju stment, layoutState.lineInfo().isFirstLine()) != oldLineWidth) { 1842 if (availableLogicalWidthForLine(oldLogicalHeight + adju stment, layoutState.lineInfo().isFirstLine()) != oldLineWidth) {
1843 // We have to delete this line, remove all floats th at got added, and let line layout re-run. 1843 // We have to delete this line, remove all floats th at got added, and let line layout re-run.
1844 lineBox->deleteLine(); 1844 lineBox->deleteLine();
1845 end = restartLayoutRunsAndFloatsInRange(oldLogicalHe ight, oldLogicalHeight + adjustment, lastFloatFromPreviousLine, resolver, oldEnd ); 1845 endOfLine = restartLayoutRunsAndFloatsInRange(oldLog icalHeight, oldLogicalHeight + adjustment, lastFloatFromPreviousLine, resolver, previousEndofLine);
1846 continue; 1846 continue;
1847 } 1847 }
1848 1848
1849 setLogicalHeight(lineBox->lineBottomWithLeading()); 1849 setLogicalHeight(lineBox->lineBottomWithLeading());
1850 } 1850 }
1851 1851
1852 if (layoutState.flowThread()) 1852 if (layoutState.flowThread())
1853 updateRegionForLine(lineBox); 1853 updateRegionForLine(lineBox);
1854 } 1854 }
1855 } 1855 }
(...skipping 23 matching lines...) Expand all
1879 ASSERT(f->renderer() == layoutState.floats()[layoutState.floatIn dex()].object); 1879 ASSERT(f->renderer() == layoutState.floats()[layoutState.floatIn dex()].object);
1880 // If a float's geometry has changed, give up on syncing with cl ean lines. 1880 // If a float's geometry has changed, give up on syncing with cl ean lines.
1881 if (layoutState.floats()[layoutState.floatIndex()].rect != f->fr ameRect()) 1881 if (layoutState.floats()[layoutState.floatIndex()].rect != f->fr ameRect())
1882 checkForEndLineMatch = false; 1882 checkForEndLineMatch = false;
1883 layoutState.setFloatIndex(layoutState.floatIndex() + 1); 1883 layoutState.setFloatIndex(layoutState.floatIndex() + 1);
1884 } 1884 }
1885 layoutState.setLastFloat(!floatingObjectSet.isEmpty() ? floatingObje ctSet.last() : 0); 1885 layoutState.setLastFloat(!floatingObjectSet.isEmpty() ? floatingObje ctSet.last() : 0);
1886 } 1886 }
1887 1887
1888 lineMidpointState.reset(); 1888 lineMidpointState.reset();
1889 resolver.setPosition(end, numberOfIsolateAncestors(end)); 1889 resolver.setPosition(endOfLine, numberOfIsolateAncestors(endOfLine));
1890 } 1890 }
1891 1891
1892 // In case we already adjusted the line positions during this layout to avoi d widows 1892 // In case we already adjusted the line positions during this layout to avoi d widows
1893 // then we need to ignore the possibility of having a new widows situation. 1893 // then we need to ignore the possibility of having a new widows situation.
1894 // Otherwise, we risk leaving empty containers which is against the block fr agmentation principles. 1894 // Otherwise, we risk leaving empty containers which is against the block fr agmentation principles.
1895 if (paginated && !style()->hasAutoWidows() && !didBreakAtLineToAvoidWidow()) { 1895 if (paginated && !style()->hasAutoWidows() && !didBreakAtLineToAvoidWidow()) {
1896 // Check the line boxes to make sure we didn't create unacceptable widow s. 1896 // Check the line boxes to make sure we didn't create unacceptable widow s.
1897 // However, we'll prioritize orphans - so nothing we do here should crea te 1897 // However, we'll prioritize orphans - so nothing we do here should crea te
1898 // a new orphan. 1898 // a new orphan.
1899 1899
(...skipping 1618 matching lines...) Expand 10 before | Expand all | Expand 10 after
3518 lineGridBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap, ver ticalPositionCache); 3518 lineGridBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap, ver ticalPositionCache);
3519 3519
3520 setLineGridBox(lineGridBox); 3520 setLineGridBox(lineGridBox);
3521 3521
3522 // FIXME: If any of the characteristics of the box change compared to the ol d one, then we need to do a deep dirtying 3522 // FIXME: If any of the characteristics of the box change compared to the ol d one, then we need to do a deep dirtying
3523 // (similar to what happens when the page height changes). Ideally, though, we only do this if someone is actually snapping 3523 // (similar to what happens when the page height changes). Ideally, though, we only do this if someone is actually snapping
3524 // to this grid. 3524 // to this grid.
3525 } 3525 }
3526 3526
3527 } 3527 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698