|
|
|
Lines 67-83
static const PRUnichar kLRO
|
Link Here
|
|---|
|
| 67 |
static const PRUnichar kRLO = 0x202E; |
67 |
static const PRUnichar kRLO = 0x202E; |
| 68 |
static const PRUnichar kPDF = 0x202C; |
68 |
static const PRUnichar kPDF = 0x202C; |
| 69 |
static const PRUnichar ALEF = 0x05D0; |
69 |
static const PRUnichar ALEF = 0x05D0; |
| 70 |
|
70 |
|
| 71 |
#define CHAR_IS_HEBREW(c) ((0x0590 <= (c)) && ((c)<= 0x05FF)) |
71 |
#define CHAR_IS_HEBREW(c) ((0x0590 <= (c)) && ((c)<= 0x05FF)) |
| 72 |
// Note: The above code are moved from gfx/src/windows/nsRenderingContextWin.cpp |
72 |
// Note: The above code are moved from gfx/src/windows/nsRenderingContextWin.cpp |
| 73 |
|
73 |
|
| 74 |
nsIFrame* |
74 |
nsIFrame* |
| 75 |
NS_NewDirectionalFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, PRUnichar aChar); |
75 |
NS_NewDirectionalFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); |
| 76 |
|
76 |
|
| 77 |
nsBidiPresUtils::nsBidiPresUtils() : mArraySize(8), |
77 |
nsBidiPresUtils::nsBidiPresUtils() : mArraySize(8), |
| 78 |
mIndexMap(nsnull), |
78 |
mIndexMap(nsnull), |
| 79 |
mLevels(nsnull), |
79 |
mLevels(nsnull), |
| 80 |
mSuccess(NS_ERROR_FAILURE), |
80 |
mSuccess(NS_ERROR_FAILURE), |
| 81 |
mBidiEngine(nsnull) |
81 |
mBidiEngine(nsnull) |
| 82 |
{ |
82 |
{ |
| 83 |
mBidiEngine = new nsBidi(); |
83 |
mBidiEngine = new nsBidi(); |
|
Lines 308-361
AdvanceLineIteratorToFrame(nsIFrame* aFr
|
Link Here
|
|---|
|
| 308 |
* We may also need to call RemoveBidiContinuation() to convert frames created |
308 |
* We may also need to call RemoveBidiContinuation() to convert frames created |
| 309 |
* by EnsureBidiContinuation() in previous reflows into fluid continuations. |
309 |
* by EnsureBidiContinuation() in previous reflows into fluid continuations. |
| 310 |
*/ |
310 |
*/ |
| 311 |
nsresult |
311 |
nsresult |
| 312 |
nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame) |
312 |
nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame) |
| 313 |
{ |
313 |
{ |
| 314 |
mLogicalFrames.Clear(); |
314 |
mLogicalFrames.Clear(); |
| 315 |
mContentToFrameIndex.Clear(); |
315 |
mContentToFrameIndex.Clear(); |
|
|
316 |
mBuffer.SetLength(0); |
| 316 |
|
317 |
|
| 317 |
nsPresContext *presContext = aBlockFrame->PresContext(); |
318 |
nsPresContext *presContext = aBlockFrame->PresContext(); |
| 318 |
nsIPresShell* shell = presContext->PresShell(); |
319 |
nsIPresShell* shell = presContext->PresShell(); |
| 319 |
nsStyleContext* styleContext = aBlockFrame->GetStyleContext(); |
320 |
nsStyleContext* styleContext = aBlockFrame->GetStyleContext(); |
| 320 |
|
321 |
|
| 321 |
// handle bidi-override being set on the block itself before calling |
322 |
// handle bidi-override being set on the block itself before calling |
| 322 |
// InitLogicalArray. |
323 |
// InitLogicalArray. |
| 323 |
const nsStyleVisibility* vis = aBlockFrame->GetStyleVisibility(); |
324 |
const nsStyleVisibility* vis = aBlockFrame->GetStyleVisibility(); |
| 324 |
const nsStyleTextReset* text = aBlockFrame->GetStyleTextReset(); |
325 |
const nsStyleTextReset* text = aBlockFrame->GetStyleTextReset(); |
| 325 |
|
326 |
|
|
|
327 |
PRUnichar ch = 0; |
| 326 |
if (text->mUnicodeBidi == NS_STYLE_UNICODE_BIDI_OVERRIDE) { |
328 |
if (text->mUnicodeBidi == NS_STYLE_UNICODE_BIDI_OVERRIDE) { |
| 327 |
nsIFrame *directionalFrame = nsnull; |
329 |
nsIFrame *directionalFrame = nsnull; |
| 328 |
|
330 |
|
| 329 |
if (NS_STYLE_DIRECTION_RTL == vis->mDirection) { |
331 |
if (NS_STYLE_DIRECTION_RTL == vis->mDirection) { |
| 330 |
directionalFrame = NS_NewDirectionalFrame(shell, styleContext, kRLO); |
332 |
ch = kRLO; |
| 331 |
} |
333 |
} |
| 332 |
else if (NS_STYLE_DIRECTION_LTR == vis->mDirection) { |
334 |
else if (NS_STYLE_DIRECTION_LTR == vis->mDirection) { |
| 333 |
directionalFrame = NS_NewDirectionalFrame(shell, styleContext, kLRO); |
335 |
ch = kLRO; |
| 334 |
} |
336 |
} |
| 335 |
|
337 |
if (ch != 0) { |
| 336 |
if (directionalFrame) { |
338 |
directionalFrame = NS_NewDirectionalFrame(shell, styleContext); |
| 337 |
mLogicalFrames.AppendElement(directionalFrame); |
339 |
if (directionalFrame) { |
|
|
340 |
mLogicalFrames.AppendElement(directionalFrame); |
| 341 |
mBuffer.Append(ch); |
| 342 |
} |
| 338 |
} |
343 |
} |
| 339 |
} |
344 |
} |
|
|
345 |
nsIContent* prevContent = nsnull; |
| 340 |
for (nsBlockFrame* block = aBlockFrame; block; |
346 |
for (nsBlockFrame* block = aBlockFrame; block; |
| 341 |
block = static_cast<nsBlockFrame*>(block->GetNextContinuation())) { |
347 |
block = static_cast<nsBlockFrame*>(block->GetNextContinuation())) { |
| 342 |
block->RemoveStateBits(NS_BLOCK_NEEDS_BIDI_RESOLUTION); |
348 |
block->RemoveStateBits(NS_BLOCK_NEEDS_BIDI_RESOLUTION); |
| 343 |
InitLogicalArray(block->GetFirstChild(nsnull)); |
349 |
InitLogicalArray(block->GetFirstChild(nsnull), prevContent); |
| 344 |
} |
350 |
} |
| 345 |
|
351 |
|
| 346 |
if (text->mUnicodeBidi == NS_STYLE_UNICODE_BIDI_OVERRIDE) { |
352 |
if (ch != 0) { |
| 347 |
nsIFrame* directionalFrame = NS_NewDirectionalFrame(shell, styleContext, kPDF); |
353 |
nsIFrame* directionalFrame = NS_NewDirectionalFrame(shell, styleContext); |
| 348 |
if (directionalFrame) { |
354 |
if (directionalFrame) { |
| 349 |
mLogicalFrames.AppendElement(directionalFrame); |
355 |
mLogicalFrames.AppendElement(directionalFrame); |
|
|
356 |
mBuffer.Append(kPDF); |
| 350 |
} |
357 |
} |
| 351 |
} |
358 |
} |
| 352 |
|
359 |
|
| 353 |
CreateBlockBuffer(); |
360 |
// XXX: TODO: Handle preformatted text ('\n') |
|
|
361 |
mBuffer.ReplaceChar("\t\r\n", kSpace); |
| 354 |
|
362 |
|
| 355 |
PRInt32 bufferLength = mBuffer.Length(); |
363 |
PRInt32 bufferLength = mBuffer.Length(); |
| 356 |
|
364 |
|
| 357 |
if (bufferLength < 1) { |
365 |
if (bufferLength < 1) { |
| 358 |
mSuccess = NS_OK; |
366 |
mSuccess = NS_OK; |
| 359 |
return mSuccess; |
367 |
return mSuccess; |
| 360 |
} |
368 |
} |
| 361 |
PRInt32 runCount; |
369 |
PRInt32 runCount; |
|
Lines 611-627
nsBidiPresUtils::Resolve(nsBlockFrame* a
|
Link Here
|
|---|
|
| 611 |
// Should this frame be treated as a leaf (e.g. when building mLogicalFrames)? |
619 |
// Should this frame be treated as a leaf (e.g. when building mLogicalFrames)? |
| 612 |
PRBool IsBidiLeaf(nsIFrame* aFrame) { |
620 |
PRBool IsBidiLeaf(nsIFrame* aFrame) { |
| 613 |
nsIFrame* kid = aFrame->GetFirstChild(nsnull); |
621 |
nsIFrame* kid = aFrame->GetFirstChild(nsnull); |
| 614 |
return !kid |
622 |
return !kid |
| 615 |
|| !aFrame->IsFrameOfType(nsIFrame::eBidiInlineContainer); |
623 |
|| !aFrame->IsFrameOfType(nsIFrame::eBidiInlineContainer); |
| 616 |
} |
624 |
} |
| 617 |
|
625 |
|
| 618 |
void |
626 |
void |
| 619 |
nsBidiPresUtils::InitLogicalArray(nsIFrame* aCurrentFrame) |
627 |
nsBidiPresUtils::InitLogicalArray(nsIFrame* aCurrentFrame, |
|
|
628 |
nsIContent*& aPrevContent) |
| 620 |
{ |
629 |
{ |
| 621 |
if (!aCurrentFrame) |
630 |
if (!aCurrentFrame) |
| 622 |
return; |
631 |
return; |
| 623 |
|
632 |
|
| 624 |
nsIPresShell* shell = aCurrentFrame->PresContext()->PresShell(); |
633 |
nsIPresShell* shell = aCurrentFrame->PresContext()->PresShell(); |
| 625 |
nsStyleContext* styleContext; |
634 |
nsStyleContext* styleContext; |
| 626 |
|
635 |
|
| 627 |
for (nsIFrame* childFrame = aCurrentFrame; childFrame; |
636 |
for (nsIFrame* childFrame = aCurrentFrame; childFrame; |
|
Lines 666-762
nsBidiPresUtils::InitLogicalArray(nsIFra
|
Link Here
|
|---|
|
| 666 |
ch = kLRO; |
675 |
ch = kLRO; |
| 667 |
} |
676 |
} |
| 668 |
break; |
677 |
break; |
| 669 |
} |
678 |
} |
| 670 |
|
679 |
|
| 671 |
// Create a directional frame before the first frame of an |
680 |
// Create a directional frame before the first frame of an |
| 672 |
// element specifying embedding or override |
681 |
// element specifying embedding or override |
| 673 |
if (ch != 0 && !frame->GetPrevContinuation()) { |
682 |
if (ch != 0 && !frame->GetPrevContinuation()) { |
| 674 |
nsIFrame* dirFrame = NS_NewDirectionalFrame(shell, styleContext, ch); |
683 |
nsIFrame* dirFrame = NS_NewDirectionalFrame(shell, styleContext); |
| 675 |
if (dirFrame) { |
684 |
if (dirFrame) { |
| 676 |
mLogicalFrames.AppendElement(dirFrame); |
685 |
mLogicalFrames.AppendElement(dirFrame); |
|
|
686 |
mBuffer.Append(ch); |
| 677 |
} |
687 |
} |
| 678 |
} |
688 |
} |
| 679 |
} |
689 |
} |
| 680 |
|
690 |
|
| 681 |
if (IsBidiLeaf(frame)) { |
691 |
if (IsBidiLeaf(frame)) { |
| 682 |
/* Bidi leaf frame: add the frame to the mLogicalFrames array, |
692 |
/* Bidi leaf frame: add the frame to the mLogicalFrames array, |
| 683 |
* and add its index to the mContentToFrameIndex hashtable. This |
693 |
* and add its index to the mContentToFrameIndex hashtable. This |
| 684 |
* will be used in RemoveBidiContinuation() to identify the last |
694 |
* will be used in RemoveBidiContinuation() to identify the last |
| 685 |
* frame in the array with a given content. |
695 |
* frame in the array with a given content. |
| 686 |
*/ |
696 |
*/ |
| 687 |
nsIContent* content = frame->GetContent(); |
697 |
nsIContent* content = frame->GetContent(); |
| 688 |
if (content) { |
698 |
if (content) { |
| 689 |
mContentToFrameIndex.Put(content, mLogicalFrames.Length()); |
699 |
mContentToFrameIndex.Put(content, mLogicalFrames.Length()); |
| 690 |
} |
700 |
} |
| 691 |
mLogicalFrames.AppendElement(frame); |
701 |
mLogicalFrames.AppendElement(frame); |
|
|
702 |
|
| 703 |
// Append the content of the frame to the paragraph buffer |
| 704 |
nsIAtom* frameType = frame->GetType(); |
| 705 |
if (nsGkAtoms::textFrame == frameType) { |
| 706 |
if (content != aPrevContent) { |
| 707 |
aPrevContent = content; |
| 708 |
content->AppendTextTo(mBuffer); |
| 709 |
} |
| 710 |
} else if (nsGkAtoms::brFrame == frameType) { |
| 711 |
// break frame -- append line separator |
| 712 |
mBuffer.Append(kLineSeparator); |
| 713 |
} else { |
| 714 |
// other frame type -- see the Unicode Bidi Algorithm: |
| 715 |
// "...inline objects (such as graphics) are treated as if they are ... |
| 716 |
// U+FFFC" |
| 717 |
mBuffer.Append(kObjectSubstitute); |
| 718 |
} |
| 692 |
} |
719 |
} |
| 693 |
else { |
720 |
else { |
| 694 |
nsIFrame* kid = frame->GetFirstChild(nsnull); |
721 |
nsIFrame* kid = frame->GetFirstChild(nsnull); |
| 695 |
InitLogicalArray(kid); |
722 |
InitLogicalArray(kid, aPrevContent); |
| 696 |
} |
723 |
} |
| 697 |
|
724 |
|
| 698 |
// If the element is attributed by dir, indicate direction pop (add PDF frame) |
725 |
// If the element is attributed by dir, indicate direction pop (add PDF frame) |
| 699 |
if (ch != 0 && !frame->GetNextContinuation()) { |
726 |
if (ch != 0 && !frame->GetNextContinuation()) { |
| 700 |
// Create a directional frame after the last frame of an |
727 |
// Create a directional frame after the last frame of an |
| 701 |
// element specifying embedding or override |
728 |
// element specifying embedding or override |
| 702 |
nsIFrame* dirFrame = NS_NewDirectionalFrame(shell, styleContext, kPDF); |
729 |
nsIFrame* dirFrame = NS_NewDirectionalFrame(shell, styleContext); |
| 703 |
if (dirFrame) { |
730 |
if (dirFrame) { |
| 704 |
mLogicalFrames.AppendElement(dirFrame); |
731 |
mLogicalFrames.AppendElement(dirFrame); |
|
|
732 |
mBuffer.Append(kPDF); |
| 705 |
} |
733 |
} |
| 706 |
} |
734 |
} |
| 707 |
} // for |
735 |
} // for |
| 708 |
} |
736 |
} |
| 709 |
|
737 |
|
| 710 |
void |
738 |
void |
| 711 |
nsBidiPresUtils::CreateBlockBuffer() |
|
|
| 712 |
{ |
| 713 |
mBuffer.SetLength(0); |
| 714 |
|
| 715 |
nsIFrame* frame; |
| 716 |
nsIContent* prevContent = nsnull; |
| 717 |
PRUint32 i; |
| 718 |
PRUint32 count = mLogicalFrames.Length(); |
| 719 |
|
| 720 |
for (i = 0; i < count; i++) { |
| 721 |
frame = mLogicalFrames[i]; |
| 722 |
nsIAtom* frameType = frame->GetType(); |
| 723 |
|
| 724 |
if (nsGkAtoms::textFrame == frameType) { |
| 725 |
nsIContent* content = frame->GetContent(); |
| 726 |
if (!content) { |
| 727 |
mSuccess = NS_OK; |
| 728 |
break; |
| 729 |
} |
| 730 |
if (content == prevContent) { |
| 731 |
continue; |
| 732 |
} |
| 733 |
prevContent = content; |
| 734 |
content->AppendTextTo(mBuffer); |
| 735 |
} |
| 736 |
else if (nsGkAtoms::brFrame == frameType) { // break frame |
| 737 |
// Append line separator |
| 738 |
mBuffer.Append(kLineSeparator); |
| 739 |
} |
| 740 |
else if (nsGkAtoms::directionalFrame == frameType) { |
| 741 |
nsDirectionalFrame* dirFrame = static_cast<nsDirectionalFrame*>(frame); |
| 742 |
mBuffer.Append(dirFrame->GetChar()); |
| 743 |
} |
| 744 |
else { // not text frame |
| 745 |
// See the Unicode Bidi Algorithm: |
| 746 |
// "...inline objects (such as graphics) are treated as if they are ... U+FFFC" |
| 747 |
mBuffer.Append(kObjectSubstitute); |
| 748 |
} |
| 749 |
} |
| 750 |
// XXX: TODO: Handle preformatted text ('\n') |
| 751 |
mBuffer.ReplaceChar("\t\r\n", kSpace); |
| 752 |
} |
| 753 |
|
| 754 |
void |
| 755 |
nsBidiPresUtils::ReorderFrames(nsIFrame* aFirstFrameOnLine, |
739 |
nsBidiPresUtils::ReorderFrames(nsIFrame* aFirstFrameOnLine, |
| 756 |
PRInt32 aNumFramesOnLine) |
740 |
PRInt32 aNumFramesOnLine) |
| 757 |
{ |
741 |
{ |
| 758 |
// If this line consists of a line frame, reorder the line frame's children. |
742 |
// If this line consists of a line frame, reorder the line frame's children. |
| 759 |
if (aFirstFrameOnLine->GetType() == nsGkAtoms::lineFrame) { |
743 |
if (aFirstFrameOnLine->GetType() == nsGkAtoms::lineFrame) { |
| 760 |
aFirstFrameOnLine = aFirstFrameOnLine->GetFirstChild(nsnull); |
744 |
aFirstFrameOnLine = aFirstFrameOnLine->GetFirstChild(nsnull); |
| 761 |
if (!aFirstFrameOnLine) |
745 |
if (!aFirstFrameOnLine) |
| 762 |
return; |
746 |
return; |