Commit 102fcd92 authored by Waldo Bastian's avatar Waldo Bastian
Browse files

Support for non-fixed fonts.

Based on a patch by llch@redhat.com
CCMAIL: 53713-done@bugs.kde.org

svn path=/trunk/kdebase/konsole/; revision=213124
parent 143da17e
......@@ -54,6 +54,7 @@
#include <qdragobject.h>
#include <qlayout.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
......@@ -91,6 +92,11 @@
#define SCRWIDTH 16 // width of the scrollbar
#define yMouseScroll 1
#define REPCHAR "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
"abcdefgjijklmnopqrstuvwxyz" \
"0123456789./+@"
// scroll increment used when dragging selection at top/bottom of window.
// static
......@@ -235,11 +241,19 @@ void TEWidget::fontChange(const QFont &)
// "Base character width on widest ASCII character. This prevents too wide
// characters in the presence of double wide (e.g. Japanese) characters."
int fw;
font_w = 1;
for(int i=0;i<128;i++) {
if( isprint(i) && font_w < (fw = fm.width(i)))
font_w = fw;
// Get the width from representative normal width characters
font_w = round((double)fm.width(REPCHAR)/strlen(REPCHAR));
fixed_font = true;
fw = fm.width(REPCHAR[0]);
for(int i=1; i< strlen(REPCHAR); i++){
if (fw != fm.width(REPCHAR[i])){
fixed_font = false;
break;
} else
fw = fm.width(REPCHAR[i]);
}
if (font_w>200) // don't trust unrealistic value, fallback to QFontMetrics::maxWidth()
font_w=fm.maxWidth();
if (font_w<1)
......@@ -248,8 +262,10 @@ void TEWidget::fontChange(const QFont &)
font_a = fm.ascent();
//printf("font: %s\n", font().toString().latin1());
//printf("fixed: %s\n", font().fixedPitch() ? "yes" : "no");
//printf("fixed_font: %d\n", fixed_font);
//printf("font_h: %d\n",font_h);
//printf("font_w: %d\n",font_w);
//printf("fw: %d\n",fw);
//printf("font_a: %d\n",font_a);
//printf("rawname: %s\n",font().rawName().ascii());
......@@ -371,29 +387,30 @@ TEWidget::~TEWidget()
*/
void TEWidget::drawAttrStr(QPainter &paint, QRect rect,
QString& str, ca attr, bool pm, bool clear)
QString& str, const ca *attr, bool pm, bool clear)
{
int a = font_a + m_lineSpacing / 2;
QColor fColor = color_table[attr.f].color;
if (attr.r & RE_CURSOR)
QColor fColor = color_table[attr->f].color;
QString drawstr;
if (attr->r & RE_CURSOR)
cursorRect = rect;
// Paint background
if (color_table[attr.b].transparent)
if (color_table[attr->b].transparent)
{
if (pm)
paint.setBackgroundMode( TransparentMode );
if (clear || (blinking && (attr.r & RE_BLINK)))
if (clear || (blinking && (attr->r & RE_BLINK)))
erase(rect);
}
else
{
paint.fillRect(rect, color_table[attr.b].color);
paint.fillRect(rect, color_table[attr->b].color);
}
// Paint cursor
if ((attr.r & RE_CURSOR)) {
if ((attr->r & RE_CURSOR)) {
paint.setBackgroundMode( TransparentMode );
int h = font_h - m_lineSpacing;
QRect r(rect.x(),rect.y()+m_lineSpacing/2,rect.width(),h);
......@@ -401,8 +418,8 @@ void TEWidget::drawAttrStr(QPainter &paint, QRect rect,
{
if (!cursorBlinking)
{
paint.fillRect(r, color_table[attr.f].color);
fColor = color_table[attr.b].color;
paint.fillRect(r, color_table[attr->f].color);
fColor = color_table[attr->b].color;
}
}
else
......@@ -413,19 +430,58 @@ void TEWidget::drawAttrStr(QPainter &paint, QRect rect,
}
// Paint text
if (!(blinking && (attr.r & RE_BLINK)))
if (!(blinking && (attr->r & RE_BLINK)))
{
paint.setPen(fColor);
paint.drawText(rect.x(),rect.y()+a, str, -1, QPainter::LTR);
if ((attr.r & RE_UNDERLINE) || color_table[attr.f].bold)
int x = rect.x();
if(!fixed_font)
{
// The meaning of y differs between different versions of QPainter::drawText!!
int y = rect.y(); // top of rect
for(int i=0;i<str.length();i++)
{
drawstr = str.at(i);
// Add double of the width if next c is 0;
int w = (attr+i+1)->c ? font_w : font_w * 2;
paint.drawText(x,y, w, font_h, Qt::AlignHCenter | Qt::DontClip, drawstr, -1);
x += w;
}
}
else
{
// The meaning of y differs between different versions of QPainter::drawText!!
int y = rect.y()+a; // baseline
paint.drawText(x,y, str, -1, QPainter::LTR);
}
if ((attr->r & RE_UNDERLINE) || color_table[attr->f].bold)
{
paint.setClipRect(rect);
if (color_table[attr.f].bold)
if (color_table[attr->f].bold)
{
paint.setBackgroundMode( TransparentMode );
paint.drawText(rect.x()+1,rect.y()+a, str, -1, QPainter::LTR); // second stroke
int x = rect.x()+1;
if(!fixed_font)
{
// The meaning of y differs between different versions of QPainter::drawText!!
int y = rect.y(); // top of rect
for(int i=0;i<str.length();i++)
{
drawstr = str.at(i);
// Add double of the width if next c is 0;
int w = (attr+i+1)->c ? font_w : font_w * 2;
paint.drawText(x,y, w, font_h, Qt::AlignHCenter | Qt::DontClip, drawstr, -1);
x += w;
}
}
else
{
// The meaning of y differs between different versions of QPainter::drawText!!
int y = rect.y()+a; // baseline
paint.drawText(x,y, str, -1, QPainter::LTR);
}
}
if (attr.r & RE_UNDERLINE)
if (attr->r & RE_UNDERLINE)
paint.drawLine(rect.left(), rect.y()+a+1,
rect.right(),rect.y()+a+1 );
paint.setClipping(false);
......@@ -475,17 +531,36 @@ HCNT("setImage");
int lins = QMIN(this->lines, QMAX(0,lines ));
int cols = QMIN(this->columns,QMAX(0,columns));
QChar *disstrU = new QChar[cols];
char *dirtyMask = malloc(cols+2);
//{ static int cnt = 0; printf("setImage %d\n",cnt++); }
for (y = 0; y < lins; y++)
{
const ca* lcl = &image[y*this->columns];
const ca* const ext = &newimg[y*columns];
// The dirty mask indicates which characters need repainting. We also
// mark surrounding neighbours dirty, in case the character exceeds
// its cell boundaries
memset(dirtyMask, 0, cols+2);
// Two extra so that we don't have to have to care about start and end conditions
for (x = 0; x < cols; x++)
{
if (ext[x] != lcl[x])
{
dirtyMask[x] = dirtyMask[x+1] = dirtyMask[x+2] = 1;
}
}
dirtyMask++; // Position correctly
if (!resizing) // not while resizing, we're expecting a paintEvent
for (x = 0; x < cols; x++)
{
hasBlinker |= (ext[x].r & RE_BLINK);
if (ext[x] != lcl[x])
// Start drawing if this character or the next one differs.
// We also take the next one into account to handle the situation
// where characters exceed their cell width.
if (dirtyMask[x])
{
Q_UINT16 c = ext[x+0].c;
if ( !c )
......@@ -503,7 +578,7 @@ HCNT("setImage");
continue; // Skip trailing part of multi-col chars.
if (ext[x+len].f != cf || ext[x+len].b != cb || ext[x+len].r != cr ||
ext[x+len] == lcl[x+len] )
!dirtyMask[x+len] )
break;
disstrU[p++] = fontMap(c);
......@@ -512,10 +587,13 @@ HCNT("setImage");
QString unistr(disstrU, p);
drawAttrStr(paint,
QRect(bX+tLx+font_w*x,bY+tLy+font_h*y,font_w*len,font_h),
unistr, ext[x], pm != NULL, true);
unistr, &ext[x], pm != NULL, true);
x += len - 1;
}
}
dirtyMask--; // Set back
// finally, make `image' become `newimg'.
memcpy((void*)lcl,(const void*)ext,cols*sizeof(ca));
}
......@@ -524,6 +602,7 @@ HCNT("setImage");
setUpdatesEnabled(true);
if ( hasBlinker && !blinkT->isActive()) blinkT->start(1000); // 1000 ms
if (!hasBlinker && blinkT->isActive()) { blinkT->stop(); blinking = false; }
free(dirtyMask);
delete [] disstrU;
if (resizing && terminalSizeHint)
......@@ -641,7 +720,7 @@ HCNT("paintEvent");
QString unistr(disstrU,p);
drawAttrStr(paint,
QRect(bX+tLx+font_w*x,bY+tLy+font_h*y,font_w*len,font_h),
unistr, image[loc(x,y)], pm != NULL, false);
unistr, &image[loc(x,y)], pm != NULL, false);
}
x += len - 1;
}
......
......@@ -138,7 +138,7 @@ protected:
bool event( QEvent * );
void drawAttrStr(QPainter &paint, QRect rect,
QString& str, ca attr, bool pm, bool clear);
QString& str, const ca *attr, bool pm, bool clear);
void paintEvent( QPaintEvent * );
void resizeEvent(QResizeEvent*);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment