[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kfm-devel
Subject:    patch: khtml text selection with complex text
From:       Simon Hausmann <hausmann () kde ! org>
Date:       2006-03-12 21:34:50
Message-ID: 200603122234.50714.hausmann () kde ! org
[Download RAW message or body]

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

["khtml_selection_patch.txt" (text/plain)]

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);  }
 	    }
 



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic