Changeset 24485 in webkit
- Timestamp:
- Jul 20, 2007 12:01:55 PM (17 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 5 added
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r24484 r24485 1 2007-07-20 Mitz Pettel <mitz@webkit.org> 2 3 Reviewed by Darin. 4 5 - http://bugs.webkit.org/show_bug.cgi?id=14626 6 Make bidiReorderCharacters independent of RenderBlock 7 8 No layout test possible because there is no change in functionality. 9 10 This patch generalizes RenderBlock's implementation of the Unicode Bidi Algorithm 11 in the form of the BidiResolver class template. An instance of a BidiResolver class 12 can generate a sequence of runs with corresponding level and override attributes, 13 given a range specified by start and end iterators. The iterators can optionally 14 call back to the BidiResolver instance to push or pop explicit embedding levels. 15 16 The patch replaces BidiState with a specialization of BidiResolver that uses 17 BidiIterators and generates BidiRuns. It also eliminates some of the file statics 18 in bidi.cpp, instead relying on BidiResolver data members. 19 20 The patch makes the BidiContext part of BidiStatus, thus making BidiStatus the 21 entire state that needs to be saved and restored in order to restart the bidi 22 algorithm at a given point. Previously, you had to keep and pass around two 23 separate structures, namely the BidiContext and the BidiStatus. 24 25 bidiReorderCharacters is implemented without relying on render objects, using 26 a BidiResolver specialization that uses simple character buffer iterators and 27 simple run structures. 28 29 * WebCore.pro: 30 * WebCore.vcproj/WebCore.vcproj: 31 * WebCore.xcodeproj/project.pbxproj: 32 * WebCoreSources.bkl: 33 * platform/BidiContext.cpp: Added. 34 (WebCore::operator==): 35 * platform/BidiContext.h: Added. 36 (WebCore::BidiContext::BidiContext): 37 (WebCore::BidiContext::ref): 38 (WebCore::BidiContext::deref): 39 (WebCore::BidiContext::parent): 40 (WebCore::BidiContext::level): 41 (WebCore::BidiContext::dir): 42 (WebCore::BidiContext::override): 43 * platform/BidiReorderCharacters.cpp: Added. 44 (WebCore::CharacterBufferIterator::CharacterBufferIterator): 45 (WebCore::CharacterBufferIterator::offset): 46 (WebCore::CharacterBufferIterator::increment): 47 (WebCore::CharacterBufferIterator::atEnd): 48 (WebCore::CharacterBufferIterator::current): 49 (WebCore::CharacterBufferIterator::direction): 50 (WebCore::CharacterBufferIterator::operator==): 51 (WebCore::CharacterBufferIterator::operator!=): 52 (WebCore::::appendRun): 53 (WebCore::bidiReorderCharacters): 54 * platform/BidiReorderCharacters.h: Added. 55 * platform/BidiResolver.h: Added. 56 (WebCore::BidiStatus::BidiStatus): 57 (WebCore::operator==): 58 (WebCore::operator!=): 59 (WebCore::BidiCharacterRun::BidiCharacterRun): 60 (WebCore::BidiCharacterRun::reversed): 61 (WebCore::BidiCharacterRun::dirOverride): 62 (WebCore::BidiCharacterRun::next): 63 (WebCore::BidiResolver::): 64 (WebCore::BidiResolver::context): 65 (WebCore::BidiResolver::setContext): 66 (WebCore::BidiResolver::setLastDir): 67 (WebCore::BidiResolver::setLastStrongDir): 68 (WebCore::BidiResolver::setEorDir): 69 (WebCore::BidiResolver::dir): 70 (WebCore::BidiResolver::setDir): 71 (WebCore::BidiResolver::status): 72 (WebCore::BidiResolver::setStatus): 73 (WebCore::BidiResolver::adjustEmbedding): 74 (WebCore::BidiResolver::setAdjustEmbedding): 75 (WebCore::BidiResolver::firstRun): 76 (WebCore::BidiResolver::lastRun): 77 (WebCore::BidiResolver::runCount): 78 (WebCore::::embed): 79 (WebCore::::deleteRuns): 80 (WebCore::::reverseRuns): 81 (WebCore::::createBidiRunsForLine): 82 * platform/win/PopupMenuWin.cpp: 83 (WebCore::PopupMenu::paint): 84 * rendering/RenderBlock.h: 85 * rendering/RenderFileUploadControl.cpp: 86 (WebCore::RenderFileUploadControl::paintObject): 87 * rendering/RenderListBox.cpp: 88 (WebCore::RenderListBox::paintItemForeground): 89 * rendering/RootInlineBox.cpp: 90 (WebCore::RootInlineBox::childRemoved): 91 (WebCore::RootInlineBox::lineBreakBidiStatus): 92 (WebCore::RootInlineBox::setLineBreakInfo): 93 * rendering/RootInlineBox.h: 94 (WebCore::RootInlineBox::RootInlineBox): 95 * rendering/bidi.cpp: 96 (WebCore::BidiIterator::BidiIterator): 97 (WebCore::BidiState::deleteRuns): 98 (WebCore::operator==): 99 (WebCore::operator!=): 100 (WebCore::bidiNext): 101 (WebCore::bidiFirst): 102 (WebCore::BidiState::addRun): 103 (WebCore::appendRunsForObject): 104 (WebCore::BidiState::appendRun): 105 (WebCore::RenderBlock::constructLine): 106 (WebCore::RenderBlock::computeHorizontalPositionsForLine): 107 (WebCore::RenderBlock::computeVerticalPositionsForLine): 108 (WebCore::RenderBlock::bidiReorderLine): 109 (WebCore::buildCompactRuns): 110 (WebCore::RenderBlock::layoutInlineChildren): 111 (WebCore::RenderBlock::determineStartPosition): 112 (WebCore::RenderBlock::determineEndPosition): 113 (WebCore::RenderBlock::matchedEndLine): 114 (WebCore::RenderBlock::skipWhitespace): 115 * rendering/bidi.h: 116 (WebCore::BidiRun::BidiRun): 117 (WebCore::BidiRun::next): 118 1 119 2007-07-20 Darin Adler <darin@apple.com> 2 120 -
trunk/WebCore/WebCore.pro
r24477 r24485 587 587 platform/AtomicString.cpp \ 588 588 platform/Base64.cpp \ 589 platform/BidiContext.cpp \ 590 platform/BidiReorderCharacters.cpp \ 589 591 platform/ContextMenu.cpp \ 590 592 platform/CString.cpp \ -
trunk/WebCore/WebCore.vcproj/WebCore.vcproj
r24417 r24485 2888 2888 <File 2889 2889 RelativePath="..\platform\Base64.h" 2890 > 2891 </File> 2892 <File 2893 RelativePath="..\platform\BidiContext.cpp" 2894 > 2895 </File> 2896 <File 2897 RelativePath="..\platform\BidiContext.h" 2898 > 2899 </File> 2900 <File 2901 RelativePath="..\platform\BidiReorderCharacters.cpp" 2902 > 2903 </File> 2904 <File 2905 RelativePath="..\platform\BidiReorderCharacters.h" 2906 > 2907 </File> 2908 <File 2909 RelativePath="..\platform\BidiResolver.h" 2890 2910 > 2891 2911 </File> -
trunk/WebCore/WebCore.xcodeproj/project.pbxproj
r24465 r24485 280 280 37919C230B7D188600A56998 /* PositionIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 37919C210B7D188600A56998 /* PositionIterator.cpp */; }; 281 281 37919C240B7D188600A56998 /* PositionIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = 37919C220B7D188600A56998 /* PositionIterator.h */; settings = {ATTRIBUTES = (); }; }; 282 0F31CBF92B654730BA0535E8 /* BidiContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 514AF320BE854014A7DA49FB /* BidiContext.h */; settings = {ATTRIBUTES = (Private, ); }; }; 283 F971E27FD70F4382BC66D792 /* BidiContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A579C284B928484FB9A446BC /* BidiContext.cpp */; }; 282 284 448A29BF0A46D9CB0030759F /* JSHTMLOptionsCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 448A29BD0A46D9CB0030759F /* JSHTMLOptionsCollection.h */; }; 283 285 448A29C00A46D9CB0030759F /* JSHTMLOptionsCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 448A29BE0A46D9CB0030759F /* JSHTMLOptionsCollection.cpp */; }; … … 2725 2727 B2FA3E180AB75A6F000E5AC4 /* JSSVGZoomEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2FA3D300AB75A6F000E5AC4 /* JSSVGZoomEvent.cpp */; }; 2726 2728 B2FA3E190AB75A6F000E5AC4 /* JSSVGZoomEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = B2FA3D310AB75A6F000E5AC4 /* JSSVGZoomEvent.h */; }; 2729 B402007C0C4D217800210AA6 /* BidiReorderCharacters.h in Headers */ = {isa = PBXBuildFile; fileRef = B402007A0C4D217800210AA6 /* BidiReorderCharacters.h */; }; 2730 B402007D0C4D217800210AA6 /* BidiReorderCharacters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B402007B0C4D217800210AA6 /* BidiReorderCharacters.cpp */; }; 2731 B402FD0B0C4C9C3900210AA6 /* BidiResolver.h in Headers */ = {isa = PBXBuildFile; fileRef = B402FD090C4C9C3900210AA6 /* BidiResolver.h */; settings = {ATTRIBUTES = (Private, ); }; }; 2727 2732 BC066F6F09FEB2FA00C589A7 /* WebCoreTextRenderer.h in Headers */ = {isa = PBXBuildFile; fileRef = BC066F6C09FEB2FA00C589A7 /* WebCoreTextRenderer.h */; settings = {ATTRIBUTES = (Private, ); }; }; 2728 2733 BC06ED060BFD5BAE00856E9D /* JSHTMLTableSectionElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC06ED040BFD5BAE00856E9D /* JSHTMLTableSectionElement.cpp */; }; … … 2911 2916 BCEA4790097CAAC80094C9E4 /* CSSComputedStyleDeclaration.h in Headers */ = {isa = PBXBuildFile; fileRef = BCEA477D097CAAC80094C9E4 /* CSSComputedStyleDeclaration.h */; }; 2912 2917 BCEA4852097D93020094C9E4 /* bidi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCEA4813097D93020094C9E4 /* bidi.cpp */; }; 2913 BCEA4853097D93020094C9E4 /* bidi.h in Headers */ = {isa = PBXBuildFile; fileRef = BCEA4814097D93020094C9E4 /* bidi.h */; settings = {ATTRIBUTES = (Private, ); };};2918 BCEA4853097D93020094C9E4 /* bidi.h in Headers */ = {isa = PBXBuildFile; fileRef = BCEA4814097D93020094C9E4 /* bidi.h */; }; 2914 2919 BCEA4854097D93020094C9E4 /* break_lines.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCEA4815097D93020094C9E4 /* break_lines.cpp */; }; 2915 2920 BCEA4855097D93020094C9E4 /* break_lines.h in Headers */ = {isa = PBXBuildFile; fileRef = BCEA4816097D93020094C9E4 /* break_lines.h */; }; … … 3517 3522 37919C210B7D188600A56998 /* PositionIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PositionIterator.cpp; sourceTree = "<group>"; }; 3518 3523 37919C220B7D188600A56998 /* PositionIterator.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PositionIterator.h; sourceTree = "<group>"; }; 3524 514AF320BE854014A7DA49FB /* BidiContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BidiContext.h; sourceTree = "<group>"; }; 3525 A579C284B928484FB9A446BC /* BidiContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BidiContext.cpp; sourceTree = "<group>"; }; 3519 3526 448A29BD0A46D9CB0030759F /* JSHTMLOptionsCollection.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSHTMLOptionsCollection.h; sourceTree = "<group>"; }; 3520 3527 448A29BE0A46D9CB0030759F /* JSHTMLOptionsCollection.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLOptionsCollection.cpp; sourceTree = "<group>"; }; … … 6048 6055 B2FA3D300AB75A6F000E5AC4 /* JSSVGZoomEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSSVGZoomEvent.cpp; sourceTree = "<group>"; }; 6049 6056 B2FA3D310AB75A6F000E5AC4 /* JSSVGZoomEvent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSSVGZoomEvent.h; sourceTree = "<group>"; }; 6057 B402007A0C4D217800210AA6 /* BidiReorderCharacters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BidiReorderCharacters.h; sourceTree = "<group>"; }; 6058 B402007B0C4D217800210AA6 /* BidiReorderCharacters.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BidiReorderCharacters.cpp; sourceTree = "<group>"; }; 6059 B402FD090C4C9C3900210AA6 /* BidiResolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BidiResolver.h; sourceTree = "<group>"; }; 6050 6060 BC066F6C09FEB2FA00C589A7 /* WebCoreTextRenderer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = WebCoreTextRenderer.h; sourceTree = "<group>"; }; 6051 6061 BC06ED040BFD5BAE00856E9D /* JSHTMLTableSectionElement.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLTableSectionElement.cpp; sourceTree = "<group>"; }; … … 9508 9518 E11D51910B2E7A5F0056C188 /* Base64.h */, 9509 9519 E11D51920B2E7A5F0056C188 /* Base64.cpp */, 9520 514AF320BE854014A7DA49FB /* BidiContext.h */, 9521 A579C284B928484FB9A446BC /* BidiContext.cpp */, 9522 B402007A0C4D217800210AA6 /* BidiReorderCharacters.h */, 9523 B402007B0C4D217800210AA6 /* BidiReorderCharacters.cpp */, 9524 B402FD090C4C9C3900210AA6 /* BidiResolver.h */, 9510 9525 65F5382009B2B55700F3DC4A /* character-sets.txt */, 9511 9526 93C7B5F30B52D89100B5477E /* CharacterNames.h */, … … 11680 11695 BC772C470C4EB2C60083285F /* XMLHttpRequest.h in Headers */, 11681 11696 BC772C4F0C4EB3040083285F /* MIMETypeRegistry.h in Headers */, 11697 B402FD0B0C4C9C3900210AA6 /* BidiResolver.h in Headers */, 11698 B402007C0C4D217800210AA6 /* BidiReorderCharacters.h in Headers */, 11699 0F31CBF92B654730BA0535E8 /* BidiContext.h in Headers */, 11682 11700 ); 11683 11701 runOnlyForDeploymentPostprocessing = 0; … … 13115 13133 BC772C4E0C4EB3040083285F /* MIMETypeRegistry.cpp in Sources */, 13116 13134 BC772C5E0C4EB3440083285F /* MIMETypeRegistryMac.mm in Sources */, 13135 F971E27FD70F4382BC66D792 /* BidiContext.cpp in Sources */, 13136 B402007D0C4D217800210AA6 /* BidiReorderCharacters.cpp in Sources */, 13117 13137 ); 13118 13138 runOnlyForDeploymentPostprocessing = 0; -
trunk/WebCore/WebCoreSources.bkl
r24422 r24485 163 163 platform/AtomicString.cpp 164 164 platform/Base64.cpp 165 platform/BidiContext.cpp 166 platform/BidiReorderCharacters.cpp 165 167 platform/CString.cpp 166 168 platform/ContextMenu.cpp -
trunk/WebCore/platform/win/PopupMenuWin.cpp
r24481 r24485 22 22 #include "PopupMenu.h" 23 23 24 #include "BidiReorderCharacters.h" 24 25 #include "Document.h" 25 26 #include "FloatRect.h" … … 493 494 const UChar* string = itemText.characters(); 494 495 TextStyle textStyle(0, 0, 0, false, true); 495 RenderBlock::CharacterBuffer characterBuffer;496 CharacterBuffer characterBuffer; 496 497 497 498 if (clientStyle->direction() == RTL && clientStyle->unicodeBidi() == Override) … … 500 501 // If necessary, reorder characters by running the string through the bidi algorithm 501 502 characterBuffer.append(string, length); 502 RenderBlock::bidiReorderCharacters(client()->clientDocument(), clientStyle, characterBuffer);503 bidiReorderCharacters(characterBuffer, clientStyle->direction() == RTL, clientStyle->unicodeBidi() == Override, clientStyle->visuallyOrdered()); 503 504 string = characterBuffer.data(); 504 505 } -
trunk/WebCore/rendering/RenderBlock.h
r24255 r24485 32 32 namespace WebCore { 33 33 34 class BidiIterator; 35 class BidiRun; 34 36 class Position; 37 class RootInlineBox; 38 39 template <class Iterator, class Run> class BidiResolver; 40 typedef BidiResolver<BidiIterator, BidiRun> BidiState; 35 41 36 42 enum CaretType { CursorCaret, DragCaret }; … … 38 44 class RenderBlock : public RenderFlow { 39 45 public: 40 typedef Vector<UChar, 1024> CharacterBuffer;41 static void bidiReorderCharacters(Document*, RenderStyle*, CharacterBuffer&);42 43 46 RenderBlock(Node*); 44 47 virtual ~RenderBlock(); … … 122 125 123 126 // the implementation of the following functions is in bidi.cpp 124 void bidiReorderLine(const BidiIterator& start, const BidiIterator& end, BidiState& bidi);125 RootInlineBox* determineStartPosition(bool fullLayout, BidiIterator& start, BidiState& bidi);127 void bidiReorderLine(const BidiIterator& start, const BidiIterator& end, BidiState&); 128 RootInlineBox* determineStartPosition(bool fullLayout, BidiIterator& start, BidiState&); 126 129 RootInlineBox* determineEndPosition(RootInlineBox* startBox, BidiIterator& cleanLineStart, 127 BidiStatus& cleanLineBidiStatus, BidiContext*& cleanLineBidiContext,130 BidiStatus& cleanLineBidiStatus, 128 131 int& yPos); 129 bool matchedEndLine(const BidiIterator& start, const BidiStatus& status, BidiContext* context,130 const BidiIterator& endLineStart, const BidiStatus& endLineStatus, BidiContext* endLineContext,132 bool matchedEndLine(const BidiIterator& start, const BidiStatus& status, 133 const BidiIterator& endLineStart, const BidiStatus& endLineStatus, 131 134 RootInlineBox*& endLine, int& endYPos, int& repaintBottom, int& repaintTop); 132 135 bool generatesLineBoxesForInlineChild(RenderObject*); … … 135 138 RootInlineBox* constructLine(const BidiIterator& start, const BidiIterator& end); 136 139 InlineFlowBox* createLineBoxes(RenderObject*); 137 void computeHorizontalPositionsForLine(RootInlineBox*, BidiState&);140 void computeHorizontalPositionsForLine(RootInlineBox*, bool reachedEnd); 138 141 void computeVerticalPositionsForLine(RootInlineBox*); 139 142 void checkLinesForOverflow(); -
trunk/WebCore/rendering/RenderFileUploadControl.cpp
r24327 r24485 22 22 #include "RenderFileUploadControl.h" 23 23 24 #include "BidiReorderCharacters.h" 24 25 #include "FrameView.h" 25 26 #include "GraphicsContext.h" … … 178 179 const UChar* string = displayedFilename.characters(); 179 180 TextStyle textStyle(0, 0, 0, false, true); 180 RenderBlock::CharacterBuffer characterBuffer;181 CharacterBuffer characterBuffer; 181 182 182 183 if (style()->direction() == RTL && style()->unicodeBidi() == Override) … … 185 186 // If necessary, reorder characters by running the string through the bidi algorithm 186 187 characterBuffer.append(string, length); 187 RenderBlock::bidiReorderCharacters(document(), style(), characterBuffer);188 bidiReorderCharacters(characterBuffer, style()->direction() == RTL, style()->unicodeBidi() == Override, style()->visuallyOrdered()); 188 189 string = characterBuffer.data(); 189 190 } -
trunk/WebCore/rendering/RenderListBox.cpp
r24327 r24485 32 32 #include "RenderListBox.h" 33 33 34 #include "BidiReorderCharacters.h" 34 35 #include "Document.h" 35 36 #include "EventHandler.h" … … 332 333 const UChar* string = itemText.characters(); 333 334 TextStyle textStyle(0, 0, 0, false, true); 334 RenderBlock::CharacterBuffer characterBuffer;335 CharacterBuffer characterBuffer; 335 336 336 337 if (itemStyle->direction() == RTL && itemStyle->unicodeBidi() == Override) … … 339 340 // If necessary, reorder characters by running the string through the bidi algorithm 340 341 characterBuffer.append(string, length); 341 RenderBlock::bidiReorderCharacters(document(), itemStyle, characterBuffer);342 bidiReorderCharacters(characterBuffer, itemStyle->direction() == RTL, itemStyle->unicodeBidi() == Override, itemStyle->visuallyOrdered()); 342 343 string = characterBuffer.data(); 343 344 } -
trunk/WebCore/rendering/RootInlineBox.cpp
r22037 r24485 23 23 #include "RootInlineBox.h" 24 24 25 #include "BidiResolver.h" 25 26 #include "Document.h" 26 27 #include "EllipsisBox.h" … … 195 196 { 196 197 if (box->object() == m_lineBreakObj) 197 setLineBreakInfo(0, 0, 0, 0);198 setLineBreakInfo(0, 0, BidiStatus()); 198 199 199 200 for (RootInlineBox* prev = prevRootBox(); prev && prev->lineBreakObj() == box->object(); prev = prev->prevRootBox()) { 200 prev->setLineBreakInfo(0, 0, 0, 0);201 prev->setLineBreakInfo(0, 0, BidiStatus()); 201 202 prev->markDirty(); 202 203 } … … 354 355 } 355 356 356 void RootInlineBox::setLineBreakInfo(RenderObject* obj, unsigned breakPos, BidiStatus* status, BidiContext* context) 357 BidiStatus RootInlineBox::lineBreakBidiStatus() const 358 { 359 return BidiStatus(m_lineBreakBidiStatusEor, m_lineBreakBidiStatusLastStrong, m_lineBreakBidiStatusLast, m_lineBreakContext); 360 } 361 362 void RootInlineBox::setLineBreakInfo(RenderObject* obj, unsigned breakPos, const BidiStatus& status) 357 363 { 358 364 m_lineBreakObj = obj; 359 365 m_lineBreakPos = breakPos; 360 m_lineBreakContext = context; 361 if (status) { 362 m_lineBreakBidiStatusEor = status->eor; 363 m_lineBreakBidiStatusLastStrong = status->lastStrong; 364 m_lineBreakBidiStatusLast = status->last; 365 } 366 m_lineBreakBidiStatusEor = status.eor; 367 m_lineBreakBidiStatusLastStrong = status.lastStrong; 368 m_lineBreakBidiStatusLast = status.last; 369 m_lineBreakContext = status.context; 366 370 } 367 371 -
trunk/WebCore/rendering/RootInlineBox.h
r22037 r24485 24 24 #define RootInlineBox_h 25 25 26 #include " bidi.h"26 #include "BidiContext.h" 27 27 #include "InlineFlowBox.h" 28 28 29 29 namespace WebCore { 30 30 31 class BidiStatus; 31 32 class EllipsisBox; 32 33 class HitTestResult; … … 40 41 , m_lineBreakObj(0) 41 42 , m_lineBreakPos(0) 42 , m_lineBreakContext(0)43 43 { 44 44 } … … 65 65 66 66 RenderObject* lineBreakObj() const { return m_lineBreakObj; } 67 BidiStatus lineBreakBidiStatus() const { 68 BidiStatus status; 69 status.eor = m_lineBreakBidiStatusEor; 70 status.lastStrong = m_lineBreakBidiStatusLastStrong; 71 status.last = m_lineBreakBidiStatusLast; 72 return status; 73 } 74 BidiContext* lineBreakBidiContext() const { return m_lineBreakContext.get(); } 75 void setLineBreakInfo(RenderObject*, unsigned breakPos, BidiStatus*, BidiContext*); 67 BidiStatus lineBreakBidiStatus() const; 68 void setLineBreakInfo(RenderObject*, unsigned breakPos, const BidiStatus&); 76 69 77 70 unsigned lineBreakPos() const { return m_lineBreakPos; } … … 159 152 RenderObject* m_lineBreakObj; 160 153 unsigned m_lineBreakPos; 161 162 154 RefPtr<BidiContext> m_lineBreakContext; 163 155 -
trunk/WebCore/rendering/bidi.cpp
r24278 r24485 46 46 const unsigned cMaxLineDepth = 200; 47 47 48 // an iterator which traverses all the objects within a block 49 struct BidiIterator { 50 BidiIterator() : block(0), obj(0), pos(0) {} 51 BidiIterator(RenderBlock* b, RenderObject* o, unsigned int p) 52 : block(b), obj(o), pos(p) {} 53 54 void increment(BidiState& state); 48 class BidiIterator { 49 public: 50 BidiIterator() 51 : block(0) 52 , obj(0) 53 , pos(0) 54 { 55 } 56 57 BidiIterator(RenderBlock* b, RenderObject* o, unsigned p) 58 : block(b) 59 , obj(o) 60 , pos(p) 61 { 62 } 63 64 void increment(BidiResolver<BidiIterator, BidiRun>& state); 55 65 bool atEnd() const; 56 66 57 67 UChar current() const; 58 Direction direction() const;68 WTF::Unicode::Direction direction() const; 59 69 60 70 RenderBlock* block; … … 62 72 unsigned int pos; 63 73 }; 64 65 struct BidiState {66 BidiState() : context(0), dir(OtherNeutral), adjustEmbedding(false), reachedEndOfLine(false) {}67 68 BidiIterator sor;69 BidiIterator eor;70 BidiIterator last;71 BidiIterator current;72 RefPtr<BidiContext> context;73 BidiStatus status;74 Direction dir;75 bool adjustEmbedding;76 BidiIterator endOfLine;77 bool reachedEndOfLine;78 BidiIterator lastBeforeET;79 };80 81 inline bool operator==(const BidiStatus& status1, const BidiStatus& status2)82 {83 return status1.eor == status2.eor && status1.last == status2.last && status1.lastStrong == status2.lastStrong;84 }85 86 inline bool operator!=(const BidiStatus& status1, const BidiStatus& status2)87 {88 return !(status1 == status2);89 }90 74 91 75 // Used to track a list of chained bidi runs. … … 94 78 static BidiRun* sLogicallyLastBidiRun; 95 79 static int sBidiRunCount; 96 static BidiRun* sCompactFirstBidiRun;97 static BidiRun* sCompactLastBidiRun;98 static int sCompactBidiRunCount;99 static bool sBuildingCompactRuns;100 80 101 81 // Midpoint globals. The goal is not to do any allocation when dealing with … … 109 89 static bool isLineEmpty = true; 110 90 static bool previousLineBrokeCleanly = true; 111 static bool emptyRun = true;112 91 static int numSpaces; 113 114 static void embed(Direction, BidiState&);115 static void appendRun(BidiState&);116 static void deleteBidiRuns(RenderArena*);117 118 void RenderBlock::bidiReorderCharacters(Document* document, RenderStyle* style, CharacterBuffer& characterBuffer)119 {120 unsigned bufferLength = characterBuffer.size();121 // Create a local copy of the buffer.122 String string(characterBuffer.data(), bufferLength);123 124 // Create anonymous RenderBlock125 RenderStyle* blockStyle = new (document->renderArena()) RenderStyle();126 blockStyle->inheritFrom(style);127 blockStyle->setDisplay(BLOCK);128 blockStyle->setWhiteSpace(PRE);129 RenderBlock* block = new (document->renderArena()) RenderBlock(document);130 block->setStyle(blockStyle);131 132 // Create RenderText133 RenderText* text = new (document->renderArena()) RenderText(document, string.impl());134 text->setStyle(blockStyle);135 block->appendChildNode(text, false);136 137 // Call bidiReorderLine138 BidiState bidi;139 PassRefPtr<BidiContext> startEmbed;140 if (style->direction() == LTR) {141 startEmbed = new BidiContext(0, LeftToRight, NULL, style->unicodeBidi() == Override);142 bidi.status.eor = LeftToRight;143 } else {144 startEmbed = new BidiContext(1, RightToLeft, NULL, style->unicodeBidi() == Override);145 bidi.status.eor = RightToLeft;146 }147 bidi.status.lastStrong = startEmbed->dir();148 bidi.status.last = startEmbed->dir();149 bidi.status.eor = startEmbed->dir();150 bidi.context = startEmbed;151 bidi.dir = OtherNeutral;152 betweenMidpoints = false;153 154 block->bidiReorderLine(BidiIterator(block, text, 0), BidiIterator(block, text, bufferLength), bidi);155 156 // Fill the characterBuffer.157 int index = 0;158 BidiRun* r = sFirstBidiRun;159 while (r) {160 bool reversed = r->reversed(style->visuallyOrdered());161 // If there's only one run, and it doesn't need to be reversed, return early162 if (sBidiRunCount == 1 && !reversed)163 break;164 for (int i = r->start; i < r->stop; ++i) {165 if (reversed)166 characterBuffer[index] = string[r->stop + r->start - i - 1];167 else168 characterBuffer[index] = string[i];169 ++index;170 }171 r = r->nextRun;172 }173 174 // Tear down temporary RenderBlock, RenderText, and BidiRuns175 block->removeChildNode(text, false);176 text->destroy();177 block->destroy();178 deleteBidiRuns(document->renderArena());179 }180 92 181 93 static int getBPMWidth(int childValue, Length cssUnit) … … 267 179 } 268 180 269 static void deleteBidiRuns(RenderArena* arena) 270 { 271 emptyRun = true; 272 if (! sFirstBidiRun)181 template <> 182 void BidiState::deleteRuns() 183 { 184 if (!m_firstRun) 273 185 return; 274 186 275 BidiRun* curr = sFirstBidiRun;187 BidiRun* curr = m_firstRun; 276 188 while (curr) { 277 BidiRun* s = curr->next Run;278 curr->destroy( arena);189 BidiRun* s = curr->next(); 190 curr->destroy(curr->obj->renderArena()); 279 191 curr = s; 280 192 } 281 282 sFirstBidiRun = 0;283 sLastBidiRun = 0;284 sBidiRunCount = 0;193 194 m_firstRun = 0; 195 m_lastRun = 0; 196 m_runCount = 0; 285 197 } 286 198 287 199 // --------------------------------------------------------------------- 288 200 289 /* a small helper class used internally to resolve Bidi embedding levels.290 Each line of text caches the embedding level at the start of the line for faster291 relayouting292 */293 BidiContext::BidiContext(unsigned char l, Direction e, BidiContext *p, bool o)294 : level(l), override(o), m_dir(e)295 {296 parent = p;297 if (p)298 p->ref();299 count = 0;300 }301 302 BidiContext::~BidiContext()303 {304 if (parent)305 parent->deref();306 }307 308 void BidiContext::ref() const309 {310 count++;311 }312 313 void BidiContext::deref() const314 {315 count--;316 if (count <= 0)317 delete this;318 }319 320 bool operator==(const BidiContext& c1, const BidiContext& c2)321 {322 if (&c1 == &c2)323 return true;324 if (c1.level != c2.level || c1.override != c2.override || c1.dir() != c2.dir())325 return false;326 if (!c1.parent)327 return !c2.parent;328 return c2.parent && *c1.parent == *c2.parent;329 }330 331 inline bool operator!=(const BidiContext& c1, const BidiContext& c2)332 {333 return !(c1 == c2);334 }335 336 // ---------------------------------------------------------------------337 338 201 inline bool operator==(const BidiIterator& it1, const BidiIterator& it2) 339 202 { 340 if (it1.pos != it2.pos) 341 return false; 342 if (it1.obj != it2.obj) 343 return false; 344 return true; 203 return it1.pos == it2.pos && it1.obj == it2.obj; 345 204 } 346 205 347 206 inline bool operator!=(const BidiIterator& it1, const BidiIterator& it2) 348 207 { 349 if (it1.pos != it2.pos) 350 return true; 351 if (it1.obj != it2.obj) 352 return true; 353 return false; 208 return it1.pos != it2.pos || it1.obj != it2.obj; 354 209 } 355 210 … … 366 221 if (!oldEndOfInline && !current->isFloating() && !current->isReplaced() && !current->isPositioned()) { 367 222 next = current->firstChild(); 368 if (next && bidi.adjustEmbedding && next->isInlineFlow()) {223 if (next && bidi.adjustEmbedding() && next->isInlineFlow()) { 369 224 EUnicodeBidi ub = next->style()->unicodeBidi(); 370 225 if (ub != UBNormal) { … … 373 228 ? (dir == RTL ? RightToLeftEmbedding : LeftToRightEmbedding) 374 229 : (dir == RTL ? RightToLeftOverride : LeftToRightOverride)); 375 embed(d, bidi);230 bidi.embed(d); 376 231 } 377 232 } … … 387 242 388 243 while (current && current != block) { 389 if (bidi.adjustEmbedding && current->isInlineFlow() && current->style()->unicodeBidi() != UBNormal)390 embed(PopDirectionalFormat, bidi);244 if (bidi.adjustEmbedding() && current->isInlineFlow() && current->style()->unicodeBidi() != UBNormal) 245 bidi.embed(PopDirectionalFormat); 391 246 392 247 next = current->nextSibling(); 393 248 if (next) { 394 if (bidi.adjustEmbedding && next->isInlineFlow()) {249 if (bidi.adjustEmbedding() && next->isInlineFlow()) { 395 250 EUnicodeBidi ub = next->style()->unicodeBidi(); 396 251 if (ub != UBNormal) { … … 399 254 ? (dir == RTL ? RightToLeftEmbedding: LeftToRightEmbedding) 400 255 : (dir == RTL ? RightToLeftOverride : LeftToRightOverride)); 401 embed(d, bidi);256 bidi.embed(d); 402 257 } 403 258 } … … 434 289 RenderObject* o = block->firstChild(); 435 290 if (o->isInlineFlow()) { 436 if (bidi.adjustEmbedding ) {291 if (bidi.adjustEmbedding()) { 437 292 EUnicodeBidi ub = o->style()->unicodeBidi(); 438 293 if (ub != UBNormal) { … … 441 296 ? (dir == RTL ? RightToLeftEmbedding : LeftToRightEmbedding) 442 297 : (dir == RTL ? RightToLeftOverride : LeftToRightOverride)); 443 embed(d, bidi);298 bidi.embed(d); 444 299 } 445 300 } … … 504 359 // ------------------------------------------------------------------------------------------------- 505 360 506 static void addRun(BidiRun* bidiRun) 507 { 508 if (!sFirstBidiRun) 509 sFirstBidiRun = sLastBidiRun = bidiRun; 510 else { 511 sLastBidiRun->nextRun = bidiRun; 512 sLastBidiRun = bidiRun; 513 } 514 sBidiRunCount++; 515 bidiRun->compact = sBuildingCompactRuns; 361 template <> 362 inline void BidiState::addRun(BidiRun* bidiRun) 363 { 364 if (!m_firstRun) 365 m_firstRun = bidiRun; 366 else 367 m_lastRun->m_next = bidiRun; 368 m_lastRun = bidiRun; 369 m_runCount++; 370 371 sLogicallyLastBidiRun = bidiRun; 516 372 517 373 // Compute the number of spaces in this run, … … 519 375 RenderText* text = static_cast<RenderText*>(bidiRun->obj); 520 376 if (text->characters()) { 521 for (int i = bidiRun-> start; i < bidiRun->stop; i++) {377 for (int i = bidiRun->m_start; i < bidiRun->m_stop; i++) { 522 378 UChar c = text->characters()[i]; 523 379 if (c == ' ' || c == '\n' || c == '\t') … … 526 382 } 527 383 } 528 }529 530 static void reverseRuns(int start, int end)531 {532 if (start >= end)533 return;534 535 ASSERT(start >= 0 && end < sBidiRunCount);536 537 // Get the item before the start of the runs to reverse and put it in538 // |beforeStart|. |curr| should point to the first run to reverse.539 BidiRun* curr = sFirstBidiRun;540 BidiRun* beforeStart = 0;541 int i = 0;542 while (i < start) {543 i++;544 beforeStart = curr;545 curr = curr->nextRun;546 }547 548 BidiRun* startRun = curr;549 while (i < end) {550 i++;551 curr = curr->nextRun;552 }553 BidiRun* endRun = curr;554 BidiRun* afterEnd = curr->nextRun;555 556 i = start;557 curr = startRun;558 BidiRun* newNext = afterEnd;559 while (i <= end) {560 // Do the reversal.561 BidiRun* next = curr->nextRun;562 curr->nextRun = newNext;563 newNext = curr;564 curr = next;565 i++;566 }567 568 // Now hook up beforeStart and afterEnd to the newStart and newEnd.569 if (beforeStart)570 beforeStart->nextRun = endRun;571 else572 sFirstBidiRun = endRun;573 574 startRun->nextRun = afterEnd;575 if (!afterEnd)576 sLastBidiRun = startRun;577 384 } 578 385 … … 637 444 } 638 445 639 static void appendRunsForObject(int start, int end, RenderObject* obj, BidiState &bidi)446 static void appendRunsForObject(int start, int end, RenderObject* obj, BidiState& bidi) 640 447 { 641 448 if (start > end || obj->isFloating() || … … 660 467 else { 661 468 if (!smidpoints || !haveNextMidpoint || (obj != nextMidpoint.obj)) { 662 addRun(new (obj->renderArena()) BidiRun(start, end, obj, bidi.context.get(), bidi.dir));469 bidi.addRun(new (obj->renderArena()) BidiRun(start, end, obj, bidi.context(), bidi.dir())); 663 470 return; 664 471 } … … 671 478 if (nextMidpoint.pos != UINT_MAX) { // UINT_MAX means stop at the object and don't include any of it. 672 479 if (int(nextMidpoint.pos+1) > start) 673 addRun(new (obj->renderArena())674 BidiRun(start, nextMidpoint.pos+1, obj, bidi.context .get(), bidi.dir));480 bidi.addRun(new (obj->renderArena()) 481 BidiRun(start, nextMidpoint.pos+1, obj, bidi.context(), bidi.dir())); 675 482 return appendRunsForObject(nextMidpoint.pos+1, end, obj, bidi); 676 483 } 677 484 } 678 485 else 679 addRun(new (obj->renderArena()) BidiRun(start, end, obj, bidi.context.get(), bidi.dir)); 680 } 681 } 682 683 static void appendRun(BidiState &bidi) 684 { 685 if (emptyRun || !bidi.eor.obj) 486 bidi.addRun(new (obj->renderArena()) BidiRun(start, end, obj, bidi.context(), bidi.dir())); 487 } 488 } 489 490 template <> 491 void BidiState::appendRun() 492 { 493 if (emptyRun || eor.atEnd()) 686 494 return; 687 #if defined(BIDI_DEBUG) && BIDI_DEBUG > 1 688 kdDebug(6041) << "appendRun: dir="<<(int)dir<<endl; 689 #endif 690 691 bool b = bidi.adjustEmbedding; 692 bidi.adjustEmbedding = false; 693 694 int start = bidi.sor.pos; 695 RenderObject *obj = bidi.sor.obj; 696 while (obj && obj != bidi.eor.obj && obj != bidi.endOfLine.obj) { 697 appendRunsForObject(start, obj->length(), obj, bidi); 495 bool b = m_adjustEmbedding; 496 m_adjustEmbedding = false; 497 498 int start = sor.pos; 499 RenderObject *obj = sor.obj; 500 while (obj && obj != eor.obj && obj != endOfLine.obj) { 501 appendRunsForObject(start, obj->length(), obj, *this); 698 502 start = 0; 699 obj = bidiNext( bidi.sor.block, obj, bidi);503 obj = bidiNext(sor.block, obj, *this); 700 504 } 701 505 if (obj) { 702 unsigned pos = obj == bidi.eor.obj ? bidi.eor.pos : UINT_MAX;703 if (obj == bidi.endOfLine.obj && bidi.endOfLine.pos <= pos) {704 bidi.reachedEndOfLine = true;705 pos = bidi.endOfLine.pos;506 unsigned pos = obj == eor.obj ? eor.pos : UINT_MAX; 507 if (obj == endOfLine.obj && endOfLine.pos <= pos) { 508 reachedEndOfLine = true; 509 pos = endOfLine.pos; 706 510 } 707 511 // It's OK to add runs for zero-length RenderObjects, just don't make the run larger than it should be 708 512 int end = obj->length() ? pos+1 : 0; 709 appendRunsForObject(start, end, obj, bidi); 710 } 711 712 bidi.eor.increment(bidi); 713 bidi.sor = bidi.eor; 714 bidi.dir = OtherNeutral; 715 bidi.status.eor = OtherNeutral; 716 bidi.adjustEmbedding = b; 717 } 718 719 static void embed(Direction d, BidiState& bidi) 720 { 721 bool b = bidi.adjustEmbedding; 722 bidi.adjustEmbedding = false; 723 if (d == PopDirectionalFormat) { 724 BidiContext *c = bidi.context->parent; 725 if (c) { 726 if (!emptyRun && bidi.eor != bidi.last) { 727 ASSERT(bidi.status.eor != OtherNeutral); 728 // bidi.sor ... bidi.eor ... bidi.last eor; need to append the bidi.sor-bidi.eor run or extend it through bidi.last 729 ASSERT(bidi.status.last == EuropeanNumberSeparator 730 || bidi.status.last == EuropeanNumberTerminator 731 || bidi.status.last == CommonNumberSeparator 732 || bidi.status.last == BoundaryNeutral 733 || bidi.status.last == BlockSeparator 734 || bidi.status.last == SegmentSeparator 735 || bidi.status.last == WhiteSpaceNeutral 736 || bidi.status.last == OtherNeutral); 737 if (bidi.dir == OtherNeutral) 738 bidi.dir = bidi.context->dir(); 739 if (bidi.context->dir() == LeftToRight) { 740 // bidi.sor ... bidi.eor ... bidi.last L 741 if (bidi.status.eor == EuropeanNumber) { 742 if (bidi.status.lastStrong != LeftToRight) { 743 bidi.dir = EuropeanNumber; 744 appendRun(bidi); 745 } 746 } else if (bidi.status.eor == ArabicNumber) { 747 bidi.dir = ArabicNumber; 748 appendRun(bidi); 749 } else if (bidi.status.eor != LeftToRight) 750 appendRun(bidi); 751 } else if (bidi.status.eor != RightToLeft && bidi.status.eor != RightToLeftArabic) 752 appendRun(bidi); 753 bidi.eor = bidi.last; 754 } 755 appendRun(bidi); 756 emptyRun = true; 757 // sor for the new run is determined by the higher level (rule X10) 758 bidi.status.last = bidi.context->dir(); 759 bidi.status.lastStrong = bidi.context->dir(); 760 bidi.context = c; 761 bidi.status.eor = bidi.context->dir(); 762 bidi.eor.obj = 0; 763 } 764 } else { 765 Direction runDir; 766 if (d == RightToLeftEmbedding || d == RightToLeftOverride) 767 runDir = RightToLeft; 768 else 769 runDir = LeftToRight; 770 bool override = d == LeftToRightOverride || d == RightToLeftOverride; 771 772 unsigned char level = bidi.context->level; 773 if (runDir == RightToLeft) { 774 if (level%2) // we have an odd level 775 level += 2; 776 else 777 level++; 778 } else { 779 if (level%2) // we have an odd level 780 level++; 781 else 782 level += 2; 783 } 784 785 if (level < 61) { 786 if (!emptyRun && bidi.eor != bidi.last) { 787 ASSERT(bidi.status.eor != OtherNeutral); 788 // bidi.sor ... bidi.eor ... bidi.last eor; need to append the bidi.sor-bidi.eor run or extend it through bidi.last 789 ASSERT(bidi.status.last == EuropeanNumberSeparator 790 || bidi.status.last == EuropeanNumberTerminator 791 || bidi.status.last == CommonNumberSeparator 792 || bidi.status.last == BoundaryNeutral 793 || bidi.status.last == BlockSeparator 794 || bidi.status.last == SegmentSeparator 795 || bidi.status.last == WhiteSpaceNeutral 796 || bidi.status.last == OtherNeutral); 797 if (bidi.dir == OtherNeutral) 798 bidi.dir = runDir; 799 if (runDir == LeftToRight) { 800 // bidi.sor ... bidi.eor ... bidi.last L 801 if (bidi.status.eor == EuropeanNumber) { 802 if (bidi.status.lastStrong != LeftToRight) { 803 bidi.dir = EuropeanNumber; 804 appendRun(bidi); 805 if (bidi.context->dir() != LeftToRight) 806 bidi.dir = RightToLeft; 807 } 808 } else if (bidi.status.eor == ArabicNumber) { 809 bidi.dir = ArabicNumber; 810 appendRun(bidi); 811 if (bidi.context->dir() != LeftToRight) { 812 bidi.eor = bidi.last; 813 bidi.dir = RightToLeft; 814 appendRun(bidi); 815 } 816 } else if (bidi.status.eor != LeftToRight) { 817 if (bidi.context->dir() == LeftToRight || bidi.status.lastStrong == LeftToRight) 818 appendRun(bidi); 819 else 820 bidi.dir = RightToLeft; 821 } 822 } else if (bidi.status.eor != RightToLeft && bidi.status.eor != RightToLeftArabic) { 823 // bidi.sor ... bidi.eor ... bidi.last R; bidi.eor=L/EN/AN; EN,AN behave like R (rule N1) 824 if (bidi.context->dir() == RightToLeft || bidi.status.lastStrong == RightToLeft || bidi.status.lastStrong == RightToLeftArabic) 825 appendRun(bidi); 826 else 827 bidi.dir = LeftToRight; 828 } 829 bidi.eor = bidi.last; 830 } 831 appendRun(bidi); 832 emptyRun = true; 833 bidi.context = new BidiContext(level, runDir, bidi.context.get(), override); 834 bidi.status.last = runDir; 835 bidi.status.lastStrong = runDir; 836 bidi.status.eor = runDir; 837 bidi.eor.obj = 0; 838 } 839 } 840 bidi.adjustEmbedding = b; 513 appendRunsForObject(start, end, obj, *this); 514 } 515 516 eor.increment(*this); 517 sor = eor; 518 m_direction = OtherNeutral; 519 m_status.eor = OtherNeutral; 520 m_adjustEmbedding = b; 841 521 } 842 522 … … 901 581 902 582 InlineFlowBox* parentBox = 0; 903 for (BidiRun* r = sFirstBidiRun; r; r = r->next Run) {583 for (BidiRun* r = sFirstBidiRun; r; r = r->next()) { 904 584 // Create a box for our object. 905 585 bool isOnlyRun = (sBidiRunCount == 1); … … 920 600 if (r->box->isInlineTextBox()) { 921 601 InlineTextBox *text = static_cast<InlineTextBox*>(r->box); 922 text->setStart(r-> start);923 text->setLen(r-> stop - r->start);602 text->setStart(r->m_start); 603 text->setLen(r->m_stop - r->m_start); 924 604 bool visuallyOrdered = r->obj->style()->visuallyOrdered(); 925 605 text->m_reversed = r->reversed(visuallyOrdered); … … 950 630 } 951 631 952 void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, BidiState& bidi)632 void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, bool reachedEnd) 953 633 { 954 634 // First determine our total width. … … 957 637 BidiRun* r = 0; 958 638 bool needsWordSpacing = false; 959 for (r = sFirstBidiRun; r; r = r->next Run) {639 for (r = sFirstBidiRun; r; r = r->next()) { 960 640 if (!r->box || r->obj->isPositioned() || r->box->isLineBreak()) 961 641 continue; // Positioned objects are only participating to figure out their … … 964 644 if (r->obj->isText()) { 965 645 RenderText* rt = static_cast<RenderText*>(r->obj); 966 int textWidth = rt->width(r-> start, r->stop-r->start, totWidth, m_firstLine);646 int textWidth = rt->width(r->m_start, r->m_stop - r->m_start, totWidth, m_firstLine); 967 647 int effectiveWidth = textWidth; 968 648 int rtLength = rt->textLength(); 969 649 if (rtLength != 0) { 970 if ( r->start == 0 && needsWordSpacing && DeprecatedChar(rt->characters()[r->start]).isSpace())650 if (!r->m_start && needsWordSpacing && DeprecatedChar(rt->characters()[r->m_start]).isSpace()) 971 651 effectiveWidth += rt->style(m_firstLine)->font().wordSpacing(); 972 needsWordSpacing = !DeprecatedChar(rt->characters()[r-> stop-1]).isSpace() && r->stop == rtLength;652 needsWordSpacing = !DeprecatedChar(rt->characters()[r->m_stop - 1]).isSpace() && r->m_stop == rtLength; 973 653 } 974 654 r->box->setWidth(textWidth); … … 1007 687 break; 1008 688 case JUSTIFY: 1009 if (numSpaces != 0 && ! bidi.current.atEnd()&& !lineBox->endsWithBreak())689 if (numSpaces != 0 && !reachedEnd && !lineBox->endsWithBreak()) 1010 690 break; 1011 691 // fall through … … 1033 713 1034 714 if (numSpaces > 0) { 1035 for (r = sFirstBidiRun; r; r = r->next Run) {715 for (r = sFirstBidiRun; r; r = r->next()) { 1036 716 if (!r->box) continue; 1037 717 … … 1040 720 // get the number of spaces in the run 1041 721 int spaces = 0; 1042 for ( int i = r->start; i < r->stop; i++) {722 for (int i = r->m_start; i < r->m_stop; i++) { 1043 723 UChar c = static_cast<RenderText*>(r->obj)->characters()[i]; 1044 724 if (c == ' ' || c == '\n' || c == '\t') … … 1079 759 1080 760 // Now make sure we place replaced render objects correctly. 1081 for (BidiRun* r = sFirstBidiRun; r; r = r->next Run) {761 for (BidiRun* r = sFirstBidiRun; r; r = r->next()) { 1082 762 if (!r->box) 1083 763 continue; // Skip runs with no line boxes. … … 1103 783 } 1104 784 1105 sFirstBidiRun = 0;1106 sLastBidiRun = 0;1107 sBidiRunCount = 0;1108 1109 ASSERT(bidi.dir == OtherNeutral);1110 1111 emptyRun = true;1112 1113 bidi.eor.obj = 0;1114 1115 785 numSpaces = 0; 1116 786 1117 bidi.current = start; 1118 bidi.last = bidi.current; 1119 bool pastEnd = false; 1120 BidiState stateAtEnd; 1121 1122 while (true) { 1123 Direction dirCurrent; 1124 if (pastEnd && (previousLineBrokeCleanly || bidi.current.atEnd())) { 1125 BidiContext *c = bidi.context.get(); 1126 while (c->parent) 1127 c = c->parent; 1128 dirCurrent = c->dir(); 1129 if (previousLineBrokeCleanly) { 1130 // A deviation from the Unicode Bidi Algorithm in order to match 1131 // Mac OS X text and WinIE: a hard line break resets bidi state. 1132 stateAtEnd.context = c; 1133 stateAtEnd.status.eor = dirCurrent; 1134 stateAtEnd.status.last = dirCurrent; 1135 stateAtEnd.status.lastStrong = dirCurrent; 1136 } 1137 } else { 1138 dirCurrent = bidi.current.direction(); 1139 if (bidi.context->override 1140 && dirCurrent != RightToLeftEmbedding 1141 && dirCurrent != LeftToRightEmbedding 1142 && dirCurrent != RightToLeftOverride 1143 && dirCurrent != LeftToRightOverride 1144 && dirCurrent != PopDirectionalFormat) 1145 dirCurrent = bidi.context->dir(); 1146 else if (dirCurrent == NonSpacingMark) 1147 dirCurrent = bidi.status.last; 1148 } 1149 1150 ASSERT(bidi.status.eor != OtherNeutral); 1151 switch (dirCurrent) { 1152 1153 // embedding and overrides (X1-X9 in the Bidi specs) 1154 case RightToLeftEmbedding: 1155 case LeftToRightEmbedding: 1156 case RightToLeftOverride: 1157 case LeftToRightOverride: 1158 case PopDirectionalFormat: 1159 embed(dirCurrent, bidi); 1160 break; 1161 1162 // strong types 1163 case LeftToRight: 1164 switch(bidi.status.last) { 1165 case RightToLeft: 1166 case RightToLeftArabic: 1167 case EuropeanNumber: 1168 case ArabicNumber: 1169 if (bidi.status.last != EuropeanNumber || bidi.status.lastStrong != LeftToRight) 1170 appendRun(bidi); 1171 break; 1172 case LeftToRight: 1173 break; 1174 case EuropeanNumberSeparator: 1175 case EuropeanNumberTerminator: 1176 case CommonNumberSeparator: 1177 case BoundaryNeutral: 1178 case BlockSeparator: 1179 case SegmentSeparator: 1180 case WhiteSpaceNeutral: 1181 case OtherNeutral: 1182 if (bidi.status.eor == EuropeanNumber) { 1183 if (bidi.status.lastStrong != LeftToRight) { 1184 // the numbers need to be on a higher embedding level, so let's close that run 1185 bidi.dir = EuropeanNumber; 1186 appendRun(bidi); 1187 if (bidi.context->dir() != LeftToRight) { 1188 // the neutrals take the embedding direction, which is R 1189 bidi.eor = bidi.last; 1190 bidi.dir = RightToLeft; 1191 appendRun(bidi); 1192 } 1193 } 1194 } else if (bidi.status.eor == ArabicNumber) { 1195 // Arabic numbers are always on a higher embedding level, so let's close that run 1196 bidi.dir = ArabicNumber; 1197 appendRun(bidi); 1198 if (bidi.context->dir() != LeftToRight) { 1199 // the neutrals take the embedding direction, which is R 1200 bidi.eor = bidi.last; 1201 bidi.dir = RightToLeft; 1202 appendRun(bidi); 1203 } 1204 } else if(bidi.status.eor != LeftToRight) { 1205 //last stuff takes embedding dir 1206 if (bidi.context->dir() != LeftToRight && bidi.status.lastStrong != LeftToRight) { 1207 bidi.eor = bidi.last; 1208 bidi.dir = RightToLeft; 1209 } 1210 appendRun(bidi); 1211 } 1212 default: 1213 break; 1214 } 1215 bidi.eor = bidi.current; 1216 bidi.status.eor = LeftToRight; 1217 bidi.status.lastStrong = LeftToRight; 1218 bidi.dir = LeftToRight; 1219 break; 1220 case RightToLeftArabic: 1221 case RightToLeft: 1222 switch (bidi.status.last) { 1223 case LeftToRight: 1224 case EuropeanNumber: 1225 case ArabicNumber: 1226 appendRun(bidi); 1227 case RightToLeft: 1228 case RightToLeftArabic: 1229 break; 1230 case EuropeanNumberSeparator: 1231 case EuropeanNumberTerminator: 1232 case CommonNumberSeparator: 1233 case BoundaryNeutral: 1234 case BlockSeparator: 1235 case SegmentSeparator: 1236 case WhiteSpaceNeutral: 1237 case OtherNeutral: 1238 if (bidi.status.eor != RightToLeft && bidi.status.eor != RightToLeftArabic) { 1239 //last stuff takes embedding dir 1240 if (bidi.context->dir() != RightToLeft && bidi.status.lastStrong != RightToLeft 1241 && bidi.status.lastStrong != RightToLeftArabic) { 1242 bidi.eor = bidi.last; 1243 bidi.dir = LeftToRight; 1244 } 1245 appendRun(bidi); 1246 } 1247 default: 1248 break; 1249 } 1250 bidi.eor = bidi.current; 1251 bidi.status.eor = RightToLeft; 1252 bidi.status.lastStrong = dirCurrent; 1253 bidi.dir = RightToLeft; 1254 break; 1255 1256 // weak types: 1257 1258 case EuropeanNumber: 1259 if (bidi.status.lastStrong != RightToLeftArabic) { 1260 // if last strong was AL change EN to AN 1261 switch (bidi.status.last) { 1262 case EuropeanNumber: 1263 case LeftToRight: 1264 break; 1265 case RightToLeft: 1266 case RightToLeftArabic: 1267 case ArabicNumber: 1268 bidi.eor = bidi.last; 1269 appendRun(bidi); 1270 bidi.dir = EuropeanNumber; 1271 break; 1272 case EuropeanNumberSeparator: 1273 case CommonNumberSeparator: 1274 if (bidi.status.eor == EuropeanNumber) 1275 break; 1276 case EuropeanNumberTerminator: 1277 case BoundaryNeutral: 1278 case BlockSeparator: 1279 case SegmentSeparator: 1280 case WhiteSpaceNeutral: 1281 case OtherNeutral: 1282 if (bidi.status.eor == RightToLeft) { 1283 // neutrals go to R 1284 bidi.eor = bidi.status.last == EuropeanNumberTerminator ? bidi.lastBeforeET : bidi.last; 1285 appendRun(bidi); 1286 bidi.dir = EuropeanNumber; 1287 } else if (bidi.status.eor != LeftToRight && 1288 (bidi.status.eor != EuropeanNumber || bidi.status.lastStrong != LeftToRight) && 1289 bidi.dir != LeftToRight) { 1290 // numbers on both sides, neutrals get right to left direction 1291 appendRun(bidi); 1292 bidi.eor = bidi.status.last == EuropeanNumberTerminator ? bidi.lastBeforeET : bidi.last; 1293 bidi.dir = RightToLeft; 1294 appendRun(bidi); 1295 bidi.dir = EuropeanNumber; 1296 } 1297 default: 1298 break; 1299 } 1300 bidi.eor = bidi.current; 1301 bidi.status.eor = EuropeanNumber; 1302 if (bidi.dir == OtherNeutral) 1303 bidi.dir = LeftToRight; 1304 break; 1305 } 1306 case ArabicNumber: 1307 dirCurrent = ArabicNumber; 1308 switch (bidi.status.last) { 1309 case LeftToRight: 1310 if (bidi.context->dir() == LeftToRight) 1311 appendRun(bidi); 1312 break; 1313 case ArabicNumber: 1314 break; 1315 case RightToLeft: 1316 case RightToLeftArabic: 1317 case EuropeanNumber: 1318 bidi.eor = bidi.last; 1319 appendRun(bidi); 1320 break; 1321 case CommonNumberSeparator: 1322 if (bidi.status.eor == ArabicNumber) 1323 break; 1324 case EuropeanNumberSeparator: 1325 case EuropeanNumberTerminator: 1326 case BoundaryNeutral: 1327 case BlockSeparator: 1328 case SegmentSeparator: 1329 case WhiteSpaceNeutral: 1330 case OtherNeutral: 1331 if (bidi.status.eor != RightToLeft && bidi.status.eor != RightToLeftArabic) { 1332 // run of L before neutrals, neutrals take embedding dir (N2) 1333 if (bidi.context->dir() == RightToLeft || bidi.status.lastStrong == RightToLeft 1334 || bidi.status.lastStrong == RightToLeftArabic) { 1335 // the embedding direction is R 1336 // close the L run 1337 appendRun(bidi); 1338 // neutrals become an R run 1339 bidi.dir = RightToLeft; 1340 } else { 1341 // the embedding direction is L 1342 // append neutrals to the L run and close it 1343 bidi.dir = LeftToRight; 1344 } 1345 } 1346 bidi.eor = bidi.last; 1347 appendRun(bidi); 1348 default: 1349 break; 1350 } 1351 bidi.eor = bidi.current; 1352 bidi.status.eor = ArabicNumber; 1353 if (bidi.dir == OtherNeutral) 1354 bidi.dir = ArabicNumber; 1355 break; 1356 case EuropeanNumberSeparator: 1357 case CommonNumberSeparator: 1358 break; 1359 case EuropeanNumberTerminator: 1360 if (bidi.status.last == EuropeanNumber) { 1361 dirCurrent = EuropeanNumber; 1362 bidi.eor = bidi.current; 1363 bidi.status.eor = dirCurrent; 1364 } else if (bidi.status.last != EuropeanNumberTerminator) 1365 bidi.lastBeforeET = emptyRun ? bidi.eor : bidi.last; 1366 break; 1367 1368 // boundary neutrals should be ignored 1369 case BoundaryNeutral: 1370 if (bidi.eor == bidi.last) 1371 bidi.eor = bidi.current; 1372 break; 1373 // neutrals 1374 case BlockSeparator: 1375 // ### what do we do with newline and paragraph seperators that come to here? 1376 break; 1377 case SegmentSeparator: 1378 // ### implement rule L1 1379 break; 1380 case WhiteSpaceNeutral: 1381 break; 1382 case OtherNeutral: 1383 break; 1384 default: 1385 break; 1386 } 1387 1388 if (pastEnd) { 1389 if (bidi.eor == bidi.current) { 1390 if (!bidi.reachedEndOfLine) { 1391 bidi.eor = bidi.endOfLine; 1392 switch (bidi.status.eor) { 1393 case LeftToRight: 1394 case RightToLeft: 1395 case ArabicNumber: 1396 bidi.dir = bidi.status.eor; 1397 break; 1398 case EuropeanNumber: 1399 bidi.dir = bidi.status.lastStrong == LeftToRight ? LeftToRight : EuropeanNumber; 1400 break; 1401 default: 1402 ASSERT(false); 1403 } 1404 appendRun(bidi); 1405 } 1406 bidi = stateAtEnd; 1407 bidi.dir = OtherNeutral; 1408 break; 1409 } 1410 } 1411 1412 // set status.last as needed. 1413 switch (dirCurrent) { 1414 case EuropeanNumberTerminator: 1415 if (bidi.status.last != EuropeanNumber) 1416 bidi.status.last = EuropeanNumberTerminator; 1417 break; 1418 case EuropeanNumberSeparator: 1419 case CommonNumberSeparator: 1420 case SegmentSeparator: 1421 case WhiteSpaceNeutral: 1422 case OtherNeutral: 1423 switch(bidi.status.last) { 1424 case LeftToRight: 1425 case RightToLeft: 1426 case RightToLeftArabic: 1427 case EuropeanNumber: 1428 case ArabicNumber: 1429 bidi.status.last = dirCurrent; 1430 break; 1431 default: 1432 bidi.status.last = OtherNeutral; 1433 } 1434 break; 1435 case NonSpacingMark: 1436 case BoundaryNeutral: 1437 case RightToLeftEmbedding: 1438 case LeftToRightEmbedding: 1439 case RightToLeftOverride: 1440 case LeftToRightOverride: 1441 case PopDirectionalFormat: 1442 // ignore these 1443 break; 1444 case EuropeanNumber: 1445 // fall through 1446 default: 1447 bidi.status.last = dirCurrent; 1448 } 1449 1450 bidi.last = bidi.current; 1451 1452 if (emptyRun && !(dirCurrent == RightToLeftEmbedding 1453 || dirCurrent == LeftToRightEmbedding 1454 || dirCurrent == RightToLeftOverride 1455 || dirCurrent == LeftToRightOverride 1456 || dirCurrent == PopDirectionalFormat)) { 1457 bidi.sor = bidi.current; 1458 emptyRun = false; 1459 } 1460 1461 // this causes the operator ++ to open and close embedding levels as needed 1462 // for the CSS unicode-bidi property 1463 bidi.adjustEmbedding = true; 1464 bidi.current.increment(bidi); 1465 bidi.adjustEmbedding = false; 1466 if (emptyRun && (dirCurrent == RightToLeftEmbedding 1467 || dirCurrent == LeftToRightEmbedding 1468 || dirCurrent == RightToLeftOverride 1469 || dirCurrent == LeftToRightOverride 1470 || dirCurrent == PopDirectionalFormat)) { 1471 // exclude the embedding char itself from the new run so that ATSUI will never see it 1472 bidi.eor.obj = 0; 1473 bidi.last = bidi.current; 1474 bidi.sor = bidi.current; 1475 } 1476 1477 if (!pastEnd && (bidi.current == end || bidi.current.atEnd())) { 1478 if (emptyRun) 1479 break; 1480 stateAtEnd = bidi; 1481 bidi.endOfLine = bidi.last; 1482 pastEnd = true; 1483 } 1484 } 1485 1486 sLogicallyLastBidiRun = sLastBidiRun; 1487 1488 // reorder line according to run structure... 1489 // do not reverse for visually ordered web sites 1490 if (!style()->visuallyOrdered()) { 1491 1492 // first find highest and lowest levels 1493 unsigned char levelLow = 128; 1494 unsigned char levelHigh = 0; 1495 BidiRun* r = sFirstBidiRun; 1496 while (r) { 1497 if (r->level > levelHigh) 1498 levelHigh = r->level; 1499 if (r->level < levelLow) 1500 levelLow = r->level; 1501 r = r->nextRun; 1502 } 1503 1504 // implements reordering of the line (L2 according to Bidi spec): 1505 // L2. From the highest level found in the text to the lowest odd level on each line, 1506 // reverse any contiguous sequence of characters that are at that level or higher. 1507 1508 // reversing is only done up to the lowest odd level 1509 if (!(levelLow%2)) 1510 levelLow++; 1511 1512 int count = sBidiRunCount - 1; 1513 1514 while (levelHigh >= levelLow) { 1515 int i = 0; 1516 BidiRun* currRun = sFirstBidiRun; 1517 while (i < count) { 1518 while (i < count && currRun && currRun->level < levelHigh) { 1519 i++; 1520 currRun = currRun->nextRun; 1521 } 1522 int start = i; 1523 while (i <= count && currRun && currRun->level >= levelHigh) { 1524 i++; 1525 currRun = currRun->nextRun; 1526 } 1527 int end = i-1; 1528 reverseRuns(start, end); 1529 } 1530 levelHigh--; 1531 } 1532 } 1533 bidi.endOfLine.obj = 0; 787 bidi.createBidiRunsForLine(start, end, style()->visuallyOrdered(), previousLineBrokeCleanly); 788 789 sFirstBidiRun = bidi.firstRun(); 790 sLastBidiRun = bidi.lastRun(); 791 sBidiRunCount = bidi.runCount(); 1534 792 } 1535 793 1536 794 static void buildCompactRuns(RenderObject* compactObj, BidiState& bidi) 1537 795 { 1538 sBuildingCompactRuns = true; 1539 if (!compactObj->isRenderBlock()) { 1540 // Just append a run for our object. 1541 isLineEmpty = false; 1542 addRun(new (compactObj->renderArena()) BidiRun(0, compactObj->length(), compactObj, bidi.context.get(), bidi.dir)); 1543 } 1544 else { 1545 // Format the compact like it is its own single line. We build up all the runs for 1546 // the little compact and then reorder them for bidi. 1547 RenderBlock* compactBlock = static_cast<RenderBlock*>(compactObj); 1548 bidi.adjustEmbedding = true; 1549 BidiIterator start(compactBlock, bidiFirst(compactBlock, bidi), 0); 1550 bidi.adjustEmbedding = false; 1551 BidiIterator end = start; 1552 1553 betweenMidpoints = false; 1554 isLineEmpty = true; 1555 previousLineBrokeCleanly = true; 1556 1557 end = compactBlock->findNextLineBreak(start, bidi); 1558 if (!isLineEmpty) 1559 compactBlock->bidiReorderLine(start, end, bidi); 1560 } 1561 1562 sCompactFirstBidiRun = sFirstBidiRun; 1563 sCompactLastBidiRun = sLastBidiRun; 1564 sCompactBidiRunCount = sBidiRunCount; 796 ASSERT(compactObj->isRenderBlock()); 797 ASSERT(!bidi.firstRun()); 798 799 // Format the compact like it is its own single line. We build up all the runs for 800 // the little compact and then reorder them for bidi. 801 RenderBlock* compactBlock = static_cast<RenderBlock*>(compactObj); 802 bidi.setAdjustEmbedding(true); 803 BidiIterator start(compactBlock, bidiFirst(compactBlock, bidi), 0); 804 bidi.setAdjustEmbedding(false); 805 BidiIterator end = start; 806 807 betweenMidpoints = false; 808 isLineEmpty = true; 809 previousLineBrokeCleanly = true; 810 811 end = compactBlock->findNextLineBreak(start, bidi); 812 if (!isLineEmpty) 813 compactBlock->bidiReorderLine(start, end, bidi); 814 815 for (BidiRun* run = bidi.firstRun(); run; run = run->next()) 816 run->compact = true; 1565 817 1566 818 sNumMidpoints = 0; 1567 819 sCurrMidpoint = 0; 1568 820 betweenMidpoints = false; 1569 sBuildingCompactRuns = false;1570 821 } 1571 822 … … 1651 902 } 1652 903 1653 BidiContext *startEmbed; 1654 if (style()->direction() == LTR) { 1655 startEmbed = new BidiContext(0, LeftToRight, NULL, style()->unicodeBidi() == Override); 1656 bidi.status.eor = LeftToRight; 1657 } else { 1658 startEmbed = new BidiContext(1, RightToLeft, NULL, style()->unicodeBidi() == Override); 1659 bidi.status.eor = RightToLeft; 1660 } 1661 1662 bidi.status.lastStrong = startEmbed->dir(); 1663 bidi.status.last = startEmbed->dir(); 1664 bidi.status.eor = startEmbed->dir(); 1665 bidi.context = startEmbed; 1666 bidi.dir = OtherNeutral; 904 BidiContext* startEmbed; 905 if (style()->direction() == LTR) 906 startEmbed = new BidiContext(0, LeftToRight, style()->unicodeBidi() == Override); 907 else 908 startEmbed = new BidiContext(1, RightToLeft, style()->unicodeBidi() == Override); 909 910 bidi.setLastStrongDir(startEmbed->dir()); 911 bidi.setLastDir(startEmbed->dir()); 912 bidi.setEorDir(startEmbed->dir()); 913 bidi.setContext(startEmbed); 1667 914 1668 915 if (!smidpoints) … … 1671 918 sNumMidpoints = 0; 1672 919 sCurrMidpoint = 0; 1673 sCompactFirstBidiRun = sCompactLastBidiRun = 0;1674 sCompactBidiRunCount = 0;1675 920 1676 921 // We want to skip ahead to the first dirty line … … 1682 927 BidiIterator cleanLineStart; 1683 928 BidiStatus cleanLineBidiStatus; 1684 BidiContext* cleanLineBidiContext = 0;1685 929 int endLineYPos = 0; 1686 930 RootInlineBox* endLine = (fullLayout || !startLine) ? 1687 0 : determineEndPosition(startLine, cleanLineStart, cleanLineBidiStatus, cleanLineBidiContext, endLineYPos); 1688 if (endLine && cleanLineBidiContext) 1689 cleanLineBidiContext->ref(); 931 0 : determineEndPosition(startLine, cleanLineStart, cleanLineBidiStatus, endLineYPos); 932 1690 933 if (startLine) { 1691 934 useRepaintBounds = true; … … 1709 952 while (!end.atEnd()) { 1710 953 start = end; 1711 if (endLine && (endLineMatched = matchedEndLine(start, bidi.status , bidi.context.get(), cleanLineStart, cleanLineBidiStatus, cleanLineBidiContext, endLine, endLineYPos, repaintBottom, repaintTop)))954 if (endLine && (endLineMatched = matchedEndLine(start, bidi.status(), cleanLineStart, cleanLineBidiStatus, endLine, endLineYPos, repaintBottom, repaintTop))) 1712 955 break; 1713 956 … … 1721 964 end = findNextLineBreak(start, bidi); 1722 965 if (start.atEnd()) { 1723 deleteBidiRuns(renderArena());966 bidi.deleteRuns(); 1724 967 break; 1725 968 } … … 1730 973 // At the same time we figure out where border/padding/margin should be applied for 1731 974 // inline flow boxes. 1732 if (sCompactFirstBidiRun) {1733 // We have a compact line sharing this line. Link the compact runs1734 // to our runs to create a single line of runs.1735 sCompactLastBidiRun->nextRun = sFirstBidiRun;1736 sFirstBidiRun = sCompactFirstBidiRun;1737 sBidiRunCount += sCompactBidiRunCount;1738 }1739 975 1740 976 RootInlineBox* lineBox = 0; … … 1743 979 if (lineBox) { 1744 980 lineBox->setEndsWithBreak(previousLineBrokeCleanly); 1745 981 1746 982 // Now we position all of our text runs horizontally. 1747 computeHorizontalPositionsForLine(lineBox, bidi);983 computeHorizontalPositionsForLine(lineBox, end.atEnd()); 1748 984 1749 985 // Now position our text runs vertically. … … 1758 994 } 1759 995 1760 deleteBidiRuns(renderArena());996 bidi.deleteRuns(); 1761 997 1762 998 if (end == start) { 1763 bidi. adjustEmbedding = true;999 bidi.setAdjustEmbedding(true); 1764 1000 end.increment(bidi); 1765 bidi. adjustEmbedding = false;1001 bidi.setAdjustEmbedding(false); 1766 1002 } 1767 1003 1768 1004 if (lineBox) { 1769 lineBox->setLineBreakInfo(end.obj, end.pos, &bidi.status, bidi.context.get());1005 lineBox->setLineBreakInfo(end.obj, end.pos, bidi.status()); 1770 1006 if (useRepaintBounds) { 1771 1007 repaintTop = min(repaintTop, lineBox->topOverflow()); … … 1780 1016 sNumMidpoints = 0; 1781 1017 sCurrMidpoint = 0; 1782 sCompactFirstBidiRun = sCompactLastBidiRun = 0;1783 sCompactBidiRunCount = 0;1784 1018 } 1785 1019 … … 1812 1046 } 1813 1047 } 1814 if (cleanLineBidiContext)1815 cleanLineBidiContext->deref();1816 1048 } 1817 1049 } … … 1890 1122 startObj = last->lineBreakObj(); 1891 1123 pos = last->lineBreakPos(); 1892 bidi.status = last->lineBreakBidiStatus(); 1893 bidi.context = last->lineBreakBidiContext(); 1124 bidi.setStatus(last->lineBreakBidiStatus()); 1894 1125 } else { 1895 bidi. adjustEmbedding = true;1126 bidi.setAdjustEmbedding(true); 1896 1127 startObj = bidiFirst(this, bidi, 0); 1897 bidi. adjustEmbedding = false;1128 bidi.setAdjustEmbedding(false); 1898 1129 } 1899 1130 … … 1903 1134 } 1904 1135 1905 RootInlineBox* RenderBlock::determineEndPosition(RootInlineBox* startLine, BidiIterator& cleanLineStart, 1906 BidiStatus& cleanLineBidiStatus, BidiContext*& cleanLineBidiContext, 1907 int& yPos) 1136 RootInlineBox* RenderBlock::determineEndPosition(RootInlineBox* startLine, BidiIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus, int& yPos) 1908 1137 { 1909 1138 RootInlineBox* last = 0; … … 1925 1154 cleanLineStart = BidiIterator(this, prev->lineBreakObj(), prev->lineBreakPos()); 1926 1155 cleanLineBidiStatus = prev->lineBreakBidiStatus(); 1927 cleanLineBidiContext = prev->lineBreakBidiContext();1928 1156 yPos = prev->blockHeight(); 1929 1157 … … 1935 1163 } 1936 1164 1937 bool RenderBlock::matchedEndLine(const BidiIterator& start, const BidiStatus& status, BidiContext* context,1938 const BidiIterator& endLineStart, const BidiStatus& endLineStatus, BidiContext* endLineContext,1165 bool RenderBlock::matchedEndLine(const BidiIterator& start, const BidiStatus& status, 1166 const BidiIterator& endLineStart, const BidiStatus& endLineStatus, 1939 1167 RootInlineBox*& endLine, int& endYPos, int& repaintBottom, int& repaintTop) 1940 1168 { 1941 1169 if (start == endLineStart) 1942 return status == endLineStatus && *context == *endLineContext;1170 return status == endLineStatus; 1943 1171 else { 1944 1172 // The first clean line doesn't match, but we can check a handful of following lines to try … … 1949 1177 if (line->lineBreakObj() == start.obj && line->lineBreakPos() == start.pos) { 1950 1178 // We have a match. 1951 if (line->lineBreakBidiStatus() != status || *line->lineBreakBidiContext() != *context)1179 if (line->lineBreakBidiStatus() != status) 1952 1180 return false; // ...but the bidi state doesn't match. 1953 1181 RootInlineBox* result = line->nextRootBox(); … … 2037 1265 // object iteration process. 2038 1266 int w = lineWidth(m_height); 2039 bidi. adjustEmbedding = true;1267 bidi.setAdjustEmbedding(true); 2040 1268 2041 1269 while (!it.atEnd() && !requiresLineBox(it)) { … … 2079 1307 } 2080 1308 2081 bidi. adjustEmbedding = false;1309 bidi.setAdjustEmbedding(false); 2082 1310 return w; 2083 1311 } -
trunk/WebCore/rendering/bidi.h
r19414 r24485 25 25 #define bidi_h 26 26 27 #include <wtf/unicode/Unicode.h>27 #include "BidiResolver.h" 28 28 29 29 namespace WebCore { 30 30 31 class RenderArena; 32 class RenderBlock; 33 class RenderObject; 34 class InlineBox; 31 class BidiIterator; 32 class RenderArena; 33 class RenderBlock; 34 class RenderObject; 35 class InlineBox; 35 36 36 struct BidiStatus { 37 BidiStatus() 38 : eor(WTF::Unicode::OtherNeutral) 39 , lastStrong(WTF::Unicode::OtherNeutral) 40 , last(WTF::Unicode::OtherNeutral) 41 { 42 } 37 struct BidiRun : BidiCharacterRun { 38 BidiRun(int start, int stop, RenderObject* o, BidiContext* context, WTF::Unicode::Direction dir) 39 : BidiCharacterRun(start, stop, context, dir) 40 , obj(o) 41 , box(0) 42 , compact(false) 43 { 44 } 43 45 44 WTF::Unicode::Direction eor; 45 WTF::Unicode::Direction lastStrong; 46 WTF::Unicode::Direction last; 47 }; 46 void destroy(RenderArena*); 48 47 49 class BidiContext { 50 public: 51 BidiContext(unsigned char level, WTF::Unicode::Direction embedding, BidiContext* parent = 0, bool override = false); 52 ~BidiContext(); 48 // Overloaded new operator. 49 void* operator new(size_t, RenderArena*) throw(); 53 50 54 void ref() const;55 void deref() const;51 // Overridden to prevent the normal delete from being called. 52 void operator delete(void*, size_t); 56 53 57 WTF::Unicode::Direction dir() const { return static_cast<WTF::Unicode::Direction>(m_dir); }54 BidiRun* next() { return static_cast<BidiRun*>(m_next); } 58 55 59 unsigned char level; 60 bool override : 1;61 unsigned m_dir : 5; // WTF::Unicode::Direction56 private: 57 // The normal operator new is disallowed. 58 void* operator new(size_t) throw(); 62 59 63 BidiContext* parent; 64 65 // refcounting.... 66 mutable int count; 67 }; 68 69 struct BidiRun { 70 BidiRun(int start_, int stop_, RenderObject* o, BidiContext* context, WTF::Unicode::Direction dir) 71 : start(start_) 72 , stop(stop_) 73 , obj(o) 74 , box(0) 75 , override(context->override) 76 , nextRun(0) 77 { 78 if (dir == WTF::Unicode::OtherNeutral) 79 dir = context->dir(); 80 81 level = context->level; 82 83 // add level of run (cases I1 & I2) 84 if (level % 2) { 85 if(dir == WTF::Unicode::LeftToRight || dir == WTF::Unicode::ArabicNumber || dir == WTF::Unicode::EuropeanNumber) 86 level++; 87 } else { 88 if (dir == WTF::Unicode::RightToLeft) 89 level++; 90 else if (dir == WTF::Unicode::ArabicNumber || dir == WTF::Unicode::EuropeanNumber) 91 level += 2; 92 } 93 } 94 95 void destroy(RenderArena*); 96 97 // Overloaded new operator. 98 void* operator new(size_t, RenderArena*) throw(); 99 100 // Overridden to prevent the normal delete from being called. 101 void operator delete(void*, size_t); 102 103 private: 104 // The normal operator new is disallowed. 105 void* operator new(size_t) throw(); 106 107 public: 108 int start; 109 int stop; 110 111 RenderObject* obj; 112 InlineBox* box; 113 114 // explicit + implicit levels here 115 unsigned char level; 116 bool override : 1; 117 bool compact : 1; 118 119 BidiRun* nextRun; 120 121 bool reversed(bool visuallyOrdered) { return level % 2 && !visuallyOrdered; } 122 bool dirOverride(bool visuallyOrdered) { return override || visuallyOrdered; } 123 }; 124 125 struct BidiIterator; 126 struct BidiState; 60 public: 61 RenderObject* obj; 62 InlineBox* box; 63 bool compact; 64 }; 127 65 128 66 } // namespace WebCore
Note: See TracChangeset
for help on using the changeset viewer.