Commit 5062b40d authored by Waldo Bastian's avatar Waldo Bastian
Browse files

Don't rely on font for line-drawing.

Patch by Maksim Orlovich
BUG: 61637

svn path=/trunk/kdebase/konsole/; revision=382259
parent 29f0ead7
......@@ -6,6 +6,7 @@ INCLUDES = -I. $(all_includes)
# you can add here more. This one gets installed
# bin_PROGRAMS = kcmkonsole
bin_PROGRAMS =
noinst_PROGRAMS = fontembedder
lib_LTLIBRARIES =
kdeinit_LTLIBRARIES = konsole.la
kde_module_LTLIBRARIES = libkonsolepart.la kded_kwrited.la
......@@ -26,6 +27,10 @@ libkonsolepart_la_SOURCES = TEPty.cpp BlockArray.cpp konsole_part.cpp \
libkonsolepart_la_LDFLAGS = $(KDE_PLUGIN) $(all_libraries)
libkonsolepart_la_LIBADD = $(XTESTLIB) $(LIB_KPARTS)
fontembedder_SOURCES = fontembedder.cpp
fontembedder_LDFLAGS = $(all_libraries)
fontembedder_LDADD = $(LIB_QT)
# kwrited kded module
kded_kwrited_la_SOURCES = kwrited.cpp TEPty.cpp kwrited.skel
kded_kwrited_la_LIBADD = $(LIB_KDECORE)
......@@ -47,7 +52,7 @@ noinst_HEADERS = TEWidget.h TEPty.h TEmulation.h TEmuVt102.h \
TECommon.h TEScreen.h konsole.h schema.h session.h konsole_wcwidth.h \
kwrited.h TEHistory.h keytrans.h default.keytab.h BlockArray.h \
konsolebookmarkhandler.h konsolebookmarkmenu.h zmodem_dialog.h \
printsettings.h
printsettings.h linefont.h
METASOURCES = AUTO
......@@ -70,3 +75,6 @@ mimedir = $(kde_mimedir)/application
mime_DATA = x-konsole.desktop
EXTRA_DIST = $(mime_DATA)
fonts: fontembedder
./fontembedder $(srcdir)/linefont.src > linefont.h
......@@ -196,6 +196,8 @@ void TEWidget::setColorTable(const ColorEntry table[])
QCodec.
*/
static inline bool isLineChar(Q_UINT16 c) { return ((c & 0xFF80) == 0x2500);}
// assert for i in [0..31] : vt100extended(vt100_graphics[i]) == i.
unsigned short vt100_graphics[32] =
......@@ -269,10 +271,9 @@ void TEWidget::fontChange(const QFont &)
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)
......@@ -426,6 +427,122 @@ TEWidget::~TEWidget()
/* */
/* ------------------------------------------------------------------------- */
/**
A table for emulating the simple (single width) unicode drawing chars.
It represents the 250x - 257x glyphs. If it's zero, we can't use it.
if it's not, it's encoded as follows: imagine a 5x5 grid where the points are numbered
0 to 24 left to top, top to bottom. Each point is represented by the corresponding bit.
Then, the pixels basically have the following interpretation:
_|||_
-...-
-...-
-...-
_|||_
where _ = none
| = vertical line.
- = horizontal line.
*/
enum LineEncode
{
TopL = (1<<1),
TopC = (1<<2),
TopR = (1<<3),
LeftT = (1<<5),
Int11 = (1<<6),
Int12 = (1<<7),
Int13 = (1<<8),
RightT = (1<<9),
LeftC = (1<<10),
Int21 = (1<<11),
Int22 = (1<<12),
Int23 = (1<<13),
RightC = (1<<14),
LeftB = (1<<15),
Int31 = (1<<16),
Int32 = (1<<17),
Int33 = (1<<18),
RightB = (1<<19),
BotL = (1<<21),
BotC = (1<<22),
BotR = (1<<23),
};
#include "linefont.h"
static void drawLineChar(QPainter& paint, int x, int y, int w, int h, uchar code)
{
//Calculate cell midpoints, end points.
int cx = x + w/2;
int cy = y + h/2;
int ex = x + w - 1;
int ey = y + h - 1;
Q_UINT32 toDraw = LineChars[code];
//Top lines:
if (toDraw & TopL)
paint.drawLine(cx-1, y, cx-1, cy-2);
if (toDraw & TopC)
paint.drawLine(cx, y, cx, cy-2);
if (toDraw & TopR)
paint.drawLine(cx+1, y, cx+1, cy-2);
//Bot lines:
if (toDraw & BotL)
paint.drawLine(cx-1, cy+2, cx-1, ey);
if (toDraw & BotC)
paint.drawLine(cx, cy+2, cx, ey);
if (toDraw & BotR)
paint.drawLine(cx+1, cy+2, cx+1, ey);
//Left lines:
if (toDraw & LeftT)
paint.drawLine(x, cy-1, cx-2, cy-1);
if (toDraw & LeftC)
paint.drawLine(x, cy, cx-2, cy);
if (toDraw & LeftB)
paint.drawLine(x, cy+1, cx-2, cy+1);
//Right lines:
if (toDraw & RightT)
paint.drawLine(cx+2, cy-1, ex, cy-1);
if (toDraw & RightC)
paint.drawLine(cx+2, cy, ex, cy);
if (toDraw & RightB)
paint.drawLine(cx+2, cy+1, ex, cy+1);
//Intersection points.
if (toDraw & Int11)
paint.drawPoint(cx-1, cy-1);
if (toDraw & Int12)
paint.drawPoint(cx, cy-1);
if (toDraw & Int13)
paint.drawPoint(cx+1, cy-1);
if (toDraw & Int21)
paint.drawPoint(cx-1, cy);
if (toDraw & Int22)
paint.drawPoint(cx, cy);
if (toDraw & Int23)
paint.drawPoint(cx+1, cy);
if (toDraw & Int31)
paint.drawPoint(cx-1, cy+1);
if (toDraw & Int32)
paint.drawPoint(cx, cy+1);
if (toDraw & Int33)
paint.drawPoint(cx+1, cy+1);
}
void TEWidget::drawTextFixed(QPainter &paint, int x, int y,
QString& str, const ca *attr)
{
......@@ -446,6 +563,19 @@ void TEWidget::drawTextFixed(QPainter &paint, int x, int y,
w = font_w*2;
nc+=2;
}
//Check for line-drawing char
if (isLineChar(drawstr[0].unicode()))
{
uchar code = drawstr[0].cell();
if (LineChars[code])
{
drawLineChar(paint, x, y, w, font_h, code);
x += w;
continue;
}
}
paint.drawText(x,y, w, font_h, Qt::AlignHCenter | Qt::DontClip, drawstr, -1);
x += w;
}
......@@ -671,6 +801,7 @@ HCNT("setImage");
int tLy = tL.y();
hasBlinker = false;
bool lineDraw = false;
int cf = -1; // undefined
int cb = -1; // undefined
int cr = -1; // undefined
......@@ -717,6 +848,7 @@ HCNT("setImage");
continue;
int p = 0;
disstrU[p++] = c; //fontMap(c);
lineDraw = isLineChar(c);
cr = ext[x].r;
cb = ext[x].b;
if (ext[x].f != cf) cf = ext[x].f;
......@@ -731,7 +863,7 @@ HCNT("setImage");
}
if (ext[x+len].f != cf || ext[x+len].b != cb || ext[x+len].r != cr ||
!dirtyMask[x+len] )
!dirtyMask[x+len] || isLineChar(c) != lineDraw)
break;
disstrU[p++] = c; //fontMap(c);
......@@ -756,9 +888,13 @@ HCNT("setImage");
m_isIMSel = true;
}
bool save_fixed_font = fixed_font;
if (lineDraw)
fixed_font = false;
drawAttrStr(paint,
QRect(bX+tLx+font_w*x,bY+tLy+font_h*y,font_w*len,font_h),
unistr, &ext[x], pm != NULL, true);
fixed_font = save_fixed_font;
x += len - 1;
}
}
......@@ -918,15 +1054,16 @@ void TEWidget::paintContents(QPainter &paint, const QRect &rect, bool pm)
c = image[loc(x,y)].c;
if (c)
disstrU[p++] = c; //fontMap(c);
bool lineDraw = isLineChar(c);
int cf = image[loc(x,y)].f;
int cb = image[loc(x,y)].b;
int cr = image[loc(x,y)].r;
while (x+len <= rlx &&
image[loc(x+len,y)].f == cf &&
image[loc(x+len,y)].b == cb &&
image[loc(x+len,y)].r == cr )
image[loc(x+len,y)].r == cr &&
isLineChar( c = image[loc(x+len,y)].c) == lineDraw) // Assignment!
{
c = image[loc(x+len,y)].c;
if (c)
disstrU[p++] = c; //fontMap(c);
else
......@@ -941,10 +1078,14 @@ void TEWidget::paintContents(QPainter &paint, const QRect &rect, bool pm)
if (!isBlinkEvent || (cr & RE_BLINK))
{
bool save_fixed_font = fixed_font;
if (lineDraw)
fixed_font = false;
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, !(isBlinkEvent || isPrinting));
fixed_font = save_fixed_font;
}
x += len - 1;
}
......
#include <qfile.h>
#include <qtextstream.h>
#include <iostream>
#include <iomanip>
using namespace std;
Q_UINT32 charVal(QChar val)
{
if (val == ' ')
return 0;
else
return 1;
}
Q_UINT32 readGlyphLine(QTextStream& input)
{
QString line = input.readLine();
while (line.length() < 5)
line += ' ';
Q_UINT32 val = charVal(line[0]) |
(charVal(line[1]) << 1) |
(charVal(line[2]) << 2) |
(charVal(line[3]) << 3) |
(charVal(line[4]) << 4);
return val;
}
Q_UINT32 readGlyph(QTextStream& input)
{
return readGlyphLine(input) |
(readGlyphLine(input) << 5) |
(readGlyphLine(input) << 10) |
(readGlyphLine(input) << 15) |
(readGlyphLine(input) << 20);
}
int main(int argc, char **argv)
{
if (argc < 1)
{
qWarning("usage: fontembedder font.src > font.h");
exit(1);
}
QFile inFile(argv[1]);
if (!inFile.open(IO_ReadOnly))
{
qFatal("Can not open %s", argv[1]);
}
QTextStream input(&inFile);
Q_UINT32 glyphStates[128];
for (int i = 0; i < 128; ++i)
glyphStates[i] = 0; //nothing..
while (!input.atEnd())
{
QString line = input.readLine();
line = line.stripWhiteSpace();
if (line.isEmpty())
continue; //Skip empty lines
if (line[0] == '#')
continue; //Skip comments
//Must be a glyph ID.
int glyph = line.toInt(0, 16);
if ((glyph < 0x2500) || (glyph > 0x257f))
qFatal("Invalid glyph number");
glyph = glyph - 0x2500;
glyphStates[glyph] = readGlyph(input);
}
//Output.
cout<<"// WARNING: Autogenerated by \"fontembedder " << argv[1] << "\".\n";
cout<<"// You probably do not want to hand-edit this!\n\n";
cout<<"static const Q_UINT32 LineChars[] = {\n";
//Nicely formatted: 8 per line, 16 lines
for (int line = 0; line < 128; line += 8)
{
cout<<"\t";
for (int col = line; col < line + 8; ++col)
{
cout<<"0x"<<hex<<setw(8)<<setfill('0')<<glyphStates[col];
if (col != 127)
cout<<", ";
}
cout<<"\n";
}
cout<<"};\n";
return 0;
}
//kate: indent-width 4; tab-width 4; space-indent on;
// WARNING: Autogenerated by "fontembedder ./linefont.src".
// You probably do not want to hand-edit this!
static const Q_UINT32 LineChars[] = {
0x00007c00, 0x000fffe0, 0x00421084, 0x00e739ce, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00427000, 0x004e7380, 0x00e77800, 0x00ef7bc0,
0x00421c00, 0x00439ce0, 0x00e73c00, 0x00e7bde0, 0x00007084, 0x000e7384, 0x000079ce, 0x000f7bce,
0x00001c84, 0x00039ce4, 0x00003dce, 0x0007bdee, 0x00427084, 0x004e7384, 0x004279ce, 0x00e77884,
0x00e779ce, 0x004f7bce, 0x00ef7bc4, 0x00ef7bce, 0x00421c84, 0x00439ce4, 0x00423dce, 0x00e73c84,
0x00e73dce, 0x0047bdee, 0x00e7bde4, 0x00e7bdee, 0x00427c00, 0x0043fce0, 0x004e7f80, 0x004fffe0,
0x004fffe0, 0x00e7fde0, 0x006f7fc0, 0x00efffe0, 0x00007c84, 0x0003fce4, 0x000e7f84, 0x000fffe4,
0x00007dce, 0x0007fdee, 0x000f7fce, 0x000fffee, 0x00427c84, 0x0043fce4, 0x004e7f84, 0x004fffe4,
0x00427dce, 0x00e77c84, 0x00e77dce, 0x0047fdee, 0x004e7fce, 0x00e7fde4, 0x00ef7f84, 0x004fffee,
0x00efffe4, 0x00e7fdee, 0x00ef7fce, 0x00efffee, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x000f83e0, 0x00a5294a, 0x004e1380, 0x00a57800, 0x00ad0bc0, 0x004390e0, 0x00a53c00, 0x00a5a1e0,
0x000e1384, 0x0000794a, 0x000f0b4a, 0x000390e4, 0x00003d4a, 0x0007a16a, 0x004e1384, 0x00a5694a,
0x00ad2b4a, 0x004390e4, 0x00a52d4a, 0x00a5a16a, 0x004f83e0, 0x00a57c00, 0x00ad83e0, 0x000f83e4,
0x00007d4a, 0x000f836a, 0x004f93e4, 0x00a57d4a, 0x00ad836a, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00001c00, 0x00001084, 0x00007000, 0x00421000,
0x00039ce0, 0x000039ce, 0x000e7380, 0x00e73800, 0x000e7f80, 0x00e73884, 0x0003fce0, 0x004239ce
};
#2500: single horizontal line
2500
-----
#2501: triple horizontal line
2501
-----
-----
-----
#2502: single vertical line
2502
|
|
|
|
|
#2503: triple vertical line
2503
|||
|||
|||
|||
|||
#2504-250B are dashed - not handled
#250C: top-left corner (lines on bottom + right)
250C
.--
|
|
#250D: as above, but top line triple-width
250D
.--
.--
|--
|
#250E: now the vert line triple-width
250E
..--
|||
|||
#250F: and now both lines triple-width
250F
.___
|.--
||._
|||
#2510: top-right corner
2510
--.
|
|
2511
==.
==.
==|
|
2512
==..
|||
|||
2513
===.
==.|
=.||
|||
#2514: bottom-left corner
2514
|
|
.==
2515
|
|==
|==
===
2516
|||
|||
|.==
2517
|||
||.=
|.==
.===
#2518: bottm-right corner
2518
|
|
==.
2519
|
==|
==|
===
251A
|||
|||
====
251B
|||
=.||
==.|
===.
#251C: Join of vertical line and one from the right
251C
|
|
|==
|
|
251D
|
|==
|==
|==
|
251E
|||
|||
||==
|
|
251F
|
|
||==
|||
|||
2520
|||
|||
||==
|||
|||
2521
|||
|||=
||==
.|==
|
2522
|
.|==
||==
|||=
|||
2523
|||
||.=
||==
||.=
|||
#2524: Join of vertical line and one from the left
2524
|
|
==|
|
|
2525
|
==|
==|
==|
|
2526
|||
|||
==+|
|
|
2527
|
|
==+|
|||
|||
2528