mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
Bug 482138 [TSF] nsTextFrame has to draw composition string by TIP specified style r+sr=roc
This commit is contained in:
parent
257a5fc973
commit
cfff67f8c9
@ -47,15 +47,17 @@ interface nsIContent;
|
||||
class nsFrameSelection;
|
||||
class nsIFrame;
|
||||
class nsIPresShell;
|
||||
struct nsTextRangeStyle;
|
||||
struct nsPoint;
|
||||
%}
|
||||
|
||||
[ptr] native nsFrameSelection(nsFrameSelection);
|
||||
[ptr] native nsIFrame(nsIFrame);
|
||||
[ptr] native nsIPresShell(nsIPresShell);
|
||||
[ref] native constTextRangeStyleRef(const nsTextRangeStyle);
|
||||
[ref] native nsPointRef(nsPoint);
|
||||
|
||||
[scriptable, uuid(b416c692-eeb8-4186-addd-c444e81b68e5)]
|
||||
[scriptable, uuid(98552206-ad7a-4d2d-8ce3-b6fa2389298b)]
|
||||
interface nsISelectionPrivate : nsISupports
|
||||
{
|
||||
const short ENDOFPRECEDINGLINE=0;
|
||||
@ -118,5 +120,13 @@ interface nsISelectionPrivate : nsISupports
|
||||
[noscript] nsFrameSelection getFrameSelection();
|
||||
|
||||
[noscript] void setAncestorLimiter(in nsIContent aContent);
|
||||
|
||||
/**
|
||||
* Set the painting style for the range. The range must be a range in
|
||||
* the selection. The textRangeStyle will be used by text frame
|
||||
* when it is painting the selection.
|
||||
*/
|
||||
[noscript] void setTextRangeStyle(in nsIDOMRange range,
|
||||
in constTextRangeStyleRef textRangeStyle);
|
||||
};
|
||||
|
||||
|
@ -41,10 +41,12 @@
|
||||
#include "nsISupports.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsGUIEvent.h"
|
||||
|
||||
// {B13C4BD8-CB9F-4763-A020-E99ABC9C2803}
|
||||
#define NS_IPRIVATETEXTRANGE_IID \
|
||||
{0xb471ab41, 0x2a79, 0x11d3, \
|
||||
{ 0x9e, 0xa4, 0x0, 0x60, 0x8, 0x9f, 0xe5, 0x9b } }
|
||||
{ 0xb13c4bd8, 0xcb9f, 0x4763, \
|
||||
{ 0xa0, 0x20, 0xe9, 0x9a, 0xbc, 0x9c, 0x28, 0x3 } }
|
||||
|
||||
class nsIPrivateTextRange : public nsISupports {
|
||||
public:
|
||||
@ -68,6 +70,8 @@ public:
|
||||
|
||||
NS_IMETHOD GetRangeType(PRUint16* aRangeType)=0;
|
||||
NS_IMETHOD SetRangeType(PRUint16 aRangeType)=0;
|
||||
|
||||
NS_IMETHOD GetRangeStyle(nsTextRangeStyle* aTextRangeStyle)=0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIPrivateTextRange, NS_IPRIVATETEXTRANGE_IID)
|
||||
|
@ -73,9 +73,7 @@ nsDOMTextEvent::nsDOMTextEvent(nsPresContext* aPresContext,
|
||||
|
||||
for(i = 0; i < te->rangeCount; i++) {
|
||||
nsRefPtr<nsPrivateTextRange> tempPrivateTextRange = new
|
||||
nsPrivateTextRange(te->rangeArray[i].mStartOffset,
|
||||
te->rangeArray[i].mEndOffset,
|
||||
te->rangeArray[i].mRangeType);
|
||||
nsPrivateTextRange(te->rangeArray[i]);
|
||||
|
||||
if (tempPrivateTextRange) {
|
||||
mTextRange->AppendTextRange(tempPrivateTextRange);
|
||||
|
@ -38,10 +38,11 @@
|
||||
#include "nsPrivateTextRange.h"
|
||||
|
||||
|
||||
nsPrivateTextRange::nsPrivateTextRange(PRUint16 aRangeStart, PRUint16 aRangeEnd, PRUint16 aRangeType)
|
||||
: mRangeStart(aRangeStart),
|
||||
mRangeEnd(aRangeEnd),
|
||||
mRangeType(aRangeType)
|
||||
nsPrivateTextRange::nsPrivateTextRange(const nsTextRange &aTextRange)
|
||||
: mRangeStart(PRUint16(aTextRange.mStartOffset)),
|
||||
mRangeEnd(PRUint16(aTextRange.mEndOffset)),
|
||||
mRangeType(PRUint16(aTextRange.mRangeType)),
|
||||
mRangeStyle(aTextRange.mRangeStyle)
|
||||
{
|
||||
}
|
||||
|
||||
@ -87,6 +88,13 @@ NS_METHOD nsPrivateTextRange::SetRangeType(PRUint16 aRangeType)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_METHOD nsPrivateTextRange::GetRangeStyle(nsTextRangeStyle* aTextRangeStyle)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aTextRangeStyle);
|
||||
*aTextRangeStyle = mRangeStyle;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsPrivateTextRangeList, nsIPrivateTextRangeList)
|
||||
|
||||
void nsPrivateTextRangeList::AppendTextRange(nsRefPtr<nsPrivateTextRange>& aRange)
|
||||
|
@ -47,7 +47,7 @@ class nsPrivateTextRange : public nsIPrivateTextRange
|
||||
NS_DECL_ISUPPORTS
|
||||
public:
|
||||
|
||||
nsPrivateTextRange(PRUint16 aRangeStart, PRUint16 aRangeEnd, PRUint16 aRangeType);
|
||||
nsPrivateTextRange(const nsTextRange &aTextRange);
|
||||
virtual ~nsPrivateTextRange(void);
|
||||
|
||||
NS_IMETHOD GetRangeStart(PRUint16* aRangeStart);
|
||||
@ -59,11 +59,14 @@ public:
|
||||
NS_IMETHOD GetRangeType(PRUint16* aRangeType);
|
||||
NS_IMETHOD SetRangeType(PRUint16 aRangeType);
|
||||
|
||||
NS_IMETHOD GetRangeStyle(nsTextRangeStyle* aRangeStyle);
|
||||
|
||||
protected:
|
||||
|
||||
PRUint16 mRangeStart;
|
||||
PRUint16 mRangeEnd;
|
||||
PRUint16 mRangeType;
|
||||
nsTextRangeStyle mRangeStyle;
|
||||
};
|
||||
|
||||
class nsPrivateTextRangeList: public nsIPrivateTextRangeList
|
||||
|
@ -337,21 +337,38 @@ NS_IMETHODIMP IMETextTxn::CollapseTextSelection(void)
|
||||
if(NS_FAILED(result))
|
||||
break;
|
||||
|
||||
newRange->SetStart(mElement,mOffset+selectionStart);
|
||||
result = newRange->SetStart(mElement,mOffset+selectionStart);
|
||||
NS_ASSERTION(NS_SUCCEEDED(result), "Cannot SetStart");
|
||||
if(NS_FAILED(result))
|
||||
break;
|
||||
|
||||
newRange->SetEnd(mElement,mOffset+selectionEnd);
|
||||
result = newRange->SetEnd(mElement,mOffset+selectionEnd);
|
||||
NS_ASSERTION(NS_SUCCEEDED(result), "Cannot SetEnd");
|
||||
if(NS_FAILED(result))
|
||||
break;
|
||||
|
||||
imeSel->AddRange(newRange);
|
||||
result = imeSel->AddRange(newRange);
|
||||
NS_ASSERTION(NS_SUCCEEDED(result), "Cannot AddRange");
|
||||
if(NS_FAILED(result))
|
||||
break;
|
||||
|
||||
nsCOMPtr<nsISelectionPrivate> imeSelPriv(
|
||||
do_QueryInterface(imeSel));
|
||||
if (imeSelPriv) {
|
||||
nsTextRangeStyle textRangeStyle;
|
||||
result = textRange->GetRangeStyle(&textRangeStyle);
|
||||
NS_ASSERTION(NS_SUCCEEDED(result),
|
||||
"nsIPrivateTextRange::GetRangeStyle failed");
|
||||
if (NS_FAILED(result))
|
||||
break;
|
||||
result = imeSelPriv->SetTextRangeStyle(newRange, textRangeStyle);
|
||||
NS_ASSERTION(NS_SUCCEEDED(result),
|
||||
"nsISelectionPrivate::SetTextRangeStyle failed");
|
||||
if (NS_FAILED(result))
|
||||
break;
|
||||
} else {
|
||||
NS_WARNING("IME selection doesn't have nsISelectionPrivate");
|
||||
}
|
||||
} // if GetRangeEnd
|
||||
} // for textRangeListLength
|
||||
if(! setCaret) {
|
||||
|
@ -49,10 +49,10 @@
|
||||
#include "nsIRange.h"
|
||||
|
||||
// IID for the nsFrameSelection interface
|
||||
// d78edc5a-28d0-48f0-8abb-1597b1591556
|
||||
// 0ea74459-e3f9-48b0-8aa4-5dfef53bf1f7
|
||||
#define NS_FRAME_SELECTION_IID \
|
||||
{ 0xd78edc5a, 0x28d0, 0x48f0, \
|
||||
{ 0x8a, 0xbb, 0x15, 0x97, 0xb1, 0x59, 0x15, 0x56 } }
|
||||
{ 0xea74459, 0xe3f9, 0x48b0, \
|
||||
{ 0x8a, 0xa4, 0x5d, 0xfe, 0xf5, 0x3b, 0xf1, 0xf7 } }
|
||||
|
||||
#ifdef IBMBIDI // Constant for Set/Get CaretBidiLevel
|
||||
#define BIDI_LEVEL_UNDEFINED 0x80
|
||||
@ -75,6 +75,7 @@ struct SelectionDetails
|
||||
PRInt32 mStart;
|
||||
PRInt32 mEnd;
|
||||
SelectionType mType;
|
||||
nsTextRangeStyle mTextRangeStyle;
|
||||
SelectionDetails *mNext;
|
||||
};
|
||||
|
||||
|
@ -164,6 +164,7 @@ struct RangeData
|
||||
|
||||
nsCOMPtr<nsIRange> mRange;
|
||||
PRInt32 mEndIndex; // index into mRangeEndings of this item
|
||||
nsTextRangeStyle mTextRangeStyle;
|
||||
};
|
||||
|
||||
static RangeData sEmptyData(nsnull, 0);
|
||||
@ -357,6 +358,7 @@ private:
|
||||
nsINode* aEndNode, PRInt32 aEndOffset,
|
||||
PRBool aAllowAdjacent,
|
||||
nsCOMArray<nsIRange>* aRanges);
|
||||
RangeData* FindRangeData(nsIDOMRange* aRange);
|
||||
|
||||
nsTArray<RangeData> mRanges;
|
||||
nsTArray<PRInt32> mRangeEndings; // references info mRanges
|
||||
@ -4542,6 +4544,10 @@ nsTypedSelection::LookUpSelection(nsIContent *aContent, PRInt32 aContentOffset,
|
||||
details->mStart = start;
|
||||
details->mEnd = end;
|
||||
details->mType = aType;
|
||||
RangeData *rd = FindRangeData(range);
|
||||
if (rd) {
|
||||
details->mTextRangeStyle = rd->mTextRangeStyle;
|
||||
}
|
||||
*aReturnDetails = details;
|
||||
}
|
||||
return NS_OK;
|
||||
@ -4647,6 +4653,29 @@ nsTypedSelection::SetAncestorLimiter(nsIContent *aContent)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RangeData*
|
||||
nsTypedSelection::FindRangeData(nsIDOMRange* aRange)
|
||||
{
|
||||
NS_ENSURE_TRUE(aRange, nsnull);
|
||||
for (PRUint32 i = 0; i < mRanges.Length(); i++) {
|
||||
if (mRanges[i].mRange == aRange)
|
||||
return &mRanges[i];
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTypedSelection::SetTextRangeStyle(nsIDOMRange *aRange,
|
||||
const nsTextRangeStyle &aTextRangeStyle)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRange);
|
||||
RangeData *rd = FindRangeData(aRange);
|
||||
if (rd) {
|
||||
rd->mTextRangeStyle = aTextRangeStyle;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTypedSelection::StartAutoScrollTimer(nsPresContext *aPresContext,
|
||||
nsIView *aView,
|
||||
|
@ -4090,23 +4090,58 @@ static const SelectionType SelectionTypesWithDecorations =
|
||||
nsISelectionController::SELECTION_IME_CONVERTEDTEXT |
|
||||
nsISelectionController::SELECTION_IME_SELECTEDCONVERTEDTEXT;
|
||||
|
||||
static PRUint8
|
||||
GetTextDecorationStyle(const nsTextRangeStyle &aRangeStyle)
|
||||
{
|
||||
NS_PRECONDITION(aRangeStyle.IsLineStyleDefined(),
|
||||
"aRangeStyle.mLineStyle have to be defined");
|
||||
switch (aRangeStyle.mLineStyle) {
|
||||
case nsTextRangeStyle::LINESTYLE_NONE:
|
||||
return nsCSSRendering::DECORATION_STYLE_NONE;
|
||||
case nsTextRangeStyle::LINESTYLE_SOLID:
|
||||
return nsCSSRendering::DECORATION_STYLE_SOLID;
|
||||
case nsTextRangeStyle::LINESTYLE_DOTTED:
|
||||
return nsCSSRendering::DECORATION_STYLE_DOTTED;
|
||||
case nsTextRangeStyle::LINESTYLE_DASHED:
|
||||
return nsCSSRendering::DECORATION_STYLE_DASHED;
|
||||
case nsTextRangeStyle::LINESTYLE_DOUBLE:
|
||||
return nsCSSRendering::DECORATION_STYLE_DOUBLE;
|
||||
case nsTextRangeStyle::LINESTYLE_WAVY:
|
||||
return nsCSSRendering::DECORATION_STYLE_WAVY;
|
||||
default:
|
||||
NS_WARNING("Requested underline style is not valid");
|
||||
return nsCSSRendering::DECORATION_STYLE_SOLID;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This, plus SelectionTypesWithDecorations, encapsulates all knowledge about
|
||||
* drawing text decoration for selections.
|
||||
*/
|
||||
static void DrawSelectionDecorations(gfxContext* aContext, SelectionType aType,
|
||||
nsTextPaintStyle& aTextPaintStyle, const gfxPoint& aPt, gfxFloat aWidth,
|
||||
nsTextPaintStyle& aTextPaintStyle,
|
||||
const nsTextRangeStyle &aRangeStyle,
|
||||
const gfxPoint& aPt, gfxFloat aWidth,
|
||||
gfxFloat aAscent, const gfxFont::Metrics& aFontMetrics)
|
||||
{
|
||||
gfxPoint pt(aPt);
|
||||
gfxSize size(aWidth, aFontMetrics.underlineSize);
|
||||
gfxFloat descentLimit = aFontMetrics.maxDescent;
|
||||
|
||||
float relativeSize;
|
||||
PRUint8 style;
|
||||
nscolor color;
|
||||
PRInt32 index =
|
||||
nsTextPaintStyle::GetUnderlineStyleIndexForSelectionType(aType);
|
||||
PRBool weDefineSelectionUnderline =
|
||||
aTextPaintStyle.GetSelectionUnderlineForPaint(index, &color,
|
||||
&relativeSize, &style);
|
||||
|
||||
switch (aType) {
|
||||
case nsISelectionController::SELECTION_IME_RAWINPUT:
|
||||
case nsISelectionController::SELECTION_IME_SELECTEDRAWTEXT:
|
||||
case nsISelectionController::SELECTION_IME_CONVERTEDTEXT:
|
||||
case nsISelectionController::SELECTION_IME_SELECTEDCONVERTEDTEXT:
|
||||
case nsISelectionController::SELECTION_IME_SELECTEDCONVERTEDTEXT: {
|
||||
// IME decoration lines should not be drawn on the both ends, i.e., we
|
||||
// need to cut both edges of the decoration lines. Because same style
|
||||
// IME selections can adjoin, but the users need to be able to know
|
||||
@ -4122,26 +4157,46 @@ static void DrawSelectionDecorations(gfxContext* aContext, SelectionType aType,
|
||||
// gap gap gap
|
||||
pt.x += 1.0;
|
||||
size.width -= 2.0;
|
||||
case nsISelectionController::SELECTION_SPELLCHECK: {
|
||||
float relativeSize;
|
||||
PRUint8 style;
|
||||
nscolor color;
|
||||
PRInt32 index =
|
||||
nsTextPaintStyle::GetUnderlineStyleIndexForSelectionType(aType);
|
||||
if (aTextPaintStyle.GetSelectionUnderlineForPaint(index, &color,
|
||||
&relativeSize,
|
||||
&style)) {
|
||||
size.height *= relativeSize;
|
||||
nsCSSRendering::PaintDecorationLine(
|
||||
aContext, color, pt, size, aAscent, aFontMetrics.underlineOffset,
|
||||
NS_STYLE_TEXT_DECORATION_UNDERLINE, style, descentLimit);
|
||||
if (aRangeStyle.IsDefined()) {
|
||||
// If IME defines the style, that should override our definition.
|
||||
if (aRangeStyle.IsLineStyleDefined()) {
|
||||
if (aRangeStyle.mLineStyle == nsTextRangeStyle::LINESTYLE_NONE) {
|
||||
return;
|
||||
}
|
||||
style = GetTextDecorationStyle(aRangeStyle);
|
||||
relativeSize = aRangeStyle.mIsBoldLine ? 2.0f : 1.0f;
|
||||
} else if (!weDefineSelectionUnderline) {
|
||||
// There is no underline style definition.
|
||||
return;
|
||||
}
|
||||
if (aRangeStyle.IsUnderlineColorDefined()) {
|
||||
color = aRangeStyle.mUnderlineColor;
|
||||
} else if (aRangeStyle.IsForegroundColorDefined()) {
|
||||
color = aRangeStyle.mForegroundColor;
|
||||
} else {
|
||||
NS_ASSERTION(!aRangeStyle.IsBackgroundColorDefined(),
|
||||
"Only the background color is defined");
|
||||
color = aTextPaintStyle.GetTextColor();
|
||||
}
|
||||
} else if (!weDefineSelectionUnderline) {
|
||||
// IME doesn't specify the selection style and we don't define selection
|
||||
// underline.
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case nsISelectionController::SELECTION_SPELLCHECK:
|
||||
if (!weDefineSelectionUnderline)
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
NS_WARNING("Requested selection decorations when there aren't any");
|
||||
break;
|
||||
return;
|
||||
}
|
||||
size.height *= relativeSize;
|
||||
nsCSSRendering::PaintDecorationLine(
|
||||
aContext, color, pt, size, aAscent, aFontMetrics.underlineOffset,
|
||||
NS_STYLE_TEXT_DECORATION_UNDERLINE, style, descentLimit);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4152,7 +4207,9 @@ static void DrawSelectionDecorations(gfxContext* aContext, SelectionType aType,
|
||||
* @param aBackground the background color to use, or RGBA(0,0,0,0) if no
|
||||
* background should be painted
|
||||
*/
|
||||
static PRBool GetSelectionTextColors(SelectionType aType, nsTextPaintStyle& aTextPaintStyle,
|
||||
static PRBool GetSelectionTextColors(SelectionType aType,
|
||||
nsTextPaintStyle& aTextPaintStyle,
|
||||
const nsTextRangeStyle &aRangeStyle,
|
||||
nscolor* aForeground, nscolor* aBackground)
|
||||
{
|
||||
switch (aType) {
|
||||
@ -4165,11 +4222,25 @@ static PRBool GetSelectionTextColors(SelectionType aType, nsTextPaintStyle& aTex
|
||||
case nsISelectionController::SELECTION_IME_SELECTEDRAWTEXT:
|
||||
case nsISelectionController::SELECTION_IME_CONVERTEDTEXT:
|
||||
case nsISelectionController::SELECTION_IME_SELECTEDCONVERTEDTEXT:
|
||||
if (aRangeStyle.IsDefined()) {
|
||||
*aForeground = aTextPaintStyle.GetTextColor();
|
||||
*aBackground = NS_RGBA(0,0,0,0);
|
||||
if (!aRangeStyle.IsForegroundColorDefined() &&
|
||||
!aRangeStyle.IsBackgroundColorDefined()) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (aRangeStyle.IsForegroundColorDefined()) {
|
||||
*aForeground = aRangeStyle.mForegroundColor;
|
||||
}
|
||||
if (aRangeStyle.IsBackgroundColorDefined()) {
|
||||
*aBackground = aRangeStyle.mBackgroundColor;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
aTextPaintStyle.GetIMESelectionColors(
|
||||
nsTextPaintStyle::GetUnderlineStyleIndexForSelectionType(aType),
|
||||
aForeground, aBackground);
|
||||
return PR_TRUE;
|
||||
|
||||
default:
|
||||
*aForeground = aTextPaintStyle.GetTextColor();
|
||||
*aBackground = NS_RGBA(0,0,0,0);
|
||||
@ -4187,13 +4258,13 @@ static PRBool GetSelectionTextColors(SelectionType aType, nsTextPaintStyle& aTex
|
||||
class SelectionIterator {
|
||||
public:
|
||||
/**
|
||||
* aStart and aLength are in the original string. aSelectionBuffer is
|
||||
* aStart and aLength are in the original string. aSelectionDetails is
|
||||
* according to the original string.
|
||||
*/
|
||||
SelectionIterator(SelectionType* aSelectionBuffer, PRInt32 aStart,
|
||||
PRInt32 aLength, PropertyProvider& aProvider,
|
||||
gfxTextRun* aTextRun);
|
||||
|
||||
SelectionIterator(SelectionDetails** aSelectionDetails,
|
||||
PRInt32 aStart, PRInt32 aLength,
|
||||
PropertyProvider& aProvider, gfxTextRun* aTextRun);
|
||||
|
||||
/**
|
||||
* Returns the next segment of uniformly selected (or not) text.
|
||||
* @param aXOffset the offset from the origin of the frame to the start
|
||||
@ -4204,16 +4275,18 @@ public:
|
||||
* @param aHyphenWidth if a hyphen is to be rendered after the text, the
|
||||
* width of the hyphen, otherwise zero
|
||||
* @param aType the selection type for this segment
|
||||
* @param aStyle the selection style for this segment
|
||||
* @return false if there are no more segments
|
||||
*/
|
||||
PRBool GetNextSegment(gfxFloat* aXOffset, PRUint32* aOffset, PRUint32* aLength,
|
||||
gfxFloat* aHyphenWidth, SelectionType* aType);
|
||||
gfxFloat* aHyphenWidth, SelectionType* aType,
|
||||
nsTextRangeStyle* aStyle);
|
||||
void UpdateWithAdvance(gfxFloat aAdvance) {
|
||||
mXOffset += aAdvance*mTextRun->GetDirection();
|
||||
}
|
||||
|
||||
private:
|
||||
SelectionType* mSelectionBuffer;
|
||||
SelectionDetails** mSelectionDetails;
|
||||
PropertyProvider& mProvider;
|
||||
gfxTextRun* mTextRun;
|
||||
gfxSkipCharsIterator mIterator;
|
||||
@ -4222,10 +4295,10 @@ private:
|
||||
gfxFloat mXOffset;
|
||||
};
|
||||
|
||||
SelectionIterator::SelectionIterator(SelectionType* aSelectionBuffer,
|
||||
SelectionIterator::SelectionIterator(SelectionDetails** aSelectionDetails,
|
||||
PRInt32 aStart, PRInt32 aLength, PropertyProvider& aProvider,
|
||||
gfxTextRun* aTextRun)
|
||||
: mSelectionBuffer(aSelectionBuffer), mProvider(aProvider),
|
||||
: mSelectionDetails(aSelectionDetails), mProvider(aProvider),
|
||||
mTextRun(aTextRun), mIterator(aProvider.GetStart()),
|
||||
mOriginalStart(aStart), mOriginalEnd(aStart + aLength),
|
||||
mXOffset(mTextRun->IsRightToLeft() ? aProvider.GetFrame()->GetSize().width : 0)
|
||||
@ -4234,7 +4307,8 @@ SelectionIterator::SelectionIterator(SelectionType* aSelectionBuffer,
|
||||
}
|
||||
|
||||
PRBool SelectionIterator::GetNextSegment(gfxFloat* aXOffset,
|
||||
PRUint32* aOffset, PRUint32* aLength, gfxFloat* aHyphenWidth, SelectionType* aType)
|
||||
PRUint32* aOffset, PRUint32* aLength, gfxFloat* aHyphenWidth,
|
||||
SelectionType* aType, nsTextRangeStyle* aStyle)
|
||||
{
|
||||
if (mIterator.GetOriginalOffset() >= mOriginalEnd)
|
||||
return PR_FALSE;
|
||||
@ -4243,13 +4317,19 @@ PRBool SelectionIterator::GetNextSegment(gfxFloat* aXOffset,
|
||||
PRUint32 runOffset = mIterator.GetSkippedOffset();
|
||||
|
||||
PRInt32 index = mIterator.GetOriginalOffset() - mOriginalStart;
|
||||
SelectionType type = mSelectionBuffer[index];
|
||||
SelectionDetails* sdptr = mSelectionDetails[index];
|
||||
SelectionType type =
|
||||
sdptr ? sdptr->mType : nsISelectionController::SELECTION_NONE;
|
||||
nsTextRangeStyle style;
|
||||
if (sdptr) {
|
||||
style = sdptr->mTextRangeStyle;
|
||||
}
|
||||
for (++index; mOriginalStart + index < mOriginalEnd; ++index) {
|
||||
if (mSelectionBuffer[index] != type)
|
||||
if (sdptr != mSelectionDetails[index])
|
||||
break;
|
||||
}
|
||||
mIterator.SetOriginalOffset(index + mOriginalStart);
|
||||
|
||||
|
||||
// Advance to the next cluster boundary
|
||||
while (mIterator.GetOriginalOffset() < mOriginalEnd &&
|
||||
!mIterator.IsOriginalCharSkipped() &&
|
||||
@ -4267,6 +4347,7 @@ PRBool SelectionIterator::GetNextSegment(gfxFloat* aXOffset,
|
||||
*aHyphenWidth = mProvider.GetHyphenWidth();
|
||||
}
|
||||
*aType = type;
|
||||
*aStyle = style;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
@ -4362,14 +4443,15 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
|
||||
PRInt32 contentLength = aProvider.GetOriginalLength();
|
||||
|
||||
// Figure out which selections control the colors to use for each character.
|
||||
nsAutoTArray<SelectionType,BIG_TEXT_NODE_SIZE> prevailingSelectionsBuffer;
|
||||
nsAutoTArray<SelectionDetails*,BIG_TEXT_NODE_SIZE> prevailingSelectionsBuffer;
|
||||
if (!prevailingSelectionsBuffer.AppendElements(contentLength))
|
||||
return;
|
||||
SelectionType* prevailingSelections = prevailingSelectionsBuffer.Elements();
|
||||
SelectionDetails** prevailingSelections = prevailingSelectionsBuffer.Elements();
|
||||
|
||||
PRInt32 i;
|
||||
SelectionType allTypes = 0;
|
||||
for (i = 0; i < contentLength; ++i) {
|
||||
prevailingSelections[i] = nsISelectionController::SELECTION_NONE;
|
||||
prevailingSelections[i] = nsnull;
|
||||
}
|
||||
|
||||
SelectionDetails *sdptr = aDetails;
|
||||
@ -4382,16 +4464,16 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
|
||||
allTypes |= type;
|
||||
// Ignore selections that don't set colors
|
||||
nscolor foreground, background;
|
||||
if (GetSelectionTextColors(type, aTextPaintStyle, &foreground, &background)) {
|
||||
if (GetSelectionTextColors(type, aTextPaintStyle, sdptr->mTextRangeStyle,
|
||||
&foreground, &background)) {
|
||||
if (NS_GET_A(background) > 0) {
|
||||
anyBackgrounds = PR_TRUE;
|
||||
}
|
||||
for (i = start; i < end; ++i) {
|
||||
PRInt16 currentPrevailingSelection = prevailingSelections[i];
|
||||
// Favour normal selection over IME selections
|
||||
if (currentPrevailingSelection == nsISelectionController::SELECTION_NONE ||
|
||||
type < currentPrevailingSelection) {
|
||||
prevailingSelections[i] = type;
|
||||
if (!prevailingSelections[i] ||
|
||||
type < prevailingSelections[i]->mType) {
|
||||
prevailingSelections[i] = sdptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4403,13 +4485,16 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
|
||||
gfxFloat xOffset, hyphenWidth;
|
||||
PRUint32 offset, length; // in transformed string
|
||||
SelectionType type;
|
||||
nsTextRangeStyle rangeStyle;
|
||||
// Draw background colors
|
||||
if (anyBackgrounds) {
|
||||
SelectionIterator iterator(prevailingSelections, contentOffset, contentLength,
|
||||
aProvider, mTextRun);
|
||||
while (iterator.GetNextSegment(&xOffset, &offset, &length, &hyphenWidth, &type)) {
|
||||
while (iterator.GetNextSegment(&xOffset, &offset, &length, &hyphenWidth,
|
||||
&type, &rangeStyle)) {
|
||||
nscolor foreground, background;
|
||||
GetSelectionTextColors(type, aTextPaintStyle, &foreground, &background);
|
||||
GetSelectionTextColors(type, aTextPaintStyle, rangeStyle,
|
||||
&foreground, &background);
|
||||
// Draw background color
|
||||
gfxFloat advance = hyphenWidth +
|
||||
mTextRun->GetAdvanceWidth(offset, length, &aProvider);
|
||||
@ -4426,9 +4511,11 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
|
||||
// Draw text
|
||||
SelectionIterator iterator(prevailingSelections, contentOffset, contentLength,
|
||||
aProvider, mTextRun);
|
||||
while (iterator.GetNextSegment(&xOffset, &offset, &length, &hyphenWidth, &type)) {
|
||||
while (iterator.GetNextSegment(&xOffset, &offset, &length, &hyphenWidth,
|
||||
&type, &rangeStyle)) {
|
||||
nscolor foreground, background;
|
||||
GetSelectionTextColors(type, aTextPaintStyle, &foreground, &background);
|
||||
GetSelectionTextColors(type, aTextPaintStyle, rangeStyle,
|
||||
&foreground, &background);
|
||||
// Draw text segment
|
||||
aCtx->SetColor(gfxRGBA(foreground));
|
||||
gfxFloat advance;
|
||||
@ -4453,15 +4540,14 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx,
|
||||
PRInt32 contentOffset = aProvider.GetStart().GetOriginalOffset();
|
||||
PRInt32 contentLength = aProvider.GetOriginalLength();
|
||||
|
||||
// Figure out which characters will be decorated for this selection. Here
|
||||
// we just fill the buffer with either SELECTION_NONE or aSelectionType.
|
||||
nsAutoTArray<SelectionType,BIG_TEXT_NODE_SIZE> selectedCharsBuffer;
|
||||
// Figure out which characters will be decorated for this selection.
|
||||
nsAutoTArray<SelectionDetails*, BIG_TEXT_NODE_SIZE> selectedCharsBuffer;
|
||||
if (!selectedCharsBuffer.AppendElements(contentLength))
|
||||
return;
|
||||
SelectionType* selectedChars = selectedCharsBuffer.Elements();
|
||||
SelectionDetails** selectedChars = selectedCharsBuffer.Elements();
|
||||
PRInt32 i;
|
||||
for (i = 0; i < contentLength; ++i) {
|
||||
selectedChars[i] = nsISelectionController::SELECTION_NONE;
|
||||
selectedChars[i] = nsnull;
|
||||
}
|
||||
|
||||
SelectionDetails *sdptr = aDetails;
|
||||
@ -4470,7 +4556,7 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx,
|
||||
PRInt32 start = PR_MAX(0, sdptr->mStart - contentOffset);
|
||||
PRInt32 end = PR_MIN(contentLength, sdptr->mEnd - contentOffset);
|
||||
for (i = start; i < end; ++i) {
|
||||
selectedChars[i] = aSelectionType;
|
||||
selectedChars[i] = sdptr;
|
||||
}
|
||||
}
|
||||
sdptr = sdptr->mNext;
|
||||
@ -4491,7 +4577,9 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx,
|
||||
// XXX aTextBaselinePt is in AppUnits, shouldn't it be nsFloatPoint?
|
||||
gfxPoint pt(0.0, (aTextBaselinePt.y - mAscent) / app);
|
||||
SelectionType type;
|
||||
while (iterator.GetNextSegment(&xOffset, &offset, &length, &hyphenWidth, &type)) {
|
||||
nsTextRangeStyle selectedStyle;
|
||||
while (iterator.GetNextSegment(&xOffset, &offset, &length, &hyphenWidth,
|
||||
&type, &selectedStyle)) {
|
||||
gfxFloat advance = hyphenWidth +
|
||||
mTextRun->GetAdvanceWidth(offset, length, &aProvider);
|
||||
if (type == aSelectionType) {
|
||||
@ -4499,6 +4587,7 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx,
|
||||
(mTextRun->IsRightToLeft() ? advance : 0)) / app;
|
||||
gfxFloat width = PR_ABS(advance) / app;
|
||||
DrawSelectionDecorations(aCtx, aSelectionType, aTextPaintStyle,
|
||||
selectedStyle,
|
||||
pt, width, mAscent / app, decorationMetrics);
|
||||
}
|
||||
iterator.UpdateWithAdvance(advance);
|
||||
@ -4799,9 +4888,26 @@ nsTextFrame::CombineSelectionUnderlineRect(nsPresContext* aPresContext,
|
||||
float relativeSize;
|
||||
PRInt32 index =
|
||||
nsTextPaintStyle::GetUnderlineStyleIndexForSelectionType(sd->mType);
|
||||
if (!nsTextPaintStyle::GetSelectionUnderline(aPresContext, index, nsnull,
|
||||
&relativeSize, &style)) {
|
||||
continue;
|
||||
if (sd->mType == nsISelectionController::SELECTION_SPELLCHECK) {
|
||||
if (!nsTextPaintStyle::GetSelectionUnderline(aPresContext, index, nsnull,
|
||||
&relativeSize, &style)) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// IME selections
|
||||
nsTextRangeStyle& rangeStyle = sd->mTextRangeStyle;
|
||||
if (rangeStyle.IsDefined()) {
|
||||
if (!rangeStyle.IsLineStyleDefined() ||
|
||||
rangeStyle.mLineStyle == nsTextRangeStyle::LINESTYLE_NONE) {
|
||||
continue;
|
||||
}
|
||||
style = GetTextDecorationStyle(rangeStyle);
|
||||
relativeSize = rangeStyle.mIsBoldLine ? 2.0f : 1.0f;
|
||||
} else if (!nsTextPaintStyle::GetSelectionUnderline(aPresContext, index,
|
||||
nsnull, &relativeSize,
|
||||
&style)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
nsRect decorationArea;
|
||||
gfxSize size(aPresContext->AppUnitsToGfxUnits(aRect.width),
|
||||
|
@ -843,6 +843,96 @@ public:
|
||||
/**
|
||||
* IME Related Events
|
||||
*/
|
||||
|
||||
struct nsTextRangeStyle
|
||||
{
|
||||
enum {
|
||||
LINESTYLE_NONE = 0,
|
||||
LINESTYLE_SOLID = 1,
|
||||
LINESTYLE_DOTTED = 2,
|
||||
LINESTYLE_DASHED = 3,
|
||||
LINESTYLE_DOUBLE = 4,
|
||||
LINESTYLE_WAVY = 5
|
||||
};
|
||||
|
||||
enum {
|
||||
DEFINED_NONE = 0x00,
|
||||
DEFINED_LINESTYLE = 0x01,
|
||||
DEFINED_FOREGROUND_COLOR = 0x02,
|
||||
DEFINED_BACKGROUND_COLOR = 0x04,
|
||||
DEFINED_UNDERLINE_COLOR = 0x08
|
||||
};
|
||||
|
||||
// Initialize all members, because nsTextRange instances may be compared by
|
||||
// memcomp.
|
||||
nsTextRangeStyle() :
|
||||
mDefinedStyles(DEFINED_NONE), mLineStyle(LINESTYLE_NONE),
|
||||
mIsBoldLine(PR_FALSE), mForegroundColor(NS_RGBA(0, 0, 0, 0)),
|
||||
mBackgroundColor(NS_RGBA(0, 0, 0, 0)), mUnderlineColor(NS_RGBA(0, 0, 0, 0))
|
||||
{
|
||||
}
|
||||
|
||||
PRBool IsDefined() const { return mDefinedStyles != DEFINED_NONE; }
|
||||
|
||||
PRBool IsLineStyleDefined() const
|
||||
{
|
||||
return (mDefinedStyles & DEFINED_LINESTYLE) != 0;
|
||||
}
|
||||
|
||||
PRBool IsForegroundColorDefined() const
|
||||
{
|
||||
return (mDefinedStyles & DEFINED_FOREGROUND_COLOR) != 0;
|
||||
}
|
||||
|
||||
PRBool IsBackgroundColorDefined() const
|
||||
{
|
||||
return (mDefinedStyles & DEFINED_BACKGROUND_COLOR) != 0;
|
||||
}
|
||||
|
||||
PRBool IsUnderlineColorDefined() const
|
||||
{
|
||||
return (mDefinedStyles & DEFINED_UNDERLINE_COLOR) != 0;
|
||||
}
|
||||
|
||||
PRBool Equals(const nsTextRangeStyle& aOther)
|
||||
{
|
||||
if (mDefinedStyles != aOther.mDefinedStyles)
|
||||
return PR_FALSE;
|
||||
if (IsLineStyleDefined() && (mLineStyle != aOther.mLineStyle ||
|
||||
!mIsBoldLine != !aOther.mIsBoldLine))
|
||||
return PR_FALSE;
|
||||
if (IsForegroundColorDefined() &&
|
||||
(mForegroundColor != aOther.mForegroundColor))
|
||||
return PR_FALSE;
|
||||
if (IsBackgroundColorDefined() &&
|
||||
(mBackgroundColor != aOther.mBackgroundColor))
|
||||
return PR_FALSE;
|
||||
if (IsUnderlineColorDefined() &&
|
||||
(mUnderlineColor != aOther.mUnderlineColor))
|
||||
return PR_FALSE;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool operator !=(const nsTextRangeStyle &aOther)
|
||||
{
|
||||
return !Equals(aOther);
|
||||
}
|
||||
|
||||
PRBool operator ==(const nsTextRangeStyle &aOther)
|
||||
{
|
||||
return Equals(aOther);
|
||||
}
|
||||
|
||||
PRUint8 mDefinedStyles;
|
||||
PRUint8 mLineStyle; // DEFINED_LINESTYLE
|
||||
|
||||
PRPackedBool mIsBoldLine; // DEFINED_LINESTYLE
|
||||
|
||||
nscolor mForegroundColor; // DEFINED_FOREGROUND_COLOR
|
||||
nscolor mBackgroundColor; // DEFINED_BACKGROUND_COLOR
|
||||
nscolor mUnderlineColor; // DEFINED_UNDERLINE_COLOR
|
||||
};
|
||||
|
||||
struct nsTextRange
|
||||
{
|
||||
nsTextRange()
|
||||
@ -853,6 +943,8 @@ struct nsTextRange
|
||||
PRUint32 mStartOffset;
|
||||
PRUint32 mEndOffset;
|
||||
PRUint32 mRangeType;
|
||||
|
||||
nsTextRangeStyle mRangeStyle;
|
||||
};
|
||||
|
||||
typedef nsTextRange* nsTextRangeArray;
|
||||
|
@ -621,6 +621,50 @@ nsTextStore::UpdateCompositionExtent(ITfRange* aRangeNew)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
GetColor(const TF_DA_COLOR &aTSFColor, nscolor &aResult)
|
||||
{
|
||||
switch (aTSFColor.type) {
|
||||
case TF_CT_SYSCOLOR: {
|
||||
DWORD sysColor = ::GetSysColor(aTSFColor.nIndex);
|
||||
aResult = NS_RGB(GetRValue(sysColor), GetGValue(sysColor),
|
||||
GetBValue(sysColor));
|
||||
return PR_TRUE;
|
||||
}
|
||||
case TF_CT_COLORREF:
|
||||
aResult = NS_RGB(GetRValue(aTSFColor.cr), GetGValue(aTSFColor.cr),
|
||||
GetBValue(aTSFColor.cr));
|
||||
return PR_TRUE;
|
||||
case TF_CT_NONE:
|
||||
default:
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static PRBool
|
||||
GetLineStyle(TF_DA_LINESTYLE aTSFLineStyle, PRUint8 &aTextRangeLineStyle)
|
||||
{
|
||||
switch (aTSFLineStyle) {
|
||||
case TF_LS_NONE:
|
||||
aTextRangeLineStyle = nsTextRangeStyle::LINESTYLE_NONE;
|
||||
return PR_TRUE;
|
||||
case TF_LS_SOLID:
|
||||
aTextRangeLineStyle = nsTextRangeStyle::LINESTYLE_SOLID;
|
||||
return PR_TRUE;
|
||||
case TF_LS_DOT:
|
||||
aTextRangeLineStyle = nsTextRangeStyle::LINESTYLE_DOTTED;
|
||||
return PR_TRUE;
|
||||
case TF_LS_DASH:
|
||||
aTextRangeLineStyle = nsTextRangeStyle::LINESTYLE_DASHED;
|
||||
return PR_TRUE;
|
||||
case TF_LS_SQUIGGLE:
|
||||
aTextRangeLineStyle = nsTextRangeStyle::LINESTYLE_WAVY;
|
||||
return PR_TRUE;
|
||||
default:
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT
|
||||
nsTextStore::SendTextEventForCompositionString()
|
||||
{
|
||||
@ -677,6 +721,7 @@ nsTextStore::SendTextEventForCompositionString()
|
||||
if (FAILED(GetRangeExtent(range, &start, &length)))
|
||||
continue;
|
||||
|
||||
nsTextRange newRange;
|
||||
newRange.mStartOffset = PRUint32(start - mCompositionStart);
|
||||
// The end of the last range in the array is
|
||||
// always kept at the end of composition
|
||||
@ -684,8 +729,28 @@ nsTextStore::SendTextEventForCompositionString()
|
||||
|
||||
TF_DISPLAYATTRIBUTE attr;
|
||||
hr = GetDisplayAttribute(attrPropetry, range, &attr);
|
||||
newRange.mRangeType =
|
||||
SUCCEEDED(hr) ? GetGeckoSelectionValue(attr) : NS_TEXTRANGE_RAWINPUT;
|
||||
if (FAILED(hr)) {
|
||||
newRange.mRangeType = NS_TEXTRANGE_RAWINPUT;
|
||||
} else {
|
||||
newRange.mRangeType = GetGeckoSelectionValue(attr);
|
||||
if (GetColor(attr.crText, newRange.mRangeStyle.mForegroundColor)) {
|
||||
newRange.mRangeStyle.mDefinedStyles |=
|
||||
nsTextRangeStyle::DEFINED_FOREGROUND_COLOR;
|
||||
}
|
||||
if (GetColor(attr.crBk, newRange.mRangeStyle.mBackgroundColor)) {
|
||||
newRange.mRangeStyle.mDefinedStyles |=
|
||||
nsTextRangeStyle::DEFINED_BACKGROUND_COLOR;
|
||||
}
|
||||
if (GetColor(attr.crLine, newRange.mRangeStyle.mUnderlineColor)) {
|
||||
newRange.mRangeStyle.mDefinedStyles |=
|
||||
nsTextRangeStyle::DEFINED_UNDERLINE_COLOR;
|
||||
}
|
||||
if (GetLineStyle(attr.lsStyle, newRange.mRangeStyle.mLineStyle)) {
|
||||
newRange.mRangeStyle.mDefinedStyles |=
|
||||
nsTextRangeStyle::DEFINED_LINESTYLE;
|
||||
newRange.mRangeStyle.mIsBoldLine = attr.fBoldLine != 0;
|
||||
}
|
||||
}
|
||||
|
||||
nsTextRange& lastRange = textRanges[textRanges.Length() - 1];
|
||||
if (lastRange.mStartOffset == newRange.mStartOffset) {
|
||||
|
Loading…
Reference in New Issue
Block a user