patch: khtml text selection with complex text
Simon Hausmann
hausmann at kde.org
Sun Mar 12 21:34:50 GMT 2006
Hi,
text selection with complex text is currently broken in khtml, because khtml
draws the selected text as a separate string, breaking it apart at invalid
positions. You can see that easily on web sites with arabic text for example.
The only solution to that problem is unfortunately to draw the run of text
that is part of the beginning or the end of the selection twice, once
unselected and once selected with a clip rectangle set. The clipping is
necessary as there may be valid cursor positions inside a ligature.
Attached is my attempt at implementing this. Would be cool if somebody could
comment on the patch, or perhaps even approve it :)
Thanks,
Simon
-------------- next part --------------
Index: render_text.cpp
===================================================================
--- render_text.cpp (revision 517934)
+++ render_text.cpp (working copy)
@@ -140,10 +140,29 @@
p->setPen(hc);
//kdDebug( 6040 ) << "textRun::painting(" << QConstString(text->str->s + m_start, m_len).string().left(30) << ") at(" << m_x+tx << "/" << m_y+ty << ")" << endl;
+
+ p->save();
+
+ int visualSelectionStart = f->width(text->str->s, text->str->l, m_start, startPos);
+ int visualSelectionEnd = f->width(text->str->s, text->str->l, m_start, endPos);
+ int visualSelectionWidth = visualSelectionEnd - visualSelectionStart;
+ if (m_reversed) {
+ visualSelectionStart = f->width(text->str->s, text->str->l, m_start, m_len) - visualSelectionEnd;
+ }
+
+ QRect selectionRect(m_x + tx + visualSelectionStart, m_y + ty, visualSelectionWidth, height());
+ QRegion r(selectionRect);
+ if (p->hasClipping())
+ r &= p->clipRegion(QPainter::CoordPainter);
+ p->setClipRegion(r, QPainter::CoordPainter);
+ p->fillRect(selectionRect, hbg);
+
f->drawText(p, m_x + tx, m_y + ty + m_baseline, text->str->s, text->str->l,
- m_start, m_len, m_toAdd,
- m_reversed ? QPainter::RTL : QPainter::LTR,
- startPos, endPos, hbg, m_y + ty, height(), deco);
+ m_start, m_len, m_toAdd,
+ m_reversed ? QPainter::RTL : QPainter::LTR,
+ -1, -1, hbg, m_y + ty, height(), deco);
+
+ p->restore();
}
void InlineTextBox::paintDecoration( QPainter *pt, const Font *f, int _tx, int _ty, int deco)
@@ -923,54 +942,13 @@
#endif
if (s->m_len > 0 && pI.phase != PaintActionSelection) {
- if (!haveSelection) {
- //kdDebug( 6040 ) << "RenderObject::paintObject(" << QConstString(str->s + s->m_start, s->m_len).string() << ") at(" << s->m_x+tx << "/" << s->m_y+ty << ")" << endl;
-#ifndef APPLE_CHANGES
- if (_style->textShadow())
- s->paintShadow(pI.p, font, tx, ty, _style->textShadow());
-#endif
+ //kdDebug( 6040 ) << "RenderObject::paintObject(" << QConstString(str->s + s->m_start, s->m_len).string() << ") at(" << s->m_x+tx << "/" << s->m_y+ty << ")" << endl;
+ if (_style->textShadow())
+ s->paintShadow(pI.p, font, tx, ty, _style->textShadow());
// kdDebug(6040) << QConstString(str->s + s->m_start, s->m_len).string().left(40) << endl;
- font->drawText(pI.p, s->m_x + tx, s->m_y + ty + s->m_baseline, str->s, str->l, s->m_start, s->m_len,
- s->m_toAdd, s->m_reversed ? QPainter::RTL : QPainter::LTR);
- }
- else {
- int offset = s->m_start;
- int sPos = kMax( startPos - offset, 0 );
- int ePos = kMin( endPos - offset, int( s->m_len ) );
-// selected text is always separate in konqueror
-#ifdef APPLE_CHANGES
- if (paintSelectedTextSeparately) {
-#endif
-#ifndef APPLE_CHANGES
- if (_style->textShadow())
- s->paintShadow(pI.p, font, tx, ty, _style->textShadow());
-#endif
- if (sPos >= ePos)
- font->drawText(pI.p, s->m_x + tx, s->m_y + ty + s->m_baseline,
- str->s, str->l, s->m_start, s->m_len,
- s->m_toAdd, s->m_reversed ? QPainter::RTL : QPainter::LTR);
- else {
- if (sPos-1 >= 0)
- font->drawText(pI.p, s->m_x + tx, s->m_y + ty + s->m_baseline,
- str->s, str->l, s->m_start, s->m_len,
- s->m_toAdd, s->m_reversed ? QPainter::RTL : QPainter::LTR, 0, sPos);
- if (ePos < s->m_len)
- font->drawText(pI.p, s->m_x + tx, s->m_y + ty + s->m_baseline,
- str->s, str->l, s->m_start, s->m_len,
- s->m_toAdd, s->m_reversed ? QPainter::RTL : QPainter::LTR, ePos, s->m_len);
- }
-#ifdef APPLE_CHANGES
- }
-
- if ( sPos < ePos ) {
- if (selectionColor != p->pen().color())
- p->setPen(selectionColor);
-
- font->drawText(pI.p, s->m_x + tx, s->m_y + ty + s->m_baseline, str->s,
- str->l, s->m_start, s->m_len,
- s->m_toAdd, s->m_reversed ? QPainter::RTL : QPainter::LTR, sPos, ePos);
- }
-#endif
+ if (!haveSelection || startPos != s->m_start || endPos != s->m_start + s->m_len) {
+ font->drawText(pI.p, s->m_x + tx, s->m_y + ty + s->m_baseline, str->s, str->l, s->m_start, s->m_len,
+ s->m_toAdd, s->m_reversed ? QPainter::RTL : QPainter::LTR);
}
}
More information about the kfm-devel
mailing list