|
|
|
Lines 69-112
static const PRUnichar kObjectSubstitute
|
Link Here
|
|---|
|
| 69 |
static const PRUnichar kLRE = 0x202A; |
69 |
static const PRUnichar kLRE = 0x202A; |
| 70 |
static const PRUnichar kRLE = 0x202B; |
70 |
static const PRUnichar kRLE = 0x202B; |
| 71 |
static const PRUnichar kLRO = 0x202D; |
71 |
static const PRUnichar kLRO = 0x202D; |
| 72 |
static const PRUnichar kRLO = 0x202E; |
72 |
static const PRUnichar kRLO = 0x202E; |
| 73 |
static const PRUnichar kPDF = 0x202C; |
73 |
static const PRUnichar kPDF = 0x202C; |
| 74 |
|
74 |
|
| 75 |
#define NS_BIDI_CONTROL_FRAME ((nsIFrame*)0xfffb1d1) |
75 |
#define NS_BIDI_CONTROL_FRAME ((nsIFrame*)0xfffb1d1) |
| 76 |
|
76 |
|
| 77 |
nsBidiPresUtils::nsBidiPresUtils() : mArraySize(8), |
77 |
struct BidiParagraphData { |
| 78 |
mIndexMap(nsnull), |
78 |
nsString mBuffer; |
| 79 |
mLevels(nsnull), |
79 |
nsTArray<PRUnichar> mEmbeddingStack; |
| 80 |
mSuccess(NS_ERROR_FAILURE), |
80 |
nsTArray<nsIFrame*> mLogicalFrames; |
| 81 |
mBidiEngine(nsnull) |
81 |
nsDataHashtable<nsISupportsHashKey, PRInt32> mContentToFrameIndex; |
| 82 |
{ |
82 |
PRPackedBool mIsVisual; |
| 83 |
mBidiEngine = new nsBidi(); |
83 |
nsBidiLevel mParaLevel; |
| 84 |
if (mBidiEngine && mContentToFrameIndex.Init()) { |
84 |
nsIContent* mPrevContent; |
| 85 |
mSuccess = NS_OK; |
85 |
nsBidi* mBidiEngine; |
|
|
86 |
|
| 87 |
void Init(nsBlockFrame *aBlockFrame) |
| 88 |
{ |
| 89 |
mContentToFrameIndex.Init(); |
| 90 |
mBidiEngine = new nsBidi(); |
| 91 |
mPrevContent = nsnull; |
| 92 |
mParaLevel = |
| 93 |
(NS_STYLE_DIRECTION_RTL == aBlockFrame->GetStyleVisibility()->mDirection) ? |
| 94 |
NSBIDI_RTL : NSBIDI_LTR; |
| 95 |
|
| 96 |
mIsVisual = aBlockFrame->PresContext()->IsVisualMode(); |
| 97 |
if (mIsVisual) { |
| 98 |
/** |
| 99 |
* Drill up in content to detect whether this is an element that needs to |
| 100 |
* be rendered with logical order even on visual pages. |
| 101 |
* |
| 102 |
* We always use logical order on form controls, firstly so that text |
| 103 |
* entry will be in logical order, but also because visual pages were |
| 104 |
* written with the assumption that even if the browser had no support |
| 105 |
* for right-to-left text rendering, it would use native widgets with |
| 106 |
* bidi support to display form controls. |
| 107 |
* |
| 108 |
* We also use logical order in XUL elements, since we expect that if a |
| 109 |
* XUL element appears in a visual page, it will be generated by an XBL |
| 110 |
* binding and contain localized text which will be in logical order. |
| 111 |
*/ |
| 112 |
for (nsIContent* content = aBlockFrame->GetContent() ; content; |
| 113 |
content = content->GetParent()) { |
| 114 |
if (content->IsNodeOfType(nsINode::eHTML_FORM_CONTROL) || |
| 115 |
content->IsXUL()) { |
| 116 |
mIsVisual = PR_FALSE; |
| 117 |
break; |
| 118 |
} |
| 119 |
} |
| 120 |
} |
| 86 |
} |
121 |
} |
| 87 |
} |
|
|
| 88 |
|
122 |
|
| 89 |
nsBidiPresUtils::~nsBidiPresUtils() |
123 |
void Destroy() { delete mBidiEngine; } |
| 90 |
{ |
124 |
|
| 91 |
if (mLevels) { |
125 |
nsresult SetPara() |
| 92 |
delete[] mLevels; |
126 |
{ |
|
|
127 |
return mBidiEngine->SetPara(mBuffer.get(), BufferLength(), |
| 128 |
mParaLevel, nsnull); |
| 93 |
} |
129 |
} |
| 94 |
if (mIndexMap) { |
130 |
|
| 95 |
delete[] mIndexMap; |
131 |
nsresult CountRuns(PRInt32 *runCount){ return mBidiEngine->CountRuns(runCount); } |
|
|
132 |
|
| 133 |
nsresult GetLogicalRun(PRInt32 aLogicalStart, |
| 134 |
PRInt32* aLogicalLimit, |
| 135 |
nsBidiLevel* aLevel) |
| 136 |
{ |
| 137 |
nsresult rv = mBidiEngine->GetLogicalRun(aLogicalStart, |
| 138 |
aLogicalLimit, aLevel); |
| 139 |
if (mIsVisual || NS_FAILED(rv)) |
| 140 |
*aLevel = mParaLevel; |
| 141 |
return rv; |
| 96 |
} |
142 |
} |
| 97 |
delete mBidiEngine; |
|
|
| 98 |
} |
| 99 |
|
143 |
|
| 100 |
PRBool |
144 |
void ResetData() |
| 101 |
nsBidiPresUtils::IsSuccessful() const |
145 |
{ |
| 102 |
{ |
146 |
mLogicalFrames.Clear(); |
| 103 |
return NS_SUCCEEDED(mSuccess); |
147 |
mContentToFrameIndex.Clear(); |
| 104 |
} |
148 |
mBuffer.SetLength(0); |
|
|
149 |
for (PRUint32 i = 0; i < mEmbeddingStack.Length(); ++i) { |
| 150 |
mBuffer.Append(mEmbeddingStack[i]); |
| 151 |
mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME); |
| 152 |
} |
| 153 |
} |
| 154 |
|
| 155 |
void AppendFrame(nsIFrame* aFrame, nsIContent* aContent = nsnull) |
| 156 |
{ |
| 157 |
if (aContent) { |
| 158 |
mContentToFrameIndex.Put(aContent, FrameCount()); |
| 159 |
} |
| 160 |
mLogicalFrames.AppendElement(aFrame); |
| 161 |
} |
| 162 |
|
| 163 |
PRInt32 GetLastFrameForContent(nsIContent *aContent) |
| 164 |
{ |
| 165 |
PRInt32 index = 0; |
| 166 |
mContentToFrameIndex.Get(aContent, &index); |
| 167 |
return index; |
| 168 |
} |
| 169 |
|
| 170 |
PRInt32 FrameCount(){ return mLogicalFrames.Length(); } |
| 171 |
|
| 172 |
PRInt32 BufferLength(){ return mBuffer.Length(); } |
| 173 |
|
| 174 |
nsIFrame* FrameAt(PRInt32 aIndex){ return mLogicalFrames[aIndex]; } |
| 175 |
|
| 176 |
void AppendUnichar(PRUnichar aCh){ mBuffer.Append(aCh); } |
| 177 |
|
| 178 |
void AppendString(const nsDependentSubstring& aString){ mBuffer.Append(aString); } |
| 179 |
|
| 180 |
void PushBidiControl(PRUnichar aCh) |
| 181 |
{ |
| 182 |
mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME); |
| 183 |
mBuffer.Append(aCh); |
| 184 |
mEmbeddingStack.AppendElement(aCh); |
| 185 |
} |
| 186 |
|
| 187 |
void PopBidiControl() |
| 188 |
{ |
| 189 |
mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME); |
| 190 |
mBuffer.Append(kPDF); |
| 191 |
NS_ASSERTION(mEmbeddingStack.Length(), "embedding/override underflow"); |
| 192 |
mEmbeddingStack.TruncateLength(mEmbeddingStack.Length() - 1); |
| 193 |
} |
| 194 |
|
| 195 |
void ClearBidiControls() |
| 196 |
{ |
| 197 |
for (PRUint32 i = 0; i < mEmbeddingStack.Length(); ++i) { |
| 198 |
mBuffer.Append(kPDF); |
| 199 |
mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME); |
| 200 |
} |
| 201 |
} |
| 202 |
}; |
| 203 |
|
| 204 |
struct BidiLineData { |
| 205 |
nsTArray<nsIFrame*> mLogicalFrames; |
| 206 |
nsTArray<nsIFrame*> mVisualFrames; |
| 207 |
nsTArray<PRInt32> mIndexMap; |
| 208 |
nsTArray<PRUint8> mLevels; |
| 209 |
PRBool mIsReordered; |
| 210 |
|
| 211 |
BidiLineData(nsIFrame* aFirstFrameOnLine, PRInt32 aNumFramesOnLine) |
| 212 |
{ |
| 213 |
/** |
| 214 |
* Initialize the logically-ordered array of frames using the top-level |
| 215 |
* frames of a single line |
| 216 |
*/ |
| 217 |
mLogicalFrames.Clear(); |
| 218 |
|
| 219 |
PRBool isReordered = PR_FALSE; |
| 220 |
PRBool hasRTLFrames = PR_FALSE; |
| 221 |
|
| 222 |
for (nsIFrame* frame = aFirstFrameOnLine; |
| 223 |
frame && aNumFramesOnLine--; |
| 224 |
frame = frame->GetNextSibling()) { |
| 225 |
AppendFrame(frame); |
| 226 |
PRUint8 level = nsBidiPresUtils::GetFrameEmbeddingLevel(frame); |
| 227 |
mLevels.AppendElement(level); |
| 228 |
mIndexMap.AppendElement(0); |
| 229 |
if (level & 1) { |
| 230 |
hasRTLFrames = PR_TRUE; |
| 231 |
} |
| 232 |
} |
| 233 |
|
| 234 |
// Reorder the line |
| 235 |
nsBidi::ReorderVisual(mLevels.Elements(), FrameCount(), |
| 236 |
mIndexMap.Elements()); |
| 237 |
|
| 238 |
for (PRInt32 i = 0; i < FrameCount(); i++) { |
| 239 |
mVisualFrames.AppendElement(LogicalFrameAt(mIndexMap[i])); |
| 240 |
if (i != mIndexMap[i]) { |
| 241 |
isReordered = PR_TRUE; |
| 242 |
} |
| 243 |
} |
| 244 |
|
| 245 |
// If there's an RTL frame, assume the line is reordered |
| 246 |
mIsReordered = isReordered || hasRTLFrames; |
| 247 |
} |
| 248 |
|
| 249 |
void AppendFrame(nsIFrame* aFrame){ mLogicalFrames.AppendElement(aFrame); } |
| 250 |
|
| 251 |
PRInt32 FrameCount(){ return mLogicalFrames.Length(); } |
| 252 |
|
| 253 |
nsIFrame* LogicalFrameAt(PRInt32 aIndex){ return mLogicalFrames[aIndex]; } |
| 254 |
|
| 255 |
nsIFrame* VisualFrameAt(PRInt32 aIndex){ return mVisualFrames[aIndex]; } |
| 256 |
}; |
| 105 |
|
257 |
|
| 106 |
/* Some helper methods for Resolve() */ |
258 |
/* Some helper methods for Resolve() */ |
| 107 |
|
259 |
|
| 108 |
// Should this frame be split between text runs? |
260 |
// Should this frame be split between text runs? |
| 109 |
PRBool |
261 |
PRBool |
| 110 |
IsBidiSplittable(nsIFrame* aFrame) { |
262 |
IsBidiSplittable(nsIFrame* aFrame) { |
| 111 |
nsIAtom* frameType = aFrame->GetType(); |
263 |
nsIAtom* frameType = aFrame->GetType(); |
| 112 |
// Bidi inline containers should be split, unless they're line frames. |
264 |
// Bidi inline containers should be split, unless they're line frames. |
|
Lines 318-529
AdvanceLineIteratorToFrame(nsIFrame* aFr
|
Link Here
|
|---|
|
| 318 |
* The rendering layer requires each text frame to contain text in only one |
470 |
* The rendering layer requires each text frame to contain text in only one |
| 319 |
* direction, so we may need to call EnsureBidiContinuation() to split frames. |
471 |
* direction, so we may need to call EnsureBidiContinuation() to split frames. |
| 320 |
* We may also need to call RemoveBidiContinuation() to convert frames created |
472 |
* We may also need to call RemoveBidiContinuation() to convert frames created |
| 321 |
* by EnsureBidiContinuation() in previous reflows into fluid continuations. |
473 |
* by EnsureBidiContinuation() in previous reflows into fluid continuations. |
| 322 |
*/ |
474 |
*/ |
| 323 |
nsresult |
475 |
nsresult |
| 324 |
nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame) |
476 |
nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame) |
| 325 |
{ |
477 |
{ |
| 326 |
mLogicalFrames.Clear(); |
478 |
BidiParagraphData bpd; |
| 327 |
mContentToFrameIndex.Clear(); |
479 |
bpd.Init(aBlockFrame); |
| 328 |
mBuffer.SetLength(0); |
|
|
| 329 |
mEmbeddingStack.Clear(); |
| 330 |
|
| 331 |
nsPresContext *presContext = aBlockFrame->PresContext(); |
| 332 |
|
| 333 |
const nsStyleVisibility* vis = aBlockFrame->GetStyleVisibility(); |
| 334 |
|
| 335 |
mParaLevel = (NS_STYLE_DIRECTION_RTL == vis->mDirection) ? |
| 336 |
NSBIDI_RTL : NSBIDI_LTR; |
| 337 |
|
| 338 |
mLineIter = new nsBlockInFlowLineIterator(aBlockFrame, |
| 339 |
aBlockFrame->begin_lines(), |
| 340 |
PR_FALSE); |
| 341 |
if (mLineIter->GetLine() == aBlockFrame->end_lines()) { |
| 342 |
// Advance to first valid line (might be in a next-continuation) |
| 343 |
mLineIter->Next(); |
| 344 |
} |
| 345 |
|
| 346 |
mIsVisual = presContext->IsVisualMode(); |
| 347 |
if (mIsVisual) { |
| 348 |
/** |
| 349 |
* Drill up in content to detect whether this is an element that needs to be |
| 350 |
* rendered with logical order even on visual pages. |
| 351 |
* |
| 352 |
* We always use logical order on form controls, firstly so that text entry |
| 353 |
* will be in logical order, but also because visual pages were written with |
| 354 |
* the assumption that even if the browser had no support for right-to-left |
| 355 |
* text rendering, it would use native widgets with bidi support to display |
| 356 |
* form controls. |
| 357 |
* |
| 358 |
* We also use logical order in XUL elements, since we expect that if a XUL |
| 359 |
* element appears in a visual page, it will be generated by an XBL binding |
| 360 |
* and contain localized text which will be in logical order. |
| 361 |
*/ |
| 362 |
for (nsIContent* content = aBlockFrame->GetContent() ; content; |
| 363 |
content = content->GetParent()) { |
| 364 |
if (content->IsNodeOfType(nsINode::eHTML_FORM_CONTROL) || |
| 365 |
content->IsXUL()) { |
| 366 |
mIsVisual = PR_FALSE; |
| 367 |
break; |
| 368 |
} |
| 369 |
} |
| 370 |
} |
| 371 |
mPrevFrame = nsnull; |
| 372 |
|
480 |
|
| 373 |
// handle bidi-override being set on the block itself before calling |
481 |
// handle bidi-override being set on the block itself before calling |
| 374 |
// TraverseFrames. |
482 |
// TraverseFrames. |
| 375 |
const nsStyleTextReset* text = aBlockFrame->GetStyleTextReset(); |
483 |
const nsStyleTextReset* text = aBlockFrame->GetStyleTextReset(); |
| 376 |
PRUnichar ch = 0; |
484 |
PRUnichar ch = 0; |
| 377 |
if (text->mUnicodeBidi == NS_STYLE_UNICODE_BIDI_OVERRIDE) { |
485 |
if (text->mUnicodeBidi == NS_STYLE_UNICODE_BIDI_OVERRIDE) { |
|
|
486 |
const nsStyleVisibility* vis = aBlockFrame->GetStyleVisibility(); |
| 378 |
if (NS_STYLE_DIRECTION_RTL == vis->mDirection) { |
487 |
if (NS_STYLE_DIRECTION_RTL == vis->mDirection) { |
| 379 |
ch = kRLO; |
488 |
ch = kRLO; |
| 380 |
} |
489 |
} |
| 381 |
else if (NS_STYLE_DIRECTION_LTR == vis->mDirection) { |
490 |
else if (NS_STYLE_DIRECTION_LTR == vis->mDirection) { |
| 382 |
ch = kLRO; |
491 |
ch = kLRO; |
| 383 |
} |
492 |
} |
| 384 |
if (ch != 0) { |
493 |
if (ch != 0) { |
| 385 |
mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME); |
494 |
bpd.PushBidiControl(ch); |
| 386 |
mBuffer.Append(ch); |
|
|
| 387 |
mEmbeddingStack.AppendElement(ch); |
| 388 |
} |
495 |
} |
| 389 |
} |
496 |
} |
| 390 |
mPrevContent = nsnull; |
|
|
| 391 |
for (nsBlockFrame* block = aBlockFrame; block; |
497 |
for (nsBlockFrame* block = aBlockFrame; block; |
| 392 |
block = static_cast<nsBlockFrame*>(block->GetNextContinuation())) { |
498 |
block = static_cast<nsBlockFrame*>(block->GetNextContinuation())) { |
| 393 |
block->RemoveStateBits(NS_BLOCK_NEEDS_BIDI_RESOLUTION); |
499 |
block->RemoveStateBits(NS_BLOCK_NEEDS_BIDI_RESOLUTION); |
| 394 |
TraverseFrames(aBlockFrame, block->GetFirstChild(nsnull)); |
500 |
TraverseFrames(aBlockFrame, block->GetFirstChild(nsnull), &bpd); |
| 395 |
} |
501 |
} |
| 396 |
|
502 |
|
| 397 |
if (ch != 0) { |
503 |
if (ch != 0) { |
| 398 |
mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME); |
504 |
bpd.PopBidiControl(); |
| 399 |
mBuffer.Append(kPDF); |
|
|
| 400 |
NS_ASSERTION(mEmbeddingStack.Length(), "embedding/override underflow"); |
| 401 |
mEmbeddingStack.TruncateLength(mEmbeddingStack.Length() - 1); |
| 402 |
} |
505 |
} |
| 403 |
|
506 |
|
| 404 |
// Resolve final paragraph |
507 |
// Resolve final paragraph |
| 405 |
ResolveParagraph(aBlockFrame); |
508 |
nsresult rv = ResolveParagraph(aBlockFrame, &bpd); |
| 406 |
return mSuccess; |
509 |
bpd.Destroy(); |
|
|
510 |
return rv; |
| 407 |
} |
511 |
} |
| 408 |
|
512 |
|
| 409 |
void |
513 |
nsresult |
| 410 |
nsBidiPresUtils::ResolveParagraph(nsBlockFrame* aBlockFrame) |
514 |
nsBidiPresUtils::ResolveParagraph(nsBlockFrame* aBlockFrame, |
|
|
515 |
BidiParagraphData* aBpd) |
| 411 |
{ |
516 |
{ |
| 412 |
nsPresContext *presContext = aBlockFrame->PresContext(); |
517 |
nsPresContext *presContext = aBlockFrame->PresContext(); |
| 413 |
PRInt32 bufferLength = mBuffer.Length(); |
|
|
| 414 |
|
518 |
|
| 415 |
if (bufferLength < 1) { |
519 |
if (aBpd->BufferLength() < 1) { |
| 416 |
mSuccess = NS_OK; |
520 |
return NS_OK; |
| 417 |
return; |
|
|
| 418 |
} |
521 |
} |
| 419 |
mBuffer.ReplaceChar("\t\r\n", kSpace); |
522 |
aBpd->mBuffer.ReplaceChar("\t\r\n", kSpace); |
| 420 |
|
523 |
|
| 421 |
PRInt32 runCount; |
524 |
PRInt32 runCount; |
| 422 |
PRUint8 embeddingLevel = mParaLevel; |
525 |
PRUint8 embeddingLevel = aBpd->mParaLevel; |
| 423 |
|
526 |
|
| 424 |
mSuccess = mBidiEngine->SetPara(mBuffer.get(), bufferLength, mParaLevel, nsnull); |
527 |
nsresult rv = aBpd->SetPara(); |
| 425 |
if (NS_FAILED(mSuccess) ) { |
528 |
NS_ENSURE_SUCCESS(rv, rv); |
| 426 |
return; |
|
|
| 427 |
} |
| 428 |
|
529 |
|
| 429 |
mSuccess = mBidiEngine->CountRuns(&runCount); |
530 |
rv = aBpd->CountRuns(&runCount); |
| 430 |
if (NS_FAILED(mSuccess) ) { |
531 |
NS_ENSURE_SUCCESS(rv, rv); |
| 431 |
return; |
532 |
|
| 432 |
} |
|
|
| 433 |
PRInt32 runLength = 0; // the length of the current run of text |
533 |
PRInt32 runLength = 0; // the length of the current run of text |
| 434 |
PRInt32 lineOffset = 0; // the start of the current run |
534 |
PRInt32 lineOffset = 0; // the start of the current run |
| 435 |
PRInt32 logicalLimit = 0; // the end of the current run + 1 |
535 |
PRInt32 logicalLimit = 0; // the end of the current run + 1 |
| 436 |
PRInt32 numRun = -1; |
536 |
PRInt32 numRun = -1; |
| 437 |
PRInt32 fragmentLength = 0; // the length of the current text frame |
537 |
PRInt32 fragmentLength = 0; // the length of the current text frame |
| 438 |
PRInt32 frameIndex = -1; // index to the frames in mLogicalFrames |
538 |
PRInt32 frameIndex = -1; // index to the frames in mLogicalFrames |
| 439 |
PRInt32 frameCount = mLogicalFrames.Length(); |
539 |
PRInt32 frameCount = aBpd->FrameCount(); |
| 440 |
PRInt32 contentOffset = 0; // offset of current frame in its content node |
540 |
PRInt32 contentOffset = 0; // offset of current frame in its content node |
| 441 |
PRBool isTextFrame = PR_FALSE; |
541 |
PRBool isTextFrame = PR_FALSE; |
| 442 |
nsIFrame* frame = nsnull; |
542 |
nsIFrame* frame = nsnull; |
| 443 |
nsIContent* content = nsnull; |
543 |
nsIContent* content = nsnull; |
| 444 |
PRInt32 contentTextLength; |
544 |
PRInt32 contentTextLength; |
| 445 |
|
545 |
|
| 446 |
FramePropertyTable *propTable = presContext->PropertyTable(); |
546 |
FramePropertyTable *propTable = presContext->PropertyTable(); |
| 447 |
|
547 |
|
|
|
548 |
|
| 549 |
nsBlockInFlowLineIterator lineIter(aBlockFrame, |
| 550 |
aBlockFrame->begin_lines(), |
| 551 |
PR_FALSE); |
| 552 |
if (lineIter.GetLine() == aBlockFrame->end_lines()) { |
| 553 |
// Advance to first valid line (might be in a next-continuation) |
| 554 |
lineIter.Next(); |
| 555 |
} |
| 556 |
nsIFrame* prevFrame = nsnull; |
| 557 |
|
| 448 |
if (frameCount == 1 && runCount == 1) { |
558 |
if (frameCount == 1 && runCount == 1) { |
| 449 |
// Nothing more to do, just make sure that the frame has the right |
559 |
// Nothing more to do, just make sure that the frame has the right |
| 450 |
// embedding level. |
560 |
// embedding level. |
| 451 |
if (mIsVisual || |
561 |
aBpd->GetLogicalRun(lineOffset, &logicalLimit, &embeddingLevel); |
| 452 |
NS_FAILED(mBidiEngine->GetLogicalRun(lineOffset, &logicalLimit, |
|
|
| 453 |
&embeddingLevel))) { |
| 454 |
embeddingLevel = mParaLevel; |
| 455 |
} |
| 456 |
|
562 |
|
| 457 |
frame = mLogicalFrames[0]; |
563 |
frame = aBpd->FrameAt(0); |
| 458 |
nsBidiLevel oldEmbeddingLevel = NS_GET_EMBEDDING_LEVEL(frame); |
564 |
nsBidiLevel oldEmbeddingLevel = NS_GET_EMBEDDING_LEVEL(frame); |
| 459 |
nsBidiLevel oldBaseLevel = NS_GET_BASE_LEVEL(frame); |
565 |
nsBidiLevel oldBaseLevel = NS_GET_BASE_LEVEL(frame); |
| 460 |
|
566 |
|
| 461 |
if (oldEmbeddingLevel != embeddingLevel || |
567 |
if (oldEmbeddingLevel != embeddingLevel || |
| 462 |
oldBaseLevel != mParaLevel) { |
568 |
oldBaseLevel != aBpd->mParaLevel) { |
| 463 |
frame->Properties().Set(nsIFrame::EmbeddingLevelProperty(), |
569 |
frame->Properties().Set(nsIFrame::EmbeddingLevelProperty(), |
| 464 |
NS_INT32_TO_PTR(embeddingLevel)); |
570 |
NS_INT32_TO_PTR(embeddingLevel)); |
| 465 |
frame->Properties().Set(nsIFrame::BaseLevelProperty(), |
571 |
frame->Properties().Set(nsIFrame::BaseLevelProperty(), |
| 466 |
NS_INT32_TO_PTR(mParaLevel)); |
572 |
NS_INT32_TO_PTR(aBpd->mParaLevel)); |
| 467 |
AdvanceLineIteratorToFrame(frame, mLineIter, mPrevFrame); |
573 |
AdvanceLineIteratorToFrame(frame, &lineIter, prevFrame); |
| 468 |
mLineIter->GetLine()->MarkDirty(); |
574 |
lineIter.GetLine()->MarkDirty(); |
| 469 |
if (frame->GetType() == nsGkAtoms::textFrame) { |
575 |
if (frame->GetType() == nsGkAtoms::textFrame) { |
| 470 |
frame->AddStateBits(NS_FRAME_IS_BIDI); |
576 |
frame->AddStateBits(NS_FRAME_IS_BIDI); |
| 471 |
} |
577 |
} |
| 472 |
} |
578 |
} |
| 473 |
|
579 |
|
| 474 |
mSuccess = NS_OK; |
580 |
return NS_OK; |
| 475 |
return; |
|
|
| 476 |
} |
581 |
} |
| 477 |
|
582 |
|
| 478 |
PRBool lineNeedsUpdate = PR_FALSE; |
583 |
PRBool lineNeedsUpdate = PR_FALSE; |
| 479 |
|
584 |
|
| 480 |
#ifdef NOISY_BIDI |
585 |
#ifdef NOISY_BIDI |
| 481 |
if (mBuffer[0] != kObjectSubstitute) { |
586 |
if (aBpd->mBuffer[0] != kObjectSubstitute) { |
| 482 |
printf("Before Resolve(), aBlockFrame=0x%p, mBuffer='%s', frameCount=%d\n", |
587 |
printf("Before Resolve(), aBlockFrame=0x%p, mBuffer='%s', frameCount=%d\n", |
| 483 |
(void*)aBlockFrame, NS_ConvertUTF16toUTF8(mBuffer).get(), frameCount); |
588 |
(void*)aBlockFrame, NS_ConvertUTF16toUTF8(aBpd->mBuffer).get(), frameCount); |
| 484 |
#ifdef REALLY_NOISY_BIDI |
589 |
#ifdef REALLY_NOISY_BIDI |
| 485 |
printf(" frameTree=:\n"); |
590 |
printf(" frameTree=:\n"); |
| 486 |
nsFrame::DumpFrameTree(aBlockFrame); |
591 |
nsFrame::DumpFrameTree(aBlockFrame); |
| 487 |
#endif |
592 |
#endif |
| 488 |
} |
593 |
} |
| 489 |
#endif |
594 |
#endif |
| 490 |
for (; ;) { |
595 |
for (; ;) { |
| 491 |
if (fragmentLength <= 0) { |
596 |
if (fragmentLength <= 0) { |
| 492 |
// Get the next frame from mLogicalFrames |
597 |
// Get the next frame from mLogicalFrames |
| 493 |
if (++frameIndex >= frameCount) { |
598 |
if (++frameIndex >= frameCount) { |
| 494 |
break; |
599 |
break; |
| 495 |
} |
600 |
} |
| 496 |
frame = mLogicalFrames[frameIndex]; |
601 |
frame = aBpd->FrameAt(frameIndex); |
| 497 |
lineNeedsUpdate = PR_TRUE; |
602 |
lineNeedsUpdate = PR_TRUE; |
| 498 |
if (frame == NS_BIDI_CONTROL_FRAME || |
603 |
if (frame == NS_BIDI_CONTROL_FRAME || |
| 499 |
nsGkAtoms::textFrame != frame->GetType()) { |
604 |
nsGkAtoms::textFrame != frame->GetType()) { |
| 500 |
/* |
605 |
/* |
| 501 |
* Any non-text frame corresponds to a single character in the text buffer |
606 |
* Any non-text frame corresponds to a single character in the text buffer |
| 502 |
* (a bidi control character, LINE SEPARATOR, or OBJECT SUBSTITUTE) |
607 |
* (a bidi control character, LINE SEPARATOR, or OBJECT SUBSTITUTE) |
| 503 |
*/ |
608 |
*/ |
| 504 |
isTextFrame = PR_FALSE; |
609 |
isTextFrame = PR_FALSE; |
| 505 |
fragmentLength = 1; |
610 |
fragmentLength = 1; |
| 506 |
} |
611 |
} |
| 507 |
else { |
612 |
else { |
| 508 |
content = frame->GetContent(); |
613 |
content = frame->GetContent(); |
| 509 |
if (!content) { |
614 |
if (!content) { |
| 510 |
mSuccess = NS_OK; |
615 |
rv = NS_OK; |
| 511 |
break; |
616 |
break; |
| 512 |
} |
617 |
} |
| 513 |
contentTextLength = content->TextLength(); |
618 |
contentTextLength = content->TextLength(); |
| 514 |
if (contentTextLength == 0) { |
619 |
if (contentTextLength == 0) { |
| 515 |
frame->AdjustOffsetsForBidi(0, 0); |
620 |
frame->AdjustOffsetsForBidi(0, 0); |
| 516 |
// Set the base level and embedding level of the current run even |
621 |
// Set the base level and embedding level of the current run even |
| 517 |
// on an empty frame. Otherwise frame reordering will not be correct. |
622 |
// on an empty frame. Otherwise frame reordering will not be correct. |
| 518 |
propTable->Set(frame, nsIFrame::EmbeddingLevelProperty(), |
623 |
propTable->Set(frame, nsIFrame::EmbeddingLevelProperty(), |
| 519 |
NS_INT32_TO_PTR(embeddingLevel)); |
624 |
NS_INT32_TO_PTR(embeddingLevel)); |
| 520 |
propTable->Set(frame, nsIFrame::BaseLevelProperty(), |
625 |
propTable->Set(frame, nsIFrame::BaseLevelProperty(), |
| 521 |
NS_INT32_TO_PTR(mParaLevel)); |
626 |
NS_INT32_TO_PTR(aBpd->mParaLevel)); |
| 522 |
continue; |
627 |
continue; |
| 523 |
} |
628 |
} |
| 524 |
PRInt32 start, end; |
629 |
PRInt32 start, end; |
| 525 |
frame->GetOffsets(start, end); |
630 |
frame->GetOffsets(start, end); |
| 526 |
NS_ASSERTION(!(contentTextLength < end - start), |
631 |
NS_ASSERTION(!(contentTextLength < end - start), |
| 527 |
"Frame offsets don't fit in content"); |
632 |
"Frame offsets don't fit in content"); |
| 528 |
fragmentLength = NS_MIN(contentTextLength, end - start); |
633 |
fragmentLength = NS_MIN(contentTextLength, end - start); |
| 529 |
contentOffset = start; |
634 |
contentOffset = start; |
|
Lines 532-636
nsBidiPresUtils::ResolveParagraph(nsBloc
|
Link Here
|
|---|
|
| 532 |
} // if (fragmentLength <= 0) |
637 |
} // if (fragmentLength <= 0) |
| 533 |
|
638 |
|
| 534 |
if (runLength <= 0) { |
639 |
if (runLength <= 0) { |
| 535 |
// Get the next run of text from the Bidi engine |
640 |
// Get the next run of text from the Bidi engine |
| 536 |
if (++numRun >= runCount) { |
641 |
if (++numRun >= runCount) { |
| 537 |
break; |
642 |
break; |
| 538 |
} |
643 |
} |
| 539 |
lineOffset = logicalLimit; |
644 |
lineOffset = logicalLimit; |
| 540 |
if (NS_FAILED(mBidiEngine->GetLogicalRun( |
645 |
if (NS_FAILED(aBpd->GetLogicalRun( |
| 541 |
lineOffset, &logicalLimit, &embeddingLevel) ) ) { |
646 |
lineOffset, &logicalLimit, &embeddingLevel) ) ) { |
| 542 |
break; |
647 |
break; |
| 543 |
} |
648 |
} |
| 544 |
runLength = logicalLimit - lineOffset; |
649 |
runLength = logicalLimit - lineOffset; |
| 545 |
if (mIsVisual) { |
|
|
| 546 |
embeddingLevel = mParaLevel; |
| 547 |
} |
| 548 |
} // if (runLength <= 0) |
650 |
} // if (runLength <= 0) |
| 549 |
|
651 |
|
| 550 |
if (frame == NS_BIDI_CONTROL_FRAME) { |
652 |
if (frame == NS_BIDI_CONTROL_FRAME) { |
| 551 |
frame = nsnull; |
653 |
frame = nsnull; |
| 552 |
++lineOffset; |
654 |
++lineOffset; |
| 553 |
} |
655 |
} |
| 554 |
else { |
656 |
else { |
| 555 |
propTable->Set(frame, nsIFrame::EmbeddingLevelProperty(), |
657 |
propTable->Set(frame, nsIFrame::EmbeddingLevelProperty(), |
| 556 |
NS_INT32_TO_PTR(embeddingLevel)); |
658 |
NS_INT32_TO_PTR(embeddingLevel)); |
| 557 |
propTable->Set(frame, nsIFrame::BaseLevelProperty(), |
659 |
propTable->Set(frame, nsIFrame::BaseLevelProperty(), |
| 558 |
NS_INT32_TO_PTR(mParaLevel)); |
660 |
NS_INT32_TO_PTR(aBpd->mParaLevel)); |
| 559 |
if (isTextFrame) { |
661 |
if (isTextFrame) { |
| 560 |
if ( (runLength > 0) && (runLength < fragmentLength) ) { |
662 |
if ( (runLength > 0) && (runLength < fragmentLength) ) { |
| 561 |
/* |
663 |
/* |
| 562 |
* The text in this frame continues beyond the end of this directional run. |
664 |
* The text in this frame continues beyond the end of this directional run. |
| 563 |
* Create a non-fluid continuation frame for the next directional run. |
665 |
* Create a non-fluid continuation frame for the next directional run. |
| 564 |
*/ |
666 |
*/ |
| 565 |
if (lineNeedsUpdate) { |
667 |
if (lineNeedsUpdate) { |
| 566 |
AdvanceLineIteratorToFrame(frame, mLineIter, mPrevFrame); |
668 |
AdvanceLineIteratorToFrame(frame, &lineIter, prevFrame); |
| 567 |
lineNeedsUpdate = PR_FALSE; |
669 |
lineNeedsUpdate = PR_FALSE; |
| 568 |
} |
670 |
} |
| 569 |
mLineIter->GetLine()->MarkDirty(); |
671 |
lineIter.GetLine()->MarkDirty(); |
| 570 |
nsIFrame* nextBidi; |
672 |
nsIFrame* nextBidi; |
| 571 |
PRInt32 runEnd = contentOffset + runLength; |
673 |
PRInt32 runEnd = contentOffset + runLength; |
| 572 |
EnsureBidiContinuation(frame, &nextBidi, frameIndex, |
674 |
rv = EnsureBidiContinuation(frame, &nextBidi, frameIndex, |
| 573 |
contentOffset, |
675 |
contentOffset, |
| 574 |
runEnd); |
676 |
runEnd); |
| 575 |
if (NS_FAILED(mSuccess)) { |
677 |
if (NS_FAILED(rv)) { |
| 576 |
break; |
678 |
break; |
| 577 |
} |
679 |
} |
| 578 |
nextBidi->AdjustOffsetsForBidi(runEnd, |
680 |
nextBidi->AdjustOffsetsForBidi(runEnd, |
| 579 |
contentOffset + fragmentLength); |
681 |
contentOffset + fragmentLength); |
| 580 |
frame = nextBidi; |
682 |
frame = nextBidi; |
| 581 |
contentOffset = runEnd; |
683 |
contentOffset = runEnd; |
| 582 |
} // if (runLength < fragmentLength) |
684 |
} // if (runLength < fragmentLength) |
| 583 |
else { |
685 |
else { |
| 584 |
if (contentOffset + fragmentLength == contentTextLength) { |
686 |
if (contentOffset + fragmentLength == contentTextLength) { |
| 585 |
/* |
687 |
/* |
| 586 |
* We have finished all the text in this content node. Convert any |
688 |
* We have finished all the text in this content node. Convert any |
| 587 |
* further non-fluid continuations to fluid continuations and advance |
689 |
* further non-fluid continuations to fluid continuations and advance |
| 588 |
* frameIndex to the last frame in the content node |
690 |
* frameIndex to the last frame in the content node |
| 589 |
*/ |
691 |
*/ |
| 590 |
PRInt32 newIndex = 0; |
692 |
PRInt32 newIndex = aBpd->GetLastFrameForContent(content); |
| 591 |
mContentToFrameIndex.Get(content, &newIndex); |
|
|
| 592 |
if (newIndex > frameIndex) { |
693 |
if (newIndex > frameIndex) { |
| 593 |
RemoveBidiContinuation(frame, frameIndex, newIndex, lineOffset); |
694 |
RemoveBidiContinuation(aBpd, frame, |
|
|
695 |
frameIndex, newIndex, lineOffset); |
| 594 |
frameIndex = newIndex; |
696 |
frameIndex = newIndex; |
| 595 |
} |
697 |
} |
| 596 |
} else if (fragmentLength > 0 && runLength > fragmentLength) { |
698 |
} else if (fragmentLength > 0 && runLength > fragmentLength) { |
| 597 |
/* |
699 |
/* |
| 598 |
* There is more text that belongs to this directional run in the next |
700 |
* There is more text that belongs to this directional run in the next |
| 599 |
* text frame: make sure it is a fluid continuation of the current frame. |
701 |
* text frame: make sure it is a fluid continuation of the current frame. |
| 600 |
* Do not advance frameIndex, because the next frame may contain |
702 |
* Do not advance frameIndex, because the next frame may contain |
| 601 |
* multi-directional text and need to be split |
703 |
* multi-directional text and need to be split |
| 602 |
*/ |
704 |
*/ |
| 603 |
PRInt32 newIndex = frameIndex; |
705 |
PRInt32 newIndex = frameIndex; |
| 604 |
do { |
706 |
do { |
| 605 |
} while (++newIndex < frameCount && |
707 |
} while (++newIndex < frameCount && |
| 606 |
mLogicalFrames[newIndex] == NS_BIDI_CONTROL_FRAME); |
708 |
aBpd->FrameAt(newIndex) == NS_BIDI_CONTROL_FRAME); |
| 607 |
if (newIndex < frameCount) { |
709 |
if (newIndex < frameCount) { |
| 608 |
RemoveBidiContinuation(frame, frameIndex, newIndex, lineOffset); |
710 |
RemoveBidiContinuation(aBpd, frame, |
|
|
711 |
frameIndex, newIndex, lineOffset); |
| 609 |
} |
712 |
} |
| 610 |
} else if (runLength == fragmentLength && |
713 |
} else if (runLength == fragmentLength && |
| 611 |
numRun + 1 < runCount) { |
714 |
numRun + 1 < runCount) { |
| 612 |
/* |
715 |
/* |
| 613 |
* If the directional run ends at the end of the frame, and this is |
716 |
* If the directional run ends at the end of the frame, and this is |
| 614 |
* not the end of our paragraph, make sure that the next frame is a |
717 |
* not the end of our paragraph, make sure that the next frame is a |
| 615 |
* non-fluid continuation |
718 |
* non-fluid continuation |
| 616 |
*/ |
719 |
*/ |
| 617 |
nsIFrame* next = frame->GetNextInFlow(); |
720 |
nsIFrame* next = frame->GetNextInFlow(); |
| 618 |
if (next) { |
721 |
if (next) { |
| 619 |
frame->SetNextContinuation(next); |
722 |
frame->SetNextContinuation(next); |
| 620 |
next->SetPrevContinuation(frame); |
723 |
next->SetPrevContinuation(frame); |
| 621 |
} |
724 |
} |
| 622 |
} |
725 |
} |
| 623 |
frame->AdjustOffsetsForBidi(contentOffset, contentOffset + fragmentLength); |
726 |
frame->AdjustOffsetsForBidi(contentOffset, contentOffset + fragmentLength); |
| 624 |
if (lineNeedsUpdate) { |
727 |
if (lineNeedsUpdate) { |
| 625 |
AdvanceLineIteratorToFrame(frame, mLineIter, mPrevFrame); |
728 |
AdvanceLineIteratorToFrame(frame, &lineIter, prevFrame); |
| 626 |
lineNeedsUpdate = PR_FALSE; |
729 |
lineNeedsUpdate = PR_FALSE; |
| 627 |
} |
730 |
} |
| 628 |
mLineIter->GetLine()->MarkDirty(); |
731 |
lineIter.GetLine()->MarkDirty(); |
| 629 |
} |
732 |
} |
| 630 |
} // isTextFrame |
733 |
} // isTextFrame |
| 631 |
else { |
734 |
else { |
| 632 |
++lineOffset; |
735 |
++lineOffset; |
| 633 |
} |
736 |
} |
| 634 |
} // not bidi control frame |
737 |
} // not bidi control frame |
| 635 |
PRInt32 temp = runLength; |
738 |
PRInt32 temp = runLength; |
| 636 |
runLength -= fragmentLength; |
739 |
runLength -= fragmentLength; |
|
Lines 669-702
nsBidiPresUtils::ResolveParagraph(nsBloc
|
Link Here
|
|---|
|
| 669 |
// We're not at an end of a run. If |frame| is the last child of its |
772 |
// We're not at an end of a run. If |frame| is the last child of its |
| 670 |
// parent, and its ancestors happen to have bidi continuations, convert |
773 |
// parent, and its ancestors happen to have bidi continuations, convert |
| 671 |
// them into fluid continuations. |
774 |
// them into fluid continuations. |
| 672 |
JoinInlineAncestors(frame); |
775 |
JoinInlineAncestors(frame); |
| 673 |
} |
776 |
} |
| 674 |
} |
777 |
} |
| 675 |
} // for |
778 |
} // for |
| 676 |
#ifdef REALLY_NOISY_BIDI |
779 |
#ifdef REALLY_NOISY_BIDI |
| 677 |
if (mBuffer[0] != kObjectSubstitute) { |
780 |
if (aBpd->mBuffer[0] != kObjectSubstitute) { |
| 678 |
printf("---\nAfter Resolve(), frameTree =:\n"); |
781 |
printf("---\nAfter Resolve(), frameTree =:\n"); |
| 679 |
nsFrame::DumpFrameTree(aBlockFrame); |
782 |
nsFrame::DumpFrameTree(aBlockFrame); |
| 680 |
printf("===\n"); |
783 |
printf("===\n"); |
| 681 |
} |
784 |
} |
| 682 |
#endif |
785 |
#endif |
|
|
786 |
return rv; |
| 683 |
} |
787 |
} |
| 684 |
|
788 |
|
| 685 |
// Should this frame be treated as a leaf (e.g. when building mLogicalFrames)? |
789 |
// Should this frame be treated as a leaf (e.g. when building mLogicalFrames)? |
| 686 |
PRBool IsBidiLeaf(nsIFrame* aFrame) { |
790 |
PRBool IsBidiLeaf(nsIFrame* aFrame) { |
| 687 |
nsIFrame* kid = aFrame->GetFirstChild(nsnull); |
791 |
nsIFrame* kid = aFrame->GetFirstChild(nsnull); |
| 688 |
return !kid |
792 |
return !kid |
| 689 |
|| !aFrame->IsFrameOfType(nsIFrame::eBidiInlineContainer); |
793 |
|| !aFrame->IsFrameOfType(nsIFrame::eBidiInlineContainer); |
| 690 |
} |
794 |
} |
| 691 |
|
795 |
|
| 692 |
void |
796 |
void |
| 693 |
nsBidiPresUtils::TraverseFrames(nsBlockFrame* aBlockFrame, |
797 |
nsBidiPresUtils::TraverseFrames(nsBlockFrame* aBlockFrame, |
| 694 |
nsIFrame* aCurrentFrame) |
798 |
nsIFrame* aCurrentFrame, |
|
|
799 |
BidiParagraphData* aBpd) |
| 695 |
{ |
800 |
{ |
| 696 |
if (!aCurrentFrame) |
801 |
if (!aCurrentFrame) |
| 697 |
return; |
802 |
return; |
| 698 |
|
803 |
|
| 699 |
nsIFrame* childFrame = aCurrentFrame; |
804 |
nsIFrame* childFrame = aCurrentFrame; |
| 700 |
do { |
805 |
do { |
| 701 |
/* |
806 |
/* |
| 702 |
* It's important to get the next sibling and next continuation *before* |
807 |
* It's important to get the next sibling and next continuation *before* |
|
Lines 744-784
nsBidiPresUtils::TraverseFrames(nsBlockF
|
Link Here
|
|---|
|
| 744 |
ch = kLRO; |
849 |
ch = kLRO; |
| 745 |
} |
850 |
} |
| 746 |
break; |
851 |
break; |
| 747 |
} |
852 |
} |
| 748 |
|
853 |
|
| 749 |
// Add a dummy frame pointer representing a bidi control code before the |
854 |
// Add a dummy frame pointer representing a bidi control code before the |
| 750 |
// first frame of an element specifying embedding or override |
855 |
// first frame of an element specifying embedding or override |
| 751 |
if (ch != 0 && !frame->GetPrevContinuation()) { |
856 |
if (ch != 0 && !frame->GetPrevContinuation()) { |
| 752 |
mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME); |
857 |
aBpd->PushBidiControl(ch); |
| 753 |
mBuffer.Append(ch); |
|
|
| 754 |
mEmbeddingStack.AppendElement(ch); |
| 755 |
} |
858 |
} |
| 756 |
} |
859 |
} |
| 757 |
|
860 |
|
| 758 |
if (IsBidiLeaf(frame)) { |
861 |
if (IsBidiLeaf(frame)) { |
| 759 |
/* Bidi leaf frame: add the frame to the mLogicalFrames array, |
862 |
/* Bidi leaf frame: add the frame to the mLogicalFrames array, |
| 760 |
* and add its index to the mContentToFrameIndex hashtable. This |
863 |
* and add its index to the mContentToFrameIndex hashtable. This |
| 761 |
* will be used in RemoveBidiContinuation() to identify the last |
864 |
* will be used in RemoveBidiContinuation() to identify the last |
| 762 |
* frame in the array with a given content. |
865 |
* frame in the array with a given content. |
| 763 |
*/ |
866 |
*/ |
| 764 |
nsIContent* content = frame->GetContent(); |
867 |
nsIContent* content = frame->GetContent(); |
| 765 |
if (content) { |
868 |
aBpd->AppendFrame(frame, content); |
| 766 |
mContentToFrameIndex.Put(content, mLogicalFrames.Length()); |
|
|
| 767 |
} |
| 768 |
mLogicalFrames.AppendElement(frame); |
| 769 |
|
869 |
|
| 770 |
// Append the content of the frame to the paragraph buffer |
870 |
// Append the content of the frame to the paragraph buffer |
| 771 |
nsIAtom* frameType = frame->GetType(); |
871 |
nsIAtom* frameType = frame->GetType(); |
| 772 |
if (nsGkAtoms::textFrame == frameType) { |
872 |
if (nsGkAtoms::textFrame == frameType) { |
| 773 |
if (content != mPrevContent) { |
873 |
if (content != aBpd->mPrevContent) { |
| 774 |
mPrevContent = content; |
874 |
aBpd->mPrevContent = content; |
| 775 |
if (!frame->GetStyleContext()->GetStyleText()->NewlineIsSignificant()) { |
875 |
if (!frame->GetStyleContext()->GetStyleText()->NewlineIsSignificant()) { |
| 776 |
content->AppendTextTo(mBuffer); |
876 |
content->AppendTextTo(aBpd->mBuffer); |
| 777 |
} else { |
877 |
} else { |
| 778 |
/* |
878 |
/* |
| 779 |
* For preformatted text we have to do bidi resolution on each line |
879 |
* For preformatted text we have to do bidi resolution on each line |
| 780 |
* separately. |
880 |
* separately. |
| 781 |
*/ |
881 |
*/ |
| 782 |
nsAutoString text; |
882 |
nsAutoString text; |
| 783 |
content->AppendTextTo(text); |
883 |
content->AppendTextTo(text); |
| 784 |
nsIFrame* next; |
884 |
nsIFrame* next; |
|
Lines 789-836
nsBidiPresUtils::TraverseFrames(nsBlockF
|
Link Here
|
|---|
|
| 789 |
frame->GetOffsets(start, end); |
889 |
frame->GetOffsets(start, end); |
| 790 |
PRInt32 endLine = text.FindCharInSet(NS_LITERAL_STRING("\n\r"), |
890 |
PRInt32 endLine = text.FindCharInSet(NS_LITERAL_STRING("\n\r"), |
| 791 |
start); |
891 |
start); |
| 792 |
if (endLine == -1) { |
892 |
if (endLine == -1) { |
| 793 |
/* |
893 |
/* |
| 794 |
* If there is no newline in the frame, just save the text and |
894 |
* If there is no newline in the frame, just save the text and |
| 795 |
* do bidi resolution later |
895 |
* do bidi resolution later |
| 796 |
*/ |
896 |
*/ |
| 797 |
mBuffer.Append(Substring(text, start)); |
897 |
aBpd->AppendString(Substring(text, start)); |
| 798 |
break; |
898 |
break; |
| 799 |
} |
899 |
} |
| 800 |
|
900 |
|
| 801 |
/* |
901 |
/* |
| 802 |
* If there is a newline in the frame, break the frame after the |
902 |
* If there is a newline in the frame, break the frame after the |
| 803 |
* newline, do bidi resolution and repeat until the end of the |
903 |
* newline, do bidi resolution and repeat until the end of the |
| 804 |
* element. |
904 |
* element. |
| 805 |
*/ |
905 |
*/ |
| 806 |
++endLine; |
906 |
++endLine; |
| 807 |
|
907 |
|
| 808 |
/* |
908 |
/* |
| 809 |
* If the frame ends before the new line, save the text and move |
909 |
* If the frame ends before the new line, save the text and move |
| 810 |
* into the next continuation |
910 |
* into the next continuation |
| 811 |
*/ |
911 |
*/ |
| 812 |
while (end < endLine) { |
912 |
while (end < endLine) { |
| 813 |
mBuffer.Append(Substring(text, start, end - start)); |
913 |
aBpd->AppendString(Substring(text, start, end - start)); |
| 814 |
frame = frame->GetNextContinuation(); |
914 |
frame = frame->GetNextContinuation(); |
| 815 |
NS_ASSERTION(frame, "Premature end of continuation chain"); |
915 |
NS_ASSERTION(frame, "Premature end of continuation chain"); |
| 816 |
frame->GetOffsets(start, end); |
916 |
frame->GetOffsets(start, end); |
| 817 |
mLogicalFrames.AppendElement(frame); |
917 |
aBpd->AppendFrame(frame); |
| 818 |
|
918 |
|
| 819 |
/* |
919 |
/* |
| 820 |
* If we have already overshot the saved next-sibling while |
920 |
* If we have already overshot the saved next-sibling while |
| 821 |
* scanning the frame's continuations, advance it. |
921 |
* scanning the frame's continuations, advance it. |
| 822 |
*/ |
922 |
*/ |
| 823 |
if (frame == nextSibling) { |
923 |
if (frame == nextSibling) { |
| 824 |
nextSibling = frame->GetNextSibling(); |
924 |
nextSibling = frame->GetNextSibling(); |
| 825 |
} |
925 |
} |
| 826 |
} |
926 |
} |
| 827 |
|
927 |
|
| 828 |
mBuffer.Append(Substring(text, start, endLine - start)); |
928 |
aBpd->AppendString(Substring(text, start, endLine - start)); |
| 829 |
|
929 |
|
| 830 |
if (PRUint32(endLine) < text.Length()) { |
930 |
if (PRUint32(endLine) < text.Length()) { |
| 831 |
nsTextFrame* textFrame = static_cast<nsTextFrame*>(frame); |
931 |
nsTextFrame* textFrame = static_cast<nsTextFrame*>(frame); |
| 832 |
textFrame->SetLength(endLine - start, nsnull); |
932 |
textFrame->SetLength(endLine - start, nsnull); |
| 833 |
next = frame->GetNextInFlow(); |
933 |
next = frame->GetNextInFlow(); |
| 834 |
if (!next) { |
934 |
if (!next) { |
| 835 |
// If the frame already has a bidi continuation, make it fluid |
935 |
// If the frame already has a bidi continuation, make it fluid |
| 836 |
next = frame->GetNextContinuation(); |
936 |
next = frame->GetNextContinuation(); |
|
Lines 838-1022
nsBidiPresUtils::TraverseFrames(nsBlockF
|
Link Here
|
|---|
|
| 838 |
MakeContinuationFluid(frame, next); |
938 |
MakeContinuationFluid(frame, next); |
| 839 |
JoinInlineAncestors(frame); |
939 |
JoinInlineAncestors(frame); |
| 840 |
} else { |
940 |
} else { |
| 841 |
// If the frame has no next in flow, create one |
941 |
// If the frame has no next in flow, create one |
| 842 |
CreateContinuation(frame, &next, PR_TRUE); |
942 |
CreateContinuation(frame, &next, PR_TRUE); |
| 843 |
} |
943 |
} |
| 844 |
} |
944 |
} |
| 845 |
} |
945 |
} |
| 846 |
ResolveParagraphWithinBlock(aBlockFrame); |
946 |
ResolveParagraphWithinBlock(aBlockFrame, aBpd); |
| 847 |
|
947 |
|
| 848 |
if (next) { |
948 |
if (next) { |
| 849 |
frame = next; |
949 |
frame = next; |
| 850 |
mLogicalFrames.AppendElement(frame); |
950 |
aBpd->AppendFrame(frame); |
| 851 |
} |
951 |
} |
| 852 |
|
952 |
|
| 853 |
/* |
953 |
/* |
| 854 |
* If we have already overshot the saved next-sibling while |
954 |
* If we have already overshot the saved next-sibling while |
| 855 |
* scanning the frame's continuations, advance it. |
955 |
* scanning the frame's continuations, advance it. |
| 856 |
*/ |
956 |
*/ |
| 857 |
if (frame && frame == nextSibling) { |
957 |
if (frame && frame == nextSibling) { |
| 858 |
nextSibling = frame->GetNextSibling(); |
958 |
nextSibling = frame->GetNextSibling(); |
| 859 |
} |
959 |
} |
| 860 |
|
960 |
|
| 861 |
} while (next); |
961 |
} while (next); |
| 862 |
} |
962 |
} |
| 863 |
} |
963 |
} |
| 864 |
} else if (nsGkAtoms::brFrame == frameType) { |
964 |
} else if (nsGkAtoms::brFrame == frameType) { |
| 865 |
// break frame -- append line separator |
965 |
// break frame -- append line separator |
| 866 |
mBuffer.Append(kLineSeparator); |
966 |
aBpd->AppendUnichar(kLineSeparator); |
| 867 |
ResolveParagraphWithinBlock(aBlockFrame); |
967 |
ResolveParagraphWithinBlock(aBlockFrame, aBpd); |
| 868 |
} else { |
968 |
} else { |
| 869 |
// other frame type -- see the Unicode Bidi Algorithm: |
969 |
// other frame type -- see the Unicode Bidi Algorithm: |
| 870 |
// "...inline objects (such as graphics) are treated as if they are ... |
970 |
// "...inline objects (such as graphics) are treated as if they are ... |
| 871 |
// U+FFFC" |
971 |
// U+FFFC" |
| 872 |
mBuffer.Append(kObjectSubstitute); |
972 |
aBpd->AppendUnichar(kObjectSubstitute); |
| 873 |
if (!frame->GetStyleContext()->GetStyleDisplay()->IsInlineOutside()) { |
973 |
if (!frame->GetStyleContext()->GetStyleDisplay()->IsInlineOutside()) { |
| 874 |
// if it is not inline, end the paragraph |
974 |
// if it is not inline, end the paragraph |
| 875 |
ResolveParagraphWithinBlock(aBlockFrame); |
975 |
ResolveParagraphWithinBlock(aBlockFrame, aBpd); |
| 876 |
} |
976 |
} |
| 877 |
} |
977 |
} |
| 878 |
} |
978 |
} |
| 879 |
else { |
979 |
else { |
| 880 |
// For a non-leaf frame, recurse into TraverseFrames |
980 |
// For a non-leaf frame, recurse into TraverseFrames |
| 881 |
nsIFrame* kid = frame->GetFirstChild(nsnull); |
981 |
nsIFrame* kid = frame->GetFirstChild(nsnull); |
| 882 |
TraverseFrames(aBlockFrame, kid); |
982 |
TraverseFrames(aBlockFrame, kid, aBpd); |
| 883 |
} |
983 |
} |
| 884 |
|
984 |
|
| 885 |
// If the element is attributed by dir, indicate direction pop (add PDF frame) |
985 |
// If the element is attributed by dir, indicate direction pop (add PDF frame) |
| 886 |
if (ch != 0 && isLastFrame) { |
986 |
if (ch != 0 && isLastFrame) { |
| 887 |
// Add a dummy frame pointer representing a bidi control code after the |
987 |
// Add a dummy frame pointer representing a bidi control code after the |
| 888 |
// last frame of an element specifying embedding or override |
988 |
// last frame of an element specifying embedding or override |
| 889 |
mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME); |
989 |
aBpd->PopBidiControl(); |
| 890 |
mBuffer.Append(kPDF); |
|
|
| 891 |
NS_ASSERTION(mEmbeddingStack.Length(), "embedding/override underflow"); |
| 892 |
mEmbeddingStack.TruncateLength(mEmbeddingStack.Length() - 1); |
| 893 |
} |
990 |
} |
| 894 |
childFrame = nextSibling; |
991 |
childFrame = nextSibling; |
| 895 |
} while (childFrame); |
992 |
} while (childFrame); |
| 896 |
} |
993 |
} |
| 897 |
|
994 |
|
| 898 |
void |
995 |
void |
| 899 |
nsBidiPresUtils::ResolveParagraphWithinBlock(nsBlockFrame* aBlockFrame) |
996 |
nsBidiPresUtils::ResolveParagraphWithinBlock(nsBlockFrame* aBlockFrame, |
|
|
997 |
BidiParagraphData* aBpd) |
| 900 |
{ |
998 |
{ |
| 901 |
nsIPresShell* shell; |
999 |
// pop all embeddings and overrides |
| 902 |
nsStyleContext* styleContext; |
1000 |
aBpd->ClearBidiControls(); |
| 903 |
|
1001 |
|
| 904 |
if (mEmbeddingStack.Length() > 0) { |
1002 |
ResolveParagraph(aBlockFrame, aBpd); |
| 905 |
shell = aBlockFrame->PresContext()->PresShell(); |
|
|
| 906 |
styleContext = aBlockFrame->GetStyleContext(); |
| 907 |
|
| 908 |
// pop all embeddings and overrides |
| 909 |
for (PRUint32 i = 0; i < mEmbeddingStack.Length(); ++i) { |
| 910 |
mBuffer.Append(kPDF); |
| 911 |
mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME); |
| 912 |
} |
| 913 |
} |
| 914 |
|
| 915 |
ResolveParagraph(aBlockFrame); |
| 916 |
|
1003 |
|
| 917 |
// Clear the frame array and paragraph buffer, and restore the stored |
1004 |
// Clear the frame array and paragraph buffer, and restore the stored |
| 918 |
// embeddings and overrides |
1005 |
// embeddings and overrides |
| 919 |
mLogicalFrames.Clear(); |
1006 |
aBpd->ResetData(); |
| 920 |
mContentToFrameIndex.Clear(); |
|
|
| 921 |
mBuffer.SetLength(0); |
| 922 |
if (mEmbeddingStack.Length() > 0) { |
| 923 |
for (PRUint32 i = 0; i < mEmbeddingStack.Length(); ++i) { |
| 924 |
mBuffer.Append(mEmbeddingStack[i]); |
| 925 |
mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME); |
| 926 |
} |
| 927 |
} |
| 928 |
} |
1007 |
} |
| 929 |
|
1008 |
|
| 930 |
void |
1009 |
void |
| 931 |
nsBidiPresUtils::ReorderFrames(nsIFrame* aFirstFrameOnLine, |
1010 |
nsBidiPresUtils::ReorderFrames(nsIFrame* aFirstFrameOnLine, |
| 932 |
PRInt32 aNumFramesOnLine) |
1011 |
PRInt32 aNumFramesOnLine) |
| 933 |
{ |
1012 |
{ |
| 934 |
// If this line consists of a line frame, reorder the line frame's children. |
1013 |
// If this line consists of a line frame, reorder the line frame's children. |
| 935 |
if (aFirstFrameOnLine->GetType() == nsGkAtoms::lineFrame) { |
1014 |
if (aFirstFrameOnLine->GetType() == nsGkAtoms::lineFrame) { |
| 936 |
aFirstFrameOnLine = aFirstFrameOnLine->GetFirstChild(nsnull); |
1015 |
aFirstFrameOnLine = aFirstFrameOnLine->GetFirstChild(nsnull); |
| 937 |
if (!aFirstFrameOnLine) |
1016 |
if (!aFirstFrameOnLine) |
| 938 |
return; |
1017 |
return; |
| 939 |
// All children of the line frame are on the first line. Setting aNumFramesOnLine |
1018 |
// All children of the line frame are on the first line. Setting aNumFramesOnLine |
| 940 |
// to -1 makes InitLogicalArrayFromLine look at all of them. |
1019 |
// to -1 makes InitLogicalArrayFromLine look at all of them. |
| 941 |
aNumFramesOnLine = -1; |
1020 |
aNumFramesOnLine = -1; |
| 942 |
} |
1021 |
} |
| 943 |
|
1022 |
|
| 944 |
InitLogicalArrayFromLine(aFirstFrameOnLine, aNumFramesOnLine); |
1023 |
BidiLineData bld(aFirstFrameOnLine, aNumFramesOnLine); |
| 945 |
|
1024 |
RepositionInlineFrames(&bld, aFirstFrameOnLine); |
| 946 |
PRBool isReordered; |
|
|
| 947 |
PRBool hasRTLFrames; |
| 948 |
Reorder(isReordered, hasRTLFrames); |
| 949 |
RepositionInlineFrames(aFirstFrameOnLine); |
| 950 |
} |
| 951 |
|
| 952 |
nsresult |
| 953 |
nsBidiPresUtils::Reorder(PRBool& aReordered, PRBool& aHasRTLFrames) |
| 954 |
{ |
| 955 |
aReordered = PR_FALSE; |
| 956 |
aHasRTLFrames = PR_FALSE; |
| 957 |
PRInt32 count = mLogicalFrames.Length(); |
| 958 |
|
| 959 |
if (mArraySize < count) { |
| 960 |
mArraySize = count << 1; |
| 961 |
if (mLevels) { |
| 962 |
delete[] mLevels; |
| 963 |
mLevels = nsnull; |
| 964 |
} |
| 965 |
if (mIndexMap) { |
| 966 |
delete[] mIndexMap; |
| 967 |
mIndexMap = nsnull; |
| 968 |
} |
| 969 |
} |
| 970 |
if (!mLevels) { |
| 971 |
mLevels = new PRUint8[mArraySize]; |
| 972 |
if (!mLevels) { |
| 973 |
return NS_ERROR_OUT_OF_MEMORY; |
| 974 |
} |
| 975 |
} |
| 976 |
memset(mLevels, 0, sizeof(PRUint8) * mArraySize); |
| 977 |
|
| 978 |
nsIFrame* frame; |
| 979 |
PRInt32 i; |
| 980 |
|
| 981 |
for (i = 0; i < count; i++) { |
| 982 |
frame = mLogicalFrames[i]; |
| 983 |
mLevels[i] = GetFrameEmbeddingLevel(frame); |
| 984 |
if (mLevels[i] & 1) { |
| 985 |
aHasRTLFrames = PR_TRUE; |
| 986 |
} |
| 987 |
} |
| 988 |
if (!mIndexMap) { |
| 989 |
mIndexMap = new PRInt32[mArraySize]; |
| 990 |
} |
| 991 |
if (!mIndexMap) { |
| 992 |
mSuccess = NS_ERROR_OUT_OF_MEMORY; |
| 993 |
} |
| 994 |
else { |
| 995 |
memset(mIndexMap, 0, sizeof(PRUint32) * mArraySize); |
| 996 |
|
| 997 |
mSuccess = mBidiEngine->ReorderVisual(mLevels, count, mIndexMap); |
| 998 |
|
| 999 |
if (NS_SUCCEEDED(mSuccess) ) { |
| 1000 |
mVisualFrames.Clear(); |
| 1001 |
|
| 1002 |
for (i = 0; i < count; i++) { |
| 1003 |
mVisualFrames.AppendElement(mLogicalFrames[mIndexMap[i]]); |
| 1004 |
if (i != mIndexMap[i]) { |
| 1005 |
aReordered = PR_TRUE; |
| 1006 |
} |
| 1007 |
} |
| 1008 |
} // NS_SUCCEEDED(mSuccess) |
| 1009 |
} // indexMap |
| 1010 |
|
| 1011 |
if (NS_FAILED(mSuccess) ) { |
| 1012 |
aReordered = PR_FALSE; |
| 1013 |
} |
| 1014 |
return mSuccess; |
| 1015 |
} |
1025 |
} |
| 1016 |
|
1026 |
|
| 1017 |
nsBidiLevel |
1027 |
nsBidiLevel |
| 1018 |
nsBidiPresUtils::GetFrameEmbeddingLevel(nsIFrame* aFrame) |
1028 |
nsBidiPresUtils::GetFrameEmbeddingLevel(nsIFrame* aFrame) |
| 1019 |
{ |
1029 |
{ |
| 1020 |
nsIFrame* firstLeaf = aFrame; |
1030 |
nsIFrame* firstLeaf = aFrame; |
| 1021 |
while (!IsBidiLeaf(firstLeaf)) { |
1031 |
while (!IsBidiLeaf(firstLeaf)) { |
| 1022 |
nsIFrame* firstChild = firstLeaf->GetFirstChild(nsnull); |
1032 |
nsIFrame* firstChild = firstLeaf->GetFirstChild(nsnull); |
|
Lines 1036-1052
nsBidiPresUtils::GetFrameBaseLevel(nsIFr
|
Link Here
|
|---|
|
| 1036 |
} |
1046 |
} |
| 1037 |
return NS_GET_BASE_LEVEL(firstLeaf); |
1047 |
return NS_GET_BASE_LEVEL(firstLeaf); |
| 1038 |
} |
1048 |
} |
| 1039 |
|
1049 |
|
| 1040 |
void |
1050 |
void |
| 1041 |
nsBidiPresUtils::IsLeftOrRightMost(nsIFrame* aFrame, |
1051 |
nsBidiPresUtils::IsLeftOrRightMost(nsIFrame* aFrame, |
| 1042 |
nsContinuationStates* aContinuationStates, |
1052 |
nsContinuationStates* aContinuationStates, |
| 1043 |
PRBool& aIsLeftMost /* out */, |
1053 |
PRBool& aIsLeftMost /* out */, |
| 1044 |
PRBool& aIsRightMost /* out */) const |
1054 |
PRBool& aIsRightMost /* out */) |
| 1045 |
{ |
1055 |
{ |
| 1046 |
const nsStyleVisibility* vis = aFrame->GetStyleVisibility(); |
1056 |
const nsStyleVisibility* vis = aFrame->GetStyleVisibility(); |
| 1047 |
PRBool isLTR = (NS_STYLE_DIRECTION_LTR == vis->mDirection); |
1057 |
PRBool isLTR = (NS_STYLE_DIRECTION_LTR == vis->mDirection); |
| 1048 |
|
1058 |
|
| 1049 |
/* |
1059 |
/* |
| 1050 |
* Since we lay out frames from left to right (in both LTR and RTL), visiting a |
1060 |
* Since we lay out frames from left to right (in both LTR and RTL), visiting a |
| 1051 |
* frame with 'mFirstVisualFrame == nsnull', means it's the first appearance of |
1061 |
* frame with 'mFirstVisualFrame == nsnull', means it's the first appearance of |
| 1052 |
* one of its continuation chain frames on the line. |
1062 |
* one of its continuation chain frames on the line. |
|
Lines 1130-1146
nsBidiPresUtils::IsLeftOrRightMost(nsIFr
|
Link Here
|
|---|
|
| 1130 |
// Reduce number of remaining frames of the continuation chain on the line. |
1140 |
// Reduce number of remaining frames of the continuation chain on the line. |
| 1131 |
firstFrameState->mFrameCount--; |
1141 |
firstFrameState->mFrameCount--; |
| 1132 |
} |
1142 |
} |
| 1133 |
|
1143 |
|
| 1134 |
void |
1144 |
void |
| 1135 |
nsBidiPresUtils::RepositionFrame(nsIFrame* aFrame, |
1145 |
nsBidiPresUtils::RepositionFrame(nsIFrame* aFrame, |
| 1136 |
PRBool aIsOddLevel, |
1146 |
PRBool aIsOddLevel, |
| 1137 |
nscoord& aLeft, |
1147 |
nscoord& aLeft, |
| 1138 |
nsContinuationStates* aContinuationStates) const |
1148 |
nsContinuationStates* aContinuationStates) |
| 1139 |
{ |
1149 |
{ |
| 1140 |
if (!aFrame) |
1150 |
if (!aFrame) |
| 1141 |
return; |
1151 |
return; |
| 1142 |
|
1152 |
|
| 1143 |
PRBool isLeftMost, isRightMost; |
1153 |
PRBool isLeftMost, isRightMost; |
| 1144 |
IsLeftOrRightMost(aFrame, |
1154 |
IsLeftOrRightMost(aFrame, |
| 1145 |
aContinuationStates, |
1155 |
aContinuationStates, |
| 1146 |
isLeftMost /* out */, |
1156 |
isLeftMost /* out */, |
|
Lines 1215-1231
nsBidiPresUtils::RepositionFrame(nsIFram
|
Link Here
|
|---|
|
| 1215 |
aFrame->SetRect(nsRect(start, rect.y, aLeft - start, rect.height)); |
1225 |
aFrame->SetRect(nsRect(start, rect.y, aLeft - start, rect.height)); |
| 1216 |
|
1226 |
|
| 1217 |
if (isRightMost) |
1227 |
if (isRightMost) |
| 1218 |
aLeft += margin.right; |
1228 |
aLeft += margin.right; |
| 1219 |
} |
1229 |
} |
| 1220 |
|
1230 |
|
| 1221 |
void |
1231 |
void |
| 1222 |
nsBidiPresUtils::InitContinuationStates(nsIFrame* aFrame, |
1232 |
nsBidiPresUtils::InitContinuationStates(nsIFrame* aFrame, |
| 1223 |
nsContinuationStates* aContinuationStates) const |
1233 |
nsContinuationStates* aContinuationStates) |
| 1224 |
{ |
1234 |
{ |
| 1225 |
nsFrameContinuationState* state = aContinuationStates->PutEntry(aFrame); |
1235 |
nsFrameContinuationState* state = aContinuationStates->PutEntry(aFrame); |
| 1226 |
state->mFirstVisualFrame = nsnull; |
1236 |
state->mFirstVisualFrame = nsnull; |
| 1227 |
state->mFrameCount = 0; |
1237 |
state->mFrameCount = 0; |
| 1228 |
|
1238 |
|
| 1229 |
if (!IsBidiLeaf(aFrame)) { |
1239 |
if (!IsBidiLeaf(aFrame)) { |
| 1230 |
// Continue for child frames |
1240 |
// Continue for child frames |
| 1231 |
nsIFrame* frame; |
1241 |
nsIFrame* frame; |
|
Lines 1234-1398
nsBidiPresUtils::InitContinuationStates(
|
Link Here
|
|---|
|
| 1234 |
frame = frame->GetNextSibling()) { |
1244 |
frame = frame->GetNextSibling()) { |
| 1235 |
InitContinuationStates(frame, |
1245 |
InitContinuationStates(frame, |
| 1236 |
aContinuationStates); |
1246 |
aContinuationStates); |
| 1237 |
} |
1247 |
} |
| 1238 |
} |
1248 |
} |
| 1239 |
} |
1249 |
} |
| 1240 |
|
1250 |
|
| 1241 |
void |
1251 |
void |
| 1242 |
nsBidiPresUtils::RepositionInlineFrames(nsIFrame* aFirstChild) const |
1252 |
nsBidiPresUtils::RepositionInlineFrames(BidiLineData *aBld, |
|
|
1253 |
nsIFrame* aFirstChild) |
| 1243 |
{ |
1254 |
{ |
| 1244 |
const nsStyleVisibility* vis = aFirstChild->GetStyleVisibility(); |
1255 |
const nsStyleVisibility* vis = aFirstChild->GetStyleVisibility(); |
| 1245 |
PRBool isLTR = (NS_STYLE_DIRECTION_LTR == vis->mDirection); |
1256 |
PRBool isLTR = (NS_STYLE_DIRECTION_LTR == vis->mDirection); |
| 1246 |
nscoord leftSpace = 0; |
1257 |
nscoord leftSpace = 0; |
| 1247 |
|
1258 |
|
| 1248 |
// This method is called from nsBlockFrame::PlaceLine via the call to |
1259 |
// This method is called from nsBlockFrame::PlaceLine via the call to |
| 1249 |
// bidiUtils->ReorderFrames, so this is guaranteed to be after the inlines |
1260 |
// bidiUtils->ReorderFrames, so this is guaranteed to be after the inlines |
| 1250 |
// have been reflowed, which is required for GetUsedMargin/Border/Padding |
1261 |
// have been reflowed, which is required for GetUsedMargin/Border/Padding |
| 1251 |
nsMargin margin = aFirstChild->GetUsedMargin(); |
1262 |
nsMargin margin = aFirstChild->GetUsedMargin(); |
| 1252 |
if (!aFirstChild->GetPrevContinuation() && |
1263 |
if (!aFirstChild->GetPrevContinuation() && |
| 1253 |
!nsLayoutUtils::FrameIsNonFirstInIBSplit(aFirstChild)) |
1264 |
!nsLayoutUtils::FrameIsNonFirstInIBSplit(aFirstChild)) |
| 1254 |
leftSpace = isLTR ? margin.left : margin.right; |
1265 |
leftSpace = isLTR ? margin.left : margin.right; |
| 1255 |
|
1266 |
|
| 1256 |
nscoord left = aFirstChild->GetPosition().x - leftSpace; |
1267 |
nscoord left = aFirstChild->GetPosition().x - leftSpace; |
| 1257 |
nsIFrame* frame; |
1268 |
nsIFrame* frame; |
| 1258 |
PRInt32 count = mVisualFrames.Length(); |
1269 |
PRInt32 count = aBld->mVisualFrames.Length(); |
| 1259 |
PRInt32 index; |
1270 |
PRInt32 index; |
| 1260 |
nsContinuationStates continuationStates; |
1271 |
nsContinuationStates continuationStates; |
| 1261 |
|
1272 |
|
| 1262 |
continuationStates.Init(); |
1273 |
continuationStates.Init(); |
| 1263 |
|
1274 |
|
| 1264 |
// Initialize continuation states to (nsnull, 0) for |
1275 |
// Initialize continuation states to (nsnull, 0) for |
| 1265 |
// each frame on the line. |
1276 |
// each frame on the line. |
| 1266 |
for (index = 0; index < count; index++) { |
1277 |
for (index = 0; index < count; index++) { |
| 1267 |
InitContinuationStates(mVisualFrames[index], &continuationStates); |
1278 |
InitContinuationStates(aBld->VisualFrameAt(index), &continuationStates); |
| 1268 |
} |
1279 |
} |
| 1269 |
|
1280 |
|
| 1270 |
// Reposition frames in visual order |
1281 |
// Reposition frames in visual order |
| 1271 |
for (index = 0; index < count; index++) { |
1282 |
for (index = 0; index < count; index++) { |
| 1272 |
frame = mVisualFrames[index]; |
1283 |
frame = aBld->VisualFrameAt(index); |
| 1273 |
RepositionFrame(frame, |
1284 |
RepositionFrame(frame, |
| 1274 |
(mLevels[mIndexMap[index]] & 1), |
1285 |
(aBld->mLevels[aBld->mIndexMap[index]] & 1), |
| 1275 |
left, |
1286 |
left, |
| 1276 |
&continuationStates); |
1287 |
&continuationStates); |
| 1277 |
} // for |
1288 |
} // for |
| 1278 |
} |
1289 |
} |
| 1279 |
|
1290 |
|
| 1280 |
void |
|
|
| 1281 |
nsBidiPresUtils::InitLogicalArrayFromLine(nsIFrame* aFirstFrameOnLine, |
| 1282 |
PRInt32 aNumFramesOnLine) { |
| 1283 |
mLogicalFrames.Clear(); |
| 1284 |
for (nsIFrame* frame = aFirstFrameOnLine; |
| 1285 |
frame && aNumFramesOnLine--; |
| 1286 |
frame = frame->GetNextSibling()) { |
| 1287 |
mLogicalFrames.AppendElement(frame); |
| 1288 |
} |
| 1289 |
} |
| 1290 |
|
| 1291 |
PRBool |
1291 |
PRBool |
| 1292 |
nsBidiPresUtils::CheckLineOrder(nsIFrame* aFirstFrameOnLine, |
1292 |
nsBidiPresUtils::CheckLineOrder(nsIFrame* aFirstFrameOnLine, |
| 1293 |
PRInt32 aNumFramesOnLine, |
1293 |
PRInt32 aNumFramesOnLine, |
| 1294 |
nsIFrame** aFirstVisual, |
1294 |
nsIFrame** aFirstVisual, |
| 1295 |
nsIFrame** aLastVisual) |
1295 |
nsIFrame** aLastVisual) |
| 1296 |
{ |
1296 |
{ |
| 1297 |
InitLogicalArrayFromLine(aFirstFrameOnLine, aNumFramesOnLine); |
1297 |
BidiLineData bld(aFirstFrameOnLine, aNumFramesOnLine); |
| 1298 |
|
1298 |
PRInt32 count = bld.FrameCount(); |
| 1299 |
PRBool isReordered; |
|
|
| 1300 |
PRBool hasRTLFrames; |
| 1301 |
Reorder(isReordered, hasRTLFrames); |
| 1302 |
PRInt32 count = mLogicalFrames.Length(); |
| 1303 |
|
1299 |
|
| 1304 |
if (aFirstVisual) { |
1300 |
if (aFirstVisual) { |
| 1305 |
*aFirstVisual = mVisualFrames[0]; |
1301 |
*aFirstVisual = bld.VisualFrameAt(0); |
| 1306 |
} |
1302 |
} |
| 1307 |
if (aLastVisual) { |
1303 |
if (aLastVisual) { |
| 1308 |
*aLastVisual = mVisualFrames[count-1]; |
1304 |
*aLastVisual = bld.VisualFrameAt(count-1); |
| 1309 |
} |
1305 |
} |
| 1310 |
|
1306 |
|
| 1311 |
// If there's an RTL frame, assume the line is reordered |
1307 |
return bld.mIsReordered; |
| 1312 |
return isReordered || hasRTLFrames; |
|
|
| 1313 |
} |
1308 |
} |
| 1314 |
|
1309 |
|
| 1315 |
nsIFrame* |
1310 |
nsIFrame* |
| 1316 |
nsBidiPresUtils::GetFrameToRightOf(const nsIFrame* aFrame, |
1311 |
nsBidiPresUtils::GetFrameToRightOf(const nsIFrame* aFrame, |
| 1317 |
nsIFrame* aFirstFrameOnLine, |
1312 |
nsIFrame* aFirstFrameOnLine, |
| 1318 |
PRInt32 aNumFramesOnLine) |
1313 |
PRInt32 aNumFramesOnLine) |
| 1319 |
{ |
1314 |
{ |
| 1320 |
InitLogicalArrayFromLine(aFirstFrameOnLine, aNumFramesOnLine); |
1315 |
BidiLineData bld(aFirstFrameOnLine, aNumFramesOnLine); |
| 1321 |
|
1316 |
|
| 1322 |
PRBool isReordered; |
1317 |
PRInt32 count = bld.mVisualFrames.Length(); |
| 1323 |
PRBool hasRTLFrames; |
|
|
| 1324 |
Reorder(isReordered, hasRTLFrames); |
| 1325 |
PRInt32 count = mVisualFrames.Length(); |
| 1326 |
|
1318 |
|
| 1327 |
if (aFrame == nsnull) |
1319 |
if (aFrame == nsnull) |
| 1328 |
return mVisualFrames[0]; |
1320 |
return bld.VisualFrameAt(0); |
| 1329 |
|
1321 |
|
| 1330 |
for (PRInt32 i = 0; i < count - 1; i++) { |
1322 |
for (PRInt32 i = 0; i < count - 1; i++) { |
| 1331 |
if (mVisualFrames[i] == aFrame) { |
1323 |
if (bld.VisualFrameAt(i) == aFrame) { |
| 1332 |
return mVisualFrames[i+1]; |
1324 |
return bld.VisualFrameAt(i+1); |
| 1333 |
} |
1325 |
} |
| 1334 |
} |
1326 |
} |
| 1335 |
|
1327 |
|
| 1336 |
return nsnull; |
1328 |
return nsnull; |
| 1337 |
} |
1329 |
} |
| 1338 |
|
1330 |
|
| 1339 |
nsIFrame* |
1331 |
nsIFrame* |
| 1340 |
nsBidiPresUtils::GetFrameToLeftOf(const nsIFrame* aFrame, |
1332 |
nsBidiPresUtils::GetFrameToLeftOf(const nsIFrame* aFrame, |
| 1341 |
nsIFrame* aFirstFrameOnLine, |
1333 |
nsIFrame* aFirstFrameOnLine, |
| 1342 |
PRInt32 aNumFramesOnLine) |
1334 |
PRInt32 aNumFramesOnLine) |
| 1343 |
{ |
1335 |
{ |
| 1344 |
InitLogicalArrayFromLine(aFirstFrameOnLine, aNumFramesOnLine); |
1336 |
BidiLineData bld(aFirstFrameOnLine, aNumFramesOnLine); |
| 1345 |
|
1337 |
|
| 1346 |
PRBool isReordered; |
1338 |
PRInt32 count = bld.mVisualFrames.Length(); |
| 1347 |
PRBool hasRTLFrames; |
|
|
| 1348 |
Reorder(isReordered, hasRTLFrames); |
| 1349 |
PRInt32 count = mVisualFrames.Length(); |
| 1350 |
|
1339 |
|
| 1351 |
if (aFrame == nsnull) |
1340 |
if (aFrame == nsnull) |
| 1352 |
return mVisualFrames[count-1]; |
1341 |
return bld.VisualFrameAt(count-1); |
| 1353 |
|
1342 |
|
| 1354 |
for (PRInt32 i = 1; i < count; i++) { |
1343 |
for (PRInt32 i = 1; i < count; i++) { |
| 1355 |
if (mVisualFrames[i] == aFrame) { |
1344 |
if (bld.VisualFrameAt(i) == aFrame) { |
| 1356 |
return mVisualFrames[i-1]; |
1345 |
return bld.VisualFrameAt(i-1); |
| 1357 |
} |
1346 |
} |
| 1358 |
} |
1347 |
} |
| 1359 |
|
1348 |
|
| 1360 |
return nsnull; |
1349 |
return nsnull; |
| 1361 |
} |
1350 |
} |
| 1362 |
|
1351 |
|
| 1363 |
inline void |
1352 |
inline nsresult |
| 1364 |
nsBidiPresUtils::EnsureBidiContinuation(nsIFrame* aFrame, |
1353 |
nsBidiPresUtils::EnsureBidiContinuation(nsIFrame* aFrame, |
| 1365 |
nsIFrame** aNewFrame, |
1354 |
nsIFrame** aNewFrame, |
| 1366 |
PRInt32& aFrameIndex, |
1355 |
PRInt32& aFrameIndex, |
| 1367 |
PRInt32 aStart, |
1356 |
PRInt32 aStart, |
| 1368 |
PRInt32 aEnd) |
1357 |
PRInt32 aEnd) |
| 1369 |
{ |
1358 |
{ |
| 1370 |
NS_PRECONDITION(aNewFrame, "null OUT ptr"); |
1359 |
NS_PRECONDITION(aNewFrame, "null OUT ptr"); |
| 1371 |
NS_PRECONDITION(aFrame, "aFrame is null"); |
1360 |
NS_PRECONDITION(aFrame, "aFrame is null"); |
| 1372 |
|
1361 |
|
| 1373 |
aFrame->AdjustOffsetsForBidi(aStart, aEnd); |
1362 |
aFrame->AdjustOffsetsForBidi(aStart, aEnd); |
| 1374 |
mSuccess = CreateContinuation(aFrame, aNewFrame, PR_FALSE); |
1363 |
return CreateContinuation(aFrame, aNewFrame, PR_FALSE); |
| 1375 |
} |
1364 |
} |
| 1376 |
|
1365 |
|
| 1377 |
void |
1366 |
void |
| 1378 |
nsBidiPresUtils::RemoveBidiContinuation(nsIFrame* aFrame, |
1367 |
nsBidiPresUtils::RemoveBidiContinuation(BidiParagraphData *aBpd, |
|
|
1368 |
nsIFrame* aFrame, |
| 1379 |
PRInt32 aFirstIndex, |
1369 |
PRInt32 aFirstIndex, |
| 1380 |
PRInt32 aLastIndex, |
1370 |
PRInt32 aLastIndex, |
| 1381 |
PRInt32& aOffset) const |
1371 |
PRInt32& aOffset) |
| 1382 |
{ |
1372 |
{ |
| 1383 |
FrameProperties props = aFrame->Properties(); |
1373 |
FrameProperties props = aFrame->Properties(); |
| 1384 |
nsBidiLevel embeddingLevel = |
1374 |
nsBidiLevel embeddingLevel = |
| 1385 |
(nsBidiLevel)NS_PTR_TO_INT32(props.Get(nsIFrame::EmbeddingLevelProperty())); |
1375 |
(nsBidiLevel)NS_PTR_TO_INT32(props.Get(nsIFrame::EmbeddingLevelProperty())); |
| 1386 |
nsBidiLevel baseLevel = |
1376 |
nsBidiLevel baseLevel = |
| 1387 |
(nsBidiLevel)NS_PTR_TO_INT32(props.Get(nsIFrame::BaseLevelProperty())); |
1377 |
(nsBidiLevel)NS_PTR_TO_INT32(props.Get(nsIFrame::BaseLevelProperty())); |
| 1388 |
|
1378 |
|
| 1389 |
for (PRInt32 index = aFirstIndex + 1; index <= aLastIndex; index++) { |
1379 |
for (PRInt32 index = aFirstIndex + 1; index <= aLastIndex; index++) { |
| 1390 |
nsIFrame* frame = mLogicalFrames[index]; |
1380 |
nsIFrame* frame = aBpd->FrameAt(index); |
| 1391 |
if (frame == NS_BIDI_CONTROL_FRAME) { |
1381 |
if (frame == NS_BIDI_CONTROL_FRAME) { |
| 1392 |
++aOffset; |
1382 |
++aOffset; |
| 1393 |
} |
1383 |
} |
| 1394 |
else { |
1384 |
else { |
| 1395 |
// Make the frame and its continuation ancestors fluid, |
1385 |
// Make the frame and its continuation ancestors fluid, |
| 1396 |
// so they can be reused or deleted by normal reflow code |
1386 |
// so they can be reused or deleted by normal reflow code |
| 1397 |
FrameProperties frameProps = frame->Properties(); |
1387 |
FrameProperties frameProps = frame->Properties(); |
| 1398 |
frameProps.Set(nsIFrame::EmbeddingLevelProperty(), |
1388 |
frameProps.Set(nsIFrame::EmbeddingLevelProperty(), |
|
Lines 1476-1492
nsBidiPresUtils::FormatUnicodeText(nsPre
|
Link Here
|
|---|
|
| 1476 |
} |
1466 |
} |
| 1477 |
|
1467 |
|
| 1478 |
StripBidiControlCharacters(aText, aTextLength); |
1468 |
StripBidiControlCharacters(aText, aTextLength); |
| 1479 |
return rv; |
1469 |
return rv; |
| 1480 |
} |
1470 |
} |
| 1481 |
|
1471 |
|
| 1482 |
void |
1472 |
void |
| 1483 |
nsBidiPresUtils::StripBidiControlCharacters(PRUnichar* aText, |
1473 |
nsBidiPresUtils::StripBidiControlCharacters(PRUnichar* aText, |
| 1484 |
PRInt32& aTextLength) const |
1474 |
PRInt32& aTextLength) |
| 1485 |
{ |
1475 |
{ |
| 1486 |
if ( (nsnull == aText) || (aTextLength < 1) ) { |
1476 |
if ( (nsnull == aText) || (aTextLength < 1) ) { |
| 1487 |
return; |
1477 |
return; |
| 1488 |
} |
1478 |
} |
| 1489 |
|
1479 |
|
| 1490 |
PRInt32 stripLen = 0; |
1480 |
PRInt32 stripLen = 0; |
| 1491 |
|
1481 |
|
| 1492 |
for (PRInt32 i = 0; i < aTextLength; i++) { |
1482 |
for (PRInt32 i = 0; i < aTextLength; i++) { |
|
Lines 1519-1561
RemoveDiacritics(PRUnichar* aText,
|
Link Here
|
|---|
|
| 1519 |
} |
1509 |
} |
| 1520 |
aTextLength = i - offset; |
1510 |
aTextLength = i - offset; |
| 1521 |
aText[aTextLength] = 0; |
1511 |
aText[aTextLength] = 0; |
| 1522 |
} |
1512 |
} |
| 1523 |
} |
1513 |
} |
| 1524 |
#endif |
1514 |
#endif |
| 1525 |
|
1515 |
|
| 1526 |
void |
1516 |
void |
| 1527 |
nsBidiPresUtils::CalculateCharType(PRInt32& aOffset, |
1517 |
nsBidiPresUtils::CalculateCharType(nsBidi* aBidiEngine, |
|
|
1518 |
const PRUnichar* aText, |
| 1519 |
PRInt32& aOffset, |
| 1528 |
PRInt32 aCharTypeLimit, |
1520 |
PRInt32 aCharTypeLimit, |
| 1529 |
PRInt32& aRunLimit, |
1521 |
PRInt32& aRunLimit, |
| 1530 |
PRInt32& aRunLength, |
1522 |
PRInt32& aRunLength, |
| 1531 |
PRInt32& aRunCount, |
1523 |
PRInt32& aRunCount, |
| 1532 |
PRUint8& aCharType, |
1524 |
PRUint8& aCharType, |
| 1533 |
PRUint8& aPrevCharType) const |
1525 |
PRUint8& aPrevCharType) |
| 1534 |
|
1526 |
|
| 1535 |
{ |
1527 |
{ |
| 1536 |
PRBool strongTypeFound = PR_FALSE; |
1528 |
PRBool strongTypeFound = PR_FALSE; |
| 1537 |
PRInt32 offset; |
1529 |
PRInt32 offset; |
| 1538 |
nsCharType charType; |
1530 |
nsCharType charType; |
| 1539 |
|
1531 |
|
| 1540 |
aCharType = eCharType_OtherNeutral; |
1532 |
aCharType = eCharType_OtherNeutral; |
| 1541 |
|
1533 |
|
| 1542 |
for (offset = aOffset; offset < aCharTypeLimit; offset++) { |
1534 |
for (offset = aOffset; offset < aCharTypeLimit; offset++) { |
| 1543 |
// Make sure we give RTL chartype to all characters that would be classified |
1535 |
// Make sure we give RTL chartype to all characters that would be classified |
| 1544 |
// as Right-To-Left by a bidi platform. |
1536 |
// as Right-To-Left by a bidi platform. |
| 1545 |
// (May differ from the UnicodeData, eg we set RTL chartype to some NSMs.) |
1537 |
// (May differ from the UnicodeData, eg we set RTL chartype to some NSMs.) |
| 1546 |
if (IS_HEBREW_CHAR(mBuffer[offset]) ) { |
1538 |
if (IS_HEBREW_CHAR(aText[offset]) ) { |
| 1547 |
charType = eCharType_RightToLeft; |
1539 |
charType = eCharType_RightToLeft; |
| 1548 |
} |
1540 |
} |
| 1549 |
else if (IS_ARABIC_ALPHABETIC(mBuffer[offset]) ) { |
1541 |
else if (IS_ARABIC_ALPHABETIC(aText[offset]) ) { |
| 1550 |
charType = eCharType_RightToLeftArabic; |
1542 |
charType = eCharType_RightToLeftArabic; |
| 1551 |
} |
1543 |
} |
| 1552 |
else { |
1544 |
else { |
| 1553 |
mBidiEngine->GetCharTypeAt(offset, &charType); |
1545 |
aBidiEngine->GetCharTypeAt(offset, &charType); |
| 1554 |
} |
1546 |
} |
| 1555 |
|
1547 |
|
| 1556 |
if (!CHARTYPE_IS_WEAK(charType) ) { |
1548 |
if (!CHARTYPE_IS_WEAK(charType) ) { |
| 1557 |
|
1549 |
|
| 1558 |
if (strongTypeFound |
1550 |
if (strongTypeFound |
| 1559 |
&& (charType != aPrevCharType) |
1551 |
&& (charType != aPrevCharType) |
| 1560 |
&& (CHARTYPE_IS_RTL(charType) || CHARTYPE_IS_RTL(aPrevCharType) ) ) { |
1552 |
&& (CHARTYPE_IS_RTL(charType) || CHARTYPE_IS_RTL(aPrevCharType) ) ) { |
| 1561 |
// Stop at this point to ensure uni-directionality of the text |
1553 |
// Stop at this point to ensure uni-directionality of the text |
|
Lines 1588-1616
nsBidiPresUtils::CalculateCharType(PRInt
|
Link Here
|
|---|
|
| 1588 |
nsresult nsBidiPresUtils::ProcessText(const PRUnichar* aText, |
1580 |
nsresult nsBidiPresUtils::ProcessText(const PRUnichar* aText, |
| 1589 |
PRInt32 aLength, |
1581 |
PRInt32 aLength, |
| 1590 |
nsBidiDirection aBaseDirection, |
1582 |
nsBidiDirection aBaseDirection, |
| 1591 |
nsPresContext* aPresContext, |
1583 |
nsPresContext* aPresContext, |
| 1592 |
BidiProcessor& aprocessor, |
1584 |
BidiProcessor& aprocessor, |
| 1593 |
Mode aMode, |
1585 |
Mode aMode, |
| 1594 |
nsBidiPositionResolve* aPosResolve, |
1586 |
nsBidiPositionResolve* aPosResolve, |
| 1595 |
PRInt32 aPosResolveCount, |
1587 |
PRInt32 aPosResolveCount, |
| 1596 |
nscoord* aWidth) |
1588 |
nscoord* aWidth, |
|
|
1589 |
nsBidi* aBidiEngine) |
| 1597 |
{ |
1590 |
{ |
| 1598 |
NS_ASSERTION((aPosResolve == nsnull) != (aPosResolveCount > 0), "Incorrect aPosResolve / aPosResolveCount arguments"); |
1591 |
NS_ASSERTION((aPosResolve == nsnull) != (aPosResolveCount > 0), "Incorrect aPosResolve / aPosResolveCount arguments"); |
| 1599 |
|
1592 |
|
| 1600 |
PRInt32 runCount; |
1593 |
PRInt32 runCount; |
| 1601 |
|
1594 |
|
| 1602 |
mBuffer.Assign(aText, aLength); |
1595 |
nsAutoString textBuffer(aText, aLength); |
| 1603 |
|
1596 |
|
| 1604 |
nsresult rv = mBidiEngine->SetPara(mBuffer.get(), aLength, aBaseDirection, nsnull); |
1597 |
nsresult rv = aBidiEngine->SetPara(aText, aLength, aBaseDirection, nsnull); |
| 1605 |
if (NS_FAILED(rv)) |
1598 |
if (NS_FAILED(rv)) |
| 1606 |
return rv; |
1599 |
return rv; |
| 1607 |
|
1600 |
|
| 1608 |
rv = mBidiEngine->CountRuns(&runCount); |
1601 |
rv = aBidiEngine->CountRuns(&runCount); |
| 1609 |
if (NS_FAILED(rv)) |
1602 |
if (NS_FAILED(rv)) |
| 1610 |
return rv; |
1603 |
return rv; |
| 1611 |
|
1604 |
|
| 1612 |
nscoord xOffset = 0; |
1605 |
nscoord xOffset = 0; |
| 1613 |
nscoord width, xEndRun; |
1606 |
nscoord width, xEndRun; |
| 1614 |
nscoord totalWidth = 0; |
1607 |
nscoord totalWidth = 0; |
| 1615 |
PRInt32 i, start, limit, length; |
1608 |
PRInt32 i, start, limit, length; |
| 1616 |
PRUint32 visualStart = 0; |
1609 |
PRUint32 visualStart = 0; |
|
Lines 1621-1641
nsresult nsBidiPresUtils::ProcessText(co
|
Link Here
|
|---|
|
| 1621 |
for(int nPosResolve=0; nPosResolve < aPosResolveCount; ++nPosResolve) |
1614 |
for(int nPosResolve=0; nPosResolve < aPosResolveCount; ++nPosResolve) |
| 1622 |
{ |
1615 |
{ |
| 1623 |
aPosResolve[nPosResolve].visualIndex = kNotFound; |
1616 |
aPosResolve[nPosResolve].visualIndex = kNotFound; |
| 1624 |
aPosResolve[nPosResolve].visualLeftTwips = kNotFound; |
1617 |
aPosResolve[nPosResolve].visualLeftTwips = kNotFound; |
| 1625 |
aPosResolve[nPosResolve].visualWidth = kNotFound; |
1618 |
aPosResolve[nPosResolve].visualWidth = kNotFound; |
| 1626 |
} |
1619 |
} |
| 1627 |
|
1620 |
|
| 1628 |
for (i = 0; i < runCount; i++) { |
1621 |
for (i = 0; i < runCount; i++) { |
| 1629 |
rv = mBidiEngine->GetVisualRun(i, &start, &length, &aBaseDirection); |
1622 |
rv = aBidiEngine->GetVisualRun(i, &start, &length, &aBaseDirection); |
| 1630 |
if (NS_FAILED(rv)) |
1623 |
if (NS_FAILED(rv)) |
| 1631 |
return rv; |
1624 |
return rv; |
| 1632 |
|
1625 |
|
| 1633 |
rv = mBidiEngine->GetLogicalRun(start, &limit, &level); |
1626 |
rv = aBidiEngine->GetLogicalRun(start, &limit, &level); |
| 1634 |
if (NS_FAILED(rv)) |
1627 |
if (NS_FAILED(rv)) |
| 1635 |
return rv; |
1628 |
return rv; |
| 1636 |
|
1629 |
|
| 1637 |
PRInt32 subRunLength = limit - start; |
1630 |
PRInt32 subRunLength = limit - start; |
| 1638 |
PRInt32 lineOffset = start; |
1631 |
PRInt32 lineOffset = start; |
| 1639 |
PRInt32 typeLimit = NS_MIN(limit, aLength); |
1632 |
PRInt32 typeLimit = NS_MIN(limit, aLength); |
| 1640 |
PRInt32 subRunCount = 1; |
1633 |
PRInt32 subRunCount = 1; |
| 1641 |
PRInt32 subRunLimit = typeLimit; |
1634 |
PRInt32 subRunLimit = typeLimit; |
|
Lines 1657-1673
nsresult nsBidiPresUtils::ProcessText(co
|
Link Here
|
|---|
|
| 1657 |
width = aprocessor.GetWidth(); |
1650 |
width = aprocessor.GetWidth(); |
| 1658 |
xOffset += width; |
1651 |
xOffset += width; |
| 1659 |
xEndRun = xOffset; |
1652 |
xEndRun = xOffset; |
| 1660 |
} |
1653 |
} |
| 1661 |
|
1654 |
|
| 1662 |
while (subRunCount > 0) { |
1655 |
while (subRunCount > 0) { |
| 1663 |
// CalculateCharType can increment subRunCount if the run |
1656 |
// CalculateCharType can increment subRunCount if the run |
| 1664 |
// contains mixed character types |
1657 |
// contains mixed character types |
| 1665 |
CalculateCharType(lineOffset, typeLimit, subRunLimit, subRunLength, subRunCount, charType, prevType); |
1658 |
CalculateCharType(aBidiEngine, aText, lineOffset, typeLimit, subRunLimit, subRunLength, subRunCount, charType, prevType); |
| 1666 |
|
1659 |
|
| 1667 |
nsAutoString runVisualText; |
1660 |
nsAutoString runVisualText; |
| 1668 |
runVisualText.Assign(aText + start, subRunLength); |
1661 |
runVisualText.Assign(aText + start, subRunLength); |
| 1669 |
if (PRInt32(runVisualText.Length()) < subRunLength) |
1662 |
if (PRInt32(runVisualText.Length()) < subRunLength) |
| 1670 |
return NS_ERROR_OUT_OF_MEMORY; |
1663 |
return NS_ERROR_OUT_OF_MEMORY; |
| 1671 |
FormatUnicodeText(aPresContext, runVisualText.BeginWriting(), subRunLength, |
1664 |
FormatUnicodeText(aPresContext, runVisualText.BeginWriting(), subRunLength, |
| 1672 |
(nsCharType)charType, level & 1); |
1665 |
(nsCharType)charType, level & 1); |
| 1673 |
|
1666 |
|
|
Lines 1848-1866
nsresult nsBidiPresUtils::ProcessTextFor
|
Link Here
|
|---|
|
| 1848 |
Mode aMode, |
1841 |
Mode aMode, |
| 1849 |
nscoord aX, |
1842 |
nscoord aX, |
| 1850 |
nscoord aY, |
1843 |
nscoord aY, |
| 1851 |
nsBidiPositionResolve* aPosResolve, |
1844 |
nsBidiPositionResolve* aPosResolve, |
| 1852 |
PRInt32 aPosResolveCount, |
1845 |
PRInt32 aPosResolveCount, |
| 1853 |
nscoord* aWidth) |
1846 |
nscoord* aWidth) |
| 1854 |
{ |
1847 |
{ |
| 1855 |
nsIRenderingContextBidiProcessor processor(&aRenderingContext, &aTextRunConstructionContext, nsPoint(aX, aY)); |
1848 |
nsIRenderingContextBidiProcessor processor(&aRenderingContext, &aTextRunConstructionContext, nsPoint(aX, aY)); |
| 1856 |
|
1849 |
nsBidi bidiEngine; |
| 1857 |
return ProcessText(aText, aLength, aBaseDirection, aPresContext, processor, |
1850 |
return ProcessText(aText, aLength, aBaseDirection, aPresContext, processor, |
| 1858 |
aMode, aPosResolve, aPosResolveCount, aWidth); |
1851 |
aMode, aPosResolve, aPosResolveCount, aWidth, &bidiEngine); |
| 1859 |
} |
1852 |
} |
| 1860 |
|
1853 |
|
| 1861 |
/* static */ |
1854 |
/* static */ |
| 1862 |
void nsBidiPresUtils::WriteReverse(const PRUnichar* aSrc, |
1855 |
void nsBidiPresUtils::WriteReverse(const PRUnichar* aSrc, |
| 1863 |
PRUint32 aSrcLength, |
1856 |
PRUint32 aSrcLength, |
| 1864 |
PRUnichar* aDest) |
1857 |
PRUnichar* aDest) |
| 1865 |
{ |
1858 |
{ |
| 1866 |
const PRUnichar* src = aSrc + aSrcLength; |
1859 |
const PRUnichar* src = aSrc + aSrcLength; |
|
Lines 1972-2026
void nsBidiPresUtils::CopyLogicalToVisua
|
Link Here
|
|---|
|
| 1972 |
// no need to use the converter -- just copy the string in reverse order |
1965 |
// no need to use the converter -- just copy the string in reverse order |
| 1973 |
WriteReverse(fromBegin.get(), srcLength, toBegin.get()); |
1966 |
WriteReverse(fromBegin.get(), srcLength, toBegin.get()); |
| 1974 |
} else { |
1967 |
} else { |
| 1975 |
// if aOverride && aBaseDirection == NSBIDI_LTR, fall through to the |
1968 |
// if aOverride && aBaseDirection == NSBIDI_LTR, fall through to the |
| 1976 |
// simple copy |
1969 |
// simple copy |
| 1977 |
aDest.SetLength(0); |
1970 |
aDest.SetLength(0); |
| 1978 |
} |
1971 |
} |
| 1979 |
} else { |
1972 |
} else { |
|
|
1973 |
nsBidi bidiEngine; |
| 1980 |
if (!WriteLogicalToVisual(fromBegin.get(), srcLength, toBegin.get(), |
1974 |
if (!WriteLogicalToVisual(fromBegin.get(), srcLength, toBegin.get(), |
| 1981 |
aBaseDirection, mBidiEngine)) { |
1975 |
aBaseDirection, &bidiEngine)) { |
| 1982 |
aDest.SetLength(0); |
1976 |
aDest.SetLength(0); |
| 1983 |
} |
1977 |
} |
| 1984 |
} |
1978 |
} |
| 1985 |
|
1979 |
|
| 1986 |
if (aDest.IsEmpty()) { |
1980 |
if (aDest.IsEmpty()) { |
| 1987 |
// Either there was an error or the source is unidirectional |
1981 |
// Either there was an error or the source is unidirectional |
| 1988 |
// left-to-right. In either case, just copy source to dest. |
1982 |
// left-to-right. In either case, just copy source to dest. |
| 1989 |
CopyUnicodeTo(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), |
1983 |
CopyUnicodeTo(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), |
| 1990 |
aDest); |
1984 |
aDest); |
| 1991 |
} |
1985 |
} |
| 1992 |
} |
1986 |
} |
| 1993 |
|
|
|
| 1994 |
PRUint32 nsBidiPresUtils::EstimateMemoryUsed() |
| 1995 |
{ |
| 1996 |
PRUint32 size = 0; |
| 1997 |
|
| 1998 |
size += sizeof(nsBidiPresUtils); |
| 1999 |
size += mBuffer.Length() * sizeof(PRUnichar); |
| 2000 |
size += moz_malloc_usable_size(mBidiEngine->mDirPropsMemory); |
| 2001 |
size += moz_malloc_usable_size(mBidiEngine->mLevelsMemory); |
| 2002 |
size += moz_malloc_usable_size(mBidiEngine->mRunsMemory); |
| 2003 |
|
| 2004 |
return size; |
| 2005 |
} |
| 2006 |
|
| 2007 |
static PLDHashOperator |
| 2008 |
TraverseKey(nsISupports *aKey, PRInt32 aData, void *aUserArg) |
| 2009 |
{ |
| 2010 |
nsCycleCollectionTraversalCallback *cb = |
| 2011 |
static_cast<nsCycleCollectionTraversalCallback*>(aUserArg); |
| 2012 |
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mContentToFrameIndex key"); |
| 2013 |
cb->NoteXPCOMChild(aKey); |
| 2014 |
return PL_DHASH_NEXT; |
| 2015 |
} |
| 2016 |
|
| 2017 |
void nsBidiPresUtils::Traverse(nsCycleCollectionTraversalCallback &cb) const |
| 2018 |
{ |
| 2019 |
mContentToFrameIndex.EnumerateRead(TraverseKey, &cb); |
| 2020 |
} |
| 2021 |
|
| 2022 |
void nsBidiPresUtils::Unlink() |
| 2023 |
{ |
| 2024 |
mContentToFrameIndex.Clear(); |
| 2025 |
} |
| 2026 |
#endif // IBMBIDI |
1987 |
#endif // IBMBIDI |