summaryrefslogtreecommitdiffstats
path: root/kernel/kls_ttf
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-24 17:43:19 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-24 17:43:19 +0000
commit0292059f4a16434600564cfa3f0ad2309a508a54 (patch)
treed95953cd53011917c4df679b96aedca39401b54f /kernel/kls_ttf
downloadlibksquirrel-0292059f4a16434600564cfa3f0ad2309a508a54.tar.gz
libksquirrel-0292059f4a16434600564cfa3f0ad2309a508a54.zip
Added libksquirrel for KDE3
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/libraries/libksquirrel@1095624 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kernel/kls_ttf')
-rw-r--r--kernel/kls_ttf/Makefile.am19
-rw-r--r--kernel/kls_ttf/fmt_codec_pnm.cpp1470
-rw-r--r--kernel/kls_ttf/fmt_codec_pnm_defs.h64
-rw-r--r--kernel/kls_ttf/ftcommon.cpp1333
-rw-r--r--kernel/kls_ttf/ftcommon.h307
-rw-r--r--kernel/kls_ttf/ftview/Makefile.am9
-rw-r--r--kernel/kls_ttf/ftview/README1
-rw-r--r--kernel/kls_ttf/ftview/gblany.h133
-rw-r--r--kernel/kls_ttf/ftview/gblblit.cpp318
-rw-r--r--kernel/kls_ttf/ftview/gblblit.h82
-rw-r--r--kernel/kls_ttf/ftview/gblcolor.h56
-rw-r--r--kernel/kls_ttf/ftview/gblender.cpp381
-rw-r--r--kernel/kls_ttf/ftview/gblender.h216
-rw-r--r--kernel/kls_ttf/ftview/gblhbgr.h74
-rw-r--r--kernel/kls_ttf/ftview/gblhrgb.h76
-rw-r--r--kernel/kls_ttf/ftview/gblvbgr.h76
-rw-r--r--kernel/kls_ttf/ftview/gblvrgb.h76
-rw-r--r--kernel/kls_ttf/ftview/graph.h653
-rw-r--r--kernel/kls_ttf/ftview/grblit.cpp2068
-rw-r--r--kernel/kls_ttf/ftview/grblit.h25
-rw-r--r--kernel/kls_ttf/ftview/grconfig.h9
-rw-r--r--kernel/kls_ttf/ftview/grevents.h117
-rw-r--r--kernel/kls_ttf/ftview/grfont.cpp373
-rw-r--r--kernel/kls_ttf/ftview/grfont.h17
-rw-r--r--kernel/kls_ttf/ftview/grobjs.cpp213
-rw-r--r--kernel/kls_ttf/ftview/grobjs.h182
-rw-r--r--kernel/kls_ttf/ftview/grtypes.h52
-rw-r--r--kernel/kls_ttf/ttf2pnm.cpp187
28 files changed, 8587 insertions, 0 deletions
diff --git a/kernel/kls_ttf/Makefile.am b/kernel/kls_ttf/Makefile.am
new file mode 100644
index 0000000..10d2efe
--- /dev/null
+++ b/kernel/kls_ttf/Makefile.am
@@ -0,0 +1,19 @@
+SUBDIRS = ftview
+
+INCLUDES = -I../include -Iftview @SQ_FT_CFLAGS@
+
+bin_PROGRAMS = ksquirrel-libs-ttf2pnm
+
+ksquirrel_libs_ttf2pnm_SOURCES = ttf2pnm.cpp ftcommon.cpp
+
+ksquirrel_libs_ttf2pnm_LDADD = @SQ_FT_LDFLAGS@ -Lftview -lftview
+
+pkglib_LTLIBRARIES = libkls_ttf.la
+
+libkls_ttf_la_SOURCES = fmt_codec_pnm.cpp fmt_codec_pnm_defs.h
+
+libkls_ttf_la_LDFLAGS = ${SQ_RELEASE}
+
+libkls_ttf_la_LIBADD = ${SQ_LOCAL_RPATH}
+
+AM_CXXFLAGS = -DCODEC_TTF -DTTF2PNM=\"${bindir}/ksquirrel-libs-ttf2pnm\"
diff --git a/kernel/kls_ttf/fmt_codec_pnm.cpp b/kernel/kls_ttf/fmt_codec_pnm.cpp
new file mode 100644
index 0000000..06aedd6
--- /dev/null
+++ b/kernel/kls_ttf/fmt_codec_pnm.cpp
@@ -0,0 +1,1470 @@
+/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net)
+
+ Copyright (c) 2004 Dmitry Baryshev <[email protected]>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation;
+ either version 2 of the License, or (at your option) any later
+ version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ as32 with this library; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <iostream>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+// we will use fork()
+#if defined CODEC_DJVU \
+ || defined CODEC_CAMERA \
+ || defined CODEC_DXF \
+ || defined CODEC_XCF \
+ || defined CODEC_TTF \
+ || defined CODEC_FIG \
+ || defined CODEC_LJPEG \
+ || defined CODEC_NETPBM
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <cstdio>
+#endif
+
+#ifdef CODEC_EPS
+#include <cstdio>
+#include <sstream>
+#include <cmath>
+#endif
+
+#include "ksquirrel-libs/fmt_types.h"
+#include "ksquirrel-libs/fileio.h"
+#include "ksquirrel-libs/error.h"
+#include "ksquirrel-libs/fmt_utils.h"
+
+#include "fmt_codec_pnm_defs.h"
+#include "fmt_codec_pnm.h"
+
+#if defined CODEC_CAMERA
+#include "../xpm/codec_camera.xpm"
+#elif defined CODEC_DJVU
+#include "../xpm/codec_djvu.xpm"
+#elif defined CODEC_XCF
+#include "../xpm/codec_xcf.xpm"
+#elif defined CODEC_DXF
+#include "../xpm/codec_dxf.xpm"
+#elif defined CODEC_NEO
+#include "../xpm/codec_neo.xpm"
+#elif defined CODEC_LEAF
+#include "../xpm/codec_leaf.xpm"
+#elif defined CODEC_PI1
+#include "../xpm/codec_pi1.xpm"
+#elif defined CODEC_PI3
+#include "../xpm/codec_pi3.xpm"
+#elif defined CODEC_XIM
+#include "../xpm/codec_xim.xpm"
+#elif defined CODEC_UTAH
+#include "../xpm/codec_utah.xpm"
+#elif defined CODEC_PICT
+#include "../xpm/codec_pict.xpm"
+#elif defined CODEC_IFF
+#include "../xpm/codec_iff.xpm"
+#elif defined CODEC_MAC
+#include "../xpm/codec_mac.xpm"
+#elif defined CODEC_TTF
+#include "../xpm/codec_ttf.xpm"
+#elif defined CODEC_FIG
+#include "../xpm/codec_fig.xpm"
+#elif defined CODEC_LJPEG
+#include "../xpm/codec_ljpeg.xpm"
+#elif defined CODEC_EPS
+#include "../xpm/codec_eps.xpm"
+#else
+#include "../xpm/codec_pnm.xpm"
+#endif
+
+/*
+ *
+ * PBM, PGM,
+ * PNM, and PPM are
+ * intermediate formats used in the conversion of many little known
+ * formats via pbmplus, the Portable Bitmap Utilities. These
+ * formats are mainly available under UNIX and
+ * on Intel-based PCs.
+ *
+ */
+
+static RGB palmono[2] = {RGB(255,255,255), RGB(0,0,0)};
+
+fmt_codec::fmt_codec() : fmt_codec_base()
+{}
+
+fmt_codec::~fmt_codec()
+{
+#ifdef CODEC_DXF
+ std::string tmmp = tmp + ".ppm";
+ unlink(tmmp.c_str());
+#endif
+}
+
+void fmt_codec::options(codec_options *o)
+{
+#if defined CODEC_CAMERA
+ o->version = "8.77"; // dcraw version
+ o->name = "Photos from different cameras";
+ o->filter = "*.arw *.bay *.bmq *.cr2 *.crw *.cs1 *.dc2 *.dcr *.dng *.erf *.fff *.hdr *.ia *.k25 *.kc2 *.kdc *.mdc *.mos *.mrw *.nef *.orf *.pef *.pxn *.raf *.raw *.rdc *.sr2 *.srf *.sti *.x3f ";
+ o->config = std::string(CAMERA_UI);
+ o->mime = "";
+ o->mimetype = "image/x-raw";
+ o->pixmap = codec_camera;
+ o->readable = true;
+ o->canbemultiple = false;
+ o->writestatic = false;
+ o->writeanimated = false;
+ o->needtempfile = true;
+#elif defined CODEC_DJVU
+ o->version = "1.0.0";
+ o->name = "DjVu Document";
+ o->filter = "*.djvu *.djv *.iw4 *.iw44 ";
+ o->config = std::string(DJVU_UI);
+ o->mime = "";
+ o->mimetype = "image/x-djvu;image/x.djvu";
+ o->pixmap = codec_djvu;
+ o->readable = true;
+ o->canbemultiple = false;
+ o->writestatic = false;
+ o->writeanimated = false;
+ o->needtempfile = true;
+#elif defined CODEC_DXF
+ o->version = "1.0.0";
+ o->name = "AutoCAD/QCAD Drawing";
+ o->filter = "*.dxf ";
+ o->config = std::string(DXF_UI);
+ o->mime = "";
+ o->mimetype = "image/x-dxf";
+ o->pixmap = codec_dxf;
+ o->readable = true;
+ o->canbemultiple = false;
+ o->writestatic = false;
+ o->writeanimated = false;
+ o->needtempfile = true;
+#elif defined CODEC_XCF
+ o->version = "1.0.0";
+ o->name = "GIMP XCF";
+ o->filter = "*.xcf ";
+ o->config = std::string(XCF_UI);
+ o->mime = "";
+ o->mimetype = "image/x-xcf-gimp";
+ o->pixmap = codec_xcf;
+ o->readable = true;
+ o->canbemultiple = false;
+ o->writestatic = false;
+ o->writeanimated = false;
+ o->needtempfile = true;
+#elif defined CODEC_NEO
+ o->version = "1.0.0";
+ o->name = "Neochrome NEO";
+ o->filter = "*.neo ";
+ o->config = "";
+ o->mime = "";
+ o->mimetype = "image/x-neo";
+ o->pixmap = codec_neo;
+ o->readable = true;
+ o->canbemultiple = false;
+ o->writestatic = false;
+ o->writeanimated = false;
+ o->needtempfile = true;
+#elif defined CODEC_LEAF
+ o->version = "1.0.0";
+ o->name = "ILEAF Image";
+ o->filter = "*.leaf ";
+ o->config = "";
+ o->mime = "";
+ o->mimetype = "image/x-leaf";
+ o->pixmap = codec_leaf;
+ o->readable = true;
+ o->canbemultiple = false;
+ o->writestatic = false;
+ o->writeanimated = false;
+ o->needtempfile = true;
+#elif defined CODEC_PI1
+ o->version = "1.0.0";
+ o->name = "Degas PI1";
+ o->filter = "*.pi1 ";
+ o->config = "";
+ o->mime = "";
+ o->mimetype = "image/x-pi1";
+ o->pixmap = codec_pi1;
+ o->readable = true;
+ o->canbemultiple = false;
+ o->writestatic = false;
+ o->writeanimated = false;
+ o->needtempfile = true;
+#elif defined CODEC_PI3
+ o->version = "1.0.0";
+ o->name = "Degas PI3";
+ o->filter = "*.pi3 ";
+ o->config = "";
+ o->mime = "";
+ o->mimetype = "image/x-pi3";
+ o->pixmap = codec_pi3;
+ o->readable = true;
+ o->canbemultiple = false;
+ o->writestatic = false;
+ o->writeanimated = false;
+ o->needtempfile = true;
+#elif defined CODEC_XIM
+ o->version = "1.0.0";
+ o->name = "X IMage";
+ o->filter = "*.xim ";
+ o->config = "";
+ o->mime = "";
+ o->mimetype = "image/x-xim";
+ o->pixmap = codec_xim;
+ o->readable = true;
+ o->canbemultiple = false;
+ o->writestatic = false;
+ o->writeanimated = false;
+ o->needtempfile = true;
+#elif defined CODEC_UTAH
+ o->version = "1.0.0";
+ o->name = "UTAH RLE";
+ o->filter = "*.rle ";
+ o->config = "";
+ o->mime = "\x0052\x00CC";
+ o->mimetype = "image/x-utah";
+ o->pixmap = codec_utah;
+ o->readable = true;
+ o->canbemultiple = false;
+ o->writestatic = false;
+ o->writeanimated = false;
+ o->needtempfile = true;
+#elif defined CODEC_PICT
+ o->version = "1.0.0";
+ o->name = "Macintosh PICT";
+ o->filter = "*.pict ";
+ o->config = "";
+ o->mime = "";
+ o->mimetype = "image/x-pict";
+ o->pixmap = codec_pict;
+ o->readable = true;
+ o->canbemultiple = false;
+ o->writestatic = false;
+ o->writeanimated = false;
+ o->needtempfile = true;
+#elif defined CODEC_IFF
+ o->version = "1.0.0";
+ o->name = "Interchange File Format";
+ o->filter = "*.iff *.ilbm *.lbm ";
+ o->config = "";
+ o->mime = "";
+ o->mimetype = "image/x-iff";
+ o->pixmap = codec_iff;
+ o->readable = true;
+ o->canbemultiple = false;
+ o->writestatic = false;
+ o->writeanimated = false;
+ o->needtempfile = true;
+#elif defined CODEC_MAC
+ o->version = "1.0.0";
+ o->name = "Macintosh Paint";
+ o->filter = "*.mac ";
+ o->config = "";
+ o->mime = "";
+ o->mimetype = "image/x-mac";
+ o->pixmap = codec_mac;
+ o->readable = true;
+ o->canbemultiple = false;
+ o->writestatic = false;
+ o->writeanimated = false;
+ o->needtempfile = true;
+#elif defined CODEC_FIG
+ o->version = "0.1.0";
+ o->name = "XFIG";
+ o->filter = "*.fig ";
+ o->config = "";
+ o->mime = "";
+ o->mimetype = "image/x-xfig";
+ o->pixmap = codec_fig;
+ o->readable = true;
+ o->canbemultiple = false;
+ o->writestatic = false;
+ o->writeanimated = false;
+ o->needtempfile = true;
+#elif defined CODEC_TTF
+ o->version = "0.3.0";
+ o->name = "TrueType and Other Fonts";
+ o->filter = "*.ttf *.ttc *.pfa *.pfb *.otf ";
+ o->config = "";
+ o->mime = "";
+ o->mimetype = "application/x-font-ttf;application/x-font-ttc;application/x-font-otf;application/x-font-type1";
+ o->pixmap = codec_ttf;
+ o->readable = true;
+ o->canbemultiple = false;
+ o->writestatic = false;
+ o->writeanimated = false;
+ o->needtempfile = true;
+#elif defined CODEC_LJPEG
+ o->version = "0.1.0";
+ o->name = "Lossless JPEG";
+ o->filter = "*.ljpg *.ljpeg ";
+ o->config = "";
+ o->mime = "";
+ o->mimetype = "image/ljpeg";
+ o->pixmap = codec_ljpeg;
+ o->readable = true;
+ o->canbemultiple = false;
+ o->writestatic = false;
+ o->writeanimated = false;
+ o->needtempfile = true;
+#elif defined CODEC_EPS
+ o->version = "0.1.0";
+ o->name = "Encapsulated PostScript";
+ o->filter = "*.eps ";
+ o->config = "";
+ o->mime = "";
+ o->mimetype = "image/x-eps";
+ o->pixmap = codec_eps;
+ o->readable = true;
+ o->canbemultiple = false;
+ o->writestatic = false;
+ o->writeanimated = false;
+ o->needtempfile = true;
+#else
+ o->version = "0.6.4";
+ o->name = "Portable aNy Map";
+ o->filter = "*.pnm *.pgm *.pbm *.ppm ";
+ o->config = "";
+ o->mime = "P[123456]";
+ o->mimetype = "image/x-portable-bitmap;image/x-portable-greymap;image/x-portable-pixmap";
+ o->pixmap = codec_pnm;
+ o->readable = true;
+ o->canbemultiple = false;
+ o->writestatic = true;
+ o->writeanimated = false;
+ o->needtempfile = false;
+#endif
+}
+
+#if defined CODEC_CAMERA
+void fmt_codec::fill_default_settings()
+{
+ settings_value val;
+
+ // scale factor in percents
+ val.type = settings_value::v_bool;
+
+ val.bVal = true;
+ m_settings["half_size"] = val;
+ m_settings["automatic_white"] = val;
+ m_settings["camera_white"] = val;
+
+ val.bVal = false;
+ m_settings["dontstretch"] = val;
+ m_settings["camera_date"] = val;
+ m_settings["document_mode"] = val;
+ m_settings["interpolate_rggb"] = val;
+ m_settings["icc_cam"] = val;
+ m_settings["embedded_cm"] = val;
+
+ val.type = settings_value::v_int;
+ val.iVal = 0;
+ m_settings["highlights"] = val;
+ m_settings["different"] = val;
+ m_settings["flipping"] = val; // 0 means camera settings
+
+ val.iVal = 0; // 1,2,3 are accepted numbers. 1 means no interpolation
+ m_settings["quick"] = val;
+ val.iVal = -1; // don't use black pixel
+ m_settings["black"] = val;
+ val.iVal = 99; // values 100...1000 are accepted. 99 means no threshold
+ m_settings["threshold"] = val;
+ val.iVal = 1;
+ m_settings["brightness"] = val;
+
+ val.type = settings_value::v_string;
+ val.sVal = "";
+ m_settings["icc_file"] = val;
+}
+#elif defined CODEC_DJVU
+void fmt_codec::fill_default_settings()
+{
+ settings_value val;
+
+ // page number
+ val.type = settings_value::v_int;
+
+ val.iVal = 1;
+ m_settings["page"] = val;
+
+ val.iVal = 2;
+ m_settings["scaledown"] = val;
+}
+#elif defined CODEC_DXF
+void fmt_codec::fill_default_settings()
+{
+ settings_value val;
+
+ // page number
+ val.type = settings_value::v_int;
+
+ val.iVal = 0;
+ m_settings["width"] = val;
+ val.iVal = 0;
+ m_settings["height"] = val;
+}
+#elif defined CODEC_XCF
+void fmt_codec::fill_default_settings()
+{
+ settings_value val;
+
+ // background color
+ val.type = settings_value::v_string;
+ val.sVal = "#ffffff";
+ m_settings["background"] = val;
+
+ val.type = settings_value::v_bool;
+ val.bVal = false;
+ m_settings["autocrop"] = val;
+}
+#endif
+
+#ifdef CODEC_EPS
+
+/*
+ * Stolen from KImageIO EPS plugin from kdelibs-3.4.0, which is
+ * under GNU LGPL
+ */
+
+#define BUFLEN 200
+
+#define BBOX "%%BoundingBox:"
+#define BBOX_LEN strlen(BBOX)
+
+static bool seekToCodeStart(ifstreamK *io, size_t &ps_offset, size_t &ps_size)
+{
+ char buf[4]; // We at most need to read 4 bytes at a time
+ ps_offset = 0L;
+ ps_size = 0L;
+
+ if(!io->readK(buf, 2)) // Read first two bytes
+ return false;
+
+ if(buf[0]=='%' && buf[1]=='!') // Check %! magic
+ {
+ }
+ else if(buf[0] == char(0xc5) && buf[1] == char(0xd0)) // Check start of MS-DOS EPS magic
+ { // May be a MS-DOS EPS file
+ if(!io->readK(buf+2, 2)) // Read further bytes of MS-DOS EPS magic
+ return false;
+
+ if(buf[2] == char(0xd3) && buf[3] == char(0xc6)) // Check last bytes of MS-DOS EPS magic
+ {
+ if(!io->readK(buf, 4)) // Get offset of PostScript code in the MS-DOS EPS file.
+ return false;
+
+ ps_offset // Offset is in little endian
+ = ((unsigned char) buf[0])
+ + ((unsigned char) buf[1] << 8)
+ + ((unsigned char) buf[2] << 16)
+ + ((unsigned char) buf[3] << 24);
+
+ if (!io->readK(buf, 4)) // Get size of PostScript code in the MS-DOS EPS file.
+ return false;
+
+ ps_size // Size is in little endian
+ = ((unsigned char) buf[0])
+ + ((unsigned char) buf[1] << 8)
+ + ((unsigned char) buf[2] << 16)
+ + ((unsigned char) buf[3] << 24);
+
+ if(!io->seekg(ps_offset, ios::beg)) // Get offset of PostScript code in the MS-DOS EPS file.
+ return false;
+
+ if(!io->readK(buf, 2)) // Read first two bytes of what should be the Postscript code
+ return false;
+
+ if(buf[0] != '%' || buf[1] != '!') // Check %! magic
+ return false;
+ }
+ else
+ return false;
+ }
+ else
+ return false;
+
+ return true;
+}
+
+static bool bbox(ifstreamK *io, int *x1, int *y1, int *x2, int *y2)
+{
+ char buf[BUFLEN+1];
+
+ bool ret = false;
+
+ while(io->getline(buf, BUFLEN).good() && strlen(buf))
+ {
+ if(strncmp(buf, BBOX, BBOX_LEN) == 0)
+ {
+ // Some EPS files have non-integer values for the bbox
+ // We don't support that currently, but at least we parse it
+ float _x1, _y1, _x2, _y2;
+
+ if(sscanf(buf, "%*s %f %f %f %f", &_x1, &_y1, &_x2, &_y2) == 4)
+ {
+ *x1 = (int)_x1;
+ *y1 = (int)_y1;
+ *x2 = (int)_x2;
+ *y2 = (int)_y2;
+
+ ret = true;
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+#endif
+
+s32 fmt_codec::read_init(const std::string &file)
+{
+ fptr = 0;
+
+#if defined CODEC_CAMERA
+ std::vector<std::string> params;
+ int status;
+
+ bool half_size,
+ dontstretch,
+ camera_date,
+ automatic_white,
+ camera_white,
+ document_mode,
+ interpolate_rggb,
+ icc_cam,
+ embedded_cm;
+
+ int quick,
+ threshold,
+ black,
+ different,
+ highlights,
+ flipping,
+ brightness;
+
+ std::string icc_file;
+
+ fmt_settings::iterator it = m_settings.find("half_size");
+ half_size = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ?
+ true : (*it).second.bVal;
+
+ it = m_settings.find("icc_cam");
+ icc_cam = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ?
+ false : (*it).second.bVal;
+
+ it = m_settings.find("embedded_cm");
+ embedded_cm = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ?
+ false : (*it).second.bVal;
+
+ it = m_settings.find("dontstretch");
+ dontstretch = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ?
+ false : (*it).second.bVal;
+
+ it = m_settings.find("camera_date");
+ camera_date = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ?
+ false : (*it).second.bVal;
+
+ it = m_settings.find("automatic_white");
+ automatic_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ?
+ true : (*it).second.bVal;
+
+ it = m_settings.find("camera_white");
+ camera_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ?
+ true : (*it).second.bVal;
+
+ it = m_settings.find("document_mode");
+ document_mode = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ?
+ false : (*it).second.bVal;
+
+ it = m_settings.find("interpolate_rggb");
+ interpolate_rggb = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ?
+ false : (*it).second.bVal;
+
+ it = m_settings.find("quick");
+ quick = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ?
+ 1 : (*it).second.iVal;
+
+ if(quick < 0 || quick > 3)
+ quick = 0;
+
+ it = m_settings.find("highlights");
+ highlights = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ?
+ 0 : (*it).second.iVal;
+
+ if(highlights < 0 || highlights > 9)
+ highlights = 0; // revert to default value
+
+ it = m_settings.find("flipping");
+ flipping = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ?
+ 0 : (*it).second.iVal;
+
+ if(flipping != 0 && flipping != 1 && flipping != 3 && flipping != 5 && flipping != 6)
+ flipping = 0; // revert to default value
+
+ it = m_settings.find("black");
+ black = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ?
+ -1 : (*it).second.iVal;
+
+ if(black < -1 || black > 255)
+ black = -1;
+
+ it = m_settings.find("different");
+ different = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ?
+ 0 : (*it).second.iVal;
+
+ if(different < 0 || different > 99)
+ different = 0; // revert to default
+
+ it = m_settings.find("threshold");
+ threshold = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ?
+ 100 : (*it).second.iVal;
+
+ if(threshold < 99 || threshold > 1000)
+ threshold = 99; // revert to default
+
+ it = m_settings.find("brightness");
+ brightness = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ?
+ 1 : (*it).second.iVal;
+
+ if(brightness < 1 || brightness > 255)
+ brightness = 1;
+
+ it = m_settings.find("icc_file");
+ icc_file = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ?
+ "" : (*it).second.sVal;
+
+ if(embedded_cm)
+ params.push_back("+M");
+ else
+ params.push_back("-M");
+
+ if(half_size) params.push_back("-h");
+ if(dontstretch) params.push_back("-j");
+ if(camera_date) params.push_back("-z");
+ if(automatic_white) params.push_back("-a");
+ if(camera_white) params.push_back("-w");
+ if(document_mode) params.push_back("-d");
+ if(interpolate_rggb) params.push_back("-f");
+
+ char ss[32];
+
+ if(quick)
+ {
+ if(quick == 1)
+ quick = 0;
+
+ sprintf(ss, "%d", quick);
+ params.push_back("-q");
+ params.push_back(ss);
+ }
+
+ if(threshold != 99)
+ {
+ sprintf(ss, "%d", threshold);
+ params.push_back("-n");
+ params.push_back(ss);
+ }
+
+ if(black >= 0)
+ {
+ sprintf(ss, "%d", black);
+ params.push_back("-k");
+ params.push_back(ss);
+ }
+
+ sprintf(ss, "%d", different);
+ params.push_back("-s");
+ params.push_back(ss);
+
+ sprintf(ss, "%d", brightness);
+ params.push_back("-b");
+ params.push_back(ss);
+
+ sprintf(ss, "%d", highlights);
+ params.push_back("-H");
+ params.push_back(ss);
+
+ if(flipping)
+ {
+ if(flipping == 1)
+ flipping = 0; // 0, 3, 5, 6 are accepted
+
+ sprintf(ss, "%d", flipping);
+ params.push_back("-t");
+ params.push_back(ss);
+ }
+
+#ifndef NO_LCMS
+ if(icc_cam)
+ {
+ params.push_back("-p");
+ params.push_back("embed");
+ }
+ else if(icc_file.length())
+ {
+ params.push_back("-p");
+ params.push_back(icc_file);
+ }
+#endif
+
+ const s32 argc = 9 + params.size();
+
+ const char *argv[argc];
+ argv[0] = KLDCRAW_S;
+
+ for(int i = 1;i < argc-8;i++)
+ argv[i] = params[i-1].c_str();
+
+ argv[argc-8] = "-c"; // write to stdout
+ argv[argc-7] = "--input";
+ argv[argc-6] = file.c_str();
+ argv[argc-5] = "--binary";
+ argv[argc-4] = KLDCRAW;
+ argv[argc-3] = "--output";
+ argv[argc-2] = tmp.c_str();
+ argv[argc-1] = (char *)0;
+
+ pid_t pid = fork();
+
+ if(!pid)
+ {
+ execvp(argv[0], (char *const *)argv);
+ exit(1);
+ }
+ else if(pid == -1)
+ return SQE_R_BADFILE;
+
+ ::waitpid(pid, &status, 0);
+
+ if(WIFEXITED(status))
+ if(WEXITSTATUS(status))
+ return SQE_R_BADFILE;
+ else;
+ else
+ return SQE_R_BADFILE;
+
+ fptr = fopen(tmp.c_str(), "rb");
+
+#elif defined CODEC_DJVU
+
+ fmt_settings::iterator it = m_settings.find("scaledown");
+
+ // get aspect
+ s32 aspect = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ?
+ 1 : (*it).second.iVal;
+
+ // correct
+ if(aspect < 1 || aspect > 12)
+ aspect = 2;
+
+ it = m_settings.find("page");
+
+ // get page number
+ s32 ipage = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ?
+ 1 : (*it).second.iVal;
+
+ // correct
+ if(ipage < 0 || ipage > 1000)
+ ipage = 1;
+
+ int status;
+
+ s8 subsample[20];
+ s8 pagesp[20];
+
+ snprintf(subsample, 20, "-subsample=%d", aspect);
+ snprintf(pagesp, 20, "-page=%d", ipage);
+
+ pid_t pid = fork();
+
+ if(!pid)
+ {
+ execlp(DJVU, DJVU, "-format=ppm", subsample, pagesp, file.c_str(), tmp.c_str(), (char *)0);
+ exit(1);
+ }
+ else if(pid == -1)
+ return SQE_R_BADFILE;
+
+ ::waitpid(pid, &status, 0);
+
+ if(WIFEXITED(status))
+ if(WEXITSTATUS(status))
+ return SQE_R_BADFILE;
+ else;
+ else
+ return SQE_R_BADFILE;
+
+ fptr = fopen(tmp.c_str(), "rb");
+
+#elif defined CODEC_DXF
+
+ std::string tmmp = tmp + ".ppm";
+ fmt_settings::iterator it = m_settings.find("width");
+
+ // get aspect
+ s32 width = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ?
+ 0 : (*it).second.iVal;
+
+ // correct
+ if(width < 0 || width > 10000)
+ width = 0;
+
+ it = m_settings.find("height");
+
+ // get page number
+ s32 height = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ?
+ 0 : (*it).second.iVal;
+
+ // correct
+ if(height < 0 || height > 10000)
+ height = 0;
+
+ s32 status;
+
+ s8 swidth[20], sheight[20];
+
+ const int argc = 8;
+ const char *argv[argc];
+ const char *x = "-x", *y = "-y";
+
+ int i = 3;
+ argv[0] = VEC2WEB;
+ argv[1] = file.c_str();
+ argv[2] = tmmp.c_str();
+
+ if(width)
+ {
+ snprintf(swidth, 20, "%d", width);
+ argv[i++] = x;
+ argv[i++] = swidth;
+ }
+
+ if(height)
+ {
+ snprintf(sheight, 20, "%d", height);
+ argv[i++] = y;
+ argv[i++] = sheight;
+ }
+
+ argv[i] = (char *)0;
+
+ pid_t pid = fork();
+
+ if(!pid)
+ {
+ execvp(VEC2WEB, (char* const*)argv);
+ exit(1);
+ }
+ else if(pid == -1)
+ return SQE_R_BADFILE;
+
+ ::waitpid(pid, &status, 0);
+
+ if(WIFEXITED(status))
+ if(WEXITSTATUS(status))
+ return SQE_R_BADFILE;
+ else;
+ else
+ return SQE_R_BADFILE;
+
+ fptr = fopen(tmmp.c_str(), "rb");
+
+#elif defined CODEC_XCF
+
+ const s32 argc = 9;
+ int status;
+
+ fmt_settings::iterator it = m_settings.find("background");
+
+ // background for transparent images
+ std::string bkgr = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ?
+ "#ffffff" : (*it).second.sVal;
+
+ it = m_settings.find("autocrop");
+
+ // autocrop ?
+ bool autocrop = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ?
+ false : (*it).second.bVal;
+
+ const char *argv[argc];
+ argv[0] = KLXCF2PNM;
+
+ std::string bg = "-b";
+ bg += bkgr;
+ argv[1] = bg.c_str();
+
+ int i = 2;
+
+ if(autocrop)
+ {
+ argv[i++] = "-C";
+ }
+
+ argv[i++] = "-T";
+ argv[i++] = "-c";
+ argv[i++] = "-o";
+ argv[i++] = tmp.c_str();
+ argv[i++] = file.c_str();
+ argv[i++] = (char *)0;
+
+ pid_t pid = fork();
+
+ if(!pid)
+ {
+ execvp(KLXCF2PNM, (char *const *)argv);
+ exit(1);
+ }
+ else if(pid == -1)
+ return SQE_R_BADFILE;
+
+ ::waitpid(pid, &status, 0); // TODO check for errors
+
+ if(WIFEXITED(status))
+ if(WEXITSTATUS(status))
+ return SQE_R_BADFILE;
+ else;
+ else
+ return SQE_R_BADFILE;
+
+ fptr = fopen(tmp.c_str(), "rb");
+
+#elif defined CODEC_NETPBM
+
+ int status;
+
+ pid_t pid = fork();
+
+ if(!pid)
+ {
+ execlp(NETPBM_S, NETPBM_S, file.c_str(), tmp.c_str(), (char *)0);
+ exit(1);
+ }
+ else if(pid == -1)
+ return SQE_R_BADFILE;
+
+ ::waitpid(pid, &status, 0);
+
+ if(WIFEXITED(status))
+ if(WEXITSTATUS(status))
+ return SQE_R_BADFILE;
+ else;
+ else
+ return SQE_R_BADFILE;
+
+ fptr = fopen(tmp.c_str(), "rb");
+
+#elif defined CODEC_LJPEG
+
+ int status;
+
+ pid_t pid = fork();
+
+ if(!pid)
+ {
+ execlp(LJPEG2PPM_S, LJPEG2PPM_S, "--input", file.c_str(), "--binary", LJPEG2PPM, "--output", tmp.c_str(), (char *)0);
+ exit(1);
+ }
+ else if(pid == -1)
+ return SQE_R_BADFILE;
+
+ ::waitpid(pid, &status, 0);
+
+ if(WIFEXITED(status))
+ if(WEXITSTATUS(status))
+ return SQE_R_BADFILE;
+ else;
+ else
+ return SQE_R_BADFILE;
+
+ fptr = fopen(tmp.c_str(), "rb");
+
+#elif defined CODEC_FIG
+
+ int status;
+
+ pid_t pid = fork();
+
+ if(!pid)
+ {
+ execlp(XFIG_S, XFIG_S, file.c_str(), tmp.c_str(), (char *)0);
+ exit(1);
+ }
+ else if(pid == -1)
+ return SQE_R_BADFILE;
+
+ ::waitpid(pid, &status, 0);
+
+ if(WIFEXITED(status))
+ if(WEXITSTATUS(status))
+ return SQE_R_BADFILE;
+ else;
+ else
+ return SQE_R_BADFILE;
+
+ fptr = fopen(tmp.c_str(), "rb");
+
+#elif defined CODEC_TTF
+
+ int status;
+
+ pid_t pid = fork();
+
+ if(!pid)
+ {
+ execlp(TTF2PNM, TTF2PNM, file.c_str(), tmp.c_str(), (char *)0);
+ exit(1);
+ }
+ else if(pid == -1)
+ return SQE_R_BADFILE;
+
+ ::waitpid(pid, &status, 0);
+
+ if(WIFEXITED(status))
+ if(WEXITSTATUS(status))
+ return SQE_R_BADFILE;
+ else;
+ else
+ return SQE_R_BADFILE;
+
+ fptr = fopen(tmp.c_str(), "rb");
+
+#elif defined CODEC_EPS
+
+ /*
+ * EPS code was grabbed from KImageIO plugin for kdelibs-3.4.0. It is under LGPL.
+ */
+
+ FILE * ghostfd;
+ int x1, y1, x2, y2;
+
+ std::string cmdBuf;
+
+ size_t ps_offset, ps_size;
+
+ ifstreamK io;
+ io.open(file.c_str(), ios::in);
+
+ if(!io.good())
+ return SQE_R_NOFILE;
+
+ // find start of PostScript code
+ if (!seekToCodeStart(&io, ps_offset, ps_size))
+ return SQE_R_BADFILE;
+
+ // find bounding box
+ if(!bbox(&io, &x1, &y1, &x2, &y2))
+ return SQE_R_BADFILE;
+
+ x2 -= x1;
+ y2 -= y1;
+
+ double xScale = 1.0;
+ double yScale = 1.0;
+ bool needsScaling = false;
+ int wantedWidth = x2;
+ int wantedHeight = y2;
+
+ std::stringstream str(cmdBuf);
+
+ str << EPS2PPM << " -sOutputFile=";
+ str << tmp;
+ str << " -q -g";
+ str << wantedWidth << "x" << wantedHeight;
+ str << " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c "
+ "0 0 moveto "
+ "1000 0 lineto "
+ "1000 1000 lineto "
+ "0 1000 lineto "
+ "1 1 254 255 div setrgbcolor fill "
+ "0 0 0 setrgbcolor - -c showpage quit";
+
+ ghostfd = popen(str.str().c_str(), "w");
+
+ if(ghostfd == 0)
+ return SQE_R_BADFILE;
+
+ fprintf(ghostfd, "\n%d %d translate\n", int(-floorf(x1*xScale)), int(-floorf(y1*yScale)));
+
+ if(needsScaling)
+ fprintf(ghostfd, "%g %g scale\n", xScale, yScale);
+
+ io.seekg(0, ios::beg);
+
+ char bbuf[4096];
+
+ if(ps_offset > 0) // We have an offset
+ io.seekg(ps_offset, ios::beg);
+
+ std::string buffer;
+
+ while(!io.eof())
+ {
+ io.read(bbuf, sizeof(bbuf));
+ buffer.append(bbuf, io.gcount());
+ }
+
+ // If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size
+ if (ps_size <= 0 || ps_size > buffer.size())
+ ps_size = buffer.size();
+
+ fwrite(buffer.c_str(), sizeof(char), ps_size, ghostfd);
+
+ pclose(ghostfd);
+
+ fptr = fopen(tmp.c_str(), "rb");
+
+#else
+
+ fptr = fopen(file.c_str(), "rb");
+
+#endif
+
+ if(!fptr)
+ return SQE_R_NOFILE;
+
+ currentImage = -1;
+
+ finfo.animated = false;
+
+ return SQE_OK;
+}
+
+s32 fmt_codec::read_next()
+{
+ currentImage++;
+
+ if(currentImage)
+ return SQE_NOTOK;
+
+ fmt_image image;
+
+ s8 str[256];
+ s32 w, h;
+ u32 maxcolor;
+
+ if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE;
+
+ pnm = str[1] - 48;
+
+ if(pnm < 1 || pnm > 6)
+ return SQE_R_BADFILE;
+
+ while(true)
+ {
+ if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE;
+
+ if(str[0] != '#')
+ break;
+ }
+
+ sscanf(str, "%d%d", &w, &h);
+
+ image.w = w;
+ image.h = h;
+
+ switch(pnm)
+ {
+ case 1:
+ case 4:
+ image.bpp = 1;
+ break;
+
+ case 2:
+ case 5:
+ image.bpp = 8;
+ break;
+
+ case 3:
+ case 6:
+ image.bpp = 8;
+ break;
+ }
+
+ if(pnm != 4 && pnm != 1)
+ {
+ fscanf(fptr, "%d", &maxcolor);
+
+ if(sq_ferror(fptr)) return SQE_R_BADFILE;
+
+ if((pnm == 5 || pnm == 6) && maxcolor > 255)
+ return SQE_R_BADFILE;
+
+ if(pnm == 2 || pnm == 3)
+ {
+ if(!skip_flood(fptr))
+ return SQE_R_BADFILE;
+ }
+ else
+ {
+ u8 dummy;
+ if(!sq_fgetc(fptr, &dummy)) return SQE_R_BADFILE;
+ }
+
+ if(maxcolor <= 9)
+ strcpy(format, "%1d");
+ else if(maxcolor >= 9 && maxcolor <= 99)
+ strcpy(format, "%2d");
+ else if(maxcolor > 99 && maxcolor <= 999)
+ strcpy(format, "%3d");
+ else if(maxcolor > 999 && maxcolor <= 9999)
+ strcpy(format, "%4d");
+
+ koeff = 255.0 / maxcolor;
+ }
+ else if(pnm == 1)
+ {
+ strcpy(format, "%1d");
+ koeff = 1.0;
+ }
+
+ image.compression = "-";
+ image.colorspace = ((pnm == 1 || pnm == 4) ? "Monochrome":"Color indexed");
+
+ finfo.image.push_back(image);
+
+ return SQE_OK;
+}
+
+s32 fmt_codec::read_scanline(RGBA *scan)
+{
+ RGB rgb;
+ u8 bt;
+ s32 i, a;
+ fmt_image *im = image(currentImage);
+ fmt_utils::fillAlpha(scan, im->w);
+
+ switch(pnm)
+ {
+ case 1:
+ {
+ for(i = 0;i < im->w;i++)
+ {
+ fscanf(fptr, format, &a);
+ if(sq_ferror(fptr)) return SQE_R_BADFILE;
+
+ a = (s32)(a * koeff);
+
+ memcpy(scan+i, palmono+a, sizeof(RGB));
+ }
+
+ if(!skip_flood(fptr))
+ return SQE_R_BADFILE;
+ }
+ break;
+
+ case 2:
+ {
+ for(i = 0;i < im->w;i++)
+ {
+ fscanf(fptr, format, &a);
+ if(sq_ferror(fptr)) return SQE_R_BADFILE;
+
+ a = (s32)(a * koeff);
+
+ memset(scan+i, a, sizeof(RGB));
+ }
+
+ if(!skip_flood(fptr))
+ return SQE_R_BADFILE;
+ }
+ break;
+
+ case 3:
+ for(i = 0;i < im->w;i++)
+ {
+ fscanf(fptr, format, &a); rgb.r = a;
+ fscanf(fptr, format, &a); rgb.g = a;
+ fscanf(fptr, format, &a); rgb.b = a;
+ if(sq_ferror(fptr)) return SQE_R_BADFILE;
+
+ memcpy(scan+i, &rgb, sizeof(RGB));
+ }
+
+ if(!skip_flood(fptr))
+ return SQE_R_BADFILE;
+ break;
+
+ case 6:
+ for(i = 0;i < im->w;i++)
+ {
+ if(!sq_fread(&rgb, sizeof(RGB), 1, fptr)) return SQE_R_BADFILE;
+
+ memcpy(scan+i, &rgb, sizeof(RGB));
+ }
+ break;
+
+ case 5:
+ {
+ for(i = 0;i < im->w;i++)
+ {
+ if(!sq_fread(&bt, 1, 1, fptr)) return SQE_R_BADFILE;
+
+ memset(scan+i, int(bt*koeff), sizeof(RGB));
+ }
+ }
+ break;
+
+ case 4:
+ {
+ s32 index;//, remain = im->w % 8;
+
+ for(i = 0;;)
+ {
+ if(!sq_fread(&bt,1,1,fptr)) return SQE_R_BADFILE;
+
+ index = (bt&128)?1:0;
+ memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break;
+ index = (bt&64)?1:0;
+ memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break;
+ index = (bt&32)?1:0;
+ memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break;
+ index = (bt&16)?1:0;
+ memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break;
+ index = (bt&8)?1:0;
+ memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break;
+ index = (bt&4)?1:0;
+ memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break;
+ index = (bt&2)?1:0;
+ memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break;
+ index = (bt&1);
+ memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break;
+ }
+ }
+ break;
+ }
+
+ return SQE_OK;
+}
+
+s32 fmt_codec::read_next_pass()
+{
+ return SQE_OK;
+}
+
+void fmt_codec::read_close()
+{
+ if(fptr)
+ fclose(fptr);
+
+ finfo.meta.clear();
+ finfo.image.clear();
+}
+
+bool skip_flood(FILE *f)
+{
+ s32 pos;
+ u8 b;
+
+ while(true)
+ {
+ pos = ftell(f);
+ if(!sq_fread(&b, 1, 1, f)) return false;
+
+ if(!isspace(b))
+ {
+ if(b == '#')
+ {
+ while(true)
+ {
+ if(!sq_fgetc(f, &b)) return false;
+
+ if(b == '\n')
+ break;
+ }
+ }
+
+ break;
+ }
+ }
+
+ fsetpos(f, (fpos_t*)&pos);
+
+ return true;
+}
+
+#ifdef CODEC_PNM
+
+void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt)
+{
+ opt->interlaced = false;
+ opt->compression_scheme = CompressionNo;
+ opt->compression_min = 0;
+ opt->compression_max = 0;
+ opt->compression_def = 0;
+ opt->passes = 1;
+ opt->needflip = false;
+ opt->palette_flags = 0 | fmt_image::pure32;
+}
+
+s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt)
+{
+ if(!image.w || !image.h || file.empty())
+ return SQE_W_WRONGPARAMS;
+
+ writeimage = image;
+ writeopt = opt;
+
+ fws.open(file.c_str(), ios::binary | ios::out);
+
+ if(!fws.good())
+ return SQE_W_NOFILE;
+
+ return SQE_OK;
+}
+
+s32 fmt_codec::write_next()
+{
+ fws << "P6" << endl << writeimage.w << " " << writeimage.h << endl << 255 << endl;
+
+ return fws.good() ? SQE_OK : SQE_W_ERROR;
+}
+
+s32 fmt_codec::write_next_pass()
+{
+ return SQE_OK;
+}
+
+s32 fmt_codec::write_scanline(RGBA *scan)
+{
+ for(s32 i = 0;i < writeimage.w;i++)
+ {
+ if(!fws.writeK(scan+i, sizeof(RGB)))
+ return SQE_W_ERROR;
+ }
+
+ return SQE_OK;
+}
+
+void fmt_codec::write_close()
+{
+ fws.close();
+}
+
+std::string fmt_codec::extension(const s32 /*bpp*/)
+{
+ return std::string("pnm");
+}
+
+#endif // CODEC_PNM
+
+#include "fmt_codec_cd_func.h"
diff --git a/kernel/kls_ttf/fmt_codec_pnm_defs.h b/kernel/kls_ttf/fmt_codec_pnm_defs.h
new file mode 100644
index 0000000..bc61ec4
--- /dev/null
+++ b/kernel/kls_ttf/fmt_codec_pnm_defs.h
@@ -0,0 +1,64 @@
+/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net)
+
+ Copyright (c) 2004 Dmitry Baryshev <[email protected]>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation;
+ either version 2 of the License, or (at your option) any later
+ version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ as32 with this library; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KSQUIRREL_READ_IMAGE_pnm
+#define KSQUIRREL_READ_IMAGE_pnm
+
+bool skip_flood(FILE *);
+
+bool sq_fgetc(FILE *f, u8 *c)
+{
+ s32 e = fgetc(f);
+
+ if(ferror(f) || feof(f))
+ return false;
+
+ *c = e;
+
+ return true;
+}
+
+bool sq_fgets(s8 *s, s32 size, FILE *stream)
+{
+ s8 *r = (s8*)fgets((char*)s, size, stream);
+
+ if(ferror(stream) || feof(stream) || !r)
+ return false;
+
+ return true;
+}
+
+bool sq_ferror(FILE *f)
+{
+ return (ferror(f) || feof(f));
+}
+
+bool sq_fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
+{
+ size_t r = fread(ptr, size, nmemb, stream);
+
+ if(ferror(stream) || feof(stream) || r != nmemb)
+ return false;
+
+ return true;
+}
+
+#endif
diff --git a/kernel/kls_ttf/ftcommon.cpp b/kernel/kls_ttf/ftcommon.cpp
new file mode 100644
index 0000000..d162452
--- /dev/null
+++ b/kernel/kls_ttf/ftcommon.cpp
@@ -0,0 +1,1333 @@
+/****************************************************************************/
+/* */
+/* The FreeType project -- a free and portable quality TrueType renderer. */
+/* */
+/* Copyright 2005, 2006 by */
+/* D. Turner, R.Wilhelm, and W. Lemberg */
+/* */
+/* */
+/* ftcommon.c - common routines for the FreeType demo programs. */
+/* */
+/****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#include FT_CACHE_H
+#include FT_CACHE_MANAGER_H
+
+#include FT_BITMAP_H
+
+#include "ftcommon.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+ FT_Error error;
+
+ /* PanicZ */
+ void
+ PanicZ( const char * )
+ {
+ /*fprintf( stderr, "%s\n error = 0x%04x\n", message, error );*/
+ exit( 1 );
+ }
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** DISPLAY-SPECIFIC DEFINITIONS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#define DIM_X 600
+#define DIM_Y 450
+
+ grBitmap*
+ FTDemo_Display_New(void)
+ {
+ grBitmap *bit = (grBitmap *)malloc(sizeof(grBitmap));
+
+ if(!bit)
+ return NULL;
+
+ bit->mode = gr_pixel_mode_rgb24;
+ bit->width = DIM_X;
+ bit->rows = DIM_Y;
+ bit->grays = 256;
+
+ grNewBitmap(bit->mode, bit->grays, bit->width, bit->rows, bit);
+
+ grSetGlyphGamma(1.0);
+
+ return bit;
+ }
+
+
+ void
+ FTDemo_Display_Done(grBitmap *bit)
+ {
+ grDoneBitmap(bit);
+ }
+
+ void
+ FTDemo_Display_Clear(grBitmap *bit)
+ {
+ int image_size = bit->width * bit->rows * 3;
+
+ memset(bit->buffer, 255, image_size);
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** FREETYPE-SPECIFIC DEFINITIONS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+#define FLOOR( x ) ( (x) & -64 )
+#define CEIL( x ) ( ( (x) + 63 ) & -64 )
+#define ROUND( x ) ( ( (x) + 32 ) & -64 )
+#define TRUNC( x ) ( (x) >> 6 )
+
+
+
+ static
+ const char* file_suffixes[] =
+ {
+ ".ttf",
+ ".ttc",
+ ".otf",
+ ".pfa",
+ ".pfb",
+ 0
+ };
+
+
+ /*************************************************************************/
+ /* */
+ /* The face requester is a function provided by the client application */
+ /* to the cache manager, whose role is to translate an `abstract' face */
+ /* ID into a real FT_Face object. */
+ /* */
+ /* In this program, the face IDs are simply pointers to TFont objects. */
+ /* */
+ static FT_Error
+ my_face_requester( FTC_FaceID face_id,
+ FT_Library lib,
+ FT_Pointer request_data,
+ FT_Face* aface )
+ {
+ PFont font = (PFont)face_id;
+
+ FT_UNUSED( request_data );
+
+ if ( font->file_address != NULL )
+ error = FT_New_Memory_Face( lib, (FT_Byte*)font->file_address, font->file_size,
+ font->face_index, aface );
+ else
+ error = FT_New_Face( lib,
+ font->filepathname,
+ font->face_index,
+ aface );
+ if ( !error )
+ {
+ const char* suffix_rchr;
+ char orig[4];
+
+ suffix_rchr = strrchr( font->filepathname, '.' );
+ char* suffix = new char[strlen(font->filepathname) + 1];
+ strcpy(suffix, suffix_rchr);
+
+ if ( suffix && ( strcasecmp( suffix, ".pfa" ) == 0 ||
+ strcasecmp( suffix, ".pfb" ) == 0 ) )
+ {
+ suffix++;
+
+ memcpy( orig, suffix, 4 );
+ memcpy( suffix, "afm", 4 );
+ FT_Attach_File( *aface, font->filepathname );
+
+ memcpy( suffix, "pfm", 4 );
+ FT_Attach_File( *aface, font->filepathname );
+ memcpy( suffix, orig, 4 );
+ }
+
+ if ( (*aface)->charmaps )
+ (*aface)->charmap = (*aface)->charmaps[font->cmap_index];
+ }
+
+ return error;
+ }
+
+
+ FTDemo_Handle*
+ FTDemo_New( FT_Encoding encoding )
+ {
+ FTDemo_Handle* handle;
+
+
+ handle = (FTDemo_Handle *)malloc( sizeof( FTDemo_Handle ) );
+ if ( !handle )
+ return NULL;
+
+ memset( handle, 0, sizeof( FTDemo_Handle ) );
+
+ error = FT_Init_FreeType( &handle->library );
+ if ( error )
+ PanicZ( "could not initialize FreeType" );
+
+ error = FTC_Manager_New( handle->library, 0, 0, 0,
+ my_face_requester, 0, &handle->cache_manager );
+ if ( error )
+ PanicZ( "could not initialize cache manager" );
+
+ error = FTC_SBitCache_New( handle->cache_manager, &handle->sbits_cache );
+ if ( error )
+ PanicZ( "could not initialize small bitmaps cache" );
+
+ error = FTC_ImageCache_New( handle->cache_manager, &handle->image_cache );
+ if ( error )
+ PanicZ( "could not initialize glyph image cache" );
+
+ error = FTC_CMapCache_New( handle->cache_manager, &handle->cmap_cache );
+ if ( error )
+ PanicZ( "could not initialize charmap cache" );
+
+
+ FT_Bitmap_New( &handle->bitmap );
+
+ handle->encoding = encoding;
+
+ handle->hinted = 1;
+ handle->antialias = 1;
+ handle->use_sbits = 1;
+ handle->low_prec = 0;
+ handle->autohint = 0;
+ handle->lcd_mode = 0;
+
+ handle->use_sbits_cache = 1;
+
+ /* string_init */
+ memset( handle->string, 0, sizeof( TGlyph ) * MAX_GLYPHS );
+ handle->string_length = 0;
+ handle->string_reload = 1;
+
+ return handle;
+ }
+
+
+ void
+ FTDemo_Done( FTDemo_Handle* handle )
+ {
+ int i;
+
+
+ for ( i = 0; i < handle->max_fonts; i++ )
+ {
+ if ( handle->fonts[i] )
+ {
+ if ( handle->fonts[i]->filepathname )
+ free( (void*)handle->fonts[i]->filepathname );
+ free( handle->fonts[i] );
+ }
+ }
+ free( handle->fonts );
+
+ /* string_done */
+ for ( i = 0; i < MAX_GLYPHS; i++ )
+ {
+ PGlyph glyph = handle->string + i;
+
+
+ if ( glyph->image )
+ FT_Done_Glyph( glyph->image );
+ }
+
+ FT_Bitmap_Done( handle->library, &handle->bitmap );
+ FTC_Manager_Done( handle->cache_manager );
+ FT_Done_FreeType( handle->library );
+
+ free( handle );
+ }
+
+
+ FT_Error
+ FTDemo_Install_Font( FTDemo_Handle* handle,
+ const char* filepath )
+ {
+ static char filename[1024 + 5];
+ int i, len, num_faces;
+ FT_Face face;
+
+
+ len = strlen( filepath );
+ if ( len > 1024 )
+ len = 1024;
+
+ strncpy( filename, filepath, len );
+ filename[len] = 0;
+
+ error = FT_New_Face( handle->library, filename, 0, &face );
+
+#ifndef macintosh
+ /* could not open the file directly; we will now try various */
+ /* suffixes like `.ttf' or `.pfb' */
+ if ( error )
+ {
+ const char** suffix;
+ char* p;
+ int found = 0;
+
+ suffix = file_suffixes;
+ p = filename + len - 1;
+
+ while ( p >= filename && *p != '\\' && *p != '/' )
+ {
+ if ( *p == '.' )
+ break;
+
+ p--;
+ }
+
+ /* no suffix found */
+ if ( p < filename || *p != '.' )
+ p = filename + len;
+
+ for ( suffix = file_suffixes; suffix[0]; suffix++ )
+ {
+ /* try with current suffix */
+ strcpy( p, suffix[0] );
+
+ error = FT_New_Face( handle->library, filename, 0, &face );
+ if ( !error )
+ {
+ found = 1;
+
+ break;
+ }
+ }
+
+ /* really couldn't open this file */
+ if ( !found )
+ return error;
+ }
+#endif /* !macintosh */
+
+ /* allocate new font object */
+ num_faces = face->num_faces;
+ for ( i = 0; i < num_faces; i++ )
+ {
+ PFont font;
+
+
+ if ( i > 0 )
+ {
+ error = FT_New_Face( handle->library, filename, i, &face );
+ if ( error )
+ continue;
+ }
+
+ if ( handle->encoding != FT_ENCODING_NONE )
+ {
+ error = FT_Select_Charmap( face, handle->encoding );
+ if ( error )
+ {
+ FT_Done_Face( face );
+ return error;
+ }
+ }
+
+ font = (PFont)malloc( sizeof ( *font ) );
+
+ font->filepathname = (char*)malloc( strlen( filename ) + 1 );
+ strcpy( (char*)font->filepathname, filename );
+
+ font->face_index = i;
+ font->cmap_index = face->charmap ? FT_Get_Charmap_Index( face->charmap )
+ : 0;
+
+ if ( handle->preload )
+ {
+ FILE* file = fopen( filename, "rb" );
+ size_t file_size;
+
+ if ( file == NULL ) /* shouldn't happen */
+ {
+ free( font );
+ return FT_Err_Invalid_Argument;
+ }
+
+ fseek( file, 0, SEEK_END );
+ file_size = ftell( file );
+ fseek( file, 0, SEEK_SET );
+
+ font->file_address = malloc( file_size );
+ fread( font->file_address, 1, file_size, file );
+
+ font->file_size = file_size;
+
+ fclose( file );
+ }
+ else
+ {
+ font->file_address = NULL;
+ font->file_size = 0;
+ }
+
+ switch ( handle->encoding )
+ {
+ case FT_ENCODING_NONE:
+ font->num_indices = face->num_glyphs;
+ break;
+
+ case FT_ENCODING_UNICODE:
+ font->num_indices = 0x110000L;
+ break;
+
+ case FT_ENCODING_MS_SYMBOL:
+ case FT_ENCODING_ADOBE_LATIN_1:
+ case FT_ENCODING_ADOBE_STANDARD:
+ case FT_ENCODING_ADOBE_EXPERT:
+ case FT_ENCODING_ADOBE_CUSTOM:
+ case FT_ENCODING_APPLE_ROMAN:
+ font->num_indices = 0x100L;
+ break;
+
+ default:
+ font->num_indices = 0x10000L;
+ }
+
+ FT_Done_Face( face );
+ face = NULL;
+
+ if ( handle->max_fonts == 0 )
+ {
+ handle->max_fonts = 16;
+ handle->fonts = (PFont*)calloc( handle->max_fonts,
+ sizeof ( PFont ) );
+ }
+ else if ( handle->num_fonts >= handle->max_fonts )
+ {
+ handle->max_fonts *= 2;
+ handle->fonts = (PFont*)realloc( handle->fonts,
+ handle->max_fonts *
+ sizeof ( PFont ) );
+
+ memset( &handle->fonts[handle->num_fonts], 0,
+ ( handle->max_fonts - handle->num_fonts ) *
+ sizeof ( PFont ) );
+ }
+
+ handle->fonts[handle->num_fonts++] = font;
+ }
+
+ return FT_Err_Ok;
+ }
+
+
+ void
+ FTDemo_Set_Current_Font( FTDemo_Handle* handle,
+ PFont font )
+ {
+ handle->current_font = font;
+ handle->image_type.face_id = (FTC_FaceID)font;
+
+ handle->string_reload = 1;
+ }
+
+
+ void
+ FTDemo_Set_Current_Size( FTDemo_Handle* handle,
+ int pixel_size )
+ {
+ if ( pixel_size > 0xFFFF )
+ pixel_size = 0xFFFF;
+
+ handle->image_type.width = (FT_UShort)pixel_size;
+ handle->image_type.height = (FT_UShort)pixel_size;
+
+ handle->string_reload = 1;
+ }
+
+ void
+ FTDemo_Set_Preload( FTDemo_Handle* handle,
+ int preload )
+ {
+ handle->preload = !!preload;
+ }
+
+ void
+ FTDemo_Set_Current_Pointsize( FTDemo_Handle* handle,
+ int point_size,
+ int res )
+ {
+ FTDemo_Set_Current_Size( handle, ( point_size * res + 36 ) / 72 );
+ }
+
+
+ void
+ FTDemo_Update_Current_Flags( FTDemo_Handle* handle )
+ {
+ FT_UInt32 flags, target;
+
+ flags = FT_LOAD_DEFAULT; /* really 0 */
+
+ flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
+
+ if ( handle->autohint )
+ flags |= FT_LOAD_FORCE_AUTOHINT;
+
+ if ( !handle->use_sbits )
+ flags |= FT_LOAD_NO_BITMAP;
+
+ if ( handle->hinted )
+ {
+ target = 0;
+
+ if ( handle->antialias )
+ {
+ switch ( handle->lcd_mode )
+ {
+ case LCD_MODE_LIGHT:
+ target = FT_LOAD_TARGET_LIGHT;
+ break;
+
+ case LCD_MODE_RGB:
+ case LCD_MODE_BGR:
+ target = FT_LOAD_TARGET_LCD;
+ break;
+
+ case LCD_MODE_VRGB:
+ case LCD_MODE_VBGR:
+ target = FT_LOAD_TARGET_LCD_V;
+ break;
+
+ default:
+ target = FT_LOAD_TARGET_NORMAL;
+ }
+ }
+ else
+ target = FT_LOAD_TARGET_MONO;
+
+ flags |= target;
+ }
+ else
+ flags |= FT_LOAD_NO_HINTING;
+
+ handle->image_type.flags = flags;
+ handle->string_reload = 1;
+ }
+
+
+ FT_UInt
+ FTDemo_Get_Index( FTDemo_Handle* handle,
+ FT_UInt32 charcode )
+ {
+ FTC_FaceID face_id = handle->image_type.face_id;
+ PFont font = handle->current_font;
+
+
+ return FTC_CMapCache_Lookup( handle->cmap_cache, face_id,
+ font->cmap_index, charcode );
+ }
+
+
+ FT_Error
+ FTDemo_Get_Size( FTDemo_Handle* handle,
+ FT_Size* asize )
+ {
+ FTC_ScalerRec scaler;
+ FT_Size size;
+
+ scaler.face_id = handle->image_type.face_id;
+ scaler.width = handle->image_type.width;
+ scaler.height = handle->image_type.height;
+ scaler.pixel = 1;
+
+ error = FTC_Manager_LookupSize( handle->cache_manager, &scaler, &size );
+
+ if ( !error )
+ *asize = size;
+
+ return error;
+ }
+
+
+ FT_Error
+ FTDemo_Glyph_To_Bitmap( FTDemo_Handle* handle,
+ FT_Glyph glyf,
+ grBitmap* target,
+ int* left,
+ int* top,
+ int* x_advance,
+ int* y_advance,
+ FT_Glyph* aglyf )
+ {
+ FT_BitmapGlyph bitmap;
+ FT_Bitmap* source;
+
+
+ *aglyf = NULL;
+
+ error = FT_Err_Ok;
+
+ if ( glyf->format == FT_GLYPH_FORMAT_OUTLINE )
+ {
+ FT_Render_Mode render_mode = FT_RENDER_MODE_MONO;
+
+
+ if ( handle->antialias )
+ {
+ if ( handle->lcd_mode == 0 )
+ render_mode = FT_RENDER_MODE_NORMAL;
+ else if ( handle->lcd_mode == 1 )
+ render_mode = FT_RENDER_MODE_LIGHT;
+ else if ( handle->lcd_mode <= 3 )
+ render_mode = FT_RENDER_MODE_LCD;
+ else
+ render_mode = FT_RENDER_MODE_LCD_V;
+ }
+
+ /* render the glyph to a bitmap, don't destroy original */
+ error = FT_Glyph_To_Bitmap( &glyf, render_mode, NULL, 0 );
+ if ( error )
+ return error;
+
+ *aglyf = glyf;
+ }
+
+ if ( glyf->format != FT_GLYPH_FORMAT_BITMAP )
+ PanicZ( "invalid glyph format returned!" );
+
+ bitmap = (FT_BitmapGlyph)glyf;
+ source = &bitmap->bitmap;
+
+ target->rows = source->rows;
+ target->width = source->width;
+ target->pitch = source->pitch;
+ target->buffer = source->buffer;
+ target->grays = source->num_grays;
+
+ switch ( source->pixel_mode )
+ {
+ case FT_PIXEL_MODE_MONO:
+ target->mode = gr_pixel_mode_mono;
+ break;
+
+ case FT_PIXEL_MODE_GRAY:
+ target->mode = gr_pixel_mode_gray;
+ target->grays = source->num_grays;
+ break;
+
+ case FT_PIXEL_MODE_GRAY2:
+ case FT_PIXEL_MODE_GRAY4:
+ (void)FT_Bitmap_Convert( handle->library, source, &handle->bitmap, 1 );
+ target->pitch = handle->bitmap.pitch;
+ target->buffer = handle->bitmap.buffer;
+ target->mode = gr_pixel_mode_gray;
+ target->grays = handle->bitmap.num_grays;
+ break;
+
+ case FT_PIXEL_MODE_LCD:
+ target->mode = handle->lcd_mode == 2 ? gr_pixel_mode_lcd
+ : gr_pixel_mode_lcd2;
+ target->grays = source->num_grays;
+ break;
+
+ case FT_PIXEL_MODE_LCD_V:
+ target->mode = handle->lcd_mode == 4 ? gr_pixel_mode_lcdv
+ : gr_pixel_mode_lcdv2;
+ target->grays = source->num_grays;
+ break;
+
+ default:
+ return FT_Err_Invalid_Glyph_Format;
+ }
+
+ *left = bitmap->left;
+ *top = bitmap->top;
+
+ *x_advance = ( glyf->advance.x + 0x8000 ) >> 16;
+ *y_advance = ( glyf->advance.y + 0x8000 ) >> 16;
+
+ return error;
+ }
+
+
+ FT_Error
+ FTDemo_Index_To_Bitmap( FTDemo_Handle* handle,
+ FT_ULong Index,
+ grBitmap* target,
+ int* left,
+ int* top,
+ int* x_advance,
+ int* y_advance,
+ FT_Glyph* aglyf )
+ {
+ int cached_bitmap = 1;
+
+ *aglyf = NULL;
+
+ /* use the SBits cache to store small glyph bitmaps; this is a lot */
+ /* more memory-efficient */
+ /* */
+ if ( handle->use_sbits_cache &&
+ handle->image_type.width < 48 &&
+ handle->image_type.height < 48 )
+ {
+ FTC_SBit sbit;
+ FT_Bitmap source;
+
+
+ error = FTC_SBitCache_Lookup( handle->sbits_cache,
+ &handle->image_type,
+ Index,
+ &sbit,
+ NULL );
+ if ( error )
+ goto Exit;
+
+ if ( sbit->buffer )
+ {
+ target->rows = sbit->height;
+ target->width = sbit->width;
+ target->pitch = sbit->pitch;
+ target->buffer = sbit->buffer;
+ target->grays = sbit->max_grays + 1;
+
+ switch ( sbit->format )
+ {
+ case FT_PIXEL_MODE_MONO:
+ target->mode = gr_pixel_mode_mono;
+ break;
+
+ case FT_PIXEL_MODE_GRAY:
+ target->mode = gr_pixel_mode_gray;
+ target->grays = sbit->max_grays + 1;
+ break;
+
+ case FT_PIXEL_MODE_GRAY2:
+ case FT_PIXEL_MODE_GRAY4:
+ source.rows = sbit->height;
+ source.width = sbit->width;
+ source.pitch = sbit->pitch;
+ source.buffer = sbit->buffer;
+ source.pixel_mode = sbit->format;
+
+ (void)FT_Bitmap_Convert( handle->library, &source,
+ &handle->bitmap, 1 );
+
+ target->pitch = handle->bitmap.pitch;
+ target->buffer = handle->bitmap.buffer;
+ target->mode = gr_pixel_mode_gray;
+ target->grays = handle->bitmap.num_grays;
+
+ cached_bitmap = 0;
+ break;
+
+ case FT_PIXEL_MODE_LCD:
+ target->mode = handle->lcd_mode == 2 ? gr_pixel_mode_lcd
+ : gr_pixel_mode_lcd2;
+ target->grays = sbit->max_grays + 1;
+ break;
+
+ case FT_PIXEL_MODE_LCD_V:
+ target->mode = handle->lcd_mode == 4 ? gr_pixel_mode_lcdv
+ : gr_pixel_mode_lcdv2;
+ target->grays = sbit->max_grays + 1;
+ break;
+
+ default:
+ return FT_Err_Invalid_Glyph_Format;
+ }
+
+
+ *left = sbit->left;
+ *top = sbit->top;
+ *x_advance = sbit->xadvance;
+ *y_advance = sbit->yadvance;
+
+ goto Exit;
+ }
+ }
+
+ /* otherwise, use an image cache to store glyph outlines, and render */
+ /* them on demand. we can thus support very large sizes easily.. */
+ {
+ FT_Glyph glyf;
+
+ error = FTC_ImageCache_Lookup( handle->image_cache,
+ &handle->image_type,
+ Index,
+ &glyf,
+ NULL );
+
+ if ( !error )
+ error = FTDemo_Glyph_To_Bitmap( handle, glyf, target, left, top,
+ x_advance, y_advance, aglyf );
+ }
+
+ Exit:
+
+#ifdef FT_RGB_FILTER_H
+ /* note that we apply the RGB filter to each cached glyph, which is
+ * a performance killer, but that's better than modifying the cache
+ * at the moment
+ */
+ if ( !error )
+ {
+ if ( target->mode == gr_pixel_mode_lcd ||
+ target->mode == gr_pixel_mode_lcdv )
+ {
+ /* copy the bitmap before filtering it, we don't want to touch
+ * the content of cache nodes at all
+ */
+ {
+ }
+ }
+ }
+
+#endif /* FT_RGB_FILTER_H */
+
+ /* don't accept a `missing' character with zero or negative width */
+ if ( Index == 0 && *x_advance <= 0 )
+ *x_advance = 1;
+
+ return error;
+ }
+
+
+ FT_Error
+ FTDemo_Draw_Index( FTDemo_Handle* handle,
+ grBitmap* bitmap,
+ int gindex,
+ int* pen_x,
+ int* pen_y )
+ {
+ int left, top, x_advance, y_advance;
+ grBitmap bit3;
+ FT_Glyph glyf;
+
+ grColor c;
+ memset(&c, 0, sizeof(grColor));
+
+ error = FTDemo_Index_To_Bitmap(handle, gindex, &bit3, &left, &top,
+ &x_advance, &y_advance, &glyf);
+ if(error)
+ return error;
+
+ /* now render the bitmap into the display surface */
+ grBlitGlyphToBitmap( bitmap, &bit3, *pen_x + left,
+ *pen_y - top, c );
+
+ if ( glyf )
+ FT_Done_Glyph( glyf );
+
+ *pen_x += x_advance + 1;
+
+ return FT_Err_Ok;
+ }
+
+
+ FT_Error
+ FTDemo_Draw_Glyph( FTDemo_Handle* handle,
+ FTDemo_Display* display,
+ FT_Glyph glyph,
+ int* pen_x,
+ int* pen_y )
+ {
+ int left, top, x_advance, y_advance;
+ grBitmap bit3;
+ FT_Glyph glyf;
+
+
+ error = FTDemo_Glyph_To_Bitmap( handle, glyph, &bit3, &left, &top,
+ &x_advance, &y_advance, &glyf );
+ if ( error )
+ {
+ FT_Done_Glyph( glyph );
+
+ return error;
+ }
+
+ /* now render the bitmap into the display surface */
+ grBlitGlyphToBitmap( display->bitmap, &bit3, *pen_x + left,
+ *pen_y - top, display->fore_color );
+
+ if ( glyf )
+ FT_Done_Glyph( glyf );
+
+ *pen_x += x_advance + 1;
+
+ return FT_Err_Ok;
+ }
+
+
+ FT_Error
+ FTDemo_Draw_Slot( FTDemo_Handle* handle,
+ FTDemo_Display* display,
+ FT_GlyphSlot slot,
+ int* pen_x,
+ int* pen_y )
+ {
+ FT_Glyph glyph;
+
+
+ error = FT_Get_Glyph( slot, &glyph );
+ if ( error )
+ return error;
+
+ error = FTDemo_Draw_Glyph( handle, display, glyph, pen_x, pen_y );
+
+ FT_Done_Glyph( glyph );
+
+ return error;
+ }
+
+
+ void
+ FTDemo_String_Set( FTDemo_Handle* handle,
+ const unsigned char* string )
+ {
+ const unsigned char* p = string;
+ unsigned long codepoint;
+ unsigned char in_code;
+ int expect;
+ PGlyph glyph = handle->string;
+
+
+ handle->string_length = 0;
+ codepoint = expect = 0;
+
+ while ( *p )
+ {
+ in_code = *p++ ;
+
+ if ( in_code >= 0xC0 )
+ {
+ if ( in_code < 0xE0 ) /* U+0080 - U+07FF */
+ {
+ expect = 1;
+ codepoint = in_code & 0x1F;
+ }
+ else if ( in_code < 0xF0 ) /* U+0800 - U+FFFF */
+ {
+ expect = 2;
+ codepoint = in_code & 0x0F;
+ }
+ else if ( in_code < 0xF8 ) /* U+10000 - U+10FFFF */
+ {
+ expect = 3;
+ codepoint = in_code & 0x07;
+ }
+ continue;
+ }
+ else if ( in_code >= 0x80 )
+ {
+ --expect;
+
+ if ( expect >= 0 )
+ {
+ codepoint <<= 6;
+ codepoint += in_code & 0x3F;
+ }
+ if ( expect > 0 )
+ continue;
+
+ expect = 0;
+ }
+ else /* ASCII, U+0000 - U+007F */
+ codepoint = in_code;
+
+ if ( handle->encoding != FT_ENCODING_NONE )
+ glyph->glyph_index = FTDemo_Get_Index( handle, codepoint );
+ else
+ glyph->glyph_index = codepoint;
+
+ glyph++;
+ handle->string_length++;
+
+ if ( handle->string_length >= MAX_GLYPHS )
+ break;
+ }
+
+ handle->string_reload = 1;
+ }
+
+
+ static FT_Error
+ string_load( FTDemo_Handle* handle )
+ {
+ int n;
+ FT_Size size;
+ FT_Face face;
+ FT_Pos prev_rsb_delta = 0;
+
+
+ error = FTDemo_Get_Size( handle, &size );
+ if ( error )
+ return error;
+
+ face = size->face;
+
+ for ( n = 0; n < handle->string_length; n++ )
+ {
+ PGlyph glyph = handle->string + n;
+
+
+ /* clear existing image if there is one */
+ if ( glyph->image )
+ {
+ FT_Done_Glyph( glyph->image );
+ glyph->image = NULL;
+ }
+
+ /* load the glyph and get the image */
+ if ( !FT_Load_Glyph( face, glyph->glyph_index,
+ handle->image_type.flags ) &&
+ !FT_Get_Glyph( face->glyph, &glyph->image ) )
+ {
+ FT_Glyph_Metrics* metrics = &face->glyph->metrics;
+
+
+ /* note that in vertical layout, y-positive goes downwards */
+
+ glyph->vvector.x = metrics->vertBearingX - metrics->horiBearingX;
+ glyph->vvector.y = -metrics->vertBearingY - metrics->horiBearingY;
+
+ glyph->vadvance.x = 0;
+ glyph->vadvance.y = -metrics->vertAdvance;
+
+ if ( prev_rsb_delta - face->glyph->lsb_delta >= 32 )
+ glyph->delta = -1 << 6;
+ else if ( prev_rsb_delta - face->glyph->lsb_delta < -32 )
+ glyph->delta = 1 << 6;
+ else
+ glyph->delta = 0;
+ }
+ }
+
+ return FT_Err_Ok;
+ }
+
+
+ FT_Error
+ string_render_prepare( FTDemo_Handle* handle,
+ FTDemo_String_Context* sc,
+ FT_Vector* advances )
+ {
+ FT_Face face;
+ FT_Size size;
+ PGlyph glyph;
+ FT_Pos track_kern = 0;
+ FT_UInt prev_index = 0;
+ FT_Vector* prev_advance = NULL;
+ FT_Vector extent = {0, 0};
+ FT_Int i;
+
+
+ error = FTDemo_Get_Size( handle, &size );
+ if ( error )
+ return error;
+
+ face = size->face;
+
+ if ( !sc->vertical && sc->kerning_degree )
+ {
+ FT_Fixed ptsize;
+
+
+ ptsize = FT_MulFix( face->units_per_EM, face->size->metrics.x_scale );
+
+ if ( FT_Get_Track_Kerning( face, ptsize << 10,
+ -sc->kerning_degree,
+ &track_kern ) )
+ track_kern = 0;
+ else
+ track_kern >>= 10;
+ }
+
+ for ( i = 0; i < handle->string_length; i++ )
+ {
+ glyph = handle->string + i;
+
+ if ( !glyph->image )
+ continue;
+
+ if ( sc->vertical )
+ advances[i] = glyph->vadvance;
+ else
+ {
+ advances[i] = glyph->image->advance;
+ advances[i].x >>= 10;
+ advances[i].y >>= 10;
+
+ if ( prev_advance )
+ {
+ prev_advance->x += track_kern;
+
+ if ( sc->kerning_mode )
+ {
+ FT_Vector kern;
+
+
+ FT_Get_Kerning( face, prev_index, glyph->glyph_index,
+ FT_KERNING_UNFITTED, &kern );
+
+ prev_advance->x += kern.x;
+ prev_advance->y += kern.y;
+
+ if ( sc->kerning_mode > KERNING_MODE_NORMAL )
+ prev_advance->x += glyph->delta;
+ }
+ }
+ }
+
+ if ( prev_advance )
+ {
+ if ( handle->hinted )
+ {
+ prev_advance->x = ROUND( prev_advance->x );
+ prev_advance->y = ROUND( prev_advance->y );
+ }
+
+ extent.x += prev_advance->x;
+ extent.y += prev_advance->y;
+ }
+
+ prev_index = glyph->glyph_index;
+ prev_advance = advances + i;
+ }
+
+ if ( prev_advance )
+ {
+ if ( handle->hinted )
+ {
+ prev_advance->x = ROUND( prev_advance->x );
+ prev_advance->y = ROUND( prev_advance->y );
+ }
+
+ extent.x += prev_advance->x;
+ extent.y += prev_advance->y;
+
+ /*store the extent in the last slot */
+ i = handle->string_length - 1;
+ advances[i] = extent;
+ }
+
+ return FT_Err_Ok;
+ }
+
+
+ static void
+ gamma_ramp_apply( FT_Byte gamma_ramp[256],
+ grBitmap* bitmap )
+ {
+ int i, j;
+ FT_Byte* p = (FT_Byte*)bitmap->buffer;
+
+ if ( bitmap->pitch < 0 )
+ p += -bitmap->pitch * ( bitmap->rows - 1 );
+
+ for ( i = 0; i < bitmap->rows; i++ )
+ {
+ for ( j = 0; j < bitmap->width; j++ )
+ p[j] = gamma_ramp[p[j]];
+
+ p += bitmap->pitch;
+ }
+ }
+
+
+ FT_Error
+ FTDemo_String_Draw( FTDemo_Handle* handle,
+ FTDemo_Display* display,
+ FTDemo_String_Context* sc,
+ int x,
+ int y )
+ {
+ int n;
+ FT_Vector pen, advances[MAX_GLYPHS];
+ FT_Size size;
+ FT_Face face;
+
+
+ if ( !sc ||
+ x < 0 ||
+ y < 0 ||
+ x > display->bitmap->width ||
+ y > display->bitmap->rows )
+ return FT_Err_Invalid_Argument;
+
+ error = FTDemo_Get_Size( handle, &size );
+ if ( error )
+ return error;
+
+ face = size->face;
+
+ if ( handle->string_reload )
+ {
+ error = string_load( handle );
+ if ( error )
+ return error;
+
+ handle->string_reload = 0;
+ }
+
+ error = string_render_prepare( handle, sc, advances );
+ if ( error )
+ return error;
+
+ /* change to Cartesian coordinates */
+ y = display->bitmap->rows - y;
+
+ /* get the extent, which we store in the last slot */
+ pen = advances[handle->string_length - 1];
+
+ pen.x = FT_MulFix( pen.x, sc->center );
+ pen.y = FT_MulFix( pen.y, sc->center );
+
+ /* XXX sbits */
+ /* get pen position */
+ if ( sc->matrix && FT_IS_SCALABLE( face ) )
+ {
+ FT_Vector_Transform( &pen, sc->matrix );
+ pen.x = ( x << 6 ) - pen.x;
+ pen.y = ( y << 6 ) - pen.y;
+ }
+ else
+ {
+ pen.x = ROUND( ( x << 6 ) - pen.x );
+ pen.y = ROUND( ( y << 6 ) - pen.y );
+ }
+
+ for ( n = 0; n < handle->string_length; n++ )
+ {
+ PGlyph glyph = handle->string + n;
+ FT_Glyph image;
+ FT_BBox bbox;
+
+
+ if ( !glyph->image )
+ continue;
+
+ /* copy image */
+ error = FT_Glyph_Copy( glyph->image, &image );
+ if ( error )
+ continue;
+
+ if ( image->format != FT_GLYPH_FORMAT_BITMAP )
+ {
+ if ( sc->vertical )
+ error = FT_Glyph_Transform( image, NULL, &glyph->vvector );
+
+ if ( !error )
+ error = FT_Glyph_Transform( image, sc->matrix, &pen );
+
+ if ( error )
+ {
+ FT_Done_Glyph( image );
+ continue;
+ }
+ }
+ else
+ {
+ FT_BitmapGlyph bitmap = (FT_BitmapGlyph)image;
+
+
+ if ( sc->vertical )
+ {
+ bitmap->left += ( glyph->vvector.x + pen.x ) >> 6;
+ bitmap->top += ( glyph->vvector.x + pen.y ) >> 6;
+ }
+ else
+ {
+ bitmap->left += pen.x >> 6;
+ bitmap->top += pen.y >> 6;
+ }
+ }
+
+ if ( sc->matrix )
+ FT_Vector_Transform( advances + n, sc->matrix );
+
+ pen.x += advances[n].x;
+ pen.y += advances[n].y;
+
+ FT_Glyph_Get_CBox( image, FT_GLYPH_BBOX_PIXELS, &bbox );
+
+#if 0
+ if ( n == 0 )
+ {
+ fprintf( stderr, "bbox = [%ld %ld %ld %ld]\n",
+ bbox.xMin, bbox.yMin, bbox.xMax, bbox.yMax );
+ }
+#endif
+
+ /* check bounding box; if it is completely outside the */
+ /* display surface, we don't need to render it */
+ if ( bbox.xMax > 0 &&
+ bbox.yMax > 0 &&
+ bbox.xMin < display->bitmap->width &&
+ bbox.yMin < display->bitmap->rows )
+ {
+ int left, top, dummy1, dummy2;
+ grBitmap bit3;
+ FT_Glyph glyf;
+
+
+ error = FTDemo_Glyph_To_Bitmap( handle, image, &bit3, &left, &top,
+ &dummy1, &dummy2, &glyf );
+ if ( !error )
+ {
+ if ( sc->gamma_ramp )
+ gamma_ramp_apply( sc->gamma_ramp, &bit3 );
+
+ /* change back to the usual coordinates */
+ top = display->bitmap->rows - top;
+
+ /* now render the bitmap into the display surface */
+ grBlitGlyphToBitmap( display->bitmap, &bit3, left, top,
+ display->fore_color );
+
+ if ( glyf )
+ FT_Done_Glyph( glyf );
+ }
+ }
+
+ FT_Done_Glyph( image );
+ }
+
+ return error;
+ }
+
+
+ FT_Encoding
+ FTDemo_Make_Encoding_Tag( const char* s )
+ {
+ int i;
+ unsigned long l = 0;
+
+
+ for ( i = 0; i < 4; i++ )
+ {
+ if ( !s[i] )
+ break;
+ l <<= 8;
+ l += (unsigned long)s[i];
+ }
+
+ return (FT_Encoding)l;
+ }
+
+
+/* End */
diff --git a/kernel/kls_ttf/ftcommon.h b/kernel/kls_ttf/ftcommon.h
new file mode 100644
index 0000000..304527f
--- /dev/null
+++ b/kernel/kls_ttf/ftcommon.h
@@ -0,0 +1,307 @@
+/****************************************************************************/
+/* */
+/* The FreeType project -- a free and portable quality TrueType renderer. */
+/* */
+/* Copyright 2005, 2006 by */
+/* D. Turner, R.Wilhelm, and W. Lemberg */
+/* */
+/* */
+/* ftcommon.h - common routines for the FreeType demo programs. */
+/* */
+/****************************************************************************/
+
+#ifndef _FT_COMMON_H_
+#define _FT_COMMON_H_
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#include FT_CACHE_H
+#include FT_CACHE_MANAGER_H
+
+#include FT_GLYPH_H
+#include FT_BITMAP_H
+
+#include <stdlib.h>
+#include <stdarg.h>
+
+ extern FT_Error error;
+
+ /* forward declarations */
+ extern void PanicZ( const char* message );
+
+#undef NODEBUG
+
+#define LOG( x ) /* */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** DISPLAY-SPECIFIC DEFINITIONS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+#include "graph.h"
+#include "grobjs.h"
+#include "grfont.h"
+
+ typedef struct
+ {
+ grSurface* surface;
+ grBitmap* bitmap;
+ grColor fore_color;
+ grColor back_color;
+
+ } FTDemo_Display;
+
+ grBitmap*
+ FTDemo_Display_New(void);
+
+
+ void
+ FTDemo_Display_Done(grBitmap *);
+
+
+ /* fill the bitmap with background color */
+ void
+ FTDemo_Display_Clear(grBitmap *);
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** FREETYPE-SPECIFIC DEFINITIONS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#define MAX_GLYPHS 512 /* at most 512 glyphs in the string */
+#define MAX_GLYPH_BYTES 150000 /* 150kB for the glyph image cache */
+
+
+ typedef struct TGlyph_
+ {
+ FT_UInt glyph_index;
+ FT_Glyph image; /* the glyph image */
+
+ FT_Pos delta; /* delta caused by hinting */
+ FT_Vector vvector; /* vert. origin => hori. origin */
+ FT_Vector vadvance; /* vertical advance */
+
+ } TGlyph, *PGlyph;
+
+ /* this simple record is used to model a given `installed' face */
+ typedef struct TFont_
+ {
+ const char* filepathname;
+ int face_index;
+ int cmap_index;
+ int num_indices;
+ void* file_address; /* for preloaded files */
+ size_t file_size;
+
+ } TFont, *PFont;
+
+ enum {
+ LCD_MODE_AA = 0,
+ LCD_MODE_LIGHT,
+ LCD_MODE_RGB,
+ LCD_MODE_BGR,
+ LCD_MODE_VRGB,
+ LCD_MODE_VBGR,
+ N_LCD_MODES
+ };
+
+ enum {
+ KERNING_DEGREE_NONE = 0,
+ KERNING_DEGREE_LIGHT,
+ KERNING_DEGREE_MEDIUM,
+ KERNING_DEGREE_TIGHT,
+ N_KERNING_DEGREES,
+ };
+
+ enum {
+ KERNING_MODE_NONE = 0, /* 0: no kerning; */
+ KERNING_MODE_NORMAL, /* 1: `kern' values */
+ KERNING_MODE_SMART, /* 2: `kern' + side bearing errors */
+ N_KERNING_MODES
+ };
+
+ typedef struct
+ {
+ int kerning_mode;
+ int kerning_degree;
+ FT_Fixed center; /* 0..1 */
+ int vertical; /* displayed vertically? */
+ FT_Matrix* matrix; /* string transformation */
+ FT_Byte* gamma_ramp; /* an array of size 256 */
+
+ } FTDemo_String_Context;
+
+ typedef struct
+ {
+ FT_Library library; /* the FreeType library */
+ FTC_Manager cache_manager; /* the cache manager */
+ FTC_ImageCache image_cache; /* the glyph image cache */
+ FTC_SBitCache sbits_cache; /* the glyph small bitmaps cache */
+ FTC_CMapCache cmap_cache; /* the charmap cache.. */
+
+ PFont* fonts; /* installed fonts */
+ int num_fonts;
+ int max_fonts;
+
+ int use_sbits_cache; /* toggle sbits cache */
+
+ /* use FTDemo_Set_Current_XXX to set the following two fields */
+ PFont current_font; /* selected font */
+ FTC_ImageTypeRec image_type;
+
+ /* call FTDemo_Update_Current_Flags after setting any of the following fields */
+ int hinted; /* is glyph hinting active? */
+ int antialias; /* is anti-aliasing active? */
+ int use_sbits; /* do we use embedded bitmaps? */
+ int low_prec; /* force low precision */
+ int autohint; /* force auto-hinting */
+ int lcd_mode;
+ int preload; /* force font file preloading */
+
+ /* don't touch the following fields! */
+
+ /* used for string rendering */
+ TGlyph string[MAX_GLYPHS];
+ int string_length;
+ int string_reload;
+
+ FT_Encoding encoding;
+ FT_Bitmap bitmap; /* used as bitmap conversion buffer */
+
+ } FTDemo_Handle;
+
+
+ FTDemo_Handle*
+ FTDemo_New( FT_Encoding encoding );
+
+
+ void
+ FTDemo_Done( FTDemo_Handle* handle );
+
+
+ /* install a font */
+ FT_Error
+ FTDemo_Install_Font( FTDemo_Handle* handle,
+ const char* filepath );
+
+
+ void
+ FTDemo_Set_Preload( FTDemo_Handle* handle,
+ int preload );
+
+ void
+ FTDemo_Set_Current_Font( FTDemo_Handle* handle,
+ PFont font );
+
+ void
+ FTDemo_Set_Current_Size( FTDemo_Handle* handle,
+ int pixel_size );
+
+ void
+ FTDemo_Set_Current_Pointsize( FTDemo_Handle* handle,
+ int point_size,
+ int res );
+
+ void
+ FTDemo_Update_Current_Flags( FTDemo_Handle* handle );
+
+
+ /* charcode => glyph index of current font */
+ FT_UInt
+ FTDemo_Get_Index( FTDemo_Handle* handle,
+ FT_UInt32 charcode );
+
+
+ /* get FT_Size of current font */
+ FT_Error
+ FTDemo_Get_Size( FTDemo_Handle* handle,
+ FT_Size* asize );
+
+
+ /* convert a FT_Glyph to a grBitmap (don't free target->buffer) */
+ /* if aglyf != NULL, you should FT_Glyph_Done the aglyf */
+ FT_Error
+ FTDemo_Glyph_To_Bitmap( FTDemo_Handle* handle,
+ FT_Glyph glyf,
+ grBitmap* target,
+ int* left,
+ int* top,
+ int* x_advance,
+ int* y_advance,
+ FT_Glyph* aglyf );
+
+ /* get a grBitmap from glyph index (don't free target->buffer) */
+ /* if aglyf != NULL, you should FT_Glyph_Done the aglyf */
+ FT_Error
+ FTDemo_Index_To_Bitmap( FTDemo_Handle* handle,
+ FT_ULong Index,
+ grBitmap* target,
+ int* left,
+ int* top,
+ int* x_advance,
+ int* y_advance,
+ FT_Glyph* aglyf );
+
+
+ /* given glyph index, draw a glyph on the display */
+ FT_Error
+ FTDemo_Draw_Index( FTDemo_Handle* handle,
+ grBitmap* display,
+ int gindex,
+ int* pen_x,
+ int* pen_y);
+
+
+ /* given FT_Glyph, draw a glyph on the display */
+ FT_Error
+ FTDemo_Draw_Glyph( FTDemo_Handle* handle,
+ FTDemo_Display* display,
+ FT_Glyph glyph,
+ int* pen_x,
+ int* pen_y);
+
+
+ /* given FT_GlyphSlot, draw a glyph on the display */
+ FT_Error
+ FTDemo_Draw_Slot( FTDemo_Handle* handle,
+ FTDemo_Display* display,
+ FT_GlyphSlot slot,
+ int* pen_x,
+ int* pen_y);
+
+
+ /* set the string to be drawn */
+ void
+ FTDemo_String_Set( FTDemo_Handle* handle,
+ const unsigned char* string );
+
+
+ /* draw a string centered at (center_x, center_y) -- */
+ /* note that handle->use_sbits_cache is not supported */
+ FT_Error
+ FTDemo_String_Draw( FTDemo_Handle* handle,
+ FTDemo_Display* display,
+ FTDemo_String_Context* sc,
+ int center_x,
+ int center_y );
+
+
+ /* make a FT_Encoding tag from a string */
+ FT_Encoding
+ FTDemo_Make_Encoding_Tag( const char* s );
+
+
+#endif /* _FTCOMMON_H_ */
+
+/* End */
diff --git a/kernel/kls_ttf/ftview/Makefile.am b/kernel/kls_ttf/ftview/Makefile.am
new file mode 100644
index 0000000..d744d11
--- /dev/null
+++ b/kernel/kls_ttf/ftview/Makefile.am
@@ -0,0 +1,9 @@
+INCLUDES = -I. @SQ_FT_CFLAGS@
+
+noinst_LTLIBRARIES = libftview.la
+
+libftview_la_SOURCES = gblblit.cpp gblender.cpp grblit.cpp grfont.cpp grobjs.cpp
+
+EXTRA_DIST = gblblit.h gblender.h gblvbgr.h grblit.cpp grevents.h grobjs.cpp \
+gblany.h gblcolor.h gblhbgr.h gblvrgb.h grblit.h grfont.cpp grobjs.h README \
+gblblit.cpp gblender.cpp gblhrgb.h graph.h grconfig.h grfont.h grtypes.h
diff --git a/kernel/kls_ttf/ftview/README b/kernel/kls_ttf/ftview/README
new file mode 100644
index 0000000..61dba91
--- /dev/null
+++ b/kernel/kls_ttf/ftview/README
@@ -0,0 +1 @@
+All code in this directory is taken from ftdemos-2.1.10 \ No newline at end of file
diff --git a/kernel/kls_ttf/ftview/gblany.h b/kernel/kls_ttf/ftview/gblany.h
new file mode 100644
index 0000000..a0bc750
--- /dev/null
+++ b/kernel/kls_ttf/ftview/gblany.h
@@ -0,0 +1,133 @@
+/* check that all macros are correctly set
+ */
+#ifndef GDST_INCR
+#error "GDST_INCR not defined"
+#endif
+
+#ifndef GDST_TYPE
+#error "GDST_TYPE not defined"
+#endif
+
+#ifndef GDST_READ
+#error "GDST_READ not defined"
+#endif
+
+#ifdef GBLENDER_STORE_BYTES
+# ifndef GDST_STOREB
+# error "GDST_STOREB not defined"
+# endif
+#else
+# ifndef GDST_STOREP
+# error "GDST_STOREP not defined"
+# endif
+#endif /* !STORE_BYTES */
+
+#ifndef GDST_STOREC
+#error "GDST_STOREC not defined"
+#endif
+
+#ifndef GDST_COPY
+#error "GDST_COPY not defined"
+#endif
+
+#ifndef GDST_COPY_VAR
+#error "GDST_COPY_VAR not defined"
+#endif
+
+#undef GCONCAT
+#undef GCONCATX
+#define GCONCAT(x,y) GCONCATX(x,y)
+#define GCONCATX(x,y) x ## y
+
+
+#include <stdio.h>
+
+static void
+GCONCAT( _gblender_blit_gray8_, GDST_TYPE )( GBlenderBlit blit,
+ GBlenderPixel color )
+{
+
+ GBlender blender = blit->blender;
+ int r = (color >> 16) & 255;
+ int g = (color >> 8) & 255;
+ int b = (color) & 255;
+
+ GDST_COPY_VAR
+
+#include "gblcolor.h"
+
+}
+
+
+static void
+GCONCAT( _gblender_blit_hrgb_, GDST_TYPE )( GBlenderBlit blit,
+ GBlenderPixel color )
+{
+ GBlender blender = blit->blender;
+ int r = (color >> 16) & 255;
+ int g = (color >> 8) & 255;
+ int b = (color) & 255;
+
+ GDST_COPY_VAR
+
+#include "gblhrgb.h"
+}
+
+
+static void
+GCONCAT( _gblender_blit_hbgr_, GDST_TYPE )( GBlenderBlit blit,
+ GBlenderPixel color )
+{
+ GBlender blender = blit->blender;
+ int r = (color >> 16) & 255;
+ int g = (color >> 8) & 255;
+ int b = (color) & 255;
+
+ GDST_COPY_VAR
+
+#include "gblhbgr.h"
+}
+
+
+static void
+GCONCAT( _gblender_blit_vrgb_, GDST_TYPE )( GBlenderBlit blit,
+ GBlenderPixel color )
+{
+ GBlender blender = blit->blender;
+ int r = (color >> 16) & 255;
+ int g = (color >> 8) & 255;
+ int b = (color) & 255;
+
+ GDST_COPY_VAR
+
+#include "gblvrgb.h"
+}
+
+static void
+GCONCAT( _gblender_blit_vbgr_, GDST_TYPE )( GBlenderBlit blit,
+ GBlenderPixel color )
+{
+ GBlender blender = blit->blender;
+ int r = (color >> 16) & 255;
+ int g = (color >> 8) & 255;
+ int b = (color) & 255;
+
+ GDST_COPY_VAR
+
+#include "gblvbgr.h"
+}
+
+/* unset the macros, to prevent accidental re-use
+ */
+
+#undef GCONCATX
+#undef GCONCAT
+#undef GDST_TYPE
+#undef GDST_INCR
+#undef GDST_READ
+#undef GDST_COPY
+#undef GDST_STOREB
+#undef GDST_STOREP
+#undef GDST_STOREC
+#undef GDST_COPY_VAR
+/* EOF */
diff --git a/kernel/kls_ttf/ftview/gblblit.cpp b/kernel/kls_ttf/ftview/gblblit.cpp
new file mode 100644
index 0000000..afb363d
--- /dev/null
+++ b/kernel/kls_ttf/ftview/gblblit.cpp
@@ -0,0 +1,318 @@
+#include "gblblit.h"
+
+#include <stdio.h>
+
+/* blitting gray glyphs
+ */
+
+/* generic macros
+ */
+#define GRGB_PACK(r,g,b) ( ((GBlenderPixel)(r) << 16) | \
+ ((GBlenderPixel)(g) << 8) | \
+ (GBlenderPixel)(b) )
+
+#define GDST_STORE3(d,r,g,b) (d)[0] = (unsigned char)(r); \
+ (d)[1] = (unsigned char)(g); \
+ (d)[2] = (unsigned char)(b)
+
+/* */
+
+#define GRGB_TO_RGB565(r,g,b) ((unsigned short)( ((r << 8) & 0xF800) | \
+ ((g << 3) & 0x07E0) | \
+ ((b >> 3) & 0x001F) ) )
+
+#define GRGB565_TO_RGB24(p) ( ( ((p) << 8) & 0xF80000 ) | \
+ ( ((p) << 3) & 0x0700F8 ) | \
+ ( ((p) << 5) & 0x00FC00 ) | \
+ ( ((p) >> 1) & 0x000300 ) | \
+ ( ((p) >> 2) & 0x000007 ) )
+
+#define GRGB24_TO_RGB565(p) ( (unsigned short)( (((p) >> 8) & 0xF800 ) | \
+ (((p) >> 5) & 0x07E0 ) | \
+ (((p) >> 3) & 0x001F ) ) )
+
+/* */
+
+#define GRGB_TO_BGR565(r,g,b) GRGB_TO_RGB565(b,g,r)
+
+#define GBGR565_TO_RGB24(p) ( ( ((p) << 19) & 0xF80000 ) | \
+ ( ((p) << 12) & 0x070000 ) | \
+ ( ((p) << 5) & 0x00FC00 ) | \
+ ( ((p) >> 1) & 0x000300 ) | \
+ ( ((p) >> 8) & 0x0000F8 ) | \
+ ( ((p) >> 13) & 0x000007 ) )
+
+#define GRGB24_TO_BGR565(p) ( (unsigned short)( (((p) << 8) & 0xF800 ) | \
+ (((p) >> 5) & 0x07E0 ) | \
+ (((p) >> 19) & 0x001F ) ) )
+
+/* */
+
+/* Rgb32 blitting routines
+ */
+
+#define GDST_TYPE rgb32
+#define GDST_INCR 4
+#define GDST_READ(d,p) (p) = *(GBlenderPixel*)(d) & 0xFFFFFF
+#define GDST_COPY(d) *(GBlenderPixel*)(d) = color
+#define GDST_STOREP(d,cells,a) *(GBlenderPixel*)(d) = (cells)[(a)]
+#define GDST_STOREB(d,cells,a) \
+ { \
+ GBlenderCell* _g = (cells) + (a)*3; \
+ \
+ GDST_STOREC(d,_g[0],_g[1],_g[2]); \
+ }
+#define GDST_STOREC(d,r,g,b) *(GBlenderPixel*)(d) = GRGB_PACK(r,g,b)
+#define GDST_COPY_VAR /* nothing */
+
+#include "gblany.h"
+
+/* Rgb24 blitting routines
+ */
+
+#define GDST_TYPE rgb24
+#define GDST_INCR 3
+#define GDST_READ(d,p) (p) = GRGB_PACK((d)[0],(d)[1],(d)[2])
+#define GDST_COPY(d) GDST_STORE3(d,r,g,b)
+#define GDST_STOREC(d,r,g,b) GDST_STORE3(d,r,g,b)
+
+#define GDST_STOREB(d,cells,a) \
+ { \
+ GBlenderCell* _g = (cells) + (a)*3; \
+ \
+ (d)[0] = _g[0]; \
+ (d)[1] = _g[1]; \
+ (d)[2] = _g[2]; \
+ }
+
+#define GDST_STOREP(d,cells,a) \
+ { \
+ GBlenderPixel _pix = (cells)[(a)]; \
+ \
+ GDST_STORE3(d,_pix >> 16,_pix >> 8,_pix); \
+ }
+
+#define GDST_COPY_VAR /* nothing */
+
+#include "gblany.h"
+
+/* Rgb565 blitting routines
+ */
+
+#define GDST_TYPE rgb565
+#define GDST_INCR 2
+
+#define GDST_READ(d,p) p = (GBlenderPixel)*(unsigned short*)(d); \
+ p = GRGB565_TO_RGB24(p)
+
+#define GDST_COPY_VAR unsigned short pix = GRGB_TO_RGB565(r,g,b);
+#define GDST_COPY(d) *(unsigned short*)(d) = pix
+
+#define GDST_STOREB(d,cells,a) \
+ { \
+ GBlenderCell* _g = (cells) + (a)*3; \
+ \
+ *(unsigned short*)(d) = GRGB_TO_RGB565(_g[0],_g[1],_g[2]); \
+ }
+
+#define GDST_STOREP(d,cells,a) \
+ { \
+ GBlenderPixel _pix = (cells)[(a)]; \
+ \
+ *(unsigned short*)(d) = GRGB24_TO_RGB565(_pix); \
+ }
+
+#define GDST_STOREC(d,r,g,b) *(unsigned short*)(d) = GRGB_TO_RGB565(r,g,b)
+
+#include "gblany.h"
+
+/* Bgr565 blitting routines
+ */
+#define GDST_TYPE bgr565
+#define GDST_INCR 2
+
+#define GDST_READ(d,p) p = (GBlenderPixel)*(unsigned short*)(d); \
+ p = GBGR565_TO_RGB24(p)
+
+#define GDST_COPY_VAR unsigned short pix = GRGB_TO_BGR565(r,g,b);
+#define GDST_COPY(d) *(d) = pix
+
+#define GDST_STOREB(d,cells,a) \
+ { \
+ GBlenderCell* _g = (cells) + (a)*3; \
+ \
+ *(unsigned short*)(d) = GRGB_TO_BGR565(_g[0],_g[1],_g[2]); \
+ }
+
+#define GDST_STOREP(d,cells,a) \
+ { \
+ GBlenderPixel _pix = (cells)[(a)]; \
+ \
+ *(unsigned short*)(d) = GRGB24_TO_BGR565(_pix); \
+ }
+
+#define GDST_STOREC(d,r,g,b) *(unsigned short*)(d) = GRGB_TO_BGR565(r,g,b)
+
+#include "gblany.h"
+
+/* */
+
+static void
+_gblender_blit_dummy( GBlenderBlit blit,
+ GBlenderPixel color )
+{
+ (blit)=(blit);
+ (color)=(color);
+}
+
+
+GBLENDER_APIDEF( int )
+gblender_blit_init( GBlenderBlit blit,
+ GBlender blender,
+ int dst_x,
+ int dst_y,
+ GBlenderSourceFormat src_format,
+ const unsigned char* src_buffer,
+ int src_pitch,
+ int src_width,
+ int src_height,
+ GBlenderTargetFormat dst_format,
+ unsigned char* dst_buffer,
+ int dst_pitch,
+ int dst_width,
+ int dst_height )
+{
+ int src_x = 0;
+ int src_y = 0;
+ int delta;
+ GBlenderBlitFunc blit_func = 0;
+
+ switch ( src_format )
+ {
+ case GBLENDER_SOURCE_GRAY8:
+ switch ( dst_format )
+ {
+ case GBLENDER_TARGET_RGB32: blit_func = _gblender_blit_gray8_rgb32; break;
+ case GBLENDER_TARGET_RGB24: blit_func = _gblender_blit_gray8_rgb24; break;
+ case GBLENDER_TARGET_RGB565: blit_func = _gblender_blit_gray8_rgb565; break;
+ case GBLENDER_TARGET_BGR565: blit_func = _gblender_blit_gray8_bgr565; break;
+ default:
+ ;
+ }
+ break;
+
+ case GBLENDER_SOURCE_HRGB:
+ switch ( dst_format )
+ {
+ case GBLENDER_TARGET_RGB32: blit_func = _gblender_blit_hrgb_rgb32; break;
+ case GBLENDER_TARGET_RGB24: blit_func = _gblender_blit_hrgb_rgb24; break;
+ case GBLENDER_TARGET_RGB565: blit_func = _gblender_blit_hrgb_rgb565; break;
+ case GBLENDER_TARGET_BGR565: blit_func = _gblender_blit_hrgb_bgr565; break;
+ default:
+ ;
+ }
+ break;
+
+ case GBLENDER_SOURCE_HBGR:
+ switch ( dst_format )
+ {
+ case GBLENDER_TARGET_RGB32: blit_func = _gblender_blit_hbgr_rgb32; break;
+ case GBLENDER_TARGET_RGB24: blit_func = _gblender_blit_hbgr_rgb24; break;
+ case GBLENDER_TARGET_RGB565: blit_func = _gblender_blit_hbgr_rgb565; break;
+ case GBLENDER_TARGET_BGR565: blit_func = _gblender_blit_hbgr_bgr565; break;
+ default:
+ ;
+ }
+ break;
+
+ case GBLENDER_SOURCE_VRGB:
+ switch ( dst_format )
+ {
+ case GBLENDER_TARGET_RGB32: blit_func = _gblender_blit_vrgb_rgb32; break;
+ case GBLENDER_TARGET_RGB24: blit_func = _gblender_blit_vrgb_rgb24; break;
+ case GBLENDER_TARGET_RGB565: blit_func = _gblender_blit_vrgb_rgb565; break;
+ case GBLENDER_TARGET_BGR565: blit_func = _gblender_blit_vrgb_bgr565; break;
+ default:
+ ;
+ }
+ break;
+
+ case GBLENDER_SOURCE_VBGR:
+ switch ( dst_format )
+ {
+ case GBLENDER_TARGET_RGB32: blit_func = _gblender_blit_vbgr_rgb32; break;
+ case GBLENDER_TARGET_RGB24: blit_func = _gblender_blit_vbgr_rgb24; break;
+ case GBLENDER_TARGET_RGB565: blit_func = _gblender_blit_vbgr_rgb565; break;
+ case GBLENDER_TARGET_BGR565: blit_func = _gblender_blit_vbgr_bgr565; break;
+ default:
+ ;
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ blit->blender = blender;
+ blit->blit_func = blit_func;
+
+ if ( blit_func == 0 )
+ {
+ /* unsupported blit mode
+ */
+ blit->blit_func = _gblender_blit_dummy;
+ return -2;
+ }
+
+ if ( dst_x < 0 )
+ {
+ src_width += dst_x;
+ src_x -= dst_x;
+ dst_x = 0;
+ }
+
+ delta = dst_x + src_width - dst_width;
+ if ( delta > 0 )
+ src_width -= delta;
+
+ if ( dst_y < 0 )
+ {
+ src_height += dst_y;
+ src_y -= dst_y;
+ dst_y = 0;
+ }
+
+ delta = dst_y + src_height - dst_height;
+ if ( delta > 0 )
+ src_height -= delta;
+
+ /* nothing to blit
+ */
+ if ( src_width <= 0 || src_height <= 0 )
+ {
+ blit->blit_func = _gblender_blit_dummy;
+ return -1;
+ }
+
+ blit->width = src_width;
+ blit->height = src_height;
+ blit->src_format = src_format;
+ blit->dst_format = dst_format;
+
+ blit->src_x = src_x;
+ blit->src_y = src_y;
+ blit->src_line = src_buffer + src_pitch*src_y;
+ blit->src_pitch = src_pitch;
+ if ( src_pitch < 0 )
+ blit->src_line -= (src_height-1)*src_pitch;
+
+ blit->dst_x = dst_x;
+ blit->dst_y = dst_y;
+ blit->dst_line = dst_buffer + dst_pitch*dst_y;
+ blit->dst_pitch = dst_pitch;
+ if ( dst_pitch < 0 )
+ blit->dst_line -= (dst_height-1)*dst_pitch;
+
+ return 0;
+}
+
diff --git a/kernel/kls_ttf/ftview/gblblit.h b/kernel/kls_ttf/ftview/gblblit.h
new file mode 100644
index 0000000..564a21d
--- /dev/null
+++ b/kernel/kls_ttf/ftview/gblblit.h
@@ -0,0 +1,82 @@
+#ifndef __GBLENDER_BLIT_H__
+#define __GBLENDER_BLIT_H__
+
+#include "gblender.h"
+
+/*
+ * blitting interface
+ *
+ */
+
+typedef enum
+{
+ GBLENDER_SOURCE_GRAY8 = 0,
+ GBLENDER_SOURCE_HRGB,
+ GBLENDER_SOURCE_HBGR,
+ GBLENDER_SOURCE_VRGB,
+ GBLENDER_SOURCE_VBGR,
+
+ GBLENDER_SOURCE_MAX
+
+} GBlenderSourceFormat;
+
+
+typedef enum
+{
+ GBLENDER_TARGET_GRAY8 = 0,
+ GBLENDER_TARGET_RGB32,
+ GBLENDER_TARGET_RGB24,
+ GBLENDER_TARGET_RGB565,
+ GBLENDER_TARGET_BGR565,
+
+ GBLENDER_TARGET_MAX
+
+} GBlenderTargetFormat;
+
+typedef struct GBlenderBlitRec_* GBlenderBlit;
+
+typedef void (*GBlenderBlitFunc)( GBlenderBlit blit,
+ GBlenderPixel color );
+
+typedef struct GBlenderBlitRec_
+{
+ int width;
+ int height;
+ const unsigned char* src_line;
+ int src_pitch;
+ int src_x;
+ int src_y;
+ unsigned char* dst_line;
+ int dst_pitch;
+ int dst_x;
+ int dst_y;
+ GBlenderSourceFormat src_format;
+ GBlenderTargetFormat dst_format;
+
+ GBlender blender;
+ GBlenderBlitFunc blit_func;
+
+} GBlenderBlitRec;
+
+
+
+GBLENDER_API( int )
+gblender_blit_init( GBlenderBlit blit,
+ GBlender blender,
+ int dst_x,
+ int dst_y,
+ GBlenderSourceFormat src_format,
+ const unsigned char* src_buffer,
+ int src_pitch,
+ int src_width,
+ int src_height,
+ GBlenderTargetFormat dst_format,
+ unsigned char* dst_buffer,
+ int dst_pitch,
+ int dst_width,
+ int dst_height );
+
+#define gblender_blit_run(b,color) (b)->blit_func( (b), (color) )
+
+
+#endif /* __GBLENDER_BLIT_H__ */
diff --git a/kernel/kls_ttf/ftview/gblcolor.h b/kernel/kls_ttf/ftview/gblcolor.h
new file mode 100644
index 0000000..0aa2b6d
--- /dev/null
+++ b/kernel/kls_ttf/ftview/gblcolor.h
@@ -0,0 +1,56 @@
+
+ GBLENDER_VARS(blender,color);
+
+ int h = blit->height;
+ const unsigned char* src_line = blit->src_line;
+ unsigned char* dst_line = blit->dst_line;
+
+ /* make compiler happy */
+ (r)=(r);
+ (g)=(g);
+ (b)=(b);
+
+ do
+ {
+ const unsigned char* src = src_line + (blit->src_x);
+ unsigned char* dst = dst_line + blit->dst_x*GDST_INCR;
+ int w = blit->width;
+
+ do
+ {
+ int a = GBLENDER_SHADE_INDEX(src[0]);
+
+ if ( a == 0 )
+ {
+ /* nothing */
+ }
+ else if ( a == GBLENDER_SHADE_COUNT )
+ {
+ GDST_COPY(dst);
+ }
+ else
+ {
+ GBlenderPixel back;
+
+ GDST_READ(dst,back);
+
+ GBLENDER_LOOKUP( blender, back );
+
+#ifdef GBLENDER_STORE_BYTES
+ GDST_STOREB(dst,_gcells,a);
+#else
+ GDST_STOREP(dst,_gcells,a);
+#endif
+ }
+
+ src += 1;
+ dst += GDST_INCR;
+ }
+ while (--w > 0);
+
+ src_line += blit->src_pitch;
+ dst_line += blit->dst_pitch;
+ }
+ while (--h > 0);
+
+ GBLENDER_CLOSE(blender);
diff --git a/kernel/kls_ttf/ftview/gblender.cpp b/kernel/kls_ttf/ftview/gblender.cpp
new file mode 100644
index 0000000..a0f204d
--- /dev/null
+++ b/kernel/kls_ttf/ftview/gblender.cpp
@@ -0,0 +1,381 @@
+#include "gblender.h"
+#include <stdlib.h>
+#include <math.h>
+
+static void
+gblender_set_gamma_table( double gamma_value,
+ unsigned short* gamma_ramp,
+ unsigned char* gamma_ramp_inv )
+{
+ int gmax = (256 << GBLENDER_GAMMA_SHIFT)-1;
+
+ if ( gamma_value <= 0 ) /* special case for sRGB */
+ {
+ int ii;
+
+ for ( ii = 0; ii < 256; ii++ )
+ {
+ double x = (double)ii / 255.0;
+
+ if ( x <= 0.03926 )
+ x = x/12.92;
+ else
+ x = pow( (x+0.055)/ 1.055, 2.4 );
+
+ gamma_ramp[ii] = (unsigned short)(gmax*x);
+ }
+
+ for ( ii = 0; ii < gmax; ii++ )
+ {
+ double x = (double)ii / gmax;
+
+ if ( x <= 0.00304 )
+ x = 12.92*x;
+ else
+ x = 1.055*pow(x,1/2.4) - 0.055;
+
+ gamma_ramp_inv[ii] = (unsigned char)(255*x);
+ }
+ }
+ else
+ {
+ int ii;
+ double gamma_inv = 1.0f / gamma_value;
+
+ /* voltage to linear */
+ for ( ii = 0; ii < 256; ii++ )
+ gamma_ramp[ii] = (unsigned short)( pow( (double)ii/255.0f, gamma_value )*gmax );
+
+ /* linear to voltage */
+ for ( ii = 0; ii < gmax; ii++ )
+ gamma_ramp_inv[ii] = (unsigned char)( pow( (double)ii/gmax, gamma_inv ) * 255.0f );
+ }
+}
+
+
+/* clear the cache
+ */
+static void
+gblender_clear( GBlender blender )
+{
+ int nn;
+ GBlenderKey keys = blender->keys;
+
+ if ( blender->channels )
+ {
+ GBlenderChanKey chan_keys = (GBlenderChanKey) blender->keys;
+
+ for ( nn = 0; nn < GBLENDER_KEY_COUNT; nn++ )
+ chan_keys[nn].index = -1;
+ }
+ else
+ {
+ for ( nn = 0; nn < GBLENDER_KEY_COUNT; nn++ )
+ keys[nn].cells = NULL;
+ }
+}
+
+GBLENDER_APIDEF( void )
+gblender_reset( GBlender blender )
+{
+ gblender_clear( blender );
+
+ blender->cache_r_back = -1;
+ blender->cache_r_fore = -1;
+ blender->cache_r_cells = 0;
+
+ blender->cache_r_back = -1;
+ blender->cache_r_fore = -1;
+ blender->cache_r_cells = 0;
+
+ blender->cache_back = 0;
+ blender->cache_fore = 0xFFFFFF;
+ blender->cache_cells = gblender_lookup( blender,
+ blender->cache_back,
+ blender->cache_fore );
+
+#ifdef GBLENDER_STATS
+ blender->stat_hits = 0;
+ blender->stat_lookups = 0;
+ blender->stat_keys = 0;
+ blender->stat_clears = 0;
+#endif
+}
+
+GBLENDER_APIDEF( void )
+gblender_init( GBlender blender,
+ double gamma_value )
+{
+ blender->channels = 0;
+
+ gblender_set_gamma_table ( gamma_value,
+ blender->gamma_ramp,
+ blender->gamma_ramp_inv );
+
+ gblender_reset( blender );
+}
+
+/* recompute the grade levels of a given key
+ */
+static void
+gblender_reset_key( GBlender blender,
+ GBlenderKey key )
+{
+ GBlenderPixel back = key->background;
+ GBlenderPixel fore = key->foreground;
+ GBlenderCell* gr = key->cells;
+ int nn;
+ int gmax = (256 << GBLENDER_GAMMA_SHIFT)-1;
+
+ const unsigned char* gamma_ramp_inv = blender->gamma_ramp_inv;
+ const unsigned short* gamma_ramp = blender->gamma_ramp;
+
+ int r1,g1,b1,r2,g2,b2;
+
+ r1 = ( back >> 16 ) & 255;
+ g1 = ( back >> 8 ) & 255;
+ b1 = ( back ) & 255;
+
+ r2 = ( fore >> 16 ) & 255;
+ g2 = ( fore >> 8 ) & 255;
+ b2 = ( fore ) & 255;
+
+#ifdef GBLENDER_STORE_BYTES
+ gr[0] = (unsigned char)r1;
+ gr[1] = (unsigned char)g1;
+ gr[2] = (unsigned char)b1;
+ gr += 3;
+#else
+ gr[0] = back;
+ gr += 1;
+#endif
+
+ r1 = gamma_ramp[r1];
+ g1 = gamma_ramp[g1];
+ b1 = gamma_ramp[b1];
+
+ r2 = gamma_ramp[r2];
+ g2 = gamma_ramp[g2];
+ b2 = gamma_ramp[b2];
+
+ for ( nn = 1; nn < GBLENDER_SHADE_COUNT; nn++ )
+ {
+ int a = (nn << GBLENDER_SHADE_BITS);
+ int r = ((r2-r1)*a + 128);
+ int g = ((g2-g1)*a + 128);
+ int b = ((g2-g1)*a + 128);
+
+ r = (r + (r >> 8)) >> 8;
+ g = (g + (g >> 8)) >> 8;
+ b = (b + (b >> 8)) >> 8;
+
+ r += r1;
+ g += g1;
+ b += b1;
+
+#if 0
+ r = ( r | -(r >> 8) ) & 255;
+ g = ( g | -(g >> 8) ) & 255;
+ b = ( b | -(b >> 8) ) & 255;
+#else
+ if ( r < 0 ) r = 0; else if ( r > gmax ) r = gmax;
+ if ( g < 0 ) g = 0; else if ( g > gmax ) g = gmax;
+ if ( b < 0 ) b = 0; else if ( b > gmax ) b = gmax;
+#endif
+
+ r = gamma_ramp_inv[r];
+ g = gamma_ramp_inv[g];
+ b = gamma_ramp_inv[b];
+
+#ifdef GBLENDER_STORE_BYTES
+ gr[0] = (unsigned char)r;
+ gr[1] = (unsigned char)g;
+ gr[2] = (unsigned char)b;
+ gr += 3;
+#else
+ gr[0] = (( r & 255 ) << 16) |
+ (( g & 255 ) << 8 ) |
+ (( b & 255 ) ) ;
+ gr ++;
+#endif
+ }
+}
+
+ /* lookup the grades of a given (background,foreground) couple
+ */
+GBLENDER_APIDEF( GBlenderCell* )
+gblender_lookup( GBlender blender,
+ GBlenderPixel background,
+ GBlenderPixel foreground )
+{
+ int idx, idx0;
+ GBlenderKey key;
+
+#ifdef GBLENDER_STATS
+ blender->stat_hits--;
+ blender->stat_lookups++;
+#endif
+
+ if ( blender->channels )
+ {
+ /* set to normal mode */
+ blender->channels = 0;
+ gblender_reset( blender );
+ }
+
+ idx0 = ( background + foreground*63 ) % GBLENDER_KEY_COUNT;
+ idx = idx0;
+ do
+ {
+ key = blender->keys + idx;
+
+ if ( key->cells == NULL )
+ goto NewNode;
+
+ if ( key->background == background &&
+ key->foreground == foreground )
+ goto Exit;
+
+ idx = (idx+1) % GBLENDER_KEY_COUNT;
+ }
+ while ( idx != idx0 );
+
+ /* the cache is full, clear it completely
+ */
+#ifdef GBLENDER_STATS
+ blender->stat_clears++;
+ gblender_clear( blender );
+#endif
+
+NewNode:
+ key->background = background;
+ key->foreground = foreground;
+ key->cells = blender->cells + \
+ idx0*(GBLENDER_SHADE_COUNT*GBLENDER_CELL_SIZE);
+
+ gblender_reset_key( blender, key );
+
+#ifdef GBLENDER_STATS
+ blender->stat_keys++;
+#endif
+
+Exit:
+ return key->cells;
+}
+
+
+static void
+gblender_reset_channel_key( GBlender blender,
+ GBlenderChanKey key )
+{
+ int back = key->backfore & 255;
+ int fore = (key->backfore >> 8) & 255;
+ unsigned char* gr = (unsigned char*)blender->cells + key->index;
+ int nn;
+
+ const unsigned char* gamma_ramp_inv = blender->gamma_ramp_inv;
+ const unsigned short* gamma_ramp = blender->gamma_ramp;
+
+ int r1,r2;
+ int gmax = (256 << GBLENDER_GAMMA_SHIFT)-1;
+
+ r1 = back;
+ r2 = fore;
+
+ gr[0] = r1;
+ gr++;
+
+
+ r1 = gamma_ramp[r1];
+ r2 = gamma_ramp[r2];
+
+ for ( nn = 1; nn < GBLENDER_SHADE_COUNT; nn++ )
+ {
+ int a = (nn << GBLENDER_SHADE_BITS);
+ int r = ((r2-r1)*a + 128);
+
+ r = (r + (r >> 8)) >> 8;
+ r += r1;
+ if ( r < 0 ) r = 0; else if ( r > gmax ) r = gmax;
+ r = gamma_ramp_inv[r];
+
+ gr[0] = (unsigned char)r;
+ gr++;
+ }
+}
+
+
+GBLENDER_APIDEF( unsigned char* )
+gblender_lookup_channel( GBlender blender,
+ int background,
+ int foreground )
+{
+ int idx, idx0;
+ unsigned short backfore = (unsigned short)((foreground << 8) | background);
+ GBlenderChanKey key;
+
+#ifdef GBLENDER_STATS
+ blender->stat_hits--;
+ blender->stat_lookups++;
+#endif
+
+ if ( !blender->channels )
+ {
+ /* set to normal mode */
+ blender->channels = 1;
+ gblender_reset( blender );
+ }
+
+ idx0 = ( background + foreground*63 ) % (2*GBLENDER_KEY_COUNT);
+ idx = idx0;
+ do
+ {
+ key = (GBlenderChanKey)blender->keys + idx;
+
+ if ( key->index < 0 )
+ goto NewNode;
+
+ if ( key->backfore == backfore )
+ goto Exit;
+
+ idx = (idx+1) % (2*GBLENDER_KEY_COUNT);
+ }
+ while ( idx != idx0 );
+
+ /* the cache is full, clear it completely
+ */
+#ifdef GBLENDER_STATS
+ blender->stat_clears++;
+ gblender_clear( blender );
+#endif
+
+NewNode:
+ key->backfore = backfore;
+ key->index = (signed short)( idx0 * GBLENDER_SHADE_COUNT );
+
+ gblender_reset_channel_key( blender, key );
+
+#ifdef GBLENDER_STATS
+ blender->stat_keys++;
+#endif
+
+Exit:
+ return (unsigned char*)blender->cells + key->index;
+}
+
+
+
+#ifdef GBLENDER_STATS
+#include <stdio.h>
+GBLENDER_APIDEF( void )
+gblender_dump_stats( GBlender blender )
+{
+ printf( "hits = %ld, miss1 = %ld, miss2 = %ld, rate1=%.2f%%, rate2=%.2f%%\n",
+ blender->stat_hits,
+ blender->stat_lookups,
+ blender->stat_keys,
+ (100.0*blender->stat_hits) / (double)(blender->stat_hits + blender->stat_lookups),
+ (100.0*blender->stat_lookups) / (double)( blender->stat_lookups + blender->stat_keys)
+ );
+}
+#endif
diff --git a/kernel/kls_ttf/ftview/gblender.h b/kernel/kls_ttf/ftview/gblender.h
new file mode 100644
index 0000000..b519b3c
--- /dev/null
+++ b/kernel/kls_ttf/ftview/gblender.h
@@ -0,0 +1,216 @@
+/****************************************************************************
+ *
+ * Gamma-correct alpha blending of text
+ *
+ * (C) 2004 David Turner
+ *
+ */
+
+#ifndef __GBLENDER_H__
+#define __GBLENDER_H__
+
+#ifndef GBLENDER_API
+#define GBLENDER_API(x) extern x
+#endif
+
+#ifndef GBLENDER_APIDEF
+#define GBLENDER_APIDEF(x) x
+#endif
+
+#define GBLENDER_SHADE_BITS 4 /* must be <= 7 !! */
+#define GBLENDER_SHADE_COUNT ( 1 << GBLENDER_SHADE_BITS )
+#define GBLENDER_SHADE_INDEX(n) ((n + (GBLENDER_SHADE_COUNT/2)) >> GBLENDER_SHADE_BITS)
+#define GBLENDER_KEY_COUNT 256
+#define GBLENDER_GAMMA_SHIFT 2
+
+#define xGBLENDER_STORE_BYTES /* define this to store (R,G,B) values on 3 \
+ * bytes, instead of a single 32-bit integer.\
+ * surprisingly, this can speed up \
+ * the blender on certain machines. \
+ * Go figure what's really happenning though :-) \
+ */
+
+#define GBLENDER_STATS /* define this to collect statistics in the \
+ * blender \
+ */
+
+ typedef unsigned int GBlenderPixel; /* needs 32-bits here !! */
+
+#ifdef GBLENDER_STORE_BYTES
+ typedef unsigned char GBlenderCell;
+# define GBLENDER_CELL_SIZE 3
+#else
+ typedef GBlenderPixel GBlenderCell;
+# define GBLENDER_CELL_SIZE 1
+#endif
+
+
+ typedef struct
+ {
+ GBlenderPixel background;
+ GBlenderPixel foreground;
+ GBlenderCell* cells;
+
+ } GBlenderKeyRec, *GBlenderKey;
+
+
+ typedef struct
+ {
+ unsigned short backfore; /* (fore << 8) | back */
+ signed short index; /* offset in (unsigned char*)cells */
+
+ } GBlenderChanKeyRec, *GBlenderChanKey;
+
+
+ typedef struct GBlenderRec_
+ {
+ GBlenderKeyRec keys [ GBLENDER_KEY_COUNT ];
+ GBlenderCell cells[ GBLENDER_KEY_COUNT*GBLENDER_SHADE_COUNT*GBLENDER_CELL_SIZE ];
+
+ /* a small cache for normal modes
+ */
+ GBlenderPixel cache_back;
+ GBlenderPixel cache_fore;
+ GBlenderCell* cache_cells;
+
+ /* a small cache for RGB channels modes
+ */
+ int cache_r_back;
+ int cache_r_fore;
+ unsigned char* cache_r_cells;
+
+ int cache_g_back;
+ int cache_g_fore;
+ unsigned char* cache_g_cells;
+
+ int cache_b_back;
+ int cache_b_fore;
+ unsigned char* cache_b_cells;
+
+ /* are we in color or channel mode ?
+ */
+ int channels;
+
+ /* the gamma table
+ */
+ unsigned short gamma_ramp[256]; /* voltage to linear */
+ unsigned char gamma_ramp_inv[256 << GBLENDER_GAMMA_SHIFT]; /* linear to voltage */
+
+#ifdef GBLENDER_STATS
+ long stat_hits; /* number of direct hits */
+ long stat_lookups; /* number of table lookups */
+ long stat_keys; /* number of table key recomputation */
+ long stat_clears; /* number of table clears */
+#endif
+
+ } GBlenderRec, *GBlender;
+
+
+ /* initialize with a given gamma */
+ GBLENDER_API( void )
+ gblender_init( GBlender blender,
+ double gamma );
+
+
+ /* clear blender, and reset stats */
+ GBLENDER_API( void )
+ gblender_reset( GBlender reset );
+
+
+ /* lookup a cell range for a given (background,foreground) pair
+ */
+ GBLENDER_API( GBlenderCell* )
+ gblender_lookup( GBlender blender,
+ GBlenderPixel background,
+ GBlenderPixel foreground );
+
+ GBLENDER_API( unsigned char* )
+ gblender_lookup_channel( GBlender blender,
+ int background,
+ int foreground );
+
+#ifdef GBLENDER_STATS
+ GBLENDER_API( void )
+ gblender_dump_stats( GBlender blender );
+#else
+# define gblender_dump_stats(b) do { } while (0);
+#endif
+
+
+ /* no final `;'! */
+#define GBLENDER_VARS(_gb,_fore) \
+ GBlenderPixel _gback = (_gb)->cache_back; \
+ GBlenderCell* _gcells = ( (_fore) == (_gb)->cache_fore ? (_gb)->cache_cells : gblender_lookup( (_gb), _gback, _fore ) ); \
+ GBlenderPixel _gfore = (_fore)
+
+#define GBLENDER_CLOSE(_gb) \
+ (_gb)->cache_back = _gback; \
+ (_gb)->cache_fore = _gfore; \
+ (_gb)->cache_cells = _gcells;
+
+
+
+ /* no final `;'! */
+#define GBLENDER_CHANNEL_VARS(_gb,_rfore,_gfore,_bfore) \
+ int _grback = (_gb)->cache_r_back; \
+ unsigned char* _grcells = ( (_rfore) == (_gb)->cache_r_fore ? (_gb)->cache_r_cells : gblender_lookup_channel( (_gb), _grback, _rfore )); \
+ int _grfore = (_rfore); \
+ int _ggback = (_gb)->cache_g_back; \
+ unsigned char* _ggcells = ( (_gfore) == (_gb)->cache_g_fore ? (_gb)->cache_g_cells : gblender_lookup_channel( (_gb), _ggback, _gfore )); \
+ int _ggfore = (_rfore); \
+ int _gbback = (_gb)->cache_b_back; \
+ unsigned char* _gbcells = ( (_bfore) == (_gb)->cache_b_fore ? (_gb)->cache_b_cells : gblender_lookup_channel( (_gb), _gbback, _bfore )); \
+ int _gbfore = (_bfore)
+
+#define GBLENDER_CHANNEL_CLOSE(_gb) \
+ (_gb)->cache_r_back = _grback; \
+ (_gb)->cache_r_fore = _grfore; \
+ (_gb)->cache_r_cells = _grcells; \
+ (_gb)->cache_g_back = _ggback; \
+ (_gb)->cache_g_fore = _ggfore; \
+ (_gb)->cache_g_cells = _ggcells; \
+ (_gb)->cache_b_back = _gbback; \
+ (_gb)->cache_b_fore = _gbfore; \
+ (_gb)->cache_b_cells = _gbcells;
+
+
+#ifdef GBLENDER_STATS
+#define GBLENDER_STAT_HIT(gb) (gb)->stat_hits++
+#else
+#define GBLENDER_STAT_HIT(gb) /* nothing */
+#endif
+
+#define GBLENDER_LOOKUP(gb,back) \
+ GBLENDER_STAT_HIT(gb); \
+ if ( _gback != (GBlenderPixel)(back) ) \
+ { \
+ _gback = (GBlenderPixel)(back); \
+ _gcells = gblender_lookup( (gb), _gback, _gfore ); \
+ }
+
+#define GBLENDER_LOOKUP_R(gb,back) \
+ GBLENDER_STAT_HIT(gb); \
+ if ( _grback != (int)(back) ) \
+ { \
+ _grback = (GBlenderPixel)(back); \
+ _grcells = gblender_lookup_channel( (gb), _grback, _grfore ); \
+ }
+
+#define GBLENDER_LOOKUP_G(gb,back) \
+ GBLENDER_STAT_HIT(gb); \
+ if ( _ggback != (int)(back) ) \
+ { \
+ _ggback = (GBlenderPixel)(back); \
+ _ggcells = gblender_lookup_channel( (gb), _ggback, _ggfore ); \
+ }
+
+#define GBLENDER_LOOKUP_B(gb,back) \
+ GBLENDER_STAT_HIT(gb); \
+ if ( _gbback != (int)(back) ) \
+ { \
+ _gbback = (GBlenderPixel)(back); \
+ _gbcells = gblender_lookup_channel( (gb), _gbback, _gbfore ); \
+ }
+
+
+#endif /* __GBENCH_CACHE_H__ */
diff --git a/kernel/kls_ttf/ftview/gblhbgr.h b/kernel/kls_ttf/ftview/gblhbgr.h
new file mode 100644
index 0000000..a2740ab
--- /dev/null
+++ b/kernel/kls_ttf/ftview/gblhbgr.h
@@ -0,0 +1,74 @@
+ GBLENDER_CHANNEL_VARS(blender,r,g,b);
+
+ int h = blit->height;
+ const unsigned char* src_line = blit->src_line;
+ unsigned char* dst_line = blit->dst_line;
+
+ do
+ {
+ const unsigned char* src = src_line + blit->src_x*3;
+ unsigned char* dst = dst_line + blit->dst_x*GDST_INCR;
+ int w = blit->width;
+
+ do
+ {
+ int ab = GBLENDER_SHADE_INDEX(src[0]);
+ int ag = GBLENDER_SHADE_INDEX(src[1]);
+ int ar = GBLENDER_SHADE_INDEX(src[2]);
+ int aa = (ar << 16) | (ag << 8) | ab;
+
+ if ( aa == 0 )
+ {
+ /* nothing */
+ }
+ else if ( aa == ((GBLENDER_SHADE_COUNT << 16) |
+ (GBLENDER_SHADE_COUNT << 8) |
+ (GBLENDER_SHADE_COUNT) ) )
+ {
+ GDST_COPY(dst);
+ }
+ else
+ {
+ GBlenderPixel back;
+ int pix_r, pix_g, pix_b;
+
+ GDST_READ(dst,back);
+
+ {
+ int back_r = (back >> 16) & 255;
+
+ GBLENDER_LOOKUP_R( blender, back_r );
+
+ pix_r = _grcells[ar];
+ }
+
+ {
+ int back_g = (back >> 8) & 255;
+
+ GBLENDER_LOOKUP_G( blender, back_g );
+
+ pix_g = _ggcells[ag];
+ }
+
+ {
+ int back_b = (back) & 255;
+
+ GBLENDER_LOOKUP_B( blender, back_b );
+
+ pix_b = _gbcells[ab];
+ }
+
+ GDST_STOREC(dst,pix_r,pix_g,pix_b);
+ }
+
+ src += 3;
+ dst += GDST_INCR;
+ }
+ while (--w > 0);
+
+ src_line += blit->src_pitch;
+ dst_line += blit->dst_pitch;
+ }
+ while (--h > 0);
+
+ GBLENDER_CHANNEL_CLOSE(blender);
diff --git a/kernel/kls_ttf/ftview/gblhrgb.h b/kernel/kls_ttf/ftview/gblhrgb.h
new file mode 100644
index 0000000..930a6c9
--- /dev/null
+++ b/kernel/kls_ttf/ftview/gblhrgb.h
@@ -0,0 +1,76 @@
+
+ GBLENDER_CHANNEL_VARS(blender,r,g,b);
+
+ int h = blit->height;
+ const unsigned char* src_line = blit->src_line;
+ unsigned char* dst_line = blit->dst_line;
+
+ do
+ {
+ const unsigned char* src = src_line + blit->src_x*3;
+ unsigned char* dst = dst_line + blit->dst_x*GDST_INCR;
+ int w = blit->width;
+
+ do
+ {
+ int ar = GBLENDER_SHADE_INDEX(src[0]);
+ int ag = GBLENDER_SHADE_INDEX(src[1]);
+ int ab = GBLENDER_SHADE_INDEX(src[2]);
+ int aa = (ar << 16) | (ag << 8) | ab;
+
+ if ( aa == 0 )
+ {
+ /* nothing */
+ }
+ else if ( aa == ((GBLENDER_SHADE_COUNT << 16) |
+ (GBLENDER_SHADE_COUNT << 8) |
+ (GBLENDER_SHADE_COUNT) ) )
+ {
+ GDST_COPY(dst);
+ }
+ else
+ {
+ GBlenderPixel back;
+ int pix_r, pix_g, pix_b;
+
+ GDST_READ(dst,back);
+
+ {
+ int back_r = (back >> 16) & 255;
+
+ GBLENDER_LOOKUP_R( blender, back_r );
+
+ pix_r = _grcells[ar];
+ }
+
+ {
+ int back_g = (back >> 8) & 255;
+
+ GBLENDER_LOOKUP_G( blender, back_g );
+
+ pix_g = _ggcells[ag];
+ }
+
+ {
+ int back_b = (back) & 255;
+
+ GBLENDER_LOOKUP_B( blender, back_b );
+
+ pix_b = _gbcells[ab];
+ }
+
+ GDST_STOREC(dst,pix_r,pix_g,pix_b);
+ }
+
+ src += 3;
+ dst += GDST_INCR;
+ }
+ while (--w > 0);
+
+ src_line += blit->src_pitch;
+ dst_line += blit->dst_pitch;
+ }
+ while (--h > 0);
+
+ GBLENDER_CHANNEL_CLOSE(blender);
+
diff --git a/kernel/kls_ttf/ftview/gblvbgr.h b/kernel/kls_ttf/ftview/gblvbgr.h
new file mode 100644
index 0000000..48565ff
--- /dev/null
+++ b/kernel/kls_ttf/ftview/gblvbgr.h
@@ -0,0 +1,76 @@
+
+ GBLENDER_CHANNEL_VARS(blender,r,g,b);
+
+ int h = blit->height;
+ const unsigned char* src_line = blit->src_line;
+ int src_pitch = blit->src_pitch;
+ unsigned char* dst_line = blit->dst_line;
+
+ do
+ {
+ const unsigned char* src = src_line + blit->src_x;
+ unsigned char* dst = dst_line + blit->dst_x*GDST_INCR;
+ int w = blit->width;
+
+ do
+ {
+ int ab = GBLENDER_SHADE_INDEX(src[0]);
+ int ag = GBLENDER_SHADE_INDEX(src[src_pitch]);
+ int ar = GBLENDER_SHADE_INDEX(src[src_pitch << 1]);
+ GBlenderPixel aa = ((GBlenderPixel)ar << 16) | (ag << 8) | ab;
+
+ if ( aa == 0 )
+ {
+ /* nothing */
+ }
+ else if ( aa == ((GBLENDER_SHADE_COUNT << 16) |
+ (GBLENDER_SHADE_COUNT << 8) |
+ (GBLENDER_SHADE_COUNT) ) )
+ {
+ GDST_COPY(dst);
+ }
+ else
+ {
+ GBlenderPixel back;
+ int pix_r, pix_g, pix_b;
+
+ GDST_READ(dst,back);
+
+ {
+ int back_r = (back >> 16) & 255;
+
+ GBLENDER_LOOKUP_R( blender, back_r );
+
+ pix_r = _grcells[ar];
+ }
+
+ {
+ int back_g = (back >> 8) & 255;
+
+ GBLENDER_LOOKUP_G( blender, back_g );
+
+ pix_g = _ggcells[ag];
+ }
+
+ {
+ int back_b = (back) & 255;
+
+ GBLENDER_LOOKUP_B( blender, back_b );
+
+ pix_b = _gbcells[ab];
+ }
+
+ GDST_STOREC(dst,pix_r,pix_g,pix_b);
+ }
+
+ src += 1;
+ dst += GDST_INCR;
+ }
+ while (--w > 0);
+
+ src_line += blit->src_pitch*3;
+ dst_line += blit->dst_pitch;
+ }
+ while (--h > 0);
+
+ GBLENDER_CHANNEL_CLOSE(blender);
diff --git a/kernel/kls_ttf/ftview/gblvrgb.h b/kernel/kls_ttf/ftview/gblvrgb.h
new file mode 100644
index 0000000..d31aaa9
--- /dev/null
+++ b/kernel/kls_ttf/ftview/gblvrgb.h
@@ -0,0 +1,76 @@
+
+ GBLENDER_CHANNEL_VARS(blender,r,g,b);
+
+ int h = blit->height;
+ const unsigned char* src_line = blit->src_line;
+ int src_pitch = blit->src_pitch;
+ unsigned char* dst_line = blit->dst_line;
+
+ do
+ {
+ const unsigned char* src = src_line + blit->src_x;
+ unsigned char* dst = dst_line + blit->dst_x*GDST_INCR;
+ int w = blit->width;
+
+ do
+ {
+ int ar = GBLENDER_SHADE_INDEX(src[0]);
+ int ag = GBLENDER_SHADE_INDEX(src[src_pitch]);
+ int ab = GBLENDER_SHADE_INDEX(src[src_pitch << 1]);
+ GBlenderPixel aa = ((GBlenderPixel)ar << 16) | (ag << 8) | ab;
+
+ if ( aa == 0 )
+ {
+ /* nothing */
+ }
+ else if ( aa == ((GBLENDER_SHADE_COUNT << 16) |
+ (GBLENDER_SHADE_COUNT << 8) |
+ (GBLENDER_SHADE_COUNT) ) )
+ {
+ GDST_COPY(dst);
+ }
+ else
+ {
+ GBlenderPixel back;
+ int pix_r, pix_g, pix_b;
+
+ GDST_READ(dst,back);
+
+ {
+ int back_r = (back >> 16) & 255;
+
+ GBLENDER_LOOKUP_R( blender, back_r );
+
+ pix_r = _grcells[ar];
+ }
+
+ {
+ int back_g = (back >> 8) & 255;
+
+ GBLENDER_LOOKUP_G( blender, back_g );
+
+ pix_g = _ggcells[ag];
+ }
+
+ {
+ int back_b = (back) & 255;
+
+ GBLENDER_LOOKUP_B( blender, back_b );
+
+ pix_b = _gbcells[ab];
+ }
+
+ GDST_STOREC(dst,pix_r,pix_g,pix_b);
+ }
+
+ src += 1;
+ dst += GDST_INCR;
+ }
+ while (--w > 0);
+
+ src_line += blit->src_pitch*3;
+ dst_line += blit->dst_pitch;
+ }
+ while (--h > 0);
+
+ GBLENDER_CHANNEL_CLOSE(blender);
diff --git a/kernel/kls_ttf/ftview/graph.h b/kernel/kls_ttf/ftview/graph.h
new file mode 100644
index 0000000..81f1716
--- /dev/null
+++ b/kernel/kls_ttf/ftview/graph.h
@@ -0,0 +1,653 @@
+/***************************************************************************
+ *
+ * graph.h
+ *
+ * Graphics Subsystem interface
+ *
+ * Copyright 1999, 2000, 2001, 2002
+ * - The FreeType Development Team - www.freetype.org
+ *
+ ***************************************************************************/
+
+#ifndef GRAPH_H
+#define GRAPH_H
+
+#include "grevents.h"
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /******** ********/
+ /******** GENERAL DEFINITIONS AND BLITTING ROUTINES ********/
+ /******** ********/
+ /******** ********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* define the global error variable */
+ extern int grError;
+
+ /* initialisation */
+ extern int grInit( void );
+
+ /* finalisation */
+ extern void grDone( void );
+
+
+ /* pixel mode constants */
+ typedef enum grPixelMode
+ {
+ gr_pixel_mode_none = 0,
+ gr_pixel_mode_mono, /* monochrome bitmaps */
+ gr_pixel_mode_pal4, /* 4-bit paletted - 16 colors */
+ gr_pixel_mode_pal8, /* 8-bit paletted - 256 colors */
+ gr_pixel_mode_gray, /* 8-bit gray levels */
+ gr_pixel_mode_rgb555, /* 15-bits mode - 32768 colors */
+ gr_pixel_mode_rgb565, /* 16-bits mode - 65536 colors */
+ gr_pixel_mode_rgb24, /* 24-bits mode - 16 million colors */
+ gr_pixel_mode_rgb32, /* 32-bits mode - 16 million colors */
+ gr_pixel_mode_lcd, /* horizontal RGB-decimated */
+ gr_pixel_mode_lcdv, /* vertical RGB-decimated */
+ gr_pixel_mode_lcd2, /* horizontal BGR-decimated */
+ gr_pixel_mode_lcdv2, /* vertical BGR-decimated */
+
+ gr_pixel_mode_max /* don't remove */
+
+ } grPixelMode;
+
+
+ /* forward declaration of the surface class */
+ typedef struct grSurface_ grSurface;
+
+
+ /*********************************************************************
+ *
+ * <Struct>
+ * grBitmap
+ *
+ * <Description>
+ * a simple bitmap descriptor
+ *
+ * <Fields>
+ * rows :: height in pixels
+ * width :: width in pixels
+ * pitch :: + or - the number of bytes per row
+ * mode :: pixel mode of bitmap buffer
+ * grays :: number of grays in palette for PAL8 mode. 0 otherwise
+ * buffer :: pointer to pixel buffer
+ *
+ * <Note>
+ * the 'pitch' is positive for downward flows, and negative otherwise
+ * Its absolute value is always the number of bytes taken by each
+ * bitmap row.
+ *
+ * All drawing operations will be performed within the first
+ * "width" pixels of each row (clipping is always performed).
+ *
+ ********************************************************************/
+
+ typedef struct grBitmap_
+ {
+ int rows;
+ int width;
+ int pitch;
+ grPixelMode mode;
+ int grays;
+ unsigned char* buffer;
+
+ } grBitmap;
+
+
+
+ typedef long grPos;
+ typedef char grBool;
+
+ typedef struct grVector_
+ {
+ grPos x;
+ grPos y;
+
+ } grVector;
+
+
+ typedef union grColor_
+ {
+ long value;
+ unsigned char chroma[4];
+
+ } grColor;
+
+
+
+ /**********************************************************************
+ *
+ * <Function>
+ * grNewBitmap
+ *
+ * <Description>
+ * creates a new bitmap
+ *
+ * <Input>
+ * pixel_mode :: the target surface's pixel_mode
+ * num_grays :: number of grays levels for PAL8 pixel mode
+ * width :: width in pixels
+ * height :: height in pixels
+ *
+ * <Output>
+ * bit :: descriptor of the new bitmap
+ *
+ * <Return>
+ * Error code. 0 means success.
+ *
+ * <Note>
+ * This function really allocates a pixel buffer, zero it, then
+ * returns a descriptor for it.
+ *
+ * Call grDoneBitmap when you're done with it..
+ *
+ **********************************************************************/
+
+ extern int grNewBitmap( grPixelMode pixel_mode,
+ int num_grays,
+ int width,
+ int height,
+ grBitmap *bit );
+
+
+ /**********************************************************************
+ *
+ * <Function>
+ * grBlitGlyphToBitmap
+ *
+ * <Description>
+ * writes a given glyph bitmap to a target surface.
+ *
+ * <Input>
+ * target :: handle to target bitmap
+ * glyph :: handle to source glyph bitmap
+ * x :: position of left-most pixel of glyph image in target surface
+ * y :: position of top-most pixel of glyph image in target surface
+ * color :: color to be used to draw a monochrome glyph
+ *
+ * <Return>
+ * Error code. 0 means success
+ *
+ * <Note>
+ * There are only two supported source pixel modes : monochrome
+ * and gray. The 8-bit images can have any number of grays between
+ * 2 and 128, and conversions to the target surface is handled
+ * _automatically_.
+ *
+ * Note however that you should avoid blitting a gray glyph to a gray
+ * bitmap with fewer levels of grays, as this would much probably
+ * give unpleasant results..
+ *
+ * This function performs clipping
+ *
+ **********************************************************************/
+
+ extern int
+ grBlitGlyphToBitmap( grBitmap* target,
+ grBitmap* glyph,
+ grPos x,
+ grPos y,
+ grColor color );
+
+
+ /**********************************************************************
+ *
+ * <Function>
+ * grFillRectangle
+ *
+ * <Description>
+ * this function is used to fill a given rectangle on a surface
+ *
+ * <Input>
+ * surface :: handle to target surface
+ * x :: x coordinate of the top-left corner of the rectangle
+ * y :: y coordinate of the top-left corner of the rectangle
+ * width :: rectangle width in pixels
+ * height :: rectangle height in pixels
+ * color :: fill color
+ *
+ **********************************************************************/
+
+ extern void grFillRectangle( grBitmap* surface,
+ grPos x,
+ grPos y,
+ grPos width,
+ grPos height,
+ grColor color );
+
+
+
+ /**********************************************************************
+ *
+ * <Function>
+ * grWriteCellChar
+ *
+ * <Description>
+ * The graphics sub-system contains an internal Latin1 8x8 font
+ * which can be used to display simple strings of text without
+ * using FreeType.
+ *
+ * This function writes a single 8x8 character on the target bitmap.
+ *
+ * <Input>
+ * target :: handle to target surface
+ * x :: x pixel position of character cell's top left corner
+ * y :: y pixel position of character cell's top left corner
+ * charcode :: Latin-1 character code
+ * color :: color to be used to draw the character
+ *
+ **********************************************************************/
+
+ extern
+ void grWriteCellChar( grBitmap* target,
+ int x,
+ int y,
+ int charcode,
+ grColor color );
+
+
+ /**********************************************************************
+ *
+ * <Function>
+ * grWriteCellString
+ *
+ * <Description>
+ * The graphics sub-system contains an internal Latin1 8x8 font
+ * which can be used to display simple strings of text without
+ * using FreeType.
+ *
+ * This function writes a string with the internal font
+ *
+ * <Input>
+ * target :: handle to target bitmap
+ * x :: x pixel position of string's top left corner
+ * y :: y pixel position of string's top left corner
+ * string :: Latin-1 text string
+ * color :: color to be used to draw the character
+ *
+ **********************************************************************/
+
+ extern
+ void grWriteCellString( grBitmap* target,
+ int x,
+ int y,
+ const char* string,
+ grColor color );
+
+ /**********************************************************************
+ *
+ * <Function>
+ * grDoneBitmap
+ *
+ * <Description>
+ * destroys a bitmap
+ *
+ * <Input>
+ * bitmap :: handle to bitmap descriptor
+ *
+ * <Note>
+ * This function does NOT release the bitmap descriptor, only
+ * the pixel buffer.
+ *
+ **********************************************************************/
+
+ extern void grDoneBitmap( grBitmap* bit );
+
+
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /******** ********/
+ /******** DEVICE-SPECIFIC DEFINITIONS AND ROUTINES ********/
+ /******** ********/
+ /******** ********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* forward declaration - the definition of grDevice is not visible */
+ /* to clients.. */
+ typedef struct grDevice_ grDevice;
+
+
+ /**********************************************************************
+ *
+ * <Struct>
+ * grDeviceChain
+ *
+ * <Description>
+ * a simple structure used to implement a linked list of
+ * graphics device descriptors. The list is called a
+ * "device chain"
+ *
+ * <Fields>
+ * name :: ASCII name of the device, e.g. "x11", "os2pm", etc..
+ * device :: handle to the device descriptor.
+ * next :: next element in chain
+ *
+ * <Note>
+ * the 'device' field is a blind pointer; it is thus unusable by
+ * client applications..
+ *
+ **********************************************************************/
+
+ typedef struct grDeviceChain_ grDeviceChain;
+
+ struct grDeviceChain_
+ {
+ const char* name;
+ grDevice* device;
+ grDeviceChain* next;
+ };
+
+
+ /**********************************************************************
+ *
+ * <Function>
+ * grInitDevices
+ *
+ * <Description>
+ * This function is in charge of initialising all system-specific
+ * devices. A device is responsible for creating and managing one
+ * or more "surfaces". A surface is either a window or a screen,
+ * depending on the system.
+ *
+ * <Return>
+ * a pointer to the first element of a device chain. The chain can
+ * be parsed to find the available devices on the current system
+ *
+ * <Note>
+ * If a device cannot be initialised correctly, it is not part of
+ * the device chain returned by this function. For example, if an
+ * X11 device was compiled in the library, it will be part of
+ * the returned device chain only if a connection to the display
+ * could be establisged
+ *
+ * If no driver could be initialised, this function returns NULL.
+ *
+ **********************************************************************/
+
+ extern
+ grDeviceChain* grInitDevices( void );
+
+
+
+ /**********************************************************************
+ *
+ * <Function>
+ * grGetDeviceModes
+ *
+ * <Description>
+ * queries the available pixel modes for a device.
+ *
+ * <Input>
+ * device_name :: name of device to be used. 0 for the default
+ * device. For a list of available devices, see
+ * grInitDevices.
+ *
+ * <Output>
+ * num_modes :: number of available modes. 0 in case of error,
+ * which really is an invalid device name.
+ *
+ * pixel_modes :: array of available pixel modes for this device
+ * this table is internal to the device and should
+ * not be freed by client applications.
+ *
+ * <Return>
+ * error code. 0 means success. invalid device name otherwise
+ *
+ * <Note>
+ * All drivers are _required_ to support at least the following
+ * pixel formats :
+ *
+ * - gr_pixel_mode_mono : i.e. monochrome bitmaps
+ * - gr_pixel_mode_gray : with any number of gray levels between
+ * 2 and 256.
+ *
+ * the pixel modes do not provide the number of grays in the case
+ * of "gray" devices. You should try to create a surface with the
+ * maximal number (256, that is) and see the value returned in
+ * the bitmap descriptor.
+ *
+ **********************************************************************/
+
+ extern void grGetDeviceModes( const char* device_name,
+ int *num_modes,
+ grPixelMode* *pixel_modes );
+
+
+
+ /**********************************************************************
+ *
+ * <Function>
+ * grNewSurface
+ *
+ * <Description>
+ * creates a new device-specific surface. A surface is either
+ * a window or a screen, depending on the device.
+ *
+ * <Input>
+ * device :: name of the device to use. A value of NULL means
+ * the default device (which depends on the system).
+ * for a list of available devices, see grInitDevices.
+ *
+ * <InOut>
+ * bitmap :: handle to a bitmap descriptor containing the
+ * requested pixel mode, number of grays and dimensions
+ * for the surface. the bitmap's 'pitch' and 'buffer'
+ * fields are ignored on input.
+ *
+ * On output, the bitmap describes the surface's image
+ * completely. It is possible to write directly in it
+ * with grBlitGlyphToBitmap, even though the use of
+ * grBlitGlyphToSurface is recommended.
+ *
+ * <Return>
+ * handle to the corresponding surface object. 0 in case of error
+ *
+ * <Note>
+ * All drivers are _required_ to support at least the following
+ * pixel formats :
+ *
+ * - gr_pixel_mode_mono : i.e. monochrome bitmaps
+ * - gr_pixel_mode_gray : with any number of gray levels between
+ * 2 and 256.
+ *
+ * This function might change the bitmap descriptor's fields. For
+ * example, when displaying a full-screen surface, the bitmap's
+ * dimensions will be set to those of the screen (e.g. 640x480
+ * or 800x600); also, the bitmap's 'buffer' field might point to
+ * the Video Ram depending on the mode requested..
+ *
+ * The surface contains a copy of the returned bitmap descriptor,
+ * you can thus discard the 'bitmap' parameter after the call.
+ *
+ **********************************************************************/
+
+ extern grSurface* grNewSurface( const char* device,
+ grBitmap* bitmap );
+
+
+
+ /**********************************************************************
+ *
+ * <Function>
+ * grRefreshRectangle
+ *
+ * <Description>
+ * this function is used to indicate that a given surface rectangle
+ * was modified and thus needs re-painting. It really is useful for
+ * windowed or gray surfaces.
+ *
+ * <Input>
+ * surface :: handle to target surface
+ * x :: x coordinate of the top-left corner of the rectangle
+ * y :: y coordinate of the top-left corner of the rectangle
+ * width :: rectangle width in pixels
+ * height :: rectangle height in pixels
+ *
+ **********************************************************************/
+
+ extern void grRefreshRectangle( grSurface* surface,
+ grPos x,
+ grPos y,
+ grPos width,
+ grPos height );
+
+
+ /**********************************************************************
+ *
+ * <Function>
+ * grRefreshSurface
+ *
+ * <Description>
+ * a variation of grRefreshRectangle which repaints the whole surface
+ * to the screen.
+ *
+ * <Input>
+ * surface :: handle to target surface
+ *
+ **********************************************************************/
+
+ extern void grRefreshSurface( grSurface* surface );
+
+
+
+ /**********************************************************************
+ *
+ * <Function>
+ * grWriteSurfaceChar
+ *
+ * <Description>
+ * This function is equivalent to calling grWriteCellChar on the
+ * surface's bitmap, then invoking grRefreshRectangle.
+ *
+ * The graphics sub-system contains an internal Latin1 8x8 font
+ * which can be used to display simple strings of text without
+ * using FreeType.
+ *
+ * This function writes a single 8x8 character on the target bitmap.
+ *
+ * <Input>
+ * target :: handle to target surface
+ * x :: x pixel position of character cell's top left corner
+ * y :: y pixel position of character cell's top left corner
+ * charcode :: Latin-1 character code
+ * color :: color to be used to draw the character
+ *
+ **********************************************************************/
+
+ extern
+ void grWriteSurfaceChar( grSurface* target,
+ int x,
+ int y,
+ int charcode,
+ grColor color );
+
+
+ /**********************************************************************
+ *
+ * <Function>
+ * grWriteSurfaceString
+ *
+ * <Description>
+ * This function is equivalent to calling grWriteCellString on the
+ * surface's bitmap, then invoking grRefreshRectangle.
+ *
+ * The graphics sub-system contains an internal Latin1 8x8 font
+ * which can be used to display simple strings of text without
+ * using FreeType.
+ *
+ * This function writes a string with the internal font
+ *
+ * <Input>
+ * target :: handle to target bitmap
+ * x :: x pixel position of string's top left corner
+ * y :: y pixel position of string's top left corner
+ * string :: Latin-1 text string
+ * color :: color to be used to draw the character
+ *
+ **********************************************************************/
+
+ extern
+ void grWriteSurfaceString( grSurface* target,
+ int x,
+ int y,
+ const char* string,
+ grColor color );
+
+
+ /**********************************************************************
+ *
+ * <Function>
+ * grSetTitle
+ *
+ * <Description>
+ * set the window title of a given windowed surface.
+ *
+ * <Input>
+ * surface :: handle to target surface
+ * title_string :: the new title
+ *
+ **********************************************************************/
+
+ extern void grSetTitle( grSurface* surface,
+ const char* title_string );
+
+
+
+
+ /**********************************************************************
+ *
+ * <Function>
+ * grListenSurface
+ *
+ * <Description>
+ * listen the events for a given surface
+ *
+ * <Input>
+ * surface :: handle to target surface
+ * event_mask :: the event mask (mode)
+ *
+ * <Output>
+ * event :: the returned event
+ *
+ * <Note>
+ * XXX : For now, only keypresses are supported.
+ *
+ **********************************************************************/
+
+ extern
+ int grListenSurface( grSurface* surface,
+ int event_mask,
+ grEvent *event );
+
+ /**********************************************************************
+ *
+ * <Function>
+ * grSetGlyphGamma
+ *
+ * <Description>
+ * set the gamma-correction coefficient. This is only used to
+ * blit glyphs
+ *
+ * <Input>
+ * gamma :: gamma value. <= 0 to select sRGB transfer function
+ *
+ **********************************************************************/
+
+ extern
+ void grSetGlyphGamma( double gamma_value );
+
+/* */
+
+#endif /* GRAPH_H */
diff --git a/kernel/kls_ttf/ftview/grblit.cpp b/kernel/kls_ttf/ftview/grblit.cpp
new file mode 100644
index 0000000..18046ab
--- /dev/null
+++ b/kernel/kls_ttf/ftview/grblit.cpp
@@ -0,0 +1,2068 @@
+/****************************************************************************/
+/* */
+/* The FreeType project -- a free and portable quality TrueType renderer. */
+/* */
+/* Copyright 1996-1999, 2000, 2001, 2002 by */
+/* D. Turner, R.Wilhelm, and W. Lemberg */
+/* */
+/* grblit.c: Support for blitting of bitmaps with various depth. */
+/* */
+/****************************************************************************/
+
+#include "grblit.h"
+#include "grobjs.h"
+
+#include <stdio.h>
+
+#define GRAY8
+
+ static
+ int compute_clips( grBlitter* blit,
+ int x_offset,
+ int y_offset )
+ {
+ int xmin, ymin, xmax, ymax, width, height, target_width;
+
+ /* perform clipping and setup variables */
+ width = blit->source.width;
+ height = blit->source.rows;
+
+ switch ( blit->source.mode )
+ {
+ case gr_pixel_mode_mono:
+ width = (width + 7) & -8;
+ break;
+
+ case gr_pixel_mode_pal4:
+ width = (width + 1) & -2;
+ break;
+
+ case gr_pixel_mode_lcd:
+ case gr_pixel_mode_lcd2:
+ width /= 3;
+ break;
+
+ case gr_pixel_mode_lcdv:
+ case gr_pixel_mode_lcdv2:
+ height /= 3;
+ break;
+
+ default:
+ ;
+ }
+
+ xmin = x_offset;
+ ymin = y_offset;
+ xmax = xmin + width-1;
+ ymax = ymin + height-1;
+
+ /* clip if necessary */
+ if ( width == 0 || height == 0 ||
+ xmax < 0 || xmin >= blit->target.width ||
+ ymax < 0 || ymin >= blit->target.rows )
+ return 1;
+
+ /* set up clipping and cursors */
+ blit->yread = 0;
+ if ( ymin < 0 )
+ {
+ blit->yread -= ymin;
+ height += ymin;
+ blit->ywrite = 0;
+ }
+ else
+ blit->ywrite = ymin;
+
+ if ( ymax >= blit->target.rows )
+ height -= ymax - blit->target.rows + 1;
+
+ blit->xread = 0;
+ if ( xmin < 0 )
+ {
+ blit->xread -= xmin;
+ width += xmin;
+ blit->xwrite = 0;
+ }
+ else
+ blit->xwrite = xmin;
+
+ target_width = blit->target.width;
+
+ switch ( blit->target.mode )
+ {
+ case gr_pixel_mode_mono:
+ target_width = (target_width + 7) & -8;
+ break;
+ case gr_pixel_mode_pal4:
+ target_width = (target_width + 1) & -2;
+ break;
+
+ default:
+ ;
+ }
+
+ blit->right_clip = xmax - target_width + 1;
+ if ( blit->right_clip > 0 )
+ width -= blit->right_clip;
+ else
+ blit->right_clip = 0;
+
+ blit->width = width;
+ blit->height = height;
+
+ /* set read and write to the top-left corner of the read */
+ /* and write areas before clipping. */
+
+ blit->read = blit->source.buffer;
+ blit->write = blit->target.buffer;
+
+ blit->read_line = blit->source.pitch;
+ blit->write_line = blit->target.pitch;
+
+ if ( blit->read_line < 0 )
+ blit->read -= (blit->source.rows-1) * blit->read_line;
+
+ if ( blit->write_line < 0 )
+ blit->write -= (blit->target.rows-1) * blit->write_line;
+
+ /* now go to the start line. Note that we do not move the */
+ /* x position yet, as this is dependent on the pixel format */
+ blit->read += blit->yread * blit->read_line;
+ blit->write += blit->ywrite * blit->write_line;
+
+ return 0;
+ }
+
+
+/**************************************************************************/
+/* */
+/* <Function> blit_mono_to_mono */
+/* */
+/**************************************************************************/
+
+ static
+ void blit_mono_to_mono( grBlitter* blit,
+ grColor color )
+ {
+ int shift, left_clip, x, y;
+ byte* read;
+ byte* write;
+
+ (void)color; /* unused argument */
+
+ left_clip = ( blit->xread > 0 );
+ shift = ( blit->xwrite - blit->xread ) & 7;
+
+ read = blit->read + (blit->xread >> 3);
+ write = blit->write + (blit->xwrite >> 3);
+
+ if ( shift == 0 )
+ {
+ y = blit->height;
+ do
+ {
+ byte* _read = read;
+ byte* _write = write;
+
+ x = blit->width;
+
+ do
+ {
+ *_write++ |= *_read++;
+ x -= 8;
+ } while ( x > 0 );
+
+ read += blit->read_line;
+ write += blit->write_line;
+ y--;
+ } while ( y > 0 );
+ }
+ else
+ {
+ int first, last, count;
+
+
+ first = blit->xwrite >> 3;
+ last = (blit->xwrite + blit->width-1) >> 3;
+
+ count = last - first;
+
+ if ( blit->right_clip )
+ count++;
+
+ y = blit->height;
+
+ do
+ {
+ unsigned char* _read = read;
+ unsigned char* _write = write;
+ unsigned int old;
+ int shift2 = (8-shift);
+
+ if ( left_clip )
+ old = (*_read++) << shift2;
+ else
+ old = 0;
+
+ x = count;
+ while ( x > 0 )
+ {
+ unsigned char val;
+
+ val = *_read++;
+ *_write++ |= (unsigned char)( (val >> shift) | old );
+ old = val << shift2;
+ x--;
+ }
+
+ if ( !blit->right_clip )
+ *_write |= (unsigned char)old;
+
+ read += blit->read_line;
+ write += blit->write_line;
+ y--;
+
+ } while ( y > 0 );
+ }
+ }
+
+
+/**************************************************************************/
+/* */
+/* <Function> blit_mono_to_pal8 */
+/* */
+/**************************************************************************/
+
+ static
+ void blit_mono_to_pal8( grBlitter* blit,
+ grColor color )
+ {
+ int x, y, shift;
+ unsigned char* read;
+ unsigned char* write;
+
+ read = blit->read + (blit->xread >> 3);
+ write = blit->write + blit->xwrite;
+ shift = blit->xread & 7;
+
+ y = blit->height;
+ do
+ {
+ unsigned char* _read = read;
+ unsigned char* _write = write;
+ unsigned long val = (*_read++ | 0x100) << shift;
+
+ x = blit->width;
+ do
+ {
+ if (val & 0x10000)
+ val = *_read++ | 0x100;
+
+ if ( val & 0x80 )
+ *_write = (unsigned char)color.value;
+
+ val <<= 1;
+ _write++;
+
+ } while ( --x > 0 );
+
+ read += blit->read_line;
+ write += blit->write_line;
+ y--;
+ } while ( y > 0 );
+ }
+
+
+/**************************************************************************/
+/* */
+/* <Function> blit_mono_to_pal4 */
+/* */
+/**************************************************************************/
+
+ static
+ void blit_mono_to_pal4( grBlitter* blit,
+ grColor color )
+ {
+ int x, y, phase,shift;
+ unsigned char* read;
+ unsigned char* write;
+ unsigned int col;
+
+
+ col = color.value & 15;
+ read = blit->read + (blit->xread >> 3);
+ write = blit->write + (blit->xwrite >> 1);
+
+ /* now begin blit */
+ shift = blit->xread & 7;
+ phase = blit->xwrite & 1;
+
+ y = blit->height;
+ do
+ {
+ unsigned char* _read = read;
+ unsigned char* _write = write;
+ int _phase = phase;
+ unsigned long val = (*_read++ | 0x100) << shift;
+
+ x = blit->width;
+ do
+ {
+ if (val & 0x10000)
+ val = *_read++ | 0x100;
+
+ if ( val & 0x80 )
+ {
+ if ( _phase )
+ *_write = (unsigned char)((*_write & 0xF0) | col);
+ else
+ *_write = (unsigned char)((*_write & 0x0F) | (col << 4));
+ }
+
+ val <<= 1;
+
+ _write += _phase;
+ _phase ^= 1;
+ x--;
+ } while ( x > 0 );
+
+ read += blit->read_line;
+ write += blit->write_line;
+ y--;
+ } while ( y > 0 );
+ }
+
+
+/**************************************************************************/
+/* */
+/* <Function> blit_mono_to_rgb16 */
+/* */
+/**************************************************************************/
+
+ static
+ void blit_mono_to_rgb16( grBlitter* blit,
+ grColor color )
+ {
+ int x, y,shift;
+ unsigned char* read;
+ unsigned char* write;
+
+ read = blit->read + (blit->xread >> 3);
+ write = blit->write + blit->xwrite*2;
+ shift = blit->xread & 7;
+
+ y = blit->height;
+ do
+ {
+ unsigned char* _read = read;
+ unsigned char* _write = write;
+ unsigned long val = (*_read++ | 0x100) << shift;
+
+ x = blit->width;
+ do
+ {
+ if (val & 0x10000)
+ val = *_read++ | 0x100;
+
+ if ( val & 0x80 )
+ *(short*)_write = (short)color.value;
+
+ val <<= 1;
+ _write +=2;
+ x--;
+ } while ( x > 0 );
+
+ read += blit->read_line;
+ write += blit->write_line;
+ y--;
+ } while ( y > 0 );
+ }
+
+
+/**************************************************************************/
+/* */
+/* <Function> blit_mono_to_rgb24 */
+/* */
+/**************************************************************************/
+
+ static
+ void blit_mono_to_rgb24( grBlitter* blit,
+ grColor color )
+ {
+ int x, y, shift;
+ unsigned char* read;
+ unsigned char* write;
+
+ read = blit->read + (blit->xread >> 3);
+ write = blit->write + blit->xwrite*3;
+ shift = blit->xread & 7;
+
+ y = blit->height;
+ do
+ {
+ unsigned char* _read = read;
+ unsigned char* _write = write;
+ unsigned long val = (*_read++ | 0x100) << shift;
+
+ x = blit->width;
+ do
+ {
+ if (val & 0x10000)
+ val = *_read++ | 0x100;
+
+ if ( val & 0x80 )
+ {
+ _write[0] = color.chroma[0];
+ _write[1] = color.chroma[1];
+ _write[2] = color.chroma[2];
+ }
+
+ val <<= 1;
+ _write += 3;
+ x--;
+ } while ( x > 0 );
+
+ read += blit->read_line;
+ write += blit->write_line;
+ y--;
+ } while ( y > 0 );
+ }
+
+
+/**************************************************************************/
+/* */
+/* <Function> blit_mono_to_rgb32 */
+/* */
+/**************************************************************************/
+
+ static
+ void blit_mono_to_rgb32( grBlitter* blit,
+ grColor color )
+ {
+ int x, y,shift;
+ unsigned char* read;
+ unsigned char* write;
+
+ read = blit->read + ( blit->xread >> 3 );
+ write = blit->write + blit->xwrite*4;
+ shift = blit->xread & 7;
+
+ y = blit->height;
+ do
+ {
+ unsigned char* _read = read;
+ unsigned char* _write = write;
+ unsigned long val = ( *_read++ | 0x100L ) << shift;
+
+ x = blit->width;
+ do
+ {
+ if ( val & 0x10000 )
+ val = *_read++ | 0x100L;
+
+ if ( val & 0x80 )
+ {
+ /* this could be greatly optimized as */
+ /* */
+ /* *(long*)_write = color.value */
+ /* */
+ /* but it wouldn't work on 64-bits systems... stupid C types! */
+ _write[0] = color.chroma[0];
+ _write[1] = color.chroma[1];
+ _write[2] = color.chroma[2];
+ _write[3] = color.chroma[3];
+ }
+
+ val <<= 1;
+ _write += 4;
+ x--;
+
+ } while ( x > 0 );
+
+ read += blit->read_line;
+ write += blit->write_line;
+ y--;
+
+ } while ( y > 0 );
+ }
+
+
+ static
+ const grBlitterFunc gr_mono_blitters[gr_pixel_mode_max] =
+ {
+ 0,
+ blit_mono_to_mono,
+ blit_mono_to_pal4,
+ blit_mono_to_pal8,
+ blit_mono_to_pal8,
+ blit_mono_to_rgb16,
+ blit_mono_to_rgb16,
+ blit_mono_to_rgb24,
+ blit_mono_to_rgb32
+ };
+
+
+ /*******************************************************************/
+ /* */
+ /* Saturation tables */
+ /* */
+ /*******************************************************************/
+
+ typedef struct grSaturation_
+ {
+ int count;
+ const byte* table;
+
+ } grSaturation;
+
+
+ static
+ const byte gr_saturation_5[8] = { 0, 1, 2, 3, 4, 4, 4, 4 };
+
+
+ static
+ const byte gr_saturation_17[32] =
+ {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ };
+
+
+ static
+ grSaturation gr_saturations[ GR_MAX_SATURATIONS ] =
+ {
+ { 5, gr_saturation_5 },
+ { 17, gr_saturation_17 }
+ };
+
+ static
+ int gr_num_saturations = 2;
+
+ static
+ grSaturation* gr_last_saturation = gr_saturations;
+
+
+ extern
+ const byte* grGetSaturation( int num_grays )
+ {
+ /* first of all, scan the current saturations table */
+ grSaturation* sat = gr_saturations;
+ grSaturation* limit = sat + gr_num_saturations;
+
+ if ( num_grays < 2 )
+ {
+ grError = gr_err_bad_argument;
+ return 0;
+ }
+
+ for ( ; sat < limit; sat++ )
+ {
+ if ( sat->count == num_grays )
+ {
+ gr_last_saturation = sat;
+ return sat->table;
+ }
+ }
+
+ /* not found, simply create a new entry if there is room */
+ if (gr_num_saturations < GR_MAX_SATURATIONS)
+ {
+ int i;
+ const byte* table;
+
+ table = (const byte*)grAlloc( (3*num_grays-1)*sizeof(byte) );
+ if (!table) return 0;
+
+ sat->count = num_grays;
+ sat->table = table;
+
+ for ( i = 0; i < num_grays; i++, table++ )
+ *(unsigned char*)table = (unsigned char)i;
+
+ for ( i = 2*num_grays-1; i > 0; i--, table++ )
+ *(unsigned char*)table = (unsigned char)(num_grays-1);
+
+ gr_num_saturations++;
+ gr_last_saturation = sat;
+ return sat->table;
+ }
+ grError = gr_err_saturation_overflow;
+ return 0;
+ }
+
+
+
+ /*******************************************************************/
+ /* */
+ /* conversion tables */
+ /* */
+ /*******************************************************************/
+
+ typedef struct grConversion_
+ {
+ int target_grays;
+ int source_grays;
+ const byte* table;
+
+ } grConversion;
+
+
+
+ static
+ const byte gr_gray5_to_gray17[5] = { 0, 4, 8, 12, 16 };
+
+
+ static
+ const byte gr_gray5_to_gray128[5] = { 0, 32, 64, 96, 127 };
+
+
+ static
+ const unsigned char gr_gray17_to_gray128[17] =
+ {
+ 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 127
+ };
+
+ static
+ grConversion gr_conversions[ GR_MAX_CONVERSIONS ] =
+ {
+ { 17, 5, gr_gray5_to_gray17 },
+ { 128, 5, gr_gray5_to_gray128 },
+ { 128, 17, gr_gray17_to_gray128 }
+ };
+
+ static
+ int gr_num_conversions = 3;
+
+ static
+ grConversion* gr_last_conversion = gr_conversions;
+
+
+ extern
+ const byte* grGetConversion( int target_grays,
+ int source_grays )
+ {
+ grConversion* conv = gr_conversions;
+ grConversion* limit = conv + gr_num_conversions;
+
+ if ( target_grays < 2 || source_grays < 2 )
+ {
+ grError = gr_err_bad_argument;
+ return 0;
+ }
+
+ /* otherwise, scan table */
+ for ( ; conv < limit; conv++ )
+ {
+ if ( conv->target_grays == target_grays &&
+ conv->source_grays == source_grays )
+ {
+ gr_last_conversion = conv;
+ return conv->table;
+ }
+ }
+
+ /* not found, add a new conversion to the table */
+ if (gr_num_conversions < GR_MAX_CONVERSIONS)
+ {
+ const byte* table;
+ int n;
+
+ table = (const byte*)grAlloc( source_grays*sizeof(byte) );
+ if (!table)
+ return 0;
+
+ conv->target_grays = target_grays;
+ conv->source_grays = source_grays;
+ conv->table = table;
+
+ for ( n = 0; n < source_grays; n++ )
+ ((unsigned char*)table)[n] = (unsigned char)(n*(target_grays-1) /
+ (source_grays-1));
+
+ gr_num_conversions++;
+ gr_last_conversion = conv;
+ return table;
+ }
+ grError = gr_err_conversion_overflow;
+ return 0;
+ }
+
+
+
+
+/**************************************************************************/
+/* */
+/* <Function> blit_gray_to_gray */
+/* */
+/**************************************************************************/
+
+ static
+ void blit_gray_to_gray( grBlitter* blit,
+ const byte* saturation,
+ const byte* conversion )
+ {
+ int y;
+ unsigned char* read;
+ unsigned char* write;
+ unsigned char max1;
+ unsigned char max2;
+
+ max1 = (unsigned char)(blit->source.grays-1);
+ max2 = (unsigned char)(blit->target.grays-1);
+
+ read = blit->read + blit->xread;
+ write = blit->write + blit->xwrite;
+
+ y = blit->height;
+ do
+ {
+ unsigned char* _read = read;
+ unsigned char* _write = write;
+ int x = blit->width;
+
+ while (x > 0)
+ {
+#ifdef GR_CONFIG_GRAY_SKIP_WHITE
+ unsigned char val = *_read;
+
+ if (val)
+ {
+ if (val == max)
+ *_write = max2;
+ else
+ *_write = saturation[ (int)*_write + conversion[ *_read ] ];
+ }
+#else
+ *_write = saturation[ (int)*_write + conversion[ *_read ] ];
+#endif
+ _write++;
+ _read++;
+ x--;
+ }
+
+ read += blit->read_line;
+ write += blit->write_line;
+ y--;
+ }
+ while (y > 0);
+ }
+
+
+/**************************************************************************/
+/* */
+/* <Function> blit_gray_to_gray_simple */
+/* */
+/**************************************************************************/
+
+ static
+ void blit_gray_to_gray_simple( grBlitter* blit,
+ const byte* saturation )
+ {
+ int y;
+ unsigned char* read;
+ unsigned char* write;
+ unsigned char max;
+
+ max = (unsigned char)(blit->source.grays-1);
+
+ read = blit->read + blit->xread;
+ write = blit->write + blit->xwrite;
+
+ y = blit->height;
+ do
+ {
+ unsigned char* _read = read;
+ unsigned char* _write = write;
+ int x = blit->width;
+
+ while (x > 0)
+ {
+#ifdef GR_CONFIG_GRAY_SKIP_WHITE
+ unsigned char val = *_read;
+
+ if (val)
+ {
+ if (val == max)
+ *_write = val;
+ else
+ *_write = saturation[ (int)*_write + *_read ];
+ }
+#else
+ *_write = saturation[ (int)*_write + *_read ];
+#endif
+ _write++;
+ _read++;
+ x--;
+ }
+
+ read += blit->read_line;
+ write += blit->write_line;
+ y--;
+ }
+ while (y > 0);
+ }
+
+
+
+#define compose_pixel_full( a, b, n0, n1, n2, max ) \
+ { \
+ int d, half = max >> 1; \
+ \
+ \
+ d = (int)b.chroma[0] - a.chroma[0]; \
+ a.chroma[0] += (unsigned char)((n0*d + half)/max); \
+ \
+ d = (int)b.chroma[1] - a.chroma[1]; \
+ a.chroma[1] += (unsigned char)((n1*d + half)/max); \
+ \
+ d = (int)b.chroma[2] - a.chroma[2]; \
+ a.chroma[2] += (unsigned char)((n2*d + half)/max); \
+ }
+
+#define compose_pixel( a, b, n, max ) \
+ compose_pixel_full( a, b, n, n, n, max )
+
+
+#define extract555( pixel, color ) \
+ color.chroma[0] = (unsigned char)((pixel >> 10) & 0x1F); \
+ color.chroma[1] = (unsigned char)((pixel >> 5) & 0x1F); \
+ color.chroma[2] = (unsigned char)((pixel ) & 0x1F);
+
+
+#define extract565( pixel, color ) \
+ color.chroma[0] = (unsigned char)((pixel >> 11) & 0x1F); \
+ color.chroma[1] = (unsigned char)((pixel >> 5) & 0x3F); \
+ color.chroma[2] = (unsigned char)((pixel ) & 0x1F);
+
+
+#define inject555( color ) \
+ ( ( (unsigned short)color.chroma[0] << 10 ) | \
+ ( (unsigned short)color.chroma[1] << 5 ) | \
+ color.chroma[2] )
+
+
+#define inject565( color ) \
+ ( ( (unsigned short)color.chroma[0] << 11 ) | \
+ ( (unsigned short)color.chroma[1] << 5 ) | \
+ color.chroma[2] )
+
+
+/**************************************************************************/
+/* */
+/* <Function> blit_gray_to_555 */
+/* */
+/**************************************************************************/
+
+#ifdef GRAY8
+ static
+ void blit_gray8_to_555( grBlitter* blit,
+ grColor color )
+ {
+ int y;
+ int sr = (color.chroma[0] << 8) & 0x7C00;
+ int sg = (color.chroma[1] << 2) & 0x03E0;
+ int sb = (color.chroma[2] ) & 0x001F;
+ unsigned char* read;
+ unsigned char* write;
+ long color2;
+
+ read = blit->read + blit->xread;
+ write = blit->write + 2*blit->xwrite;
+
+ color2 = color.value;
+ extract565( color2, color );
+
+ y = blit->height;
+ do
+ {
+ unsigned char* _read = read;
+ unsigned char* _write = write;
+ int x = blit->width;
+
+ while (x > 0)
+ {
+ unsigned char val;
+
+ val = *_read;
+ if (val)
+ {
+ unsigned short* pixel = (unsigned short*)_write;
+
+ if (val >= 254 )
+ {
+ pixel[0] = (short)color2;
+ }
+ else if ( val >= 2 )
+ {
+ /* compose gray value */
+ int pix = (int)*pixel;
+ int dr = pix & 0x7C00;
+ int dg = pix & 0x03E0;
+ int db = pix & 0x001F;
+
+ dr = pix & 0x7C00;
+ dr += ((sr-dr)*val) >> 8;
+ dr &= 0xF800;
+
+ dg = pix & 0x03E0;
+ dg += ((sg-dg)*val) >> 8;
+ dg &= 0x7E0;
+
+ db = pix & 0x001F;
+ db += ((sb-db)*val) >> 8;
+ db += 0x001F;
+
+ *pixel = (short)( dr | dg | db );
+ }
+ }
+ _write +=2;
+ _read ++;
+ x--;
+ }
+
+ read += blit->read_line;
+ write += blit->write_line;
+ y--;
+ }
+ while (y > 0);
+
+ }
+#endif /* GRAY8 */
+
+ static
+ void blit_gray_to_555( grBlitter* blit,
+ grColor color,
+ int max )
+ {
+ int y;
+ unsigned char* read;
+ unsigned char* write;
+ long color2;
+
+ read = blit->read + blit->xread;
+ write = blit->write + 2*blit->xwrite;
+
+ /* convert color to R:G:B triplet */
+ color2 = color.value;
+ extract555( color2, color );
+
+ y = blit->height;
+ do
+ {
+ unsigned char* _read = read;
+ unsigned char* _write = write;
+ int x = blit->width;
+
+ while (x > 0)
+ {
+ unsigned char val;
+
+ val = *_read;
+ if (val)
+ {
+ unsigned short* pixel = (unsigned short*)_write;
+
+ if (val == max)
+ {
+ pixel[0] = (short)color2;
+ }
+ else
+ {
+ /* compose gray value */
+ unsigned short pix16 = *pixel;
+ grColor pix;
+
+ extract555( pix16, pix );
+
+ compose_pixel( pix, color, val, max );
+ *pixel = (unsigned short)(inject555(pix));
+ }
+ }
+ _write += 2;
+ _read ++;
+ x--;
+ }
+
+ read += blit->read_line;
+ write += blit->write_line;
+ y--;
+ }
+ while (y > 0);
+ }
+
+
+/**************************************************************************/
+/* */
+/* <Function> blit_gray_to_565 */
+/* */
+/**************************************************************************/
+
+#ifdef GRAY8
+ static
+ void blit_gray8_to_565( grBlitter* blit,
+ grColor color )
+ {
+ int y;
+ int sr = (color.chroma[0] << 8) & 0xF800;
+ int sg = (color.chroma[1] << 2) & 0x07E0;
+ int sb = (color.chroma[2] ) & 0x001F;
+ unsigned char* read;
+ unsigned char* write;
+ long color2;
+
+ read = blit->read + blit->xread;
+ write = blit->write + 2*blit->xwrite;
+
+ color2 = color.value;
+ extract565( color2, color );
+
+ y = blit->height;
+ do
+ {
+ unsigned char* _read = read;
+ unsigned char* _write = write;
+ int x = blit->width;
+
+ while (x > 0)
+ {
+ unsigned char val;
+
+ val = *_read;
+ if (val)
+ {
+ unsigned short* pixel = (unsigned short*)_write;
+
+ if (val >= 254 )
+ {
+ pixel[0] = (short)color2;
+ }
+ else if ( val >= 2 )
+ {
+ /* compose gray value */
+ int pix = (int)*pixel;
+ int dr = pix & 0xF800;
+ int dg = pix & 0x07E0;
+ int db = pix & 0x001F;
+
+ dr = pix & 0xF800;
+ dr += ((sr-dr)*val) >> 8;
+ dr &= 0xF800;
+
+ dg = pix & 0x07E0;
+ dg += ((sg-dg)*val) >> 8;
+ dg &= 0x7E0;
+
+ db = pix & 0x001F;
+ db += ((sb-db)*val) >> 8;
+ db += 0x001F;
+
+ *pixel = (short)( dr | dg | db );
+ }
+ }
+ _write +=2;
+ _read ++;
+ x--;
+ }
+
+ read += blit->read_line;
+ write += blit->write_line;
+ y--;
+ }
+ while (y > 0);
+ }
+#endif
+
+ static
+ void blit_gray_to_565( grBlitter* blit,
+ grColor color,
+ int max )
+ {
+ int y;
+ unsigned char* read;
+ unsigned char* write;
+ long color2;
+
+ read = blit->read + blit->xread;
+ write = blit->write + 2*blit->xwrite;
+
+ color2 = color.value;
+ extract565( color2, color );
+
+ y = blit->height;
+ do
+ {
+ unsigned char* _read = read;
+ unsigned char* _write = write;
+ int x = blit->width;
+
+ while (x > 0)
+ {
+ unsigned char val;
+
+ val = *_read;
+ if (val)
+ {
+ unsigned short* pixel = (unsigned short*)_write;
+
+ if (val == max)
+ {
+ pixel[0] = (short)color2;
+ }
+ else
+ {
+ /* compose gray value */
+ unsigned short pix16 = *pixel;
+ grColor pix;
+
+ extract565( pix16, pix );
+
+ compose_pixel( pix, color, val, max );
+ *pixel = (short)inject565( pix );
+ }
+ }
+ _write +=2;
+ _read ++;
+ x--;
+ }
+
+ read += blit->read_line;
+ write += blit->write_line;
+ y--;
+ }
+ while (y > 0);
+ }
+
+
+/**************************************************************************/
+/* */
+/* <Function> blit_gray_to_24 */
+/* */
+/**************************************************************************/
+
+#ifdef GRAY8
+ static void
+ blit_gray8_to_24( grBlitter* blit,
+ grColor color )
+ {
+ int y;
+ int sr = color.chroma[0];
+ int sg = color.chroma[1];
+ int sb = color.chroma[2];
+ unsigned char* read;
+ unsigned char* write;
+
+ read = blit->read + blit->xread;
+ write = blit->write + 3*blit->xwrite;
+
+ y = blit->height;
+ do
+ {
+ unsigned char* _read = read;
+ unsigned char* _write = write;
+ int x = blit->width;
+
+ while (x > 0)
+ {
+ unsigned char val;
+
+ val = *_read;
+ if (val)
+ {
+ if (val >= 254)
+ {
+ _write[0] = (unsigned char)sr;
+ _write[1] = (unsigned char)sg;
+ _write[2] = (unsigned char)sb;
+ }
+ else if ( val >= 2 )
+ {
+ int dr = _write[0];
+ int dg = _write[1];
+ int db = _write[2];
+
+ dr += ((sr-dr)*val) >> 8;
+ dg += ((sg-dg)*val) >> 8;
+ db += ((sb-db)*val) >> 8;
+
+ _write[0] = (unsigned char)dr;
+ _write[1] = (unsigned char)dg,
+ _write[2] = (unsigned char)db;
+ }
+ }
+ _write += 3;
+ _read ++;
+ x--;
+ }
+
+ read += blit->read_line;
+ write += blit->write_line;
+ y--;
+ }
+ while (y > 0);
+ }
+#endif /* GRAY8 */
+
+
+ static
+ void blit_gray_to_24( grBlitter* blit,
+ grColor color,
+ int max )
+ {
+ int y;
+ unsigned char* read;
+ unsigned char* write;
+
+ read = blit->read + blit->xread;
+ write = blit->write + 3*blit->xwrite;
+
+ y = blit->height;
+ do
+ {
+ unsigned char* _read = read;
+ unsigned char* _write = write;
+ int x = blit->width;
+
+ while (x > 0)
+ {
+ unsigned char val;
+
+ val = *_read;
+ if (val)
+ {
+ if (val == max)
+ {
+ _write[0] = color.chroma[0];
+ _write[1] = color.chroma[1];
+ _write[2] = color.chroma[2];
+ }
+ else
+ {
+ /* compose gray value */
+ grColor pix;
+
+ pix.chroma[0] = _write[0];
+ pix.chroma[1] = _write[1];
+ pix.chroma[2] = _write[2];
+
+ compose_pixel( pix, color, val, max );
+
+ _write[0] = pix.chroma[0];
+ _write[1] = pix.chroma[1];
+ _write[2] = pix.chroma[2];
+ }
+ }
+ _write += 3;
+ _read ++;
+ x--;
+ }
+
+ read += blit->read_line;
+ write += blit->write_line;
+ y--;
+ }
+ while (y > 0);
+ }
+
+
+/**************************************************************************/
+/* */
+/* <Function> blit_gray_to_32 */
+/* */
+/**************************************************************************/
+
+ static
+ void blit_gray_to_32( grBlitter* blit,
+ grColor color,
+ int max )
+ {
+ int y;
+ unsigned char* read;
+ unsigned char* write;
+
+ read = blit->read + blit->xread;
+ write = blit->write + 4*blit->xwrite;
+
+ y = blit->height;
+ do
+ {
+ unsigned char* _read = read;
+ unsigned char* _write = write;
+ int x = blit->width;
+
+ while (x > 0)
+ {
+ unsigned char val;
+
+ val = *_read;
+ if (val)
+ {
+ if (val == max)
+ {
+ _write[0] = color.chroma[0];
+ _write[1] = color.chroma[1];
+ _write[2] = color.chroma[2];
+ _write[3] = color.chroma[3];
+ }
+ else
+ {
+ /* compose gray value */
+ grColor pix;
+
+ pix.chroma[0] = _write[0];
+ pix.chroma[1] = _write[1];
+ pix.chroma[2] = _write[2];
+
+ compose_pixel( pix, color, val, max );
+
+ _write[0] = pix.chroma[0];
+ _write[1] = pix.chroma[1];
+ _write[2] = pix.chroma[2];
+ }
+ }
+ _write += 4;
+ _read ++;
+ x--;
+ }
+
+ read += blit->read_line;
+ write += blit->write_line;
+ y--;
+ }
+ while (y > 0);
+ }
+
+
+ static
+ void blit_gray8_to_32( grBlitter* blit,
+ grColor color )
+ {
+ blit_gray_to_32( blit, color, 255 );
+ }
+
+
+/**************************************************************************/
+/* */
+/* <Function> blit_lcd_to_24 */
+/* */
+/**************************************************************************/
+
+#ifdef GRAY8
+ static void
+ blit_lcd8_to_24( grBlitter* blit,
+ grColor color )
+ {
+ int y;
+ int sr = color.chroma[0];
+ int sg = color.chroma[1];
+ int sb = color.chroma[2];
+ unsigned char* read;
+ unsigned char* write;
+
+ read = blit->read + 3*blit->xread;
+ write = blit->write + 3*blit->xwrite;
+
+ y = blit->height;
+ do
+ {
+ unsigned char* _read = read;
+ unsigned char* _write = write;
+ int x = blit->width;
+
+ while (x > 0)
+ {
+ int val0, val1, val2;
+
+ val0 = _read[0];
+ val1 = _read[1];
+ val2 = _read[2];
+
+ if ( val0 | val1 | val2 )
+ {
+ if ( val0 == val1 &&
+ val0 == val2 &&
+ val0 == 255 )
+ {
+ _write[0] = (unsigned char)sr;
+ _write[1] = (unsigned char)sg;
+ _write[2] = (unsigned char)sb;
+ }
+ else
+ {
+ /* compose gray value */
+ int dr, dg, db;
+
+ dr = _write[0];
+ dr += (sr-dr)*val0 >> 8;
+
+ dg = _write[1];
+ dg += (sg-dg)*val1 >> 8;
+
+ db = _write[1];
+ db += (sb-db)*val2 >> 8;
+
+ _write[0] = dr;
+ _write[1] = dg;
+ _write[2] = db;
+ }
+ }
+ _write += 3;
+ _read += 3;
+ x--;
+ }
+
+ read += blit->read_line;
+ write += blit->write_line;
+ y--;
+ }
+ while (y > 0);
+ }
+#endif /* GRAY8 */
+
+ static void
+ blit_lcd_to_24( grBlitter* blit,
+ grColor color,
+ int max )
+ {
+ int y;
+ unsigned char* read;
+ unsigned char* write;
+
+ read = blit->read + 3*blit->xread;
+ write = blit->write + 3*blit->xwrite;
+
+ y = blit->height;
+ do
+ {
+ unsigned char* _read = read;
+ unsigned char* _write = write;
+ int x = blit->width;
+
+ while (x > 0)
+ {
+ int val0, val1, val2;
+
+ val0 = _read[0];
+ val1 = _read[1];
+ val2 = _read[2];
+
+ if ( val0 | val1 | val2 )
+ {
+ if ( val0 == val1 &&
+ val0 == val2 &&
+ val0 == max )
+ {
+ _write[0] = color.chroma[0];
+ _write[1] = color.chroma[1];
+ _write[2] = color.chroma[2];
+ }
+ else
+ {
+ /* compose gray value */
+ grColor pix;
+
+ pix.chroma[0] = _write[0];
+ pix.chroma[1] = _write[1];
+ pix.chroma[2] = _write[2];
+
+ compose_pixel_full( pix, color, val0, val1, val2, max );
+
+ _write[0] = pix.chroma[0];
+ _write[1] = pix.chroma[1];
+ _write[2] = pix.chroma[2];
+ }
+ }
+ _write += 3;
+ _read += 3;
+ x--;
+ }
+
+ read += blit->read_line;
+ write += blit->write_line;
+ y--;
+ }
+ while (y > 0);
+ }
+
+
+#ifdef GRAY8
+ static void
+ blit_lcd28_to_24( grBlitter* blit,
+ grColor color )
+ {
+ int y;
+ int sr = color.chroma[0];
+ int sg = color.chroma[1];
+ int sb = color.chroma[2];
+ unsigned char* read;
+ unsigned char* write;
+
+ read = blit->read + 3*blit->xread;
+ write = blit->write + 3*blit->xwrite;
+
+ y = blit->height;
+ do
+ {
+ unsigned char* _read = read;
+ unsigned char* _write = write;
+ int x = blit->width;
+
+ while (x > 0)
+ {
+ int val0, val1, val2;
+
+ val0 = _read[2];
+ val1 = _read[1];
+ val2 = _read[0];
+
+ if ( val0 | val1 | val2 )
+ {
+ if ( val0 == val1 &&
+ val0 == val2 &&
+ val0 == 255 )
+ {
+ _write[0] = (unsigned char)sr;
+ _write[1] = (unsigned char)sg;
+ _write[2] = (unsigned char)sb;
+ }
+ else
+ {
+ /* compose gray value */
+ int dr, dg, db;
+
+ dr = _write[0];
+ dr += (sr-dr)*val0 >> 8;
+
+ dg = _write[1];
+ dg += (sg-dg)*val1 >> 8;
+
+ db = _write[1];
+ db += (sb-db)*val2 >> 8;
+
+ _write[0] = dr;
+ _write[1] = dg;
+ _write[2] = db;
+ }
+ }
+ _write += 3;
+ _read += 3;
+ x--;
+ }
+
+ read += blit->read_line;
+ write += blit->write_line;
+ y--;
+ }
+ while (y > 0);
+ }
+#endif /* GRAY8 */
+
+ static void
+ blit_lcd2_to_24( grBlitter* blit,
+ grColor color,
+ int max )
+ {
+ int y;
+ unsigned char* read;
+ unsigned char* write;
+
+ read = blit->read + 3*blit->xread;
+ write = blit->write + 3*blit->xwrite;
+
+ y = blit->height;
+ do
+ {
+ unsigned char* _read = read;
+ unsigned char* _write = write;
+ int x = blit->width;
+
+ while (x > 0)
+ {
+ int val0, val1, val2;
+
+ val0 = _read[2];
+ val1 = _read[1];
+ val2 = _read[0];
+
+ if ( val0 | val1 | val2 )
+ {
+ if ( val0 == val1 &&
+ val0 == val2 &&
+ val0 == max )
+ {
+ _write[0] = color.chroma[0];
+ _write[1] = color.chroma[1];
+ _write[2] = color.chroma[2];
+ }
+ else
+ {
+ /* compose gray value */
+ grColor pix;
+
+ pix.chroma[0] = _write[0];
+ pix.chroma[1] = _write[1];
+ pix.chroma[2] = _write[2];
+
+ compose_pixel_full( pix, color, val0, val1, val2, max );
+
+ _write[0] = pix.chroma[0];
+ _write[1] = pix.chroma[1];
+ _write[2] = pix.chroma[2];
+ }
+ }
+ _write += 3;
+ _read += 3;
+ x--;
+ }
+
+ read += blit->read_line;
+ write += blit->write_line;
+ y--;
+ }
+ while (y > 0);
+ }
+
+
+/**************************************************************************/
+/* */
+/* <Function> blit_lcdv_to_24 */
+/* */
+/**************************************************************************/
+
+ static void
+ blit_lcdv_to_24( grBlitter* blit,
+ grColor color,
+ int max )
+ {
+ int y;
+ unsigned char* read;
+ unsigned char* write;
+ long line;
+
+ read = blit->read + blit->xread;
+ write = blit->write + 3*blit->xwrite;
+ line = blit->read_line;
+
+ y = blit->height;
+ do
+ {
+ unsigned char* _read = read;
+ unsigned char* _write = write;
+ int x = blit->width;
+
+ while (x > 0)
+ {
+ unsigned char val0, val1, val2;
+
+ val0 = _read[0*line];
+ val1 = _read[1*line];
+ val2 = _read[2*line];
+
+ if ( val0 | val1 | val2 )
+ {
+ if ( val0 == val1 &&
+ val0 == val2 &&
+ val0 == max )
+ {
+ _write[0] = color.chroma[0];
+ _write[1] = color.chroma[1];
+ _write[2] = color.chroma[2];
+ }
+ else
+ {
+ /* compose gray value */
+ grColor pix;
+
+ pix.chroma[0] = _write[0];
+ pix.chroma[1] = _write[1];
+ pix.chroma[2] = _write[2];
+
+ compose_pixel_full( pix, color, val0, val1, val2, max );
+
+ _write[0] = pix.chroma[0];
+ _write[1] = pix.chroma[1];
+ _write[2] = pix.chroma[2];
+ }
+ }
+ _write += 3;
+ _read += 1;
+ x--;
+ }
+
+ read += 3*line;
+ write += blit->write_line;
+ y--;
+ }
+ while (y > 0);
+ }
+
+
+ static void
+ blit_lcdv2_to_24( grBlitter* blit,
+ grColor color,
+ int max )
+ {
+ int y;
+ unsigned char* read;
+ unsigned char* write;
+ long line;
+
+ read = blit->read + blit->xread;
+ write = blit->write + 3*blit->xwrite;
+ line = blit->read_line;
+
+ y = blit->height;
+ do
+ {
+ unsigned char* _read = read;
+ unsigned char* _write = write;
+ int x = blit->width;
+
+ while (x > 0)
+ {
+ unsigned char val0, val1, val2;
+
+ val0 = _read[2*line];
+ val1 = _read[1*line];
+ val2 = _read[0*line];
+
+ if ( val0 | val1 | val2 )
+ {
+ if ( val0 == val1 &&
+ val0 == val2 &&
+ val0 == max )
+ {
+ _write[0] = color.chroma[0];
+ _write[1] = color.chroma[1];
+ _write[2] = color.chroma[2];
+ }
+ else
+ {
+ /* compose gray value */
+ grColor pix;
+
+ pix.chroma[0] = _write[0];
+ pix.chroma[1] = _write[1];
+ pix.chroma[2] = _write[2];
+
+ compose_pixel_full( pix, color, val0, val1, val2, max );
+
+ _write[0] = pix.chroma[0];
+ _write[1] = pix.chroma[1];
+ _write[2] = pix.chroma[2];
+ }
+ }
+ _write += 3;
+ _read += 1;
+ x--;
+ }
+
+ read += 3*line;
+ write += blit->write_line;
+ y--;
+ }
+ while (y > 0);
+ }
+
+
+ /**********************************************************************
+ *
+ * <Function>
+ * grBlitGlyphBitmap
+ *
+ * <Description>
+ * writes a given glyph bitmap to a target surface.
+ *
+ * <Input>
+ * surface :: handle to target surface
+ * x :: position of left-most pixel of glyph image in surface
+ * y :: position of top-most pixel of glyph image in surface
+ * bitmap :: source glyph image
+ *
+ * <Return>
+ * Error code. 0 means success
+ *
+ **********************************************************************/
+
+ typedef void (*grColorGlyphBlitter)( grBlitter* blit,
+ grColor color,
+ int max_gray );
+
+ static
+ const grColorGlyphBlitter gr_color_blitters[gr_pixel_mode_max] =
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ blit_gray_to_555,
+ blit_gray_to_565,
+ blit_gray_to_24,
+ blit_gray_to_32
+ };
+
+#ifdef GRAY8
+ typedef void (*grGray8GlyphBlitter)( grBlitter* blit,
+ grColor color );
+
+ static
+ const grGray8GlyphBlitter gr_gray8_blitters[gr_pixel_mode_max] =
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ blit_gray8_to_555,
+ blit_gray8_to_565,
+ blit_gray8_to_24,
+ blit_gray8_to_32
+ };
+#endif
+
+
+#include "gblblit.h"
+
+ static double gr_glyph_gamma = 1.0;
+
+ void grSetGlyphGamma( double gamma )
+ {
+ gr_glyph_gamma = gamma;
+ }
+
+
+ int
+ grBlitGlyphToBitmap( grBitmap* target,
+ grBitmap* glyph,
+ grPos x,
+ grPos y,
+ grColor color )
+ {
+ grBlitter blit;
+ grPixelMode mode;
+
+
+ /* check arguments */
+ if ( !target || !glyph )
+ {
+ grError = gr_err_bad_argument;
+ return -1;
+ }
+
+ /* short cut to alpha blender for certain glyph types
+ */
+ {
+ GBlenderSourceFormat src_format;
+ GBlenderTargetFormat dst_format;
+ int width, height;
+ GBlenderBlitRec gblit[1];
+ GBlenderPixel gcolor;
+ static GBlenderRec gblender[1];
+ static double gblender_gamma = -100.0;
+
+ if ( glyph->grays != 256 )
+ goto DefaultBlit;
+
+ switch ( glyph->mode )
+ {
+ case gr_pixel_mode_gray: src_format = GBLENDER_SOURCE_GRAY8; break;
+ case gr_pixel_mode_lcd: src_format = GBLENDER_SOURCE_HRGB; break;
+ case gr_pixel_mode_lcdv: src_format = GBLENDER_SOURCE_VRGB; break;
+ case gr_pixel_mode_lcd2: src_format = GBLENDER_SOURCE_HBGR; break;
+ case gr_pixel_mode_lcdv2: src_format = GBLENDER_SOURCE_VBGR; break;
+
+ default:
+ goto DefaultBlit;
+ }
+
+ width = glyph->width;
+ height = glyph->rows;
+
+ if ( glyph->mode == gr_pixel_mode_lcd ||
+ glyph->mode == gr_pixel_mode_lcd2 )
+ width /= 3;
+
+ if ( glyph->mode == gr_pixel_mode_lcdv ||
+ glyph->mode == gr_pixel_mode_lcdv2 )
+ height /= 3;
+
+ switch ( target->mode )
+ {
+ case gr_pixel_mode_rgb32: dst_format = GBLENDER_TARGET_RGB32; break;
+ case gr_pixel_mode_rgb24: dst_format = GBLENDER_TARGET_RGB24; break;
+ case gr_pixel_mode_rgb565: dst_format = GBLENDER_TARGET_RGB565; break;
+ default:
+ goto DefaultBlit;
+ }
+
+ /* initialize blender when needed, i.e. when gamma changes
+ */
+ if ( gblender_gamma != gr_glyph_gamma )
+ {
+ gblender_gamma = gr_glyph_gamma;
+ gblender_init( gblender, gblender_gamma );
+ }
+
+ if ( gblender_blit_init( gblit, gblender,
+ x, y,
+ src_format,
+ glyph->buffer,
+ glyph->pitch,
+ width,
+ height,
+ dst_format,
+ target->buffer,
+ target->pitch,
+ target->width,
+ target->rows ) < 0 )
+ {
+ /* nothing to do */
+ return 0;
+ }
+
+ gcolor = ((GBlenderPixel)color.chroma[0] << 16) |
+ ((GBlenderPixel)color.chroma[1] << 8 ) |
+ ((GBlenderPixel)color.chroma[2] ) ;
+
+ gblender_blit_run( gblit, gcolor );
+ return 1;
+ }
+
+ DefaultBlit:
+
+ /* set up blitter and compute clipping. Return immediately if needed */
+ blit.source = *glyph;
+ blit.target = *target;
+ mode = target->mode;
+
+ if ( compute_clips( &blit, x, y ) )
+ return 0;
+
+ switch ( glyph->mode )
+ {
+ case gr_pixel_mode_mono: /* handle monochrome bitmap blitting */
+ if ( mode <= gr_pixel_mode_none || mode >= gr_pixel_mode_max )
+ {
+ grError = gr_err_bad_source_depth;
+ return -1;
+ }
+
+ gr_mono_blitters[mode]( &blit, color );
+ break;
+
+ case gr_pixel_mode_gray:
+ if ( glyph->grays > 1 )
+ {
+ int target_grays = target->grays;
+ int source_grays = glyph->grays;
+ const byte* saturation;
+
+
+ if ( mode == gr_pixel_mode_gray && target_grays > 1 )
+ {
+ /* rendering into a gray target - use special composition */
+ /* routines.. */
+ if ( gr_last_saturation->count == target_grays )
+ saturation = gr_last_saturation->table;
+ else
+ {
+ saturation = grGetSaturation( target_grays );
+ if ( !saturation )
+ return -3;
+ }
+
+ if ( target_grays == source_grays )
+ blit_gray_to_gray_simple( &blit, saturation );
+ else
+ {
+ const byte* conversion;
+
+
+ if ( gr_last_conversion->target_grays == target_grays &&
+ gr_last_conversion->source_grays == source_grays )
+ conversion = gr_last_conversion->table;
+ else
+ {
+ conversion = grGetConversion( target_grays, source_grays );
+ if ( !conversion )
+ return -3;
+ }
+
+ blit_gray_to_gray( &blit, saturation, conversion );
+ }
+ }
+ else
+ {
+ /* rendering into a color target */
+ if ( mode <= gr_pixel_mode_gray ||
+ mode >= gr_pixel_mode_max )
+ {
+ grError = gr_err_bad_target_depth;
+ return -1;
+ }
+
+#ifdef GRAY8
+ if ( source_grays == 256 )
+ gr_gray8_blitters[mode]( &blit, color );
+ else
+#endif /* GRAY8 */
+ gr_color_blitters[mode]( &blit, color, source_grays - 1 );
+ }
+ }
+ break;
+
+ case gr_pixel_mode_lcd:
+ if ( mode == gr_pixel_mode_rgb24 )
+ {
+#ifdef GRAY8
+ if ( glyph->grays == 256 )
+ blit_lcd8_to_24( &blit, color );
+ else
+#endif
+ if ( glyph->grays > 1 )
+ blit_lcd_to_24( &blit, color, glyph->grays-1 );
+ }
+ break;
+
+
+ case gr_pixel_mode_lcdv:
+ if ( glyph->grays > 1 && mode == gr_pixel_mode_rgb24 )
+ {
+ blit_lcdv_to_24( &blit, color, glyph->grays-1 );
+ break;
+ }
+
+ case gr_pixel_mode_lcd2:
+ if ( mode == gr_pixel_mode_rgb24 )
+ {
+#ifdef GRAY8
+ if ( glyph->grays == 256 )
+ blit_lcd28_to_24( &blit, color );
+ else
+#endif
+ if ( glyph->grays > 1 )
+ blit_lcd2_to_24( &blit, color, glyph->grays-1 );
+ }
+ break;
+
+ case gr_pixel_mode_lcdv2:
+ if ( mode == gr_pixel_mode_rgb24 )
+ {
+ if ( glyph->grays > 1 )
+ blit_lcdv2_to_24( &blit, color, glyph->grays-1 );
+ }
+ break;
+
+ default:
+ /* we don't support the blitting of bitmaps of the following */
+ /* types : pal4, pal8, rgb555, rgb565, rgb24, rgb32 */
+ /* */
+ grError = gr_err_bad_source_depth;
+ return -2;
+ }
+
+ return 0;
+ }
+
+
+/* End */
diff --git a/kernel/kls_ttf/ftview/grblit.h b/kernel/kls_ttf/ftview/grblit.h
new file mode 100644
index 0000000..4d0b6e5
--- /dev/null
+++ b/kernel/kls_ttf/ftview/grblit.h
@@ -0,0 +1,25 @@
+/****************************************************************************/
+/* */
+/* The FreeType project -- a free and portable quality TrueType renderer. */
+/* */
+/* Copyright 1996-1999 by */
+/* D. Turner, R.Wilhelm, and W. Lemberg */
+/* */
+/* blitter.h: Support for blitting of bitmaps with various depth. */
+/* */
+/****************************************************************************/
+
+#ifndef GRBLIT_H
+#define GRBLIT_H
+
+#include "grobjs.h"
+
+ int grBlitMono( grBitmap* target,
+ grBitmap* source,
+ int x_offset,
+ int y_offset,
+ grColor color );
+
+
+#endif /* GRBLIT_H */
+/* End */
diff --git a/kernel/kls_ttf/ftview/grconfig.h b/kernel/kls_ttf/ftview/grconfig.h
new file mode 100644
index 0000000..02d8f4d
--- /dev/null
+++ b/kernel/kls_ttf/ftview/grconfig.h
@@ -0,0 +1,9 @@
+#ifndef GRCONFIG_H
+#define GRCONFIG_H
+
+#define GR_MAX_SATURATIONS 8
+#define GR_MAX_CONVERSIONS 16
+
+#define GR_MAX_DEVICES 8
+
+#endif /* GRCONFIG_H */
diff --git a/kernel/kls_ttf/ftview/grevents.h b/kernel/kls_ttf/ftview/grevents.h
new file mode 100644
index 0000000..36dd52d
--- /dev/null
+++ b/kernel/kls_ttf/ftview/grevents.h
@@ -0,0 +1,117 @@
+#ifndef GREVENTS_H
+#define GREVENTS_H
+
+
+#define gr_event_none 0
+#define gr_event_wait 1
+#define gr_event_poll 2
+#define gr_event_flush 3
+
+#define gr_mouse_down 0x04
+#define gr_mouse_move 0x08
+#define gr_mouse_up 0x10
+#define gr_mouse_drag 0x20
+
+#define gr_key_down 0x40
+#define gr_key_up 0x80
+
+
+#define gr_event_mouse 0x3C
+#define gr_event_key 0xC0
+
+#define gr_event_type (gr_event_mouse | gr_event_key)
+
+
+ typedef enum grKey_
+ {
+ grKeyNone = 0,
+
+ grKeyF1,
+ grKeyF2,
+ grKeyF3,
+ grKeyF4,
+ grKeyF5,
+ grKeyF6,
+ grKeyF7,
+ grKeyF8,
+ grKeyF9,
+ grKeyF10,
+ grKeyF11,
+ grKeyF12,
+
+ grKeyLeft,
+ grKeyRight,
+ grKeyUp,
+ grKeyDown,
+
+ grKeyIns,
+ grKeyDel,
+ grKeyHome,
+ grKeyEnd,
+ grKeyPageUp,
+ grKeyPageDown,
+
+ grKeyEsc,
+ grKeyTab,
+ grKeyBackSpace,
+ grKeyReturn,
+
+ grKeyMax,
+ grKeyForceShort = 0x7FFF /* this forces the grKey to be stored */
+ /* on at least one short ! */
+
+ } grKey;
+
+#define grKEY(c) ((grKey)(c))
+
+#define grKeyAlt ((grKey)0x8000)
+#define grKeyCtrl ((grKey)0x4000)
+#define grKeyShift ((grKey)0x2000)
+
+#define grKeyModifiers ((grKey)0xE000)
+
+#define grKey0 grKEY('0')
+#define grKey1 grKEY('1')
+#define grKey2 grKEY('2')
+#define grKey3 grKEY('3')
+#define grKey4 grKEY('4')
+#define grKey5 grKEY('5')
+#define grKey6 grKEY('6')
+#define grKey7 grKEY('7')
+#define grKey8 grKEY('8')
+#define grKey9 grKEY('9')
+
+
+#define grKeyPlus grKEY('+')
+#define grKeyLess grKEY('-')
+#define grKeyEqual grKEY('=')
+#define grKeyMult grKEY('*')
+#define grKeyDollar grKEY('$')
+#define grKeySmaller grKEY('<')
+#define grKeyGreater grKEY('>')
+#define grKeyQuestion grKEY('?')
+#define grKeyComma grKEY(',')
+#define grKeyDot grKEY('.')
+#define grKeySemiColumn grKEY(';')
+#define grKeyColumn grKEY(':')
+#define grKeyDiv grKEY('/')
+#define grKeyExclam grKEY('!')
+#define grKeyPercent grKEY('%')
+#define grKeyLeftParen grKEY('(')
+#define grKeyRightParen grKEY('(')
+#define grKeyAt grKEY('@')
+#define grKeyUnder grKEY('_')
+
+
+ typedef struct grEvent_
+ {
+ int type;
+ grKey key;
+ int x, y;
+
+ } grEvent;
+
+
+
+#endif /* GREVENTS_H */
+
diff --git a/kernel/kls_ttf/ftview/grfont.cpp b/kernel/kls_ttf/ftview/grfont.cpp
new file mode 100644
index 0000000..b6dfa3b
--- /dev/null
+++ b/kernel/kls_ttf/ftview/grfont.cpp
@@ -0,0 +1,373 @@
+
+#include "grfont.h"
+#include <string.h>
+
+ /* font characters */
+
+ const unsigned char font_8x8[2048] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x7E, 0x81, 0xA5, 0x81, 0xBD, 0x99, 0x81, 0x7E,
+ 0x7E, 0xFF, 0xDB, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E,
+ 0x6C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00,
+ 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00,
+ 0x38, 0x7C, 0x38, 0xFE, 0xFE, 0x92, 0x10, 0x7C,
+ 0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x7C,
+ 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00,
+ 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF,
+ 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00,
+ 0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF,
+ 0x0F, 0x07, 0x0F, 0x7D, 0xCC, 0xCC, 0xCC, 0x78,
+ 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18,
+ 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x70, 0xF0, 0xE0,
+ 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x67, 0xE6, 0xC0,
+ 0x99, 0x5A, 0x3C, 0xE7, 0xE7, 0x3C, 0x5A, 0x99,
+ 0x80, 0xE0, 0xF8, 0xFE, 0xF8, 0xE0, 0x80, 0x00,
+ 0x02, 0x0E, 0x3E, 0xFE, 0x3E, 0x0E, 0x02, 0x00,
+ 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x7E, 0x3C, 0x18,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00,
+ 0x7F, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x00,
+ 0x3E, 0x63, 0x38, 0x6C, 0x6C, 0x38, 0x86, 0xFC,
+ 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x00,
+ 0x18, 0x3C, 0x7E, 0x18, 0x7E, 0x3C, 0x18, 0xFF,
+ 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x00,
+ 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00,
+ 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00,
+ 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00,
+ 0x00, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x00, 0x00,
+ 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0x7E, 0x3C, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00,
+ 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0x00,
+ 0x18, 0x7E, 0xC0, 0x7C, 0x06, 0xFC, 0x18, 0x00,
+ 0x00, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xC6, 0x00,
+ 0x38, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0x76, 0x00,
+ 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00,
+ 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00,
+ 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00,
+ 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30,
+ 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00,
+ 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00,
+ 0x7C, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0x7C, 0x00,
+ 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xFC, 0x00,
+ 0x78, 0xCC, 0x0C, 0x38, 0x60, 0xCC, 0xFC, 0x00,
+ 0x78, 0xCC, 0x0C, 0x38, 0x0C, 0xCC, 0x78, 0x00,
+ 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x1E, 0x00,
+ 0xFC, 0xC0, 0xF8, 0x0C, 0x0C, 0xCC, 0x78, 0x00,
+ 0x38, 0x60, 0xC0, 0xF8, 0xCC, 0xCC, 0x78, 0x00,
+ 0xFC, 0xCC, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00,
+ 0x78, 0xCC, 0xCC, 0x78, 0xCC, 0xCC, 0x78, 0x00,
+ 0x78, 0xCC, 0xCC, 0x7C, 0x0C, 0x18, 0x70, 0x00,
+ 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00,
+ 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30,
+ 0x18, 0x30, 0x60, 0xC0, 0x60, 0x30, 0x18, 0x00,
+ 0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00,
+ 0x60, 0x30, 0x18, 0x0C, 0x18, 0x30, 0x60, 0x00,
+ 0x3C, 0x66, 0x0C, 0x18, 0x18, 0x00, 0x18, 0x00,
+ 0x7C, 0xC6, 0xDE, 0xDE, 0xDC, 0xC0, 0x7C, 0x00,
+ 0x30, 0x78, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0x00,
+ 0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00,
+ 0x3C, 0x66, 0xC0, 0xC0, 0xC0, 0x66, 0x3C, 0x00,
+ 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00,
+ 0xFE, 0x62, 0x68, 0x78, 0x68, 0x62, 0xFE, 0x00,
+ 0xFE, 0x62, 0x68, 0x78, 0x68, 0x60, 0xF0, 0x00,
+ 0x3C, 0x66, 0xC0, 0xC0, 0xCE, 0x66, 0x3A, 0x00,
+ 0xCC, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0xCC, 0x00,
+ 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+ 0x1E, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78, 0x00,
+ 0xE6, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0xE6, 0x00,
+ 0xF0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00,
+ 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0x00,
+ 0xC6, 0xE6, 0xF6, 0xDE, 0xCE, 0xC6, 0xC6, 0x00,
+ 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00,
+ 0xFC, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00,
+ 0x7C, 0xC6, 0xC6, 0xC6, 0xD6, 0x7C, 0x0E, 0x00,
+ 0xFC, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0xE6, 0x00,
+ 0x7C, 0xC6, 0xE0, 0x78, 0x0E, 0xC6, 0x7C, 0x00,
+ 0xFC, 0xB4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xFC, 0x00,
+ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00,
+ 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xFE, 0x6C, 0x00,
+ 0xC6, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0xC6, 0x00,
+ 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x30, 0x78, 0x00,
+ 0xFE, 0xC6, 0x8C, 0x18, 0x32, 0x66, 0xFE, 0x00,
+ 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00,
+ 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x02, 0x00,
+ 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00,
+ 0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+ 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00,
+ 0xE0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xDC, 0x00,
+ 0x00, 0x00, 0x78, 0xCC, 0xC0, 0xCC, 0x78, 0x00,
+ 0x1C, 0x0C, 0x0C, 0x7C, 0xCC, 0xCC, 0x76, 0x00,
+ 0x00, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00,
+ 0x38, 0x6C, 0x64, 0xF0, 0x60, 0x60, 0xF0, 0x00,
+ 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8,
+ 0xE0, 0x60, 0x6C, 0x76, 0x66, 0x66, 0xE6, 0x00,
+ 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
+ 0x0C, 0x00, 0x1C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78,
+ 0xE0, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0xE6, 0x00,
+ 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+ 0x00, 0x00, 0xCC, 0xFE, 0xFE, 0xD6, 0xD6, 0x00,
+ 0x00, 0x00, 0xB8, 0xCC, 0xCC, 0xCC, 0xCC, 0x00,
+ 0x00, 0x00, 0x78, 0xCC, 0xCC, 0xCC, 0x78, 0x00,
+ 0x00, 0x00, 0xDC, 0x66, 0x66, 0x7C, 0x60, 0xF0,
+ 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0x1E,
+ 0x00, 0x00, 0xDC, 0x76, 0x62, 0x60, 0xF0, 0x00,
+ 0x00, 0x00, 0x7C, 0xC0, 0x70, 0x1C, 0xF8, 0x00,
+ 0x10, 0x30, 0xFC, 0x30, 0x30, 0x34, 0x18, 0x00,
+ 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00,
+ 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00,
+ 0x00, 0x00, 0xC6, 0xC6, 0xD6, 0xFE, 0x6C, 0x00,
+ 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x00,
+ 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8,
+ 0x00, 0x00, 0xFC, 0x98, 0x30, 0x64, 0xFC, 0x00,
+ 0x1C, 0x30, 0x30, 0xE0, 0x30, 0x30, 0x1C, 0x00,
+ 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00,
+ 0xE0, 0x30, 0x30, 0x1C, 0x30, 0x30, 0xE0, 0x00,
+ 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0x00,
+ 0x7C, 0xC6, 0xC0, 0xC6, 0x7C, 0x0C, 0x06, 0x7C,
+ 0x00, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00,
+ 0x1C, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00,
+ 0x7E, 0x81, 0x3C, 0x06, 0x3E, 0x66, 0x3B, 0x00,
+ 0xCC, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00,
+ 0xE0, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00,
+ 0x30, 0x30, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00,
+ 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0x78, 0x0C, 0x38,
+ 0x7E, 0x81, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00,
+ 0xCC, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00,
+ 0xE0, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00,
+ 0xCC, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
+ 0x7C, 0x82, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00,
+ 0xE0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
+ 0xC6, 0x10, 0x7C, 0xC6, 0xFE, 0xC6, 0xC6, 0x00,
+ 0x30, 0x30, 0x00, 0x78, 0xCC, 0xFC, 0xCC, 0x00,
+ 0x1C, 0x00, 0xFC, 0x60, 0x78, 0x60, 0xFC, 0x00,
+ 0x00, 0x00, 0x7F, 0x0C, 0x7F, 0xCC, 0x7F, 0x00,
+ 0x3E, 0x6C, 0xCC, 0xFE, 0xCC, 0xCC, 0xCE, 0x00,
+ 0x78, 0x84, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00,
+ 0x00, 0xCC, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00,
+ 0x00, 0xE0, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00,
+ 0x78, 0x84, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00,
+ 0x00, 0xE0, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00,
+ 0x00, 0xCC, 0x00, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8,
+ 0xC3, 0x18, 0x3C, 0x66, 0x66, 0x3C, 0x18, 0x00,
+ 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x00,
+ 0x18, 0x18, 0x7E, 0xC0, 0xC0, 0x7E, 0x18, 0x18,
+ 0x38, 0x6C, 0x64, 0xF0, 0x60, 0xE6, 0xFC, 0x00,
+ 0xCC, 0xCC, 0x78, 0x30, 0xFC, 0x30, 0xFC, 0x30,
+ 0xF8, 0xCC, 0xCC, 0xFA, 0xC6, 0xCF, 0xC6, 0xC3,
+ 0x0E, 0x1B, 0x18, 0x3C, 0x18, 0x18, 0xD8, 0x70,
+ 0x1C, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00,
+ 0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
+ 0x00, 0x1C, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00,
+ 0x00, 0x1C, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00,
+ 0x00, 0xF8, 0x00, 0xB8, 0xCC, 0xCC, 0xCC, 0x00,
+ 0xFC, 0x00, 0xCC, 0xEC, 0xFC, 0xDC, 0xCC, 0x00,
+ 0x3C, 0x6C, 0x6C, 0x3E, 0x00, 0x7E, 0x00, 0x00,
+ 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x7C, 0x00, 0x00,
+ 0x18, 0x00, 0x18, 0x18, 0x30, 0x66, 0x3C, 0x00,
+ 0x00, 0x00, 0x00, 0xFC, 0xC0, 0xC0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xFC, 0x0C, 0x0C, 0x00, 0x00,
+ 0xC6, 0xCC, 0xD8, 0x36, 0x6B, 0xC2, 0x84, 0x0F,
+ 0xC3, 0xC6, 0xCC, 0xDB, 0x37, 0x6D, 0xCF, 0x03,
+ 0x18, 0x00, 0x18, 0x18, 0x3C, 0x3C, 0x18, 0x00,
+ 0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00,
+ 0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00,
+ 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
+ 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
+ 0xDB, 0xF6, 0xDB, 0x6F, 0xDB, 0x7E, 0xD7, 0xED,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18,
+ 0x36, 0x36, 0x36, 0x36, 0xF6, 0x36, 0x36, 0x36,
+ 0x00, 0x00, 0x00, 0x00, 0xFE, 0x36, 0x36, 0x36,
+ 0x00, 0x00, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18,
+ 0x36, 0x36, 0xF6, 0x06, 0xF6, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x00, 0x00, 0xFE, 0x06, 0xF6, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0xF6, 0x06, 0xFE, 0x00, 0x00, 0x00,
+ 0x36, 0x36, 0x36, 0x36, 0xFE, 0x00, 0x00, 0x00,
+ 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, 0x00, 0x00,
+ 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x18, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
+ 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18,
+ 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x37, 0x30, 0x3F, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3F, 0x30, 0x37, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36,
+ 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00,
+ 0x36, 0x36, 0xF7, 0x00, 0xF7, 0x36, 0x36, 0x36,
+ 0x18, 0x18, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00,
+ 0x36, 0x36, 0x36, 0x36, 0xFF, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x18, 0x18, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x3F, 0x00, 0x00, 0x00,
+ 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0x3F, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0xFF, 0x36, 0x36, 0x36,
+ 0x18, 0x18, 0xFF, 0x18, 0xFF, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0xF8, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x18, 0x18,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x76, 0xDC, 0xC8, 0xDC, 0x76, 0x00,
+ 0x00, 0x78, 0xCC, 0xF8, 0xCC, 0xF8, 0xC0, 0xC0,
+ 0x00, 0xFC, 0xCC, 0xC0, 0xC0, 0xC0, 0xC0, 0x00,
+ 0x00, 0x00, 0xFE, 0x6C, 0x6C, 0x6C, 0x6C, 0x00,
+ 0xFC, 0xCC, 0x60, 0x30, 0x60, 0xCC, 0xFC, 0x00,
+ 0x00, 0x00, 0x7E, 0xD8, 0xD8, 0xD8, 0x70, 0x00,
+ 0x00, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0xC0,
+ 0x00, 0x76, 0xDC, 0x18, 0x18, 0x18, 0x18, 0x00,
+ 0xFC, 0x30, 0x78, 0xCC, 0xCC, 0x78, 0x30, 0xFC,
+ 0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0x6C, 0x38, 0x00,
+ 0x38, 0x6C, 0xC6, 0xC6, 0x6C, 0x6C, 0xEE, 0x00,
+ 0x1C, 0x30, 0x18, 0x7C, 0xCC, 0xCC, 0x78, 0x00,
+ 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0x7E, 0x00, 0x00,
+ 0x06, 0x0C, 0x7E, 0xDB, 0xDB, 0x7E, 0x60, 0xC0,
+ 0x38, 0x60, 0xC0, 0xF8, 0xC0, 0x60, 0x38, 0x00,
+ 0x78, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x00,
+ 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00,
+ 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x7E, 0x00,
+ 0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xFC, 0x00,
+ 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xFC, 0x00,
+ 0x0E, 0x1B, 0x1B, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0xD8, 0x70,
+ 0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18, 0x00,
+ 0x00, 0x76, 0xDC, 0x00, 0x76, 0xDC, 0x00, 0x00,
+ 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x0F, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x3C, 0x1C,
+ 0x58, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00,
+ 0x70, 0x98, 0x30, 0x60, 0xF8, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+
+ static
+ grBitmap gr_charcell =
+ {
+ 8, /* rows */
+ 8, /* width */
+ 1, /* pitch */
+ gr_pixel_mode_mono, /* mode */
+ 0, /* grays */
+ 0 /* buffer */
+ };
+
+ void grWriteCellChar( grBitmap* target,
+ int x,
+ int y,
+ int charcode,
+ grColor color )
+ {
+ if (charcode < 0 || charcode > 255)
+ return;
+
+ gr_charcell.buffer = (unsigned char*)font_8x8 + 8 * charcode;
+ grBlitGlyphToBitmap( target, &gr_charcell, x, y, color );
+ }
+
+
+ void grWriteCellString( grBitmap* target,
+ int x,
+ int y,
+ const char* string,
+ grColor color )
+ {
+ while (*string)
+ {
+ gr_charcell.buffer = (unsigned char *)font_8x8 +
+ 8 * (int)(unsigned char)*string++;
+ grBlitGlyphToBitmap( target, &gr_charcell, x, y, color );
+ x += 8;
+ }
+ }
+
+ static int gr_cursor_x = 0;
+ static int gr_cursor_y = 0;
+ static grBitmap* gr_text_bitmap = 0;
+ static int gr_margin_right = 0;
+ static int gr_margin_top = 0;
+
+
+ extern void grGotobitmap( grBitmap* bitmap )
+ {
+ gr_text_bitmap = bitmap;
+ }
+
+
+ extern void grSetMargin( int right, int top )
+ {
+ gr_margin_top = top << 3;
+ gr_margin_right = right << 3;
+ }
+
+
+ extern void grSetPixelMargin( int right, int top )
+ {
+ gr_margin_top = top;
+ gr_margin_right = right;
+ }
+
+
+ extern void grGotoxy ( int x, int y )
+ {
+ gr_cursor_x = x;
+ gr_cursor_y = y;
+ }
+
+
+ extern void grWrite ( const char* string )
+ {
+ if (string)
+ {
+ grColor color;
+
+ color.value = 127;
+ grWriteCellString( gr_text_bitmap,
+ gr_margin_right + (gr_cursor_x << 3),
+ gr_margin_top + (gr_cursor_y << 3),
+ string,
+ color );
+
+ gr_cursor_x += strlen(string);
+ }
+ }
+
+
+ extern void grLn( void )
+ {
+ gr_cursor_y ++;
+ gr_cursor_x = 0;
+ }
+
+
+ extern void grWriteln( const char* string )
+ {
+ grWrite( string );
+ grLn();
+ }
+
+
diff --git a/kernel/kls_ttf/ftview/grfont.h b/kernel/kls_ttf/ftview/grfont.h
new file mode 100644
index 0000000..47f226a
--- /dev/null
+++ b/kernel/kls_ttf/ftview/grfont.h
@@ -0,0 +1,17 @@
+#ifndef GRFONT_H
+#define GRFONT_H
+
+#include "graph.h"
+
+ extern const unsigned char font_8x8[];
+
+ extern void grGotobitmap( grBitmap* bitmap );
+ extern void grSetMargin( int right, int top );
+ extern void grSetPixelMargin( int right, int top );
+ extern void grGotoxy ( int x, int y );
+
+ extern void grWrite ( const char* string );
+ extern void grWriteln( const char* string );
+ extern void grLn( void );
+
+#endif /* GRFONT_H */
diff --git a/kernel/kls_ttf/ftview/grobjs.cpp b/kernel/kls_ttf/ftview/grobjs.cpp
new file mode 100644
index 0000000..283c315
--- /dev/null
+++ b/kernel/kls_ttf/ftview/grobjs.cpp
@@ -0,0 +1,213 @@
+#include "grobjs.h"
+#include <stdlib.h>
+#include <string.h>
+
+ int grError = 0;
+
+
+ /********************************************************************
+ *
+ * <Function>
+ * grRealloc
+ *
+ * <Description>
+ * Simple memory re-allocation.
+ *
+ * <Input>
+ * block :: original memory block address
+ * size :: new requested block size in bytes
+ *
+ * <Return>
+ * the memory block address. 0 in case of error
+ *
+ ********************************************************************/
+
+ unsigned char* grAlloc( long size )
+ {
+ unsigned char* p;
+
+ p = (unsigned char*)malloc(size);
+ if (!p && size > 0)
+ {
+ grError = gr_err_memory;
+ }
+
+ if (p)
+ memset( p, 0, size );
+
+ return p;
+ }
+
+
+ /********************************************************************
+ *
+ * <Function>
+ * grRealloc
+ *
+ * <Description>
+ * Simple memory re-allocation.
+ *
+ * <Input>
+ * block :: original memory block address
+ * size :: new requested block size in bytes
+ *
+ * <Return>
+ * the memory block address. 0 in case of error
+ *
+ ********************************************************************/
+
+ unsigned char* grRealloc( const unsigned char* block, long size )
+ {
+ unsigned char* p;
+
+ p = (unsigned char *)realloc( (void*)block, size );
+ if (!p && size > 0)
+ {
+ grError = gr_err_memory;
+ }
+ return p;
+ }
+
+
+ /********************************************************************
+ *
+ * <Function>
+ * grFree
+ *
+ * <Description>
+ * Simple memory release
+ *
+ * <Input>
+ * block :: target block
+ *
+ ********************************************************************/
+
+ void grFree( const void* block )
+ {
+ if (block)
+ free( (void *)block );
+ }
+
+
+
+ static
+ int check_mode( grPixelMode pixel_mode,
+ int num_grays )
+ {
+ if ( pixel_mode <= gr_pixel_mode_none ||
+ pixel_mode >= gr_pixel_mode_max )
+ goto Fail;
+
+ if ( pixel_mode != gr_pixel_mode_gray ||
+ ( num_grays >= 2 && num_grays <= 256 ) )
+ return 0;
+
+ Fail:
+ grError = gr_err_bad_argument;
+ return grError;
+ }
+
+
+ /**********************************************************************
+ *
+ * <Function>
+ * grNewBitmap
+ *
+ * <Description>
+ * creates a new bitmap
+ *
+ * <Input>
+ * pixel_mode :: the target surface's pixel_mode
+ * num_grays :: number of grays levels for PAL8 pixel mode
+ * width :: width in pixels
+ * height :: height in pixels
+ *
+ * <Output>
+ * bit :: descriptor of the new bitmap
+ *
+ * <Return>
+ * Error code. 0 means success.
+ *
+ **********************************************************************/
+
+ extern int grNewBitmap( grPixelMode pixel_mode,
+ int num_grays,
+ int width,
+ int height,
+ grBitmap *bit )
+ {
+ int pitch;
+
+ /* check mode */
+ if (check_mode(pixel_mode,num_grays))
+ goto Fail;
+
+ /* check dimensions */
+ if (width < 0 || height < 0)
+ {
+ grError = gr_err_bad_argument;
+ goto Fail;
+ }
+
+ bit->width = width;
+ bit->rows = height;
+ bit->mode = pixel_mode;
+ bit->grays = num_grays;
+
+ pitch = width;
+
+ switch (pixel_mode)
+ {
+ case gr_pixel_mode_mono : pitch = (width+7) >> 3; break;
+ case gr_pixel_mode_pal4 : pitch = (width+3) >> 2; break;
+
+ case gr_pixel_mode_pal8 :
+ case gr_pixel_mode_gray : pitch = width; break;
+
+ case gr_pixel_mode_rgb555:
+ case gr_pixel_mode_rgb565: pitch = width*2; break;
+
+ case gr_pixel_mode_rgb24 : pitch = width*3; break;
+
+ case gr_pixel_mode_rgb32 : pitch = width*4; break;
+
+ default:
+ grError = gr_err_bad_target_depth;
+ return 0;
+ }
+
+ bit->pitch = pitch;
+ bit->buffer = grAlloc( (long)bit->pitch * bit->rows );
+ if (!bit->buffer) goto Fail;
+
+ return 0;
+
+ Fail:
+ return grError;
+ }
+
+ /**********************************************************************
+ *
+ * <Function>
+ * grDoneBitmap
+ *
+ * <Description>
+ * destroys a bitmap
+ *
+ * <Input>
+ * bitmap :: handle to bitmap descriptor
+ *
+ * <Note>
+ * This function does NOT release the bitmap descriptor, only
+ * the pixel buffer.
+ *
+ **********************************************************************/
+
+ extern void grDoneBitmap( grBitmap* bit )
+ {
+ grFree( bit->buffer );
+ bit->buffer = 0;
+ }
+
+
+
diff --git a/kernel/kls_ttf/ftview/grobjs.h b/kernel/kls_ttf/ftview/grobjs.h
new file mode 100644
index 0000000..038ec54
--- /dev/null
+++ b/kernel/kls_ttf/ftview/grobjs.h
@@ -0,0 +1,182 @@
+/***************************************************************************
+ *
+ * grobjs.h
+ *
+ * basic object classes defintions
+ *
+ * Copyright 1999 - The FreeType Development Team - www.freetype.org
+ *
+ *
+ *
+ *
+ ***************************************************************************/
+
+#ifndef GROBJS_H
+#define GROBJS_H
+
+#include "graph.h"
+#include "grconfig.h"
+#include "grtypes.h"
+
+
+ typedef struct grBiColor_
+ {
+ grColor foreground;
+ grColor background;
+
+ int num_levels;
+ int max_levels;
+ grColor* levels;
+
+ } grBiColor;
+
+
+
+ /**********************************************************************
+ *
+ * Technical note : explaining how the blitter works.
+ *
+ * The blitter is used to "draw" a given source bitmap into
+ * a given target bitmap.
+ *
+ * The function called 'compute_clips' is used to compute clipping
+ * constraints. These lead us to compute two areas :
+ *
+ * - the read area : is the rectangle, within the source bitmap,
+ * which will be effectively "drawn" in the
+ * target bitmap.
+ *
+ * - the write area : is the rectangle, within the target bitmap,
+ * which will effectively "receive" the pixels
+ * from the read area
+ *
+ * Note that both areas have the same dimensions, but are
+ * located in distinct surfaces.
+ *
+ * These areas are computed by 'compute_clips' which is called
+ * by each blitting function.
+ *
+ * Note that we use the Y-downwards convention within the blitter
+ *
+ **********************************************************************/
+
+ typedef struct grBlitter_
+ {
+ int width; /* width in pixels of the areas */
+ int height; /* height in pixels of the areas */
+
+ int xread; /* x position of start point in read area */
+ int yread; /* y position of start point in read area */
+
+ int xwrite; /* x position of start point in write area */
+ int ywrite; /* y position of start point in write area */
+
+ int right_clip; /* amount of right clip */
+
+ unsigned char* read; /* top left corner of read area in source map */
+ unsigned char* write; /* top left corner of write area in target map */
+
+ int read_line; /* byte increment to go down one row in read area */
+ int write_line; /* byte increment to go down one row in write area */
+
+ grBitmap source; /* source bitmap descriptor */
+ grBitmap target; /* target bitmap descriptor */
+
+ } grBlitter;
+
+
+
+ typedef void (*grBlitterFunc)( grBlitter* blitter,
+ grColor color );
+
+ typedef void (*grSetTitleFunc)( grSurface* surface,
+ const char* title_string );
+
+ typedef void (*grRefreshRectFunc)( grSurface* surface,
+ int x,
+ int y,
+ int width,
+ int height );
+
+ typedef void (*grDoneSurfaceFunc)( grSurface* surface );
+
+ typedef int (*grListenEventFunc)( grSurface* surface,
+ int event_mode,
+ grEvent *event );
+
+
+
+ struct grSurface_
+ {
+ grDevice* device;
+ grBitmap bitmap;
+ grBool refresh;
+ grBool owner;
+
+ const byte* saturation; /* used for gray surfaces only */
+ grBlitterFunc blit_mono; /* 0 by default, set by grBlit.. */
+
+ grRefreshRectFunc refresh_rect;
+ grSetTitleFunc set_title;
+ grListenEventFunc listen_event;
+ grDoneSurfaceFunc done;
+ };
+
+
+
+ /********************************************************************
+ *
+ * <Function>
+ * grAlloc
+ *
+ * <Description>
+ * Simple memory allocation. The returned block is always zero-ed
+ *
+ * <Input>
+ * size :: size in bytes of the requested block
+ *
+ * <Return>
+ * the memory block address. 0 in case of error
+ *
+ ********************************************************************/
+
+ extern unsigned char* grAlloc( long size );
+
+
+ /********************************************************************
+ *
+ * <Function>
+ * grRealloc
+ *
+ * <Description>
+ * Simple memory re-allocation.
+ *
+ * <Input>
+ * block :: original memory block address
+ * size :: new requested block size in bytes
+ *
+ * <Return>
+ * the memory block address. 0 in case of error
+ *
+ ********************************************************************/
+
+ extern unsigned char* grRealloc( const unsigned char* block, long size );
+
+
+ /********************************************************************
+ *
+ * <Function>
+ * grFree
+ *
+ * <Description>
+ * Simple memory release
+ *
+ * <Input>
+ * block :: target block
+ *
+ ********************************************************************/
+
+ extern void grFree( const void* block );
+
+
+#endif /* GROBJS_H */
diff --git a/kernel/kls_ttf/ftview/grtypes.h b/kernel/kls_ttf/ftview/grtypes.h
new file mode 100644
index 0000000..7c39e2a
--- /dev/null
+++ b/kernel/kls_ttf/ftview/grtypes.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ *
+ * grtypes.h
+ *
+ * basic type defintions
+ *
+ * Copyright 1999 - The FreeType Development Team - www.freetype.org
+ *
+ *
+ *
+ *
+ ***************************************************************************/
+
+#ifndef GRTYPES_H
+#define GRTYPES_H
+
+ typedef unsigned char byte;
+
+#if 0
+ typedef signed char uchar;
+
+ typedef unsigned long ulong;
+ typedef unsigned short ushort;
+ typedef unsigned int uint;
+#endif
+
+ typedef struct grDimension_
+ {
+ int x;
+ int y;
+
+ } grDimension;
+
+#define gr_err_ok 0
+#define gr_err_memory -1
+#define gr_err_bad_argument -2
+#define gr_err_bad_target_depth -3
+#define gr_err_bad_source_depth -4
+#define gr_err_saturation_overflow -5
+#define gr_err_conversion_overflow -6
+#define gr_err_invalid_device -7
+
+
+#ifdef GR_MAKE_OPTION_SINGLE_OBJECT
+#define GR_LOCAL_DECL static
+#define GR_LOCAL_FUNC static
+#else
+#define GR_LOCAL_DECL extern
+#define GR_LOCAL_FUNC /* void */
+#endif
+
+#endif /* GRTYPES_H */
diff --git a/kernel/kls_ttf/ttf2pnm.cpp b/kernel/kls_ttf/ttf2pnm.cpp
new file mode 100644
index 0000000..4571731
--- /dev/null
+++ b/kernel/kls_ttf/ttf2pnm.cpp
@@ -0,0 +1,187 @@
+/****************************************************************************/
+/* */
+/* The FreeType project -- a free and portable quality TrueType renderer. */
+/* */
+/* Copyright 1996-2000, 2003, 2004, 2005, 2006 by */
+/* D. Turner, R.Wilhelm, and W. Lemberg */
+/* */
+/* */
+/* FTView - a simple font viewer. */
+/* */
+/* This is a new version using the MiGS graphics subsystem for */
+/* blitting and display. */
+/* */
+/* Press F1 when running this program to have a list of key-bindings */
+/* */
+/****************************************************************************/
+
+#include <freetype/config/ftheader.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "ftcommon.h"
+#include <math.h>
+
+ /* the following header shouldn't be used in normal programs */
+#include FT_SYNTHESIS_H
+
+#define MAXPTSIZE 500 /* dtp */
+
+#ifdef CEIL
+#undef CEIL
+#endif
+#define CEIL( x ) ( ( (x) + 63 ) >> 6 )
+
+#define INIT_SIZE( size, start_x, start_y, step_x, step_y, x, y ) \
+ do { \
+ start_x = 4; \
+ start_y = CEIL( size->metrics.height ); \
+ step_x = CEIL( size->metrics.max_advance ); \
+ step_y = CEIL( size->metrics.height ) + 4; \
+ \
+ x = start_x; \
+ y = start_y; \
+ } while ( 0 )
+
+#define X_TOO_LONG( x, size, bitmap) \
+ ( ( x ) + ( ( size )->metrics.max_advance >> 6 ) > bitmap->width )
+
+#define Y_TOO_LONG( y, size, bitmap) \
+ ( ( y ) >= bitmap->rows )
+
+grBitmap *bit;
+
+ static struct status_
+ {
+ FT_Encoding encoding;
+ int res;
+ int ptsize; /* current point size */
+
+ int font_index;
+ int Num; /* current first index */
+ int Fail;
+
+ } status = { FT_ENCODING_NONE, 72, 24, 0, 0, 0 };
+
+ static FTDemo_Handle* handle;
+
+ static FT_Error
+ Render_All( int num_indices,
+ int first_index )
+ {
+ int start_x, start_y, step_x, step_y, x, y;
+ int i;
+ FT_Size size;
+
+ error = FTDemo_Get_Size(handle, &size);
+
+ if ( error )
+ {
+ /* probably a non-existent bitmap font size */
+ return error;
+ }
+
+ INIT_SIZE( size, start_x, start_y, step_x, step_y, x, y );
+
+ i = first_index;
+
+ while ( i < num_indices )
+ {
+ int gindex;
+
+ if ( handle->encoding == FT_ENCODING_NONE )
+ gindex = i;
+ else
+ gindex = FTDemo_Get_Index( handle, i );
+
+ error = FTDemo_Draw_Index( handle, bit, gindex, &x, &y );
+
+ if ( error )
+ status.Fail++;
+ else if ( X_TOO_LONG( x, size, bit ) )
+ {
+ x = start_x;
+ y += step_y;
+
+ if ( Y_TOO_LONG( y, size, bit ) )
+ break;
+ }
+
+ i++;
+ }
+
+ return FT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** REST OF THE APPLICATION/PROGRAM *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static void
+ event_font_change()
+ {
+ int num_indices;
+
+ status.font_index = 0;
+ status.Num = 0;
+
+ FTDemo_Set_Current_Font(handle, handle->fonts[status.font_index]);
+ FTDemo_Set_Current_Pointsize(handle, status.ptsize, status.res);
+ FTDemo_Update_Current_Flags(handle);
+
+ num_indices = handle->current_font->num_indices;
+
+ if(status.Num >= num_indices)
+ status.Num = num_indices - 1;
+ }
+
+
+ int
+ main( int argc,
+ char* argv[] )
+ {
+ if(argc != 3)
+ exit(1);
+
+ /* Initialize engine */
+ handle = FTDemo_New(status.encoding);
+
+ FTDemo_Install_Font(handle, argv[1]);
+
+ if(handle->num_fonts == 0)
+ PanicZ( "could not find/open any font file" );
+
+ bit = FTDemo_Display_New();
+
+ if(!bit)
+ PanicZ( "could not allocate display surface" );
+
+ status.Fail = 0;
+
+ event_font_change();
+
+ FTDemo_Update_Current_Flags(handle);
+
+ FTDemo_Display_Clear(bit);
+
+ Render_All(handle->current_font->num_indices, status.Num);
+
+ FILE *f = fopen(argv[2], "wb");
+
+ fprintf(f, "P6\n%d %d\n255\n", bit->width, bit->rows);
+ fwrite(bit->buffer, bit->width * bit->rows * 3, 1, f);
+
+ fclose(f);
+
+ FTDemo_Display_Done(bit);
+ FTDemo_Done(handle);
+
+ return 0;
+ }