[webkit-changes] cvs commit: WebCore/khtml/rendering bidi.cpp
bidi.h render_block.h render_line.cpp render_line.h
Eric
eseidel at opensource.apple.com
Sun Nov 27 14:52:10 PST 2005
eseidel 05/11/27 14:52:10
Modified: . ChangeLog
khtml/rendering bidi.cpp bidi.h render_block.h
render_line.cpp render_line.h
Log:
Bug #: 5172
Submitted by: mitz
Reviewed by: hyatt
One test case added:
fast/text/international/bidi-layout-across-linebreak.html
Fix for: http://bugzilla.opendarwin.org/show_bug.cgi?id=5172
* khtml/rendering/bidi.cpp:
(khtml::BidiState::BidiState):
(khtml::operator==):
(khtml::operator!=):
(khtml::BidiIterator::increment):
(khtml::appendRunsForObject):
(khtml::appendRun):
(khtml::embed):
(khtml::RenderBlock::computeHorizontalPositionsForLine):
(khtml::RenderBlock::computeVerticalPositionsForLine):
(khtml::RenderBlock::bidiReorderLine):
(khtml::buildCompactRuns):
(khtml::RenderBlock::layoutInlineChildren):
(khtml::RenderBlock::determineStartPosition):
(khtml::RenderBlock::determineEndPosition):
(khtml::RenderBlock::matchedEndLine):
(khtml::RenderBlock::findNextLineBreak):
* khtml/rendering/bidi.h:
(khtml::BidiStatus::BidiStatus):
* khtml/rendering/render_block.h:
* khtml/rendering/render_line.cpp:
(khtml::RootInlineBox::childRemoved):
(khtml::RootInlineBox::setLineBreakInfo):
* khtml/rendering/render_line.h:
(khtml::RootInlineBox::RootInlineBox):
(khtml::RootInlineBox::lineBreakBidiStatus):
(khtml::RootInlineBox::lineBreakBidiContext):
Revision Changes Path
1.409 +37 -0 WebCore/ChangeLog
Index: ChangeLog
===================================================================
RCS file: /cvs/root/WebCore/ChangeLog,v
retrieving revision 1.408
retrieving revision 1.409
diff -u -r1.408 -r1.409
--- ChangeLog 27 Nov 2005 11:02:10 -0000 1.408
+++ ChangeLog 27 Nov 2005 22:52:04 -0000 1.409
@@ -1,3 +1,40 @@
+2005-11-27 Mitz Pettel <opendarwin.org at mitzpettel.com>
+
+ Reviewed by hyatt. Committed by eseidel.
+
+ One test case added:
+ fast/text/international/bidi-layout-across-linebreak.html
+
+ Fix for: http://bugzilla.opendarwin.org/show_bug.cgi?id=5172
+
+ * khtml/rendering/bidi.cpp:
+ (khtml::BidiState::BidiState):
+ (khtml::operator==):
+ (khtml::operator!=):
+ (khtml::BidiIterator::increment):
+ (khtml::appendRunsForObject):
+ (khtml::appendRun):
+ (khtml::embed):
+ (khtml::RenderBlock::computeHorizontalPositionsForLine):
+ (khtml::RenderBlock::computeVerticalPositionsForLine):
+ (khtml::RenderBlock::bidiReorderLine):
+ (khtml::buildCompactRuns):
+ (khtml::RenderBlock::layoutInlineChildren):
+ (khtml::RenderBlock::determineStartPosition):
+ (khtml::RenderBlock::determineEndPosition):
+ (khtml::RenderBlock::matchedEndLine):
+ (khtml::RenderBlock::findNextLineBreak):
+ * khtml/rendering/bidi.h:
+ (khtml::BidiStatus::BidiStatus):
+ * khtml/rendering/render_block.h:
+ * khtml/rendering/render_line.cpp:
+ (khtml::RootInlineBox::childRemoved):
+ (khtml::RootInlineBox::setLineBreakInfo):
+ * khtml/rendering/render_line.h:
+ (khtml::RootInlineBox::RootInlineBox):
+ (khtml::RootInlineBox::lineBreakBidiStatus):
+ (khtml::RootInlineBox::lineBreakBidiContext):
+
2005-11-26 Eric Seidel <eseidel at apple.com>
Reviewed by mjs.
1.157 +194 -165 WebCore/khtml/rendering/bidi.cpp
Index: bidi.cpp
===================================================================
RCS file: /cvs/root/WebCore/khtml/rendering/bidi.cpp,v
retrieving revision 1.156
retrieving revision 1.157
diff -u -r1.156 -r1.157
--- bidi.cpp 3 Nov 2005 23:53:57 -0000 1.156
+++ bidi.cpp 27 Nov 2005 22:52:08 -0000 1.157
@@ -29,6 +29,7 @@
#include "render_canvas.h"
#include "khtmlview.h"
#include "xml/dom_docimpl.h"
+#include "misc/shared.h"
#include "kdebug.h"
#include "qdatetime.h"
@@ -57,27 +58,31 @@
unsigned int pos;
};
-struct BidiStatus {
- BidiStatus() : eor(QChar::DirON), lastStrong(QChar::DirON), last(QChar::DirON) {}
-
- QChar::Direction eor;
- QChar::Direction lastStrong;
- QChar::Direction last;
-};
-
struct BidiState {
- BidiState() : context(0), dir(QChar::DirON), adjustEmbedding(false) {}
+ BidiState() : context(0), dir(QChar::DirON), adjustEmbedding(false), reachedEndOfLine(false) {}
BidiIterator sor;
BidiIterator eor;
BidiIterator last;
BidiIterator current;
- BidiContext* context;
+ SharedPtr<BidiContext> context;
BidiStatus status;
QChar::Direction dir;
bool adjustEmbedding;
+ BidiIterator endOfLine;
+ bool reachedEndOfLine;
};
+inline bool operator==(const BidiStatus& status1, const BidiStatus& status2)
+{
+ return status1.eor == status2.eor && status1.last == status2.last && status1.lastStrong == status2.lastStrong;
+}
+
+inline bool operator!=(const BidiStatus& status1, const BidiStatus& status2)
+{
+ return !(status1 == status2);
+}
+
// Used to track a list of chained bidi runs.
static BidiRun* sFirstBidiRun;
static BidiRun* sLastBidiRun;
@@ -225,6 +230,20 @@
delete this;
}
+bool operator==(const BidiContext& c1, const BidiContext& c2)
+{
+ if (&c1 == &c2)
+ return true;
+ if (c1.level != c2.level || c1.override != c2.override || c1.dir != c2.dir || c1.basicDir != c2.basicDir)
+ return false;
+ return c1.parent && c2.parent && *c1.parent == *c2.parent;
+}
+
+inline bool operator!=(const BidiContext& c1, const BidiContext& c2)
+{
+ return !(c1 == c2);
+}
+
// ---------------------------------------------------------------------
inline bool operator==(const BidiIterator& it1, const BidiIterator& it2)
@@ -329,7 +348,7 @@
return;
if (obj->isText()) {
pos++;
- if(pos >= static_cast<RenderText *>(obj)->stringLength()) {
+ if (pos >= static_cast<RenderText *>(obj)->stringLength()) {
obj = bidiNext(block, obj, bidi);
pos = 0;
}
@@ -531,7 +550,7 @@
}
else {
if (!smidpoints || !haveNextMidpoint || (obj != nextMidpoint.obj)) {
- addRun(new (obj->renderArena()) BidiRun(start, end, obj, bidi.context, bidi.dir));
+ addRun(new (obj->renderArena()) BidiRun(start, end, obj, bidi.context.get(), bidi.dir));
return;
}
@@ -543,12 +562,12 @@
if (nextMidpoint.pos != UINT_MAX) { // UINT_MAX means stop at the object and don't include any of it.
if (int(nextMidpoint.pos+1) > start)
addRun(new (obj->renderArena())
- BidiRun(start, nextMidpoint.pos+1, obj, bidi.context, bidi.dir));
+ BidiRun(start, nextMidpoint.pos+1, obj, bidi.context.get(), bidi.dir));
return appendRunsForObject(nextMidpoint.pos+1, end, obj, bidi);
}
}
else
- addRun(new (obj->renderArena()) BidiRun(start, end, obj, bidi.context, bidi.dir));
+ addRun(new (obj->renderArena()) BidiRun(start, end, obj, bidi.context.get(), bidi.dir));
}
}
@@ -565,14 +584,19 @@
int start = bidi.sor.pos;
RenderObject *obj = bidi.sor.obj;
- while (obj && obj != bidi.eor.obj) {
+ while (obj && obj != bidi.eor.obj && obj != bidi.endOfLine.obj) {
appendRunsForObject(start, obj->length(), obj, bidi);
start = 0;
obj = bidiNext(bidi.sor.block, obj, bidi);
}
if (obj) {
+ unsigned pos = obj == bidi.eor.obj ? bidi.eor.pos : UINT_MAX;
+ if (obj == bidi.endOfLine.obj && bidi.endOfLine.pos <= pos) {
+ bidi.reachedEndOfLine = true;
+ pos = bidi.endOfLine.pos;
+ }
// It's OK to add runs for zero-length RenderObjects, just don't make the run larger than it should be
- int end = obj->length() ? bidi.eor.pos + 1 : 0;
+ int end = obj->length() ? pos+1 : 0;
appendRunsForObject(start, end, obj, bidi);
}
@@ -617,7 +641,6 @@
// sor for the new run is determined by the higher level (rule X10)
bidi.status.last = bidi.context->dir;
bidi.status.lastStrong = bidi.context->dir;
- bidi.context->deref();
bidi.context = c;
bidi.status.eor = bidi.context->dir;
bidi.eor.obj = 0;
@@ -684,8 +707,7 @@
}
appendRun(bidi);
emptyRun = true;
- bidi.context = new BidiContext(level, runDir, bidi.context, override);
- bidi.context->ref();
+ bidi.context = new BidiContext(level, runDir, bidi.context.get(), override);
bidi.status.last = runDir;
bidi.status.lastStrong = runDir;
bidi.status.eor = runDir;
@@ -873,7 +895,7 @@
case CENTER:
case KHTML_CENTER:
int xd = (availableWidth - totWidth)/2;
- x += xd >0 ? xd : 0;
+ x += xd > 0 ? xd : 0;
numSpaces = 0;
break;
}
@@ -926,7 +948,8 @@
// Now make sure we place replaced render objects correctly.
for (BidiRun* r = sFirstBidiRun; r; r = r->nextRun) {
- if (!r->box) continue; // Skip runs with no line boxes.
+ if (!r->box)
+ continue; // Skip runs with no line boxes.
// Align positioned boxes with the top of the line box. This is
// a reasonable approximation of an appropriate y position.
@@ -952,26 +975,36 @@
sLastBidiRun = 0;
sBidiRunCount = 0;
+ assert(bidi.dir == QChar::DirON);
+
emptyRun = true;
- bidi.dir = QChar::DirON;
- bidi.status.eor = bidi.context->dir;
+
bidi.eor.obj = 0;
numSpaces = 0;
bidi.current = start;
bidi.last = bidi.current;
- bool atEnd = false;
+ bool pastEnd = false;
+ bool resetBidiAtEnd = false;
+ BidiState stateAtEnd;
while (true) {
QChar::Direction dirCurrent;
- if (atEnd) {
+ if (pastEnd && (resetBidiAtEnd || bidi.current.atEnd())) {
//kdDebug(6041) << "atEnd" << endl;
- BidiContext *c = bidi.context;
- if ( bidi.current.atEnd())
- while ( c->parent )
- c = c->parent;
+ BidiContext *c = bidi.context.get();
+ while (c->parent)
+ c = c->parent;
dirCurrent = c->dir;
+ if (resetBidiAtEnd) {
+ // A deviation from the Unicode Bidi Algorithm in order to match
+ // Mac OS X text and WinIE: a hard line break resets bidi state.
+ stateAtEnd.context = c;
+ stateAtEnd.status.eor = dirCurrent;
+ stateAtEnd.status.last = dirCurrent;
+ stateAtEnd.status.lastStrong = dirCurrent;
+ }
} else {
dirCurrent = bidi.current.direction();
if (bidi.context->override && dirCurrent != QChar::DirRLE && dirCurrent != QChar::DirLRE && dirCurrent != QChar::DirRLO && dirCurrent != QChar::DirLRO && dirCurrent != QChar::DirPDF)
@@ -1001,11 +1034,8 @@
case QChar::DirAN:
if (bidi.status.last != QChar::DirEN || bidi.status.lastStrong != QChar::DirL)
appendRun(bidi);
- bidi.dir = QChar::DirL;
- // fall through
+ break;
case QChar::DirL:
- bidi.eor = bidi.current;
- bidi.status.eor = QChar::DirL;
break;
case QChar::DirES:
case QChar::DirET:
@@ -1037,34 +1067,31 @@
bidi.dir = QChar::DirR;
appendRun(bidi);
}
- } else if (bidi.status.eor != QChar::DirL) {
- // last stuff takes embedding dir
- if (bidi.context->dir == QChar::DirL || bidi.status.lastStrong == QChar::DirL)
- appendRun(bidi);
- else {
- bidi.dir = QChar::DirR;
+ } else if(bidi.status.eor != QChar::DirL) {
+ //last stuff takes embedding dir
+ if (bidi.context->dir != QChar::DirL && bidi.status.lastStrong != QChar::DirL) {
bidi.eor = bidi.last;
- appendRun(bidi);
+ bidi.dir = QChar::DirR;
}
+ appendRun(bidi);
}
- bidi.eor = bidi.current;
- bidi.status.eor = QChar::DirL;
default:
break;
- }
+ }
+ bidi.eor = bidi.current;
+ bidi.status.eor = QChar::DirL;
bidi.status.lastStrong = QChar::DirL;
bidi.dir = QChar::DirL;
break;
case QChar::DirAL:
case QChar::DirR:
- switch(bidi.status.last) {
+ switch (bidi.status.last) {
case QChar::DirL:
case QChar::DirEN:
case QChar::DirAN:
appendRun(bidi);
case QChar::DirR:
case QChar::DirAL:
- bidi.eor = bidi.current;
break;
case QChar::DirES:
case QChar::DirET:
@@ -1076,20 +1103,17 @@
case QChar::DirON:
if (bidi.status.eor != QChar::DirR && bidi.status.eor != QChar::DirAL) {
//last stuff takes embedding dir
- if(bidi.context->dir == QChar::DirR || bidi.status.lastStrong == QChar::DirR
- || bidi.status.lastStrong == QChar::DirAL) {
- appendRun(bidi);
- bidi.eor = bidi.current;
- } else {
- bidi.dir = QChar::DirL;
+ if (bidi.context->dir != QChar::DirR && bidi.status.lastStrong != QChar::DirR
+ && bidi.status.lastStrong != QChar::DirAL) {
bidi.eor = bidi.last;
- appendRun(bidi);
+ bidi.dir = QChar::DirL;
}
- } else
- bidi.eor = bidi.current;
+ appendRun(bidi);
+ }
default:
break;
- }
+ }
+ bidi.eor = bidi.current;
bidi.status.eor = QChar::DirR;
bidi.status.lastStrong = dirCurrent;
bidi.dir = QChar::DirR;
@@ -1098,87 +1122,73 @@
// weak types:
case QChar::DirEN:
- if (!(bidi.status.lastStrong == QChar::DirAL)) {
+ if (bidi.status.lastStrong != QChar::DirAL) {
// if last strong was AL change EN to AN
switch (bidi.status.last) {
case QChar::DirET:
- if (bidi.status.lastStrong == QChar::DirR || bidi.status.lastStrong == QChar::DirAL) {
- appendRun(bidi);
+ if (bidi.status.lastStrong == QChar::DirR || bidi.status.lastStrong == QChar::DirAL) {
+ appendRun(bidi);
bidi.dir = QChar::DirEN;
- bidi.status.eor = QChar::DirEN;
}
// fall through
case QChar::DirEN:
case QChar::DirL:
- bidi.eor = bidi.current;
- bidi.status.eor = dirCurrent;
break;
case QChar::DirR:
case QChar::DirAL:
case QChar::DirAN:
bidi.eor = bidi.last;
appendRun(bidi);
- bidi.eor = bidi.current;
- bidi.status.eor = QChar::DirEN;
bidi.dir = QChar::DirEN;
break;
case QChar::DirES:
case QChar::DirCS:
if (bidi.status.eor == QChar::DirEN)
- bidi.eor = bidi.current; break;
+ break;
case QChar::DirBN:
case QChar::DirB:
case QChar::DirS:
case QChar::DirWS:
case QChar::DirON:
- if(bidi.status.eor == QChar::DirR) {
+ if (bidi.status.eor == QChar::DirR) {
// neutrals go to R
bidi.eor = bidi.last;
appendRun(bidi);
bidi.dir = QChar::DirEN;
- bidi.status.eor = QChar::DirEN;
- } else if (bidi.status.eor == QChar::DirL ||
- (bidi.status.eor == QChar::DirEN && bidi.status.lastStrong == QChar::DirL)) {
- bidi.eor = bidi.current;
- bidi.status.eor = dirCurrent;
- } else {
+ } else if (bidi.status.eor != QChar::DirL &&
+ (bidi.status.eor != QChar::DirEN || bidi.status.lastStrong != QChar::DirL) &&
+ bidi.dir != QChar::DirL) {
// numbers on both sides, neutrals get right to left direction
- if (bidi.dir != QChar::DirL) {
- appendRun(bidi);
- bidi.eor = bidi.last;
- bidi.dir = QChar::DirR;
- appendRun(bidi);
- bidi.dir = QChar::DirEN;
- bidi.status.eor = QChar::DirEN;
- } else
- bidi.eor = bidi.current; bidi.status.eor = dirCurrent;
+ appendRun(bidi);
+ bidi.eor = bidi.last;
+ bidi.dir = QChar::DirR;
+ appendRun(bidi);
+ bidi.dir = QChar::DirEN;
}
default:
break;
- }
+ }
+ bidi.eor = bidi.current;
+ bidi.status.eor = QChar::DirEN;
if (bidi.dir == QChar::DirON)
bidi.dir = QChar::DirL;
break;
}
case QChar::DirAN:
dirCurrent = QChar::DirAN;
- switch(bidi.status.last) {
+ switch (bidi.status.last) {
case QChar::DirL:
case QChar::DirAN:
- bidi.eor = bidi.current; bidi.status.eor = QChar::DirAN; break;
+ break;
case QChar::DirR:
case QChar::DirAL:
case QChar::DirEN:
bidi.eor = bidi.last;
appendRun(bidi);
- bidi.eor = bidi.current;
- bidi.status.eor = QChar::DirAN;
- bidi.dir = QChar::DirAN;
break;
case QChar::DirCS:
if (bidi.status.eor == QChar::DirAN)
- bidi.eor = bidi.current;
- break;
+ break;
case QChar::DirES:
case QChar::DirET:
case QChar::DirBN:
@@ -1194,27 +1204,20 @@
// close the L run
appendRun(bidi);
// neutrals become an R run
- bidi.eor = bidi.last;
bidi.dir = QChar::DirR;
- appendRun(bidi);
- bidi.eor = bidi.current;
} else {
// the embedding direction is L
// append neutrals to the L run and close it
bidi.dir = QChar::DirL;
- bidi.eor = bidi.last;
- appendRun(bidi);
}
- } else {
- bidi.eor = bidi.last;
- appendRun(bidi);
- bidi.eor = bidi.current;
}
- bidi.dir = QChar::DirAN;
- bidi.status.eor = QChar::DirAN;
+ bidi.eor = bidi.last;
+ appendRun(bidi);
default:
break;
}
+ bidi.eor = bidi.current;
+ bidi.status.eor = QChar::DirAN;
if (bidi.dir == QChar::DirON)
bidi.dir = QChar::DirAN;
break;
@@ -1261,8 +1264,29 @@
break;
}
- if (bidi.current.atEnd())
- break;
+ if (pastEnd) {
+ if (bidi.eor == bidi.current) {
+ if (!bidi.reachedEndOfLine) {
+ bidi.eor = bidi.endOfLine;
+ switch (bidi.status.eor) {
+ case QChar::DirL:
+ case QChar::DirR:
+ case QChar::DirAN:
+ bidi.dir = bidi.status.eor;
+ break;
+ case QChar::DirEN:
+ bidi.dir = bidi.status.lastStrong == QChar::DirL ? QChar::DirL : QChar::DirEN;
+ break;
+ default:
+ assert(false);
+ }
+ appendRun(bidi);
+ }
+ bidi = stateAtEnd;
+ bidi.dir = QChar::DirON;
+ break;
+ }
+ }
// set status.last as needed.
switch (dirCurrent) {
@@ -1302,8 +1326,6 @@
bidi.status.last = dirCurrent;
}
- if (atEnd)
- break;
bidi.last = bidi.current;
if (emptyRun && !(dirCurrent == QChar::DirRLE || dirCurrent == QChar::DirLRE || dirCurrent == QChar::DirRLO || dirCurrent == QChar::DirLRO || dirCurrent == QChar::DirPDF)) {
@@ -1323,44 +1345,42 @@
bidi.sor = bidi.current;
}
- if (bidi.current == end) {
- if (emptyRun)
- break;
- atEnd = true;
- }
- }
-
- if (!emptyRun && bidi.sor != bidi.current) {
- bidi.eor = bidi.last;
- appendRun(bidi);
+ if (!pastEnd && (bidi.current == end || bidi.current.atEnd())) {
+ if (emptyRun)
+ break;
+ stateAtEnd = bidi;
+ bidi.endOfLine = bidi.last;
+ pastEnd = true;
+ resetBidiAtEnd = previousLineBrokeCleanly || (end.obj && end.obj->style()->preserveNewline() && end.current() == '\n');
+ }
}
// reorder line according to run structure...
+ // do not reverse for visually ordered web sites
+ if (!style()->visuallyOrdered()) {
- // first find highest and lowest levels
- uchar levelLow = 128;
- uchar levelHigh = 0;
- BidiRun* r = sFirstBidiRun;
- while (r) {
- if (r->level > levelHigh)
- levelHigh = r->level;
- if (r->level < levelLow)
- levelLow = r->level;
- r = r->nextRun;
- }
-
- // implements reordering of the line (L2 according to Bidi spec):
- // L2. From the highest level found in the text to the lowest odd level on each line,
- // reverse any contiguous sequence of characters that are at that level or higher.
-
- // reversing is only done up to the lowest odd level
- if (!(levelLow%2))
- levelLow++;
+ // first find highest and lowest levels
+ uchar levelLow = 128;
+ uchar levelHigh = 0;
+ BidiRun* r = sFirstBidiRun;
+ while (r) {
+ if (r->level > levelHigh)
+ levelHigh = r->level;
+ if (r->level < levelLow)
+ levelLow = r->level;
+ r = r->nextRun;
+ }
+
+ // implements reordering of the line (L2 according to Bidi spec):
+ // L2. From the highest level found in the text to the lowest odd level on each line,
+ // reverse any contiguous sequence of characters that are at that level or higher.
+
+ // reversing is only done up to the lowest odd level
+ if (!(levelLow%2))
+ levelLow++;
- int count = sBidiRunCount - 1;
+ int count = sBidiRunCount - 1;
- // do not reverse for visually ordered web sites
- if (!style()->visuallyOrdered()) {
while (levelHigh >= levelLow) {
int i = 0;
BidiRun* currRun = sFirstBidiRun;
@@ -1380,6 +1400,7 @@
levelHigh--;
}
}
+ bidi.endOfLine.obj = 0;
}
static void buildCompactRuns(RenderObject* compactObj, BidiState& bidi)
@@ -1388,7 +1409,7 @@
if (!compactObj->isRenderBlock()) {
// Just append a run for our object.
isLineEmpty = false;
- addRun(new (compactObj->renderArena()) BidiRun(0, compactObj->length(), compactObj, bidi.context, bidi.dir));
+ addRun(new (compactObj->renderArena()) BidiRun(0, compactObj->length(), compactObj, bidi.context.get(), bidi.dir));
}
else {
// Format the compact like it is its own single line. We build up all the runs for
@@ -1507,11 +1528,12 @@
startEmbed = new BidiContext( 1, QChar::DirR, NULL, style()->unicodeBidi() == Override );
bidi.status.eor = QChar::DirR;
}
- startEmbed->ref();
bidi.status.lastStrong = startEmbed->dir;
bidi.status.last = startEmbed->dir;
+ bidi.status.eor = startEmbed->dir;
bidi.context = startEmbed;
+ bidi.dir = QChar::DirON;
if (!smidpoints)
smidpoints = new QMemArray<BidiIterator>;
@@ -1528,9 +1550,13 @@
// We also find the first clean line and extract these lines. We will add them back
// if we determine that we're able to synchronize after handling all our dirty lines.
BidiIterator cleanLineStart;
+ BidiStatus cleanLineBidiStatus;
+ BidiContext* cleanLineBidiContext;
int endLineYPos;
RootInlineBox* endLine = (fullLayout || !startLine) ?
- 0 : determineEndPosition(startLine, cleanLineStart, endLineYPos);
+ 0 : determineEndPosition(startLine, cleanLineStart, cleanLineBidiStatus, cleanLineBidiContext, endLineYPos);
+ if (endLine && cleanLineBidiContext)
+ cleanLineBidiContext->ref();
if (startLine) {
useRepaintRect = true;
startLineBottom = startLine->bottomOverflow();
@@ -1550,7 +1576,7 @@
bool endLineMatched = false;
while (!end.atEnd()) {
start = end;
- if (endLine && (endLineMatched = matchedEndLine(start, cleanLineStart, endLine, endLineYPos)))
+ if (endLine && (endLineMatched = matchedEndLine(start, bidi.status, bidi.context.get(), cleanLineStart, cleanLineBidiStatus, cleanLineBidiContext, endLine, endLineYPos)))
break;
betweenMidpoints = false;
@@ -1561,7 +1587,8 @@
end = start;
}
end = findNextLineBreak(start, bidi);
- if( start.atEnd() ) break;
+ if (start.atEnd())
+ break;
if (!isLineEmpty) {
bidiReorderLine(start, end, bidi);
@@ -1599,7 +1626,7 @@
}
if (lineBox)
- lineBox->setLineBreakInfo(end.obj, end.pos);
+ lineBox->setLineBreakInfo(end.obj, end.pos, &bidi.status, bidi.context.get());
m_firstLine = false;
newLine();
@@ -1610,8 +1637,6 @@
sCompactFirstBidiRun = sCompactLastBidiRun = 0;
sCompactBidiRunCount = 0;
}
- startEmbed->deref();
- //embed->deref();
if (endLine) {
if (endLineMatched) {
@@ -1654,6 +1679,8 @@
line = next;
}
}
+ if (cleanLineBidiContext)
+ cleanLineBidiContext->deref();
}
}
@@ -1716,8 +1743,7 @@
}
KHTMLAssert(!m_firstLineBox && !m_lastLineBox);
}
- }
- else {
+ } else {
for (curr = firstRootBox(); curr && !curr->isDirty(); curr = curr->nextRootBox());
if (curr) {
// We have a dirty line.
@@ -1726,8 +1752,7 @@
if (!curr->prevRootBox()->endsWithBreak())
curr = curr->prevRootBox(); // The previous line didn't break cleanly, so treat it as dirty also.
}
- }
- else {
+ } else {
// No dirty lines were found.
// If the last line didn't break cleanly, treat it as dirty.
if (lastRootBox() && !lastRootBox()->endsWithBreak())
@@ -1747,18 +1772,18 @@
m_overflowHeight = bottomOfLine;
startObj = last->lineBreakObj();
pos = last->lineBreakPos();
- }
- else
+ bidi.status = last->lineBreakBidiStatus();
+ bidi.context = last->lineBreakBidiContext();
+ } else
startObj = bidiFirst(this, bidi, 0);
- bidi.adjustEmbedding = true;
start = BidiIterator(this, startObj, pos);
- bidi.adjustEmbedding = false;
return curr;
}
RootInlineBox* RenderBlock::determineEndPosition(RootInlineBox* startLine, BidiIterator& cleanLineStart,
+ BidiStatus& cleanLineBidiStatus, BidiContext*& cleanLineBidiContext,
int& yPos)
{
RootInlineBox* last = 0;
@@ -1776,7 +1801,10 @@
if (!last)
return 0;
- cleanLineStart = BidiIterator(this, last->prevRootBox()->lineBreakObj(), last->prevRootBox()->lineBreakPos());
+ RootInlineBox* prev = last->prevRootBox();
+ cleanLineStart = BidiIterator(this, prev->lineBreakObj(), prev->lineBreakPos());
+ cleanLineBidiStatus = prev->lineBreakBidiStatus();
+ cleanLineBidiContext = prev->lineBreakBidiContext();
yPos = last->prevRootBox()->blockHeight();
for (RootInlineBox* line = last; line; line = line->nextRootBox())
@@ -1786,11 +1814,12 @@
return last;
}
-bool RenderBlock::matchedEndLine(const BidiIterator& start, const BidiIterator& endLineStart,
- RootInlineBox*& endLine, int& endYPos)
+bool RenderBlock::matchedEndLine(const BidiIterator& start, const BidiStatus& status, BidiContext* context,
+ const BidiIterator& endLineStart, const BidiStatus& endLineStatus,
+ BidiContext* endLineContext, RootInlineBox*& endLine, int& endYPos)
{
if (start == endLineStart)
- return true; // The common case. All the data we already have is correct.
+ return status == endLineStatus && *context == *endLineContext;
else {
// The first clean line doesn't match, but we can check a handful of following lines to try
// to match back up.
@@ -1799,6 +1828,8 @@
for (int i = 0; i < numLines && line; i++, line = line->nextRootBox()) {
if (line->lineBreakObj() == start.obj && line->lineBreakPos() == start.pos) {
// We have a match.
+ if (line->lineBreakBidiStatus() != status || *line->lineBreakBidiContext() != *context)
+ return false; // ...but the bidi state doesn't match.
RootInlineBox* result = line->nextRootBox();
// Set our yPos to be the block height of endLine.
@@ -1951,7 +1982,7 @@
if (!isLineEmpty) {
// only check the clear status for non-empty lines.
EClear clear = o->style()->clear();
- if(clear != CNONE)
+ if (clear != CNONE)
m_clearStatus = (EClear) (m_clearStatus | clear);
}
}
@@ -2067,13 +2098,13 @@
}
}
}
- } else if ( o->isText() ) {
+ } else if (o->isText()) {
RenderText *t = static_cast<RenderText *>(o);
int strlen = t->stringLength();
int len = strlen - pos;
QChar *str = t->text();
- const Font *f = t->htmlFont( m_firstLine );
+ const Font *f = t->htmlFont(m_firstLine);
// proportional font, needs a bit more work.
int lastSpace = pos;
int wordSpacing = o->style()->wordSpacing();
@@ -2201,13 +2232,12 @@
}
}
goto end; // Didn't fit. Jump to the end.
- }
- else if (pos > 0 && str[pos-1].unicode() == SOFT_HYPHEN)
+ } else if (pos > 0 && str[pos-1].unicode() == SOFT_HYPHEN)
// Subtract the width of the soft hyphen out since we fit on a line.
tmpW -= t->width(pos-1, 1, f, w+tmpW);
}
- if( *(str+pos) == '\n' && o->style()->preserveNewline()) {
+ if (*(str+pos) == '\n' && o->style()->preserveNewline()) {
lBreak.obj = o;
lBreak.pos = pos;
return lBreak;
@@ -2239,13 +2269,12 @@
lastSpace = pos;
}
}
- }
- else if (ignoringSpaces) {
+ } else if (ignoringSpaces) {
// Stop ignoring spaces and begin at this
// new point.
ignoringSpaces = false;
lastSpace = pos; // e.g., "Foo goo", don't add in any of the ignored spaces.
- BidiIterator startMid ( 0, o, pos );
+ BidiIterator startMid(0, o, pos);
addMidpoint(startMid);
}
@@ -2416,7 +2445,7 @@
// Add a new end midpoint that stops right at the very end.
RenderText* text = static_cast<RenderText *>(trailingSpaceObject);
unsigned pos = text->length() >=2 ? text->length() - 2 : UINT_MAX;
- BidiIterator endMid ( 0, trailingSpaceObject, pos );
+ BidiIterator endMid(0, trailingSpaceObject, pos);
addMidpoint(endMid);
}
}
1.18 +8 -0 WebCore/khtml/rendering/bidi.h
Index: bidi.h
===================================================================
RCS file: /cvs/root/WebCore/khtml/rendering/bidi.h,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- bidi.h 6 Oct 2005 00:53:55 -0000 1.17
+++ bidi.h 27 Nov 2005 22:52:08 -0000 1.18
@@ -32,6 +32,14 @@
class RenderObject;
class InlineBox;
+ struct BidiStatus {
+ BidiStatus() : eor(QChar::DirON), lastStrong(QChar::DirON), last(QChar::DirON) {}
+
+ QChar::Direction eor;
+ QChar::Direction lastStrong;
+ QChar::Direction last;
+ };
+
class BidiContext {
public:
BidiContext(unsigned char level, QChar::Direction embedding, BidiContext *parent = 0, bool override = false);
1.73 +6 -3 WebCore/khtml/rendering/render_block.h
Index: render_block.h
===================================================================
RCS file: /cvs/root/WebCore/khtml/rendering/render_block.h,v
retrieving revision 1.72
retrieving revision 1.73
diff -u -r1.72 -r1.73
--- render_block.h 3 Nov 2005 21:05:59 -0000 1.72
+++ render_block.h 27 Nov 2005 22:52:08 -0000 1.73
@@ -124,9 +124,12 @@
// the implementation of the following functions is in bidi.cpp
void bidiReorderLine(const BidiIterator &start, const BidiIterator &end, BidiState &bidi );
RootInlineBox* determineStartPosition(bool fullLayout, BidiIterator &start, BidiState &bidi);
- RootInlineBox* determineEndPosition(RootInlineBox* startBox, BidiIterator& cleanLineStart, int& yPos);
- bool matchedEndLine(const BidiIterator& start, const BidiIterator& endLineStart,
- RootInlineBox*& endLine, int& endYPos);
+ RootInlineBox* determineEndPosition(RootInlineBox* startBox, BidiIterator& cleanLineStart,
+ BidiStatus& cleanLineBidiStatus, BidiContext*& cleanLineBidiContext,
+ int& yPos);
+ bool matchedEndLine(const BidiIterator& start, const BidiStatus& status, BidiContext* context,
+ const BidiIterator& endLineStart, const BidiStatus& endLineStatus,
+ BidiContext* endLineContext, RootInlineBox*& endLine, int& endYPos);
int skipWhitespace(BidiIterator &, BidiState &);
BidiIterator findNextLineBreak(BidiIterator &start, BidiState &info );
RootInlineBox* constructLine(const BidiIterator& start, const BidiIterator& end);
1.58 +10 -2 WebCore/khtml/rendering/render_line.cpp
Index: render_line.cpp
===================================================================
RCS file: /cvs/root/WebCore/khtml/rendering/render_line.cpp,v
retrieving revision 1.57
retrieving revision 1.58
diff -u -r1.57 -r1.58
--- render_line.cpp 21 Nov 2005 01:20:25 -0000 1.57
+++ render_line.cpp 27 Nov 2005 22:52:09 -0000 1.58
@@ -1216,11 +1216,11 @@
void RootInlineBox::childRemoved(InlineBox* box)
{
if (box->object() == m_lineBreakObj)
- setLineBreakInfo(0,0);
+ setLineBreakInfo(0, 0, 0, 0);
RootInlineBox* prev = prevRootBox();
if (prev && prev->lineBreakObj() == box->object()) {
- prev->setLineBreakInfo(0,0);
+ prev->setLineBreakInfo(0, 0, 0, 0);
prev->markDirty();
}
}
@@ -1363,5 +1363,13 @@
return lastLeaf;
}
+void RootInlineBox::setLineBreakInfo(RenderObject* obj, uint breakPos, BidiStatus* status, BidiContext* context)
+{
+ m_lineBreakObj = obj;
+ m_lineBreakPos = breakPos;
+ m_lineBreakContext = context;
+ if (status)
+ m_lineBreakBidiStatus = *status;
+}
}
1.33 +10 -4 WebCore/khtml/rendering/render_line.h
Index: render_line.h
===================================================================
RCS file: /cvs/root/WebCore/khtml/rendering/render_line.h,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -r1.32 -r1.33
--- render_line.h 6 Oct 2005 00:53:57 -0000 1.32
+++ render_line.h 27 Nov 2005 22:52:09 -0000 1.33
@@ -23,6 +23,8 @@
#define RENDER_LINE_H
#include "rendering/render_object.h"
+#include "bidi.h"
+#include "misc/shared.h"
namespace DOM {
class AtomicString;
@@ -302,10 +304,10 @@
public:
RootInlineBox(RenderObject* obj)
: InlineFlowBox(obj), m_topOverflow(0), m_bottomOverflow(0), m_leftOverflow(0), m_rightOverflow(0),
- m_lineBreakObj(0), m_lineBreakPos(0),
+ m_lineBreakObj(0), m_lineBreakPos(0), m_lineBreakContext(0),
m_blockHeight(0), m_endsWithBreak(false), m_hasSelectedChildren(false), m_ellipsisBox(0)
{}
-
+
virtual void destroy(RenderArena* renderArena);
void detachEllipsisBox(RenderArena* renderArena);
@@ -321,8 +323,7 @@
virtual int rightOverflow() { return m_rightOverflow; }
virtual void setVerticalOverflowPositions(int top, int bottom) { m_topOverflow = top; m_bottomOverflow = bottom; }
void setHorizontalOverflowPositions(int left, int right) { m_leftOverflow = left; m_rightOverflow = right; }
- void setLineBreakInfo(RenderObject* obj, uint breakPos)
- { m_lineBreakObj = obj; m_lineBreakPos = breakPos; }
+ void setLineBreakInfo(RenderObject* obj, uint breakPos, BidiStatus* status, BidiContext* context);
void setLineBreakPos(int p) { m_lineBreakPos = p; }
void setBlockHeight(int h) { m_blockHeight = h; }
@@ -332,6 +333,8 @@
bool endsWithBreak() const { return m_endsWithBreak; }
RenderObject* lineBreakObj() const { return m_lineBreakObj; }
uint lineBreakPos() const { return m_lineBreakPos; }
+ BidiStatus lineBreakBidiStatus() const { return m_lineBreakBidiStatus; }
+ BidiContext* lineBreakBidiContext() const { return m_lineBreakContext.get(); }
void childRemoved(InlineBox* box);
@@ -380,6 +383,9 @@
RenderObject* m_lineBreakObj;
uint m_lineBreakPos;
+ BidiStatus m_lineBreakBidiStatus;
+ SharedPtr<BidiContext> m_lineBreakContext;
+
// The height of the block at the end of this line. This is where the next line starts.
int m_blockHeight;
More information about the webkit-changes
mailing list