Bug #260663. When pango is available use it for grapheme cluster information to figure out where valid selection points are. Change text rendering to use clip regions for rendering selected strings instead of rendering partial strings instead. r+sr=roc,a=asa
This commit is contained in:
Родитель
ee359bfc45
Коммит
7a4c1d728f
|
@ -799,6 +799,84 @@ public:
|
|||
nscoord aXImageStart, nscoord aYImageStart,
|
||||
const nsRect * aTargetRect) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Get cluster details for a chunk of text.
|
||||
*
|
||||
* This will fill in the aClusterStarts array with information about
|
||||
* what characters are the start of clusters for display. The
|
||||
* information is just a bitfield that is set to 1 if the character
|
||||
* is the start of a cluster. aClusterStarts must already be
|
||||
* allocated to at least aLength items in length. Array index zero
|
||||
* being set to one indicates that the first character is the
|
||||
* beginning of a cluster.
|
||||
*
|
||||
* @param aText Text on which to get details.
|
||||
* @param aLength Length of the text.
|
||||
* @param aClusterStarts Array of ints that will be populated
|
||||
* with information about which characters are the starts
|
||||
* of clusters.
|
||||
*
|
||||
*/
|
||||
NS_IMETHOD GetClusterInfo(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint8 *aClusterStarts) = 0;
|
||||
|
||||
/**
|
||||
* Find the closest cursor position for a given x coordinate.
|
||||
*
|
||||
* This will find the closest byte index for a given x coordinate.
|
||||
* This takes into account grapheme clusters and bidi text.
|
||||
*
|
||||
* @param aText Text on which to operate.
|
||||
* @param aLength Length of the text.
|
||||
* @param aPt the x/y position in the string to check.
|
||||
*
|
||||
* @return Index where the cursor falls. If the return is zero,
|
||||
* it's before the first character, if it falls off the end of
|
||||
* the string it's the length of the string + 1.
|
||||
*
|
||||
*/
|
||||
virtual PRInt32 GetPosition(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
nsPoint aPt) = 0;
|
||||
|
||||
/**
|
||||
* Get the width for the specific range of a given string.
|
||||
*
|
||||
* This function is similar to other GetWidth functions, except that
|
||||
* it gets the width for a part of the string instead of the entire
|
||||
* string. This is useful when you're interested in finding out the
|
||||
* length of a chunk in the middle of the string. Lots of languages
|
||||
* require you to include surrounding information to accurately
|
||||
* determine the length of a substring.
|
||||
*
|
||||
* @param aText Text on which to operate
|
||||
* @param aLength Length of the text
|
||||
* @param aStart Start index into the string
|
||||
* @param aEnd End index into the string (inclusive)
|
||||
* @param aWidth Returned with in app coordinates
|
||||
*
|
||||
*/
|
||||
NS_IMETHOD GetRangeWidth(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
PRUint32 &aWidth) = 0;
|
||||
|
||||
/**
|
||||
* Get the width for the specific range of a given string.
|
||||
*
|
||||
* Same as GetRangeWidth for PRUnichar, but takes a char * as the
|
||||
* text argument.
|
||||
*
|
||||
*/
|
||||
NS_IMETHOD GetRangeWidth(const char *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
PRUint32 &aWidth) = 0;
|
||||
|
||||
/**
|
||||
* Render an encapsulated postscript object onto the current rendering
|
||||
* surface.
|
||||
|
@ -857,6 +935,12 @@ public:
|
|||
*/
|
||||
#define NS_RENDERING_HINT_FAST_MEASURE 0x10
|
||||
|
||||
/**
|
||||
* This bit, when set, indicates that the gfx supports describing
|
||||
* cluster information in a string
|
||||
*/
|
||||
#define NS_RENDERING_HINT_TEXT_CLUSTERS 0x20
|
||||
|
||||
/**
|
||||
* This bit, when set, indicates that gfx performs glyph reordering of complex
|
||||
* text after applying character or word spacing, and so expects to be passed
|
||||
|
|
|
@ -4726,6 +4726,43 @@ nsFontMetricsGTK::SetRightToLeftText(PRBool aIsRTL)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFontMetricsGTK::GetClusterInfo(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint8 *aClusterStarts)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsFontMetricsGTK::GetPosition(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
nsPoint aPt)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsFontMetricsGTK::GetRangeWidth(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
PRUint32 &aWidth)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFontMetricsGTK::GetRangeWidth(const char *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
PRUint32 &aWidth)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
static int
|
||||
CompareSizes(const void* aArg1, const void* aArg2, void *data)
|
||||
|
|
|
@ -348,6 +348,26 @@ public:
|
|||
|
||||
virtual nsresult SetRightToLeftText(PRBool aIsRTL);
|
||||
|
||||
virtual nsresult GetClusterInfo(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint8 *aClusterStarts);
|
||||
|
||||
virtual PRInt32 GetPosition(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
nsPoint aPt);
|
||||
|
||||
virtual nsresult GetRangeWidth(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
PRUint32 &aWidth);
|
||||
|
||||
virtual nsresult GetRangeWidth(const char *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
PRUint32 &aWidth);
|
||||
|
||||
static nsresult FamilyExists(nsIDeviceContext *aDevice, const nsString& aName);
|
||||
static PRUint32 GetHints(void);
|
||||
|
||||
|
|
|
@ -144,6 +144,7 @@ nsFontMetricsPango::nsFontMetricsPango()
|
|||
mRTLPangoContext = nsnull;
|
||||
mPangoAttrList = nsnull;
|
||||
mIsRTL = PR_FALSE;
|
||||
mPangoSpaceWidth = 0;
|
||||
|
||||
static PRBool initialized = PR_FALSE;
|
||||
if (initialized)
|
||||
|
@ -342,6 +343,14 @@ nsFontMetricsPango::CacheFontMetrics(void)
|
|||
// mMaxAdvance
|
||||
mMaxAdvance = nscoord(xftFont->max_advance_width * f);
|
||||
|
||||
// mPangoSpaceWidth
|
||||
PangoLayout *layout = pango_layout_new(mPangoContext);
|
||||
pango_layout_set_text(layout, " ", 1);
|
||||
int pswidth, psheight;
|
||||
pango_layout_get_size(layout, &pswidth, &psheight);
|
||||
mPangoSpaceWidth = pswidth;
|
||||
g_object_unref(layout);
|
||||
|
||||
// mSpaceWidth (width of a space)
|
||||
nscoord tmpWidth;
|
||||
GetWidth(" ", 1, tmpWidth, NULL);
|
||||
|
@ -475,17 +484,18 @@ nsFontMetricsPango::GetWidth(const char* aString, PRUint32 aLength,
|
|||
|
||||
pango_layout_set_text(layout, aString, aLength);
|
||||
|
||||
if (mPangoSpaceWidth)
|
||||
FixupSpaceWidths(layout, aString);
|
||||
|
||||
int width, height;
|
||||
|
||||
pango_layout_get_size(layout, &width, &height);
|
||||
|
||||
width /= PANGO_SCALE;
|
||||
|
||||
g_object_unref(layout);
|
||||
|
||||
float f;
|
||||
f = mDeviceContext->DevUnitsToAppUnits();
|
||||
aWidth = NSToCoordRound(width * f);
|
||||
aWidth = NSToCoordRound(width * f / PANGO_SCALE);
|
||||
|
||||
// printf("GetWidth (char *) %d\n", aWidth);
|
||||
|
||||
|
@ -516,13 +526,12 @@ nsFontMetricsPango::GetWidth(const PRUnichar* aString, PRUint32 aLength,
|
|||
gint width, height;
|
||||
|
||||
pango_layout_set_text(layout, text, strlen(text));
|
||||
FixupSpaceWidths(layout, text);
|
||||
pango_layout_get_size(layout, &width, &height);
|
||||
|
||||
width /= PANGO_SCALE;
|
||||
|
||||
float f;
|
||||
f = mDeviceContext->DevUnitsToAppUnits();
|
||||
aWidth = NSToCoordRound(width * f);
|
||||
aWidth = NSToCoordRound(width * f / PANGO_SCALE);
|
||||
|
||||
// printf("GetWidth %d\n", aWidth);
|
||||
|
||||
|
@ -563,6 +572,7 @@ nsFontMetricsPango::GetTextDimensions(const PRUnichar* aString,
|
|||
|
||||
|
||||
pango_layout_set_text(layout, text, strlen(text));
|
||||
FixupSpaceWidths(layout, text);
|
||||
|
||||
// Get the logical extents
|
||||
PangoLayoutLine *line;
|
||||
|
@ -577,9 +587,9 @@ nsFontMetricsPango::GetTextDimensions(const PRUnichar* aString,
|
|||
float P2T;
|
||||
P2T = mDeviceContext->DevUnitsToAppUnits();
|
||||
|
||||
aDimensions.width = NSToCoordRound(rect.width / PANGO_SCALE * P2T);
|
||||
aDimensions.ascent = NSToCoordRound(PANGO_ASCENT(rect) / PANGO_SCALE * P2T);
|
||||
aDimensions.descent = NSToCoordRound(PANGO_DESCENT(rect) / PANGO_SCALE * P2T);
|
||||
aDimensions.width = NSToCoordRound(rect.width * P2T / PANGO_SCALE);
|
||||
aDimensions.ascent = NSToCoordRound(PANGO_ASCENT(rect) * P2T / PANGO_SCALE);
|
||||
aDimensions.descent = NSToCoordRound(PANGO_DESCENT(rect) * P2T / PANGO_SCALE);
|
||||
|
||||
// printf("GetTextDimensions %d %d %d\n", aDimensions.width,
|
||||
//aDimensions.ascent, aDimensions.descent);
|
||||
|
@ -705,6 +715,7 @@ nsFontMetricsPango::DrawString(const char *aString, PRUint32 aLength,
|
|||
PangoLayout *layout = pango_layout_new(mPangoContext);
|
||||
|
||||
pango_layout_set_text(layout, aString, aLength);
|
||||
FixupSpaceWidths(layout, aString);
|
||||
|
||||
int x = aX;
|
||||
int y = aY;
|
||||
|
@ -768,6 +779,7 @@ nsFontMetricsPango::DrawString(const PRUnichar* aString, PRUint32 aLength,
|
|||
}
|
||||
|
||||
pango_layout_set_text(layout, text, strlen(text));
|
||||
FixupSpaceWidths(layout, text);
|
||||
|
||||
aContext->GetTranMatrix()->TransformCoord(&x, &y);
|
||||
|
||||
|
@ -837,6 +849,7 @@ nsFontMetricsPango::GetBoundingMetrics(const PRUnichar *aString,
|
|||
}
|
||||
|
||||
pango_layout_set_text(layout, text, strlen(text));
|
||||
FixupSpaceWidths(layout, text);
|
||||
|
||||
// Get the logical extents
|
||||
PangoLayoutLine *line;
|
||||
|
@ -853,12 +866,12 @@ nsFontMetricsPango::GetBoundingMetrics(const PRUnichar *aString,
|
|||
P2T = mDeviceContext->DevUnitsToAppUnits();
|
||||
|
||||
aBoundingMetrics.leftBearing =
|
||||
NSToCoordRound(rect.x / PANGO_SCALE * P2T);
|
||||
NSToCoordRound(rect.x * P2T / PANGO_SCALE);
|
||||
aBoundingMetrics.rightBearing =
|
||||
NSToCoordRound(rect.width / PANGO_SCALE * P2T);
|
||||
aBoundingMetrics.width = NSToCoordRound((rect.x + rect.width) / PANGO_SCALE * P2T);
|
||||
aBoundingMetrics.ascent = NSToCoordRound(rect.y / PANGO_SCALE * P2T);
|
||||
aBoundingMetrics.descent = NSToCoordRound(rect.height / PANGO_SCALE * P2T);
|
||||
NSToCoordRound(rect.width * P2T / PANGO_SCALE);
|
||||
aBoundingMetrics.width = NSToCoordRound((rect.x + rect.width) * P2T / PANGO_SCALE);
|
||||
aBoundingMetrics.ascent = NSToCoordRound(rect.y * P2T / PANGO_SCALE);
|
||||
aBoundingMetrics.descent = NSToCoordRound(rect.height * P2T / PANGO_SCALE);
|
||||
|
||||
loser:
|
||||
g_free(text);
|
||||
|
@ -897,6 +910,237 @@ nsFontMetricsPango::SetRightToLeftText(PRBool aIsRTL)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFontMetricsPango::GetClusterInfo(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint8 *aClusterStarts)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
PangoLogAttr *attrs = NULL;
|
||||
gint n_attrs = 0;
|
||||
PangoLayout *layout = pango_layout_new(mPangoContext);
|
||||
|
||||
// Convert the incoming UTF-16 to UTF-8
|
||||
gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
|
||||
|
||||
if (!text) {
|
||||
#ifdef DEBUG
|
||||
NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
|
||||
DUMP_PRUNICHAR(aText, aLength)
|
||||
#endif
|
||||
rv = NS_ERROR_FAILURE;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
// Set up the pango layout
|
||||
pango_layout_set_text(layout, text, strlen(text));
|
||||
FixupSpaceWidths(layout, text);
|
||||
|
||||
// Convert back to UTF-16 while filling in the cluster info
|
||||
// structure.
|
||||
pango_layout_get_log_attrs(layout, &attrs, &n_attrs);
|
||||
|
||||
for (PRUint32 pos = 0; pos < aLength; pos++) {
|
||||
if (IS_HIGH_SURROGATE(aText[pos])) {
|
||||
aClusterStarts[pos] = 1;
|
||||
pos++;
|
||||
}
|
||||
else {
|
||||
aClusterStarts[pos] = attrs[pos].is_cursor_position;
|
||||
}
|
||||
}
|
||||
|
||||
loser:
|
||||
if (attrs)
|
||||
g_free(attrs);
|
||||
if (text)
|
||||
g_free(text);
|
||||
if (layout)
|
||||
g_object_unref(layout);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsFontMetricsPango::GetPosition(const PRUnichar *aText, PRUint32 aLength,
|
||||
nsPoint aPt)
|
||||
{
|
||||
int trailing = 0;
|
||||
int inx = 0;
|
||||
gboolean found = FALSE;
|
||||
const gchar *curChar;
|
||||
PRInt32 retval = 0;
|
||||
|
||||
float f = mDeviceContext->AppUnitsToDevUnits();
|
||||
|
||||
PangoLayout *layout = pango_layout_new(mPangoContext);
|
||||
PRUint32 localX = (PRUint32)(aPt.x * PANGO_SCALE * f);
|
||||
PRUint32 localY = (PRUint32)(aPt.y * PANGO_SCALE * f);
|
||||
|
||||
// Convert the incoming UTF-16 to UTF-8
|
||||
gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
|
||||
|
||||
if (!text) {
|
||||
#ifdef DEBUG
|
||||
NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
|
||||
DUMP_PRUNICHAR(aText, aLength)
|
||||
#endif
|
||||
retval = -1;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
// Set up the pango layout
|
||||
pango_layout_set_text(layout, text, strlen(text));
|
||||
FixupSpaceWidths(layout, text);
|
||||
|
||||
found = pango_layout_xy_to_index(layout, localX, localY,
|
||||
&inx, &trailing);
|
||||
|
||||
// Convert the index back to the utf-16 index
|
||||
curChar = text;
|
||||
|
||||
// Jump to the end if it's not found.
|
||||
if (!found) {
|
||||
if (inx = 0)
|
||||
retval = 0;
|
||||
else if (trailing)
|
||||
retval = aLength;
|
||||
|
||||
goto loser;
|
||||
}
|
||||
|
||||
for (PRUint32 curOffset=0; curOffset < aLength;
|
||||
curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
|
||||
|
||||
// Check for a match before checking for a surrogate pair
|
||||
if (curChar - text == inx) {
|
||||
retval = curOffset;
|
||||
break;
|
||||
}
|
||||
|
||||
if (IS_HIGH_SURROGATE(aText[curOffset]))
|
||||
curOffset++;
|
||||
}
|
||||
|
||||
// If there was a trailing result, advance the index pointer the
|
||||
// number of characters equal to the trailing result.
|
||||
while (trailing) {
|
||||
retval++;
|
||||
// Yes, this can make aInx > length to indicate the end of the
|
||||
// string.
|
||||
if (retval < (PRInt32)aLength && IS_HIGH_SURROGATE(aText[retval]))
|
||||
retval++;
|
||||
trailing--;
|
||||
}
|
||||
|
||||
loser:
|
||||
if (text)
|
||||
g_free(text);
|
||||
if (layout)
|
||||
g_object_unref(layout);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFontMetricsPango::GetRangeWidth(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
PRUint32 &aWidth)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
PRUint32 utf8Start = 0;
|
||||
PRUint32 utf8End = 0;
|
||||
|
||||
aWidth = 0;
|
||||
|
||||
// Convert the incoming UTF-16 to UTF-8
|
||||
gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
|
||||
gchar *curChar = text;
|
||||
|
||||
if (!text) {
|
||||
#ifdef DEBUG
|
||||
NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
|
||||
DUMP_PRUNICHAR(aText, aLength)
|
||||
#endif
|
||||
rv = NS_ERROR_FAILURE;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
// Convert the utf16 offsets into utf8 offsets
|
||||
for (PRUint32 curOffset = 0; curOffset < aLength;
|
||||
curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
|
||||
|
||||
if (curOffset == aStart)
|
||||
utf8Start = curChar - text;
|
||||
|
||||
if (curOffset == aEnd)
|
||||
utf8End = curChar - text;
|
||||
|
||||
if (IS_HIGH_SURROGATE(aText[curOffset]))
|
||||
curOffset++;
|
||||
}
|
||||
|
||||
// Special case where the end index is the same as the length
|
||||
if (aLength == aEnd)
|
||||
utf8End = strlen(text);
|
||||
|
||||
rv = GetRangeWidth(text, strlen(text), utf8Start, utf8End, aWidth);
|
||||
|
||||
loser:
|
||||
if (text)
|
||||
g_free(text);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFontMetricsPango::GetRangeWidth(const char *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
PRUint32 &aWidth)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
int *ranges = NULL;
|
||||
int n_ranges = 0;
|
||||
float f;
|
||||
|
||||
aWidth = 0;
|
||||
|
||||
PangoLayout *layout = pango_layout_new(mPangoContext);
|
||||
|
||||
if (!aText) {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
pango_layout_set_text(layout, aText, aLength);
|
||||
FixupSpaceWidths(layout, aText);
|
||||
|
||||
PangoLayoutLine *line;
|
||||
if (pango_layout_get_line_count(layout) != 1) {
|
||||
printf("Warning: more than one line!\n");
|
||||
}
|
||||
line = pango_layout_get_line(layout, 0);
|
||||
|
||||
pango_layout_line_get_x_ranges(line, aStart, aEnd, &ranges, &n_ranges);
|
||||
|
||||
aWidth = (ranges[((n_ranges - 1) * 2) + 1] - ranges[0]);
|
||||
|
||||
f = mDeviceContext-> DevUnitsToAppUnits();
|
||||
aWidth = nscoord(aWidth * f / PANGO_SCALE);
|
||||
|
||||
loser:
|
||||
if (ranges)
|
||||
g_free(ranges);
|
||||
if (layout)
|
||||
g_object_unref(layout);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* static */
|
||||
PRUint32
|
||||
nsFontMetricsPango::GetHints(void)
|
||||
|
@ -904,7 +1148,8 @@ nsFontMetricsPango::GetHints(void)
|
|||
return (NS_RENDERING_HINT_BIDI_REORDERING |
|
||||
NS_RENDERING_HINT_ARABIC_SHAPING |
|
||||
NS_RENDERING_HINT_FAST_MEASURE |
|
||||
NS_RENDERING_HINT_REORDER_SPACED_TEXT);
|
||||
NS_RENDERING_HINT_REORDER_SPACED_TEXT |
|
||||
NS_RENDERING_HINT_TEXT_CLUSTERS);
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
@ -1020,6 +1265,10 @@ nsFontMetricsPango::RealizeFont(void)
|
|||
mLTRPangoContext = pango_xft_get_context(GDK_DISPLAY(), 0);
|
||||
mPangoContext = mLTRPangoContext;
|
||||
|
||||
// Make sure to set the base direction to LTR - if layout needs to
|
||||
// render RTL text it will use ::SetRightToLeftText()
|
||||
pango_context_set_base_dir(mPangoContext, PANGO_DIRECTION_LTR);
|
||||
|
||||
// Set the color map so we can draw later.
|
||||
gdk_pango_context_set_colormap(mPangoContext, gdk_rgb_get_cmap());
|
||||
|
||||
|
@ -1128,13 +1377,11 @@ nsFontMetricsPango::DrawStringSlowly(const gchar *aText,
|
|||
}
|
||||
|
||||
/* printf(" rendering at X coord %d\n", aX + offset); */
|
||||
|
||||
gdk_draw_glyphs(aDrawable, aGC, layoutRun->item->analysis.font,
|
||||
aX + (gint)(offset / PANGO_SCALE), aY, layoutRun->glyphs);
|
||||
|
||||
offset += tmpOffset;
|
||||
}
|
||||
|
||||
gdk_draw_layout_line(aDrawable, aGC, aX, aY, aLine);
|
||||
|
||||
delete[] utf8spacing;
|
||||
}
|
||||
|
||||
|
@ -1286,6 +1533,26 @@ nsFontMetricsPango::GetTextDimensionsInternal(const gchar* aString,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsFontMetricsPango::FixupSpaceWidths (PangoLayout *aLayout,
|
||||
const char *aString)
|
||||
{
|
||||
PangoLayoutLine *line = pango_layout_get_line(aLayout, 0);
|
||||
|
||||
gint curRun = 0;
|
||||
|
||||
for (GSList *tmpList = line->runs; tmpList && tmpList->data;
|
||||
tmpList = tmpList->next, curRun++) {
|
||||
PangoLayoutRun *layoutRun = (PangoLayoutRun *)tmpList->data;
|
||||
|
||||
for (gint i=0; i < layoutRun->glyphs->num_glyphs; i++) {
|
||||
gint thisOffset = (gint)layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset;
|
||||
if (aString[thisOffset] == ' ')
|
||||
layoutRun->glyphs->glyphs[i].geometry.width = mPangoSpaceWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
PRBool
|
||||
IsASCIIFontName(const nsString& aName)
|
||||
|
|
|
@ -195,6 +195,26 @@ public:
|
|||
|
||||
virtual nsresult SetRightToLeftText(PRBool aIsRTL);
|
||||
|
||||
virtual nsresult GetClusterInfo(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint8 *aClusterStarts);
|
||||
|
||||
virtual PRInt32 GetPosition(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
nsPoint aPt);
|
||||
|
||||
virtual nsresult GetRangeWidth(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
PRUint32 &aWidth);
|
||||
|
||||
virtual nsresult GetRangeWidth(const char *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
PRUint32 &aWidth);
|
||||
|
||||
// get hints for the font
|
||||
static PRUint32 GetHints (void);
|
||||
|
||||
|
@ -240,6 +260,7 @@ private:
|
|||
nscoord mMaxDescent;
|
||||
nscoord mMaxAdvance;
|
||||
nscoord mSpaceWidth;
|
||||
nscoord mPangoSpaceWidth;
|
||||
nscoord mAveCharWidth;
|
||||
|
||||
// Private methods
|
||||
|
@ -266,6 +287,8 @@ private:
|
|||
PRInt32& aNumCharsFit,
|
||||
nsTextDimensions& aLastWordDimensions,
|
||||
nsRenderingContextGTK *aContext);
|
||||
|
||||
void FixupSpaceWidths (PangoLayout *aLayout, const char *aString);
|
||||
};
|
||||
|
||||
class nsFontEnumeratorPango : public nsIFontEnumerator
|
||||
|
|
|
@ -735,6 +735,42 @@ nsFontMetricsXft::SetRightToLeftText(PRBool aIsRTL)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFontMetricsXft::GetClusterInfo(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint8 *aClusterStarts)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsFontMetricsXft::GetPosition(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
nsPoint aPt)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFontMetricsXft::GetRangeWidth(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
PRUint32 &aWidth)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFontMetricsXft::GetRangeWidth(const char *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
PRUint32 &aWidth)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsFontMetricsXft::GetHints(void)
|
||||
{
|
||||
|
|
|
@ -204,6 +204,26 @@ public:
|
|||
|
||||
virtual nsresult SetRightToLeftText(PRBool aIsRTL);
|
||||
|
||||
virtual nsresult GetClusterInfo(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint8 *aClusterStarts);
|
||||
|
||||
virtual PRInt32 GetPosition(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
nsPoint aPt);
|
||||
|
||||
virtual nsresult GetRangeWidth(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
PRUint32 &aWidth);
|
||||
|
||||
virtual nsresult GetRangeWidth(const char *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
PRUint32 &aWidth);
|
||||
|
||||
// get hints for the font
|
||||
static PRUint32 GetHints (void);
|
||||
|
||||
|
|
|
@ -297,98 +297,42 @@ void nsGCCache::ReuseGC(GCCacheEntry *entry, GdkGCValues *gcv, GdkGCValuesMask f
|
|||
// We have old GC, reuse it and check what
|
||||
// we have to change
|
||||
|
||||
XGCValues xvalues;
|
||||
unsigned long xvalues_mask=0;
|
||||
GdkGCValues xvalues;
|
||||
int xvalues_mask = 0;
|
||||
|
||||
if (entry->clipRegion) {
|
||||
// set it to none here and then set the clip region with
|
||||
// gdk_gc_set_clip_region in GetGC()
|
||||
xvalues.clip_mask = None;
|
||||
xvalues_mask |= GCClipMask;
|
||||
xvalues_mask |= GDK_GC_CLIP_MASK;
|
||||
gdk_region_destroy(entry->clipRegion);
|
||||
entry->clipRegion = NULL;
|
||||
}
|
||||
|
||||
if (entry->gcv.foreground.pixel != gcv->foreground.pixel) {
|
||||
xvalues.foreground = gcv->foreground.pixel;
|
||||
xvalues_mask |= GCForeground;
|
||||
xvalues.foreground.pixel = gcv->foreground.pixel;
|
||||
xvalues_mask |= GDK_GC_FOREGROUND;
|
||||
}
|
||||
|
||||
if (entry->gcv.function != gcv->function) {
|
||||
switch (gcv->function) {
|
||||
case GDK_COPY:
|
||||
xvalues.function = GXcopy;
|
||||
break;
|
||||
case GDK_INVERT:
|
||||
xvalues.function = GXinvert;
|
||||
break;
|
||||
case GDK_XOR:
|
||||
xvalues.function = GXxor;
|
||||
break;
|
||||
case GDK_CLEAR:
|
||||
xvalues.function = GXclear;
|
||||
break;
|
||||
case GDK_AND:
|
||||
xvalues.function = GXand;
|
||||
break;
|
||||
case GDK_AND_REVERSE:
|
||||
xvalues.function = GXandReverse;
|
||||
break;
|
||||
case GDK_AND_INVERT:
|
||||
xvalues.function = GXandInverted;
|
||||
break;
|
||||
case GDK_NOOP:
|
||||
xvalues.function = GXnoop;
|
||||
break;
|
||||
case GDK_OR:
|
||||
xvalues.function = GXor;
|
||||
break;
|
||||
case GDK_EQUIV:
|
||||
xvalues.function = GXequiv;
|
||||
break;
|
||||
case GDK_OR_REVERSE:
|
||||
xvalues.function = GXorReverse;
|
||||
break;
|
||||
case GDK_COPY_INVERT:
|
||||
xvalues.function = GXcopyInverted;
|
||||
break;
|
||||
case GDK_OR_INVERT:
|
||||
xvalues.function = GXorInverted;
|
||||
break;
|
||||
case GDK_NAND:
|
||||
xvalues.function = GXnand;
|
||||
break;
|
||||
case GDK_SET:
|
||||
xvalues.function = GXset;
|
||||
break;
|
||||
}
|
||||
xvalues_mask |= GCFunction;
|
||||
xvalues.function = gcv->function;
|
||||
xvalues_mask |= GDK_GC_FUNCTION;
|
||||
}
|
||||
|
||||
if(entry->gcv.font != gcv->font && flags & GDK_GC_FONT) {
|
||||
xvalues.font = ((XFontStruct *)GDK_FONT_XFONT(gcv->font))->fid;
|
||||
xvalues_mask |= GCFont;
|
||||
xvalues.font = gcv->font;
|
||||
xvalues_mask |= GDK_GC_FONT;
|
||||
}
|
||||
|
||||
if (entry->gcv.line_style != gcv->line_style) {
|
||||
switch (gcv->line_style) {
|
||||
case GDK_LINE_SOLID:
|
||||
xvalues.line_style = LineSolid;
|
||||
break;
|
||||
case GDK_LINE_ON_OFF_DASH:
|
||||
xvalues.line_style = LineOnOffDash;
|
||||
break;
|
||||
case GDK_LINE_DOUBLE_DASH:
|
||||
xvalues.line_style = LineDoubleDash;
|
||||
break;
|
||||
}
|
||||
xvalues_mask |= GCLineStyle;
|
||||
xvalues.line_style = gcv->line_style;
|
||||
xvalues_mask |= GDK_GC_LINE_STYLE;
|
||||
}
|
||||
|
||||
if (xvalues_mask != 0) {
|
||||
XChangeGC(GDK_GC_XDISPLAY(entry->gc), GDK_GC_XGC(entry->gc),
|
||||
xvalues_mask, &xvalues);
|
||||
gdk_gc_set_values(entry->gc, &xvalues, (GdkGCValuesMask)xvalues_mask);
|
||||
}
|
||||
|
||||
entry->flags = flags;
|
||||
entry->gcv = *gcv;
|
||||
}
|
||||
|
|
|
@ -125,6 +125,25 @@ public:
|
|||
// Set the direction of the text rendering
|
||||
virtual nsresult SetRightToLeftText(PRBool aIsRTL) = 0;
|
||||
|
||||
virtual nsresult GetClusterInfo(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint8 *aClusterStarts) = 0;
|
||||
|
||||
virtual PRInt32 GetPosition(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
nsPoint aPt) = 0;
|
||||
|
||||
virtual nsresult GetRangeWidth(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
PRUint32 &aWidth) = 0;
|
||||
virtual nsresult GetRangeWidth(const char *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
PRUint32 &aWidth) = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif /* __nsIFontMetricsGTK_h */
|
||||
|
|
|
@ -1446,6 +1446,33 @@ NS_IMETHODIMP nsRenderingContextGTK::SetRightToLeftText(PRBool aIsRTL)
|
|||
return mFontMetrics->SetRightToLeftText(aIsRTL);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsRenderingContextGTK::GetClusterInfo(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint8 *aClusterStarts)
|
||||
{
|
||||
return mFontMetrics->GetClusterInfo(aText, aLength, aClusterStarts);
|
||||
}
|
||||
|
||||
PRInt32 nsRenderingContextGTK::GetPosition(const PRUnichar *aText, PRUint32 aLength,
|
||||
nsPoint aPt)
|
||||
{
|
||||
return mFontMetrics->GetPosition(aText, aLength, aPt);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsRenderingContextGTK::GetRangeWidth(const PRUnichar *aText, PRUint32 aLength,
|
||||
PRUint32 aStart, PRUint32 aEnd,
|
||||
PRUint32 &aWidth)
|
||||
{
|
||||
return mFontMetrics->GetRangeWidth(aText, aLength, aStart, aEnd, aWidth);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsRenderingContextGTK::GetRangeWidth(const char *aText, PRUint32 aLength,
|
||||
PRUint32 aStart, PRUint32 aEnd,
|
||||
PRUint32 &aWidth)
|
||||
{
|
||||
return mFontMetrics->GetRangeWidth(aText, aLength, aStart, aEnd, aWidth);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsRenderingContextGTK::DrawImage(imgIContainer *aImage, const nsRect & aSrcRect, const nsRect & aDestRect)
|
||||
{
|
||||
UpdateGC();
|
||||
|
|
|
@ -193,6 +193,20 @@ public:
|
|||
NS_IMETHOD RetrieveCurrentNativeGraphicData(PRUint32 * ngd);
|
||||
|
||||
NS_IMETHOD SetRightToLeftText(PRBool aIsRTL);
|
||||
NS_IMETHOD GetClusterInfo(const PRUnichar *aText, PRUint32 aLength,
|
||||
PRUint8 *aClusterStarts);
|
||||
virtual PRInt32 GetPosition(const PRUnichar *aText, PRUint32 aLength,
|
||||
nsPoint aPt);
|
||||
NS_IMETHOD GetRangeWidth(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
PRUint32 &aWidth);
|
||||
NS_IMETHOD GetRangeWidth(const char *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
PRUint32 &aWidth);
|
||||
|
||||
NS_IMETHOD DrawImage(imgIContainer *aImage, const nsRect & aSrcRect, const nsRect & aDestRect);
|
||||
|
||||
|
|
|
@ -107,6 +107,23 @@ public:
|
|||
NS_IMETHOD DrawImage(imgIContainer *aImage, const nsRect & aSrcRect, const nsRect & aDestRect);
|
||||
NS_IMETHOD DrawTile(imgIContainer *aImage, nscoord aXOffset, nscoord aYOffset, const nsRect * aTargetRect);
|
||||
|
||||
NS_IMETHOD GetClusterInfo(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint8 *aClusterStarts);
|
||||
virtual PRInt32 GetPosition(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
nsPoint aPt);
|
||||
NS_IMETHOD GetRangeWidth(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
PRUint32 &aWidth);
|
||||
NS_IMETHOD GetRangeWidth(const char *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
PRUint32 &aWidth);
|
||||
|
||||
NS_IMETHOD RenderEPS(const nsRect& aRect, FILE *aDataFile);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -437,6 +437,42 @@ nsRenderingContextImpl::FlushRect(nscoord aX, nscoord aY, nscoord aWidth, nscoor
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsRenderingContextImpl::GetClusterInfo(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint8 *aClusterStarts)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsRenderingContextImpl::GetPosition(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
nsPoint aPt)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsRenderingContextImpl::GetRangeWidth(const PRUnichar *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
PRUint32 &aWidth)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsRenderingContextImpl::GetRangeWidth(const char *aText,
|
||||
PRUint32 aLength,
|
||||
PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
PRUint32 &aWidth)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsRenderingContextImpl::RenderEPS(const nsRect& aRect, FILE *aDataFile)
|
||||
{
|
||||
|
|
|
@ -202,6 +202,59 @@ nsAutoIndexBuffer::GrowTo(PRInt32 aAtLeast)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
struct nsAutoPRUint8Buffer {
|
||||
nsAutoPRUint8Buffer();
|
||||
~nsAutoPRUint8Buffer();
|
||||
|
||||
nsresult GrowTo(PRInt32 aAtLeast);
|
||||
|
||||
PRUint8* mBuffer;
|
||||
PRInt32 mBufferLen;
|
||||
PRUint8 mAutoBuffer[TEXT_BUF_SIZE];
|
||||
};
|
||||
|
||||
nsAutoPRUint8Buffer::nsAutoPRUint8Buffer()
|
||||
: mBuffer(mAutoBuffer),
|
||||
mBufferLen(TEXT_BUF_SIZE)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
memset(mAutoBuffer, 0xdd, sizeof(mAutoBuffer));
|
||||
#endif
|
||||
}
|
||||
|
||||
nsAutoPRUint8Buffer::~nsAutoPRUint8Buffer()
|
||||
{
|
||||
if (mBuffer && (mBuffer != mAutoBuffer)) {
|
||||
delete [] mBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAutoPRUint8Buffer::GrowTo(PRInt32 aAtLeast)
|
||||
{
|
||||
if (aAtLeast > mBufferLen)
|
||||
{
|
||||
PRInt32 newSize = mBufferLen * 2;
|
||||
if (newSize < mBufferLen + aAtLeast) {
|
||||
newSize = mBufferLen * 2 + aAtLeast;
|
||||
}
|
||||
PRUint8* newBuffer = new PRUint8[newSize];
|
||||
if (!newBuffer) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
memset(newBuffer, 0xdd, sizeof(PRUint8) * newSize);
|
||||
#endif
|
||||
memcpy(newBuffer, mBuffer, sizeof(PRUint8) * mBufferLen);
|
||||
if (mBuffer != mAutoBuffer) {
|
||||
delete [] mBuffer;
|
||||
}
|
||||
mBuffer = newBuffer;
|
||||
mBufferLen = newSize;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
|
@ -808,6 +861,9 @@ protected:
|
|||
|
||||
PRBool IsChineseJapaneseLangGroup();
|
||||
PRBool IsJustifiableCharacter(PRUnichar aChar, PRBool aLangIsCJ);
|
||||
|
||||
void FillClusterBuffer(nsPresContext *aPresContext, const PRUnichar *aText,
|
||||
PRUint32 aLength, PRUint8 *aClusterStarts);
|
||||
};
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
|
@ -1596,6 +1652,34 @@ nsTextFrame::IsJustifiableCharacter(PRUnichar aChar, PRBool aLangIsCJ)
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nsTextFrame::FillClusterBuffer(nsPresContext *aPresContext, const PRUnichar *aText,
|
||||
PRUint32 aLength, PRUint8 *aClusterStarts)
|
||||
{
|
||||
// Fill in the cluster hint information, if it's available.
|
||||
nsCOMPtr<nsIRenderingContext> acx;
|
||||
PRUint32 clusterHint = 0;
|
||||
|
||||
nsIPresShell *shell = aPresContext->GetPresShell();
|
||||
if (shell) {
|
||||
shell->CreateRenderingContext(this, getter_AddRefs(acx));
|
||||
|
||||
// Find the font metrics for this text
|
||||
SetFontFromStyle(acx, mStyleContext);
|
||||
|
||||
if (acx)
|
||||
acx->GetHints(clusterHint);
|
||||
clusterHint &= NS_RENDERING_HINT_TEXT_CLUSTERS;
|
||||
}
|
||||
|
||||
if (clusterHint) {
|
||||
acx->GetClusterInfo(aText, aLength, aClusterStarts);
|
||||
}
|
||||
else {
|
||||
memset(aClusterStarts, 1, sizeof(PRInt8) * aLength);
|
||||
}
|
||||
}
|
||||
|
||||
inline PRBool IsEndOfLine(nsFrameState aState)
|
||||
{
|
||||
return (aState & TEXT_IS_END_OF_LINE) ? PR_TRUE : PR_FALSE;
|
||||
|
@ -2396,7 +2480,6 @@ nsTextFrame::PaintUnicodeText(nsPresContext* aPresContext,
|
|||
PRBool isOddLevel = PR_FALSE;
|
||||
#endif
|
||||
|
||||
|
||||
if (NS_FAILED(GetTextInfoForPainting(aPresContext,
|
||||
aRenderingContext,
|
||||
getter_AddRefs(shell),
|
||||
|
@ -2547,6 +2630,23 @@ nsTextFrame::PaintUnicodeText(nsPresContext* aPresContext,
|
|||
sdptr = sdptr->mNext;
|
||||
}
|
||||
if (!hideStandardSelection) {
|
||||
/*
|
||||
* Text is drawn by drawing the entire string every time, but
|
||||
* using clip regions to control which part of the text is shown
|
||||
* (selected or unselected.) We do this because you can't
|
||||
* assume that the layout of a part of text will be the same
|
||||
* when it's drawn apart from the entire string. This is true
|
||||
* in languages like arabic, where shaping affects entire words.
|
||||
* Simply put: length("abcd") != length("ab") + length("cd") in
|
||||
* some languages.
|
||||
*/
|
||||
|
||||
// See if this rendering backend supports getting cluster
|
||||
// information.
|
||||
PRUint32 clusterHint = 0;
|
||||
aRenderingContext.GetHints(clusterHint);
|
||||
clusterHint &= NS_RENDERING_HINT_TEXT_CLUSTERS;
|
||||
|
||||
//while we have substrings...
|
||||
//PRBool drawn = PR_FALSE;
|
||||
DrawSelectionIterator iter(content, details,text,(PRUint32)textLength,aTextStyle, selectionValue, aPresContext, mStyleContext);
|
||||
|
@ -2567,39 +2667,58 @@ nsTextFrame::PaintUnicodeText(nsPresContext* aPresContext,
|
|||
//TextStyle ¤tStyle = iter.CurrentStyle();
|
||||
nscolor currentFGColor, currentBKColor;
|
||||
PRBool isCurrentBKColorTransparent;
|
||||
|
||||
PRBool isSelection = iter.GetSelectionColors(¤tFGColor,
|
||||
¤tBKColor,
|
||||
&isCurrentBKColorTransparent);
|
||||
#ifdef IBMBIDI
|
||||
if (currentlength > 0
|
||||
&& NS_SUCCEEDED(aRenderingContext.GetWidth(currenttext, currentlength,newWidth)))//ADJUST FOR CHAR SPACING
|
||||
{
|
||||
|
||||
if (isRightToLeftOnBidiPlatform)
|
||||
currentX -= newWidth;
|
||||
#else // not IBMBIDI
|
||||
if (NS_SUCCEEDED(aRenderingContext.GetWidth(currenttext, currentlength,newWidth)))//ADJUST FOR CHAR SPACING
|
||||
if (currentlength > 0)
|
||||
{
|
||||
#endif
|
||||
if (isSelection && !isPaginated)
|
||||
{//DRAW RECT HERE!!!
|
||||
if (!isCurrentBKColorTransparent) {
|
||||
aRenderingContext.SetColor(currentBKColor);
|
||||
aRenderingContext.FillRect(currentX, dy, newWidth, mRect.height);
|
||||
}
|
||||
if (clusterHint) {
|
||||
PRUint32 tmpWidth;
|
||||
rv = aRenderingContext.GetRangeWidth(text, textLength, currenttext - text,
|
||||
(currenttext - text) + currentlength,
|
||||
tmpWidth);
|
||||
newWidth = nscoord(tmpWidth);
|
||||
}
|
||||
else {
|
||||
rv = aRenderingContext.GetWidth(currenttext, currentlength,newWidth); //ADJUST FOR CHAR SPACING
|
||||
}
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (isRightToLeftOnBidiPlatform)
|
||||
currentX -= newWidth;
|
||||
if (isSelection && !isPaginated)
|
||||
{//DRAW RECT HERE!!!
|
||||
if (!isCurrentBKColorTransparent) {
|
||||
aRenderingContext.SetColor(currentBKColor);
|
||||
aRenderingContext.FillRect(currentX, dy, newWidth, mRect.height);
|
||||
}
|
||||
currentFGColor = EnsureDifferentColors(currentFGColor, currentBKColor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
newWidth = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
newWidth =0;
|
||||
|
||||
else {
|
||||
newWidth = 0;
|
||||
}
|
||||
|
||||
aRenderingContext.PushState();
|
||||
|
||||
nsRect rect(currentX, dy, newWidth, mRect.height);
|
||||
aRenderingContext.SetClipRect(rect, nsClipCombine_kIntersect);
|
||||
|
||||
if (isPaginated && !iter.IsBeforeOrAfter()) {
|
||||
aRenderingContext.SetColor(nsCSSRendering::TransformColor(aTextStyle.mColor->mColor,canDarkenColor));
|
||||
aRenderingContext.DrawString(currenttext, currentlength, currentX, dy + mAscent);
|
||||
aRenderingContext.DrawString(text, PRUint32(textLength), dx, dy + mAscent);
|
||||
} else if (!isPaginated) {
|
||||
aRenderingContext.SetColor(nsCSSRendering::TransformColor(currentFGColor,canDarkenColor));
|
||||
aRenderingContext.DrawString(currenttext, currentlength, currentX, dy + mAscent);
|
||||
aRenderingContext.DrawString(text, PRUint32(textLength), dx, dy + mAscent);
|
||||
}
|
||||
|
||||
aRenderingContext.PopState();
|
||||
|
||||
#ifdef IBMBIDI
|
||||
if (!isRightToLeftOnBidiPlatform)
|
||||
#endif
|
||||
|
@ -3507,6 +3626,16 @@ nsTextFrame::PaintAsciiText(nsPresContext* aPresContext,
|
|||
//ITS OK TO CAST HERE THE RESULT WE USE WILLNOT DO BAD CONVERSION
|
||||
DrawSelectionIterator iter(content, details,(PRUnichar *)text,(PRUint32)textLength,aTextStyle,
|
||||
selectionValue, aPresContext, mStyleContext);
|
||||
|
||||
// See if this rendering backend supports getting cluster
|
||||
// information.
|
||||
PRUint32 clusterHint = 0;
|
||||
aRenderingContext.GetHints(clusterHint);
|
||||
clusterHint &= NS_RENDERING_HINT_TEXT_CLUSTERS;
|
||||
|
||||
nscoord foo;
|
||||
aRenderingContext.GetWidth(text, textLength, foo);
|
||||
|
||||
if (!iter.IsDone() && iter.First())
|
||||
{
|
||||
nscoord currentX = dx;
|
||||
|
@ -3518,11 +3647,23 @@ nsTextFrame::PaintAsciiText(nsPresContext* aPresContext,
|
|||
//TextStyle ¤tStyle = iter.CurrentStyle();
|
||||
nscolor currentFGColor, currentBKColor;
|
||||
PRBool isCurrentBKColorTransparent;
|
||||
|
||||
if (clusterHint) {
|
||||
PRUint32 tmpWidth;
|
||||
rv = aRenderingContext.GetRangeWidth(text, textLength, currenttext - text,
|
||||
(currenttext - text) + currentlength,
|
||||
tmpWidth);
|
||||
newWidth = nscoord(tmpWidth);
|
||||
}
|
||||
else {
|
||||
rv = aRenderingContext.GetWidth(currenttext, currentlength,newWidth); //ADJUST FOR CHAR SPACING
|
||||
}
|
||||
|
||||
PRBool isSelection = iter.GetSelectionColors(¤tFGColor,
|
||||
¤tBKColor,
|
||||
&isCurrentBKColorTransparent);
|
||||
if (NS_SUCCEEDED(aRenderingContext.GetWidth(currenttext, currentlength,newWidth)))//ADJUST FOR CHAR SPACING
|
||||
{
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (isSelection && !isPaginated)
|
||||
{//DRAW RECT HERE!!!
|
||||
if (!isCurrentBKColorTransparent) {
|
||||
|
@ -3531,16 +3672,25 @@ nsTextFrame::PaintAsciiText(nsPresContext* aPresContext,
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else {
|
||||
newWidth =0;
|
||||
}
|
||||
|
||||
aRenderingContext.PushState();
|
||||
|
||||
nsRect rect(currentX, dy, newWidth, mRect.height);
|
||||
aRenderingContext.SetClipRect(rect, nsClipCombine_kIntersect);
|
||||
|
||||
if (isPaginated && !iter.IsBeforeOrAfter()) {
|
||||
aRenderingContext.DrawString(currenttext, currentlength, currentX, dy + mAscent);
|
||||
aRenderingContext.SetColor(nsCSSRendering::TransformColor(aTextStyle.mColor->mColor,canDarkenColor));
|
||||
aRenderingContext.DrawString(text, PRUint32(textLength), dx, dy + mAscent);
|
||||
} else if (!isPaginated) {
|
||||
aRenderingContext.SetColor(nsCSSRendering::TransformColor(currentFGColor,isPaginated));
|
||||
aRenderingContext.DrawString(currenttext, currentlength, currentX, dy + mAscent);
|
||||
aRenderingContext.SetColor(nsCSSRendering::TransformColor(currentFGColor,canDarkenColor));
|
||||
aRenderingContext.DrawString(text, PRUint32(textLength), dx, dy + mAscent);
|
||||
}
|
||||
|
||||
aRenderingContext.PopState();
|
||||
|
||||
currentX+=newWidth;//increment twips X start
|
||||
|
||||
iter.Next();
|
||||
|
@ -3725,6 +3875,17 @@ nsTextFrame::GetPosition(nsPresContext* aPresContext,
|
|||
PRInt32 textWidth = 0;
|
||||
PRUnichar* text = paintBuffer.mBuffer;
|
||||
|
||||
// See if the font backend will do all the hard work for us.
|
||||
PRUint32 clusterHint = 0;
|
||||
rendContext->GetHints(clusterHint);
|
||||
clusterHint &= NS_RENDERING_HINT_TEXT_CLUSTERS;
|
||||
if (clusterHint) {
|
||||
nsPoint pt;
|
||||
pt.x = aPoint.x - origin.x;
|
||||
pt.y = aPoint.y - origin.y;
|
||||
indx = rendContext->GetPosition(text, textLength, pt);
|
||||
}
|
||||
else {
|
||||
#ifdef IBMBIDI
|
||||
PRBool getReversedPos = NS_GET_EMBEDDING_LEVEL(this) & 1;
|
||||
nscoord posX = (getReversedPos) ?
|
||||
|
@ -3761,6 +3922,7 @@ nsTextFrame::GetPosition(nsPresContext* aPresContext,
|
|||
indx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aContentOffset = indx + mContentOffset;
|
||||
//reusing wordBufMem
|
||||
|
@ -4200,6 +4362,12 @@ nsTextFrame::PeekOffset(nsPresContext* aPresContext, nsPeekOffsetStruct *aPos)
|
|||
}
|
||||
PRInt32* ip = indexBuffer.mBuffer;
|
||||
|
||||
nsAutoPRUint8Buffer clusterBuffer;
|
||||
rv = clusterBuffer.GrowTo(mContentLength + 1);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32 textLength;
|
||||
nsresult result(NS_ERROR_FAILURE);
|
||||
aPos->mResultContent = mContent;//do this right off
|
||||
|
@ -4265,8 +4433,12 @@ nsTextFrame::PeekOffset(nsPresContext* aPresContext, nsPeekOffsetStruct *aPos)
|
|||
aPos->mContentOffset = 0;
|
||||
PRInt32 i;
|
||||
|
||||
FillClusterBuffer(aPresContext, paintBuffer.mBuffer,
|
||||
(PRUint32)textLength, clusterBuffer.mBuffer);
|
||||
|
||||
for (i = aPos->mStartOffset -1 - mContentOffset; i >=0; i--){
|
||||
if ((ip[i] < ip[aPos->mStartOffset - mContentOffset]) &&
|
||||
(clusterBuffer.mBuffer[ip[i] - mContentOffset]) &&
|
||||
(! IS_LOW_SURROGATE(paintBuffer.mBuffer[ip[i]-mContentOffset])))
|
||||
{
|
||||
aPos->mContentOffset = i + mContentOffset;
|
||||
|
@ -4317,14 +4489,19 @@ nsTextFrame::PeekOffset(nsPresContext* aPresContext, nsPeekOffsetStruct *aPos)
|
|||
PRInt32 i;
|
||||
aPos->mContentOffset = mContentLength;
|
||||
|
||||
for (i = aPos->mStartOffset +1 - mContentOffset; i <= mContentLength; i++){
|
||||
FillClusterBuffer(aPresContext, paintBuffer.mBuffer,
|
||||
(PRUint32)textLength, clusterBuffer.mBuffer);
|
||||
|
||||
for (i = aPos->mStartOffset - mContentOffset; i <= mContentLength; i++) {
|
||||
if ((ip[i] > ip[aPos->mStartOffset - mContentOffset]) &&
|
||||
(! IS_LOW_SURROGATE(paintBuffer.mBuffer[ip[i]-mContentOffset])))
|
||||
{
|
||||
((i == mContentLength) ||
|
||||
(!IS_LOW_SURROGATE(paintBuffer.mBuffer[ip[i] - mContentOffset])) &&
|
||||
(clusterBuffer.mBuffer[ip[i] - mContentOffset]))) {
|
||||
aPos->mContentOffset = i + mContentOffset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SUNCTL
|
||||
static NS_DEFINE_CID(kLECID, NS_ULE_CID);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче