diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-24 17:43:19 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-24 17:43:19 +0000 |
commit | 0292059f4a16434600564cfa3f0ad2309a508a54 (patch) | |
tree | d95953cd53011917c4df679b96aedca39401b54f /kernel/kls_ttf | |
download | libksquirrel-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')
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; + } |