From 7fe60435bce6595a9c58a9bfd8244d74b5320e96 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 15 Jan 2013 08:46:13 +0100 Subject: Import DirectFB141_2k11R3_beta5 --- Source/DirectFB/tools/mkdgiff.c | 616 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 616 insertions(+) create mode 100755 Source/DirectFB/tools/mkdgiff.c (limited to 'Source/DirectFB/tools/mkdgiff.c') diff --git a/Source/DirectFB/tools/mkdgiff.c b/Source/DirectFB/tools/mkdgiff.c new file mode 100755 index 0000000..459d2a7 --- /dev/null +++ b/Source/DirectFB/tools/mkdgiff.c @@ -0,0 +1,616 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This file is subject to the terms and conditions of the MIT License: + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#undef SIZEOF_LONG +#include +#include FT_GLYPH_H + +#define MAX_SIZE_COUNT 256 +#define MAX_ROW_WIDTH 2047 + +D_DEBUG_DOMAIN( mkdgiff, "mkdgiff", "DirectFB Glyph Image File Format Tool" ); + +static DirectFBPixelFormatNames( format_names ); + +static const char *filename; +static int face_index; +static DFBSurfacePixelFormat format = DSPF_A8; + +static int size_count; +static int face_sizes[MAX_SIZE_COUNT]; + +/**********************************************************************************************************************/ + +static void +print_usage (const char *prg_name) +{ + int i = 0; + + fprintf (stderr, "\nDirectFB Glyph Image File Format Tool (version %s)\n\n", DIRECTFB_VERSION); + fprintf (stderr, "Usage: %s [options]\n\n", prg_name); + fprintf (stderr, "Options:\n"); + fprintf (stderr, " -f, --format Choose the pixel format (default A8)\n"); + fprintf (stderr, " -s, --sizes [,s2...] Choose sizes to generate glyph images for\n"); + fprintf (stderr, " -h, --help Show this help message\n"); + fprintf (stderr, " -v, --version Print version information\n"); + fprintf (stderr, "\n"); + + fprintf (stderr, "Known pixel formats with alpha:\n"); + + while (format_names[i].format != DSPF_UNKNOWN) { + DFBSurfacePixelFormat format = format_names[i].format; + + if (DFB_PIXELFORMAT_HAS_ALPHA(format)) { + fprintf (stderr, " %-10s %2d bits, %d bytes", + format_names[i].name, DFB_BITS_PER_PIXEL(format), + DFB_BYTES_PER_PIXEL(format)); + + if (DFB_PIXELFORMAT_IS_INDEXED(format)) + fprintf (stderr, " INDEXED"); + + if (DFB_PLANAR_PIXELFORMAT(format)) { + int planes = DFB_PLANE_MULTIPLY(format, 1000); + + fprintf (stderr, " PLANAR (x%d.%03d)", + planes / 1000, planes % 1000); + } + + fprintf (stderr, "\n"); + } + + ++i; + } + fprintf (stderr, "\n"); +} + +static DFBBoolean +parse_format( const char *arg, DFBSurfacePixelFormat *ret_format ) +{ + int i = 0; + + while (format_names[i].format != DSPF_UNKNOWN) { + if (!strcasecmp( arg, format_names[i].name )) { + *ret_format = format_names[i].format; + return DFB_TRUE; + } + + ++i; + } + + fprintf (stderr, "\nInvalid format specified!\n\n" ); + + return DFB_FALSE; +} + +static DFBBoolean +parse_sizes( const char *arg ) +{ + int i = 0; + int size = 0; + + for (i=0; arg[i]; i++) { + switch (arg[i]) { + case '0' ... '9': + if (size_count == MAX_SIZE_COUNT) { + fprintf (stderr, "\nMaximum number of sizes (%d) exceeded!\n\n", MAX_SIZE_COUNT ); + return DFB_FALSE; + } + size = size * 10 + arg[i] - '0'; + break; + + case ',': + if (size) { + face_sizes[size_count++] = size; + size = 0; + } + break; + + default: + fprintf (stderr, "\nInvalid character used in sizes argument!\n\n" ); + return DFB_FALSE; + } + } + + if (size) + face_sizes[size_count++] = size; + + return DFB_TRUE; +} + +static DFBBoolean +parse_command_line( int argc, char *argv[] ) +{ + int n; + + for (n = 1; n < argc; n++) { + const char *arg = argv[n]; + + if (strcmp (arg, "-h") == 0 || strcmp (arg, "--help") == 0) { + print_usage (argv[0]); + return DFB_FALSE; + } + + if (strcmp (arg, "-v") == 0 || strcmp (arg, "--version") == 0) { + fprintf (stderr, "mkdgiff version %s\n", DIRECTFB_VERSION); + return DFB_FALSE; + } + + if (strcmp (arg, "-f") == 0 || strcmp (arg, "--format") == 0) { + if (++n == argc) { + print_usage (argv[0]); + return DFB_FALSE; + } + + if (!parse_format( argv[n], &format )) + return DFB_FALSE; + + continue; + } + + if (strcmp (arg, "-s") == 0 || strcmp (arg, "--sizes") == 0) { + if (++n == argc) { + print_usage (argv[0]); + return DFB_FALSE; + } + + if (!parse_sizes( argv[n] )) + return DFB_FALSE; + + continue; + } + + if (filename || access( arg, R_OK )) { + print_usage (argv[0]); + return DFB_FALSE; + } + + filename = arg; + } + + if (!filename) { + print_usage (argv[0]); + return DFB_FALSE; + } + + return DFB_TRUE; +} + +/**********************************************************************************************************************/ + +static void +write_glyph( DGIFFGlyphInfo *glyph, FT_GlyphSlot slot, void *dst, int pitch ) +{ + int y; + u8 *src = slot->bitmap.buffer; + + D_DEBUG_AT( mkdgiff, "%s( %p, %p, %p, %d ) <- width %d\n", + __FUNCTION__, glyph, slot, dst, pitch, glyph->width ); + + for (y=0; y < glyph->height; y++) { + int i, j, n; + u8 *dst8 = dst; + u16 *dst16 = dst; + u32 *dst32 = dst; + + switch (slot->bitmap.pixel_mode) { + case ft_pixel_mode_grays: + switch (format) { + case DSPF_ARGB: + if (0){//FIXME thiz->surface_caps & DSCAPS_PREMULTIPLIED) { + for (i=0; iwidth; i++) + dst32[i] = ((src[i] << 24) | + (src[i] << 16) | + (src[i] << 8) | src[i]); + } + else + for (i=0; iwidth; i++) + dst32[i] = (src[i] << 24) | 0xFFFFFF; + break; + case DSPF_AiRGB: + for (i=0; iwidth; i++) + dst32[i] = ((src[i] ^ 0xFF) << 24) | 0xFFFFFF; + break; + case DSPF_ARGB4444: + for (i=0; iwidth; i++) + dst16[i] = (src[i] << 8) | 0xFFF; + break; + case DSPF_ARGB2554: + for (i=0; iwidth; i++) + dst16[i] = (src[i] << 8) | 0x3FFF; + break; + case DSPF_ARGB1555: + for (i=0; iwidth; i++) + dst16[i] = (src[i] << 8) | 0x7FFF; + break; + case DSPF_A8: + direct_memcpy( dst, src, glyph->width ); + break; + case DSPF_A4: + for (i=0, j=0; iwidth; i+=2, j++) + dst8[j] = (src[i] & 0xF0) | (src[i+1] >> 4); + break; + case DSPF_A1: + for (i=0, j=0; i < glyph->width; ++j) { + register u8 p = 0; + + for (n=0; n<8 && iwidth; ++i, ++n) + p |= (src[i] & 0x80) >> n; + + dst8[j] = p; + } + break; + default: + break; + } + break; + + case ft_pixel_mode_mono: + switch (format) { + case DSPF_ARGB: + for (i=0; iwidth; i++) + dst32[i] = (((src[i>>3] & (1<<(7-(i%8)))) ? + 0xFF : 0x00) << 24) | 0xFFFFFF; + break; + case DSPF_AiRGB: + for (i=0; iwidth; i++) + dst32[i] = (((src[i>>3] & (1<<(7-(i%8)))) ? + 0x00 : 0xFF) << 24) | 0xFFFFFF; + break; + case DSPF_ARGB4444: + for (i=0; iwidth; i++) + dst16[i] = (((src[i>>3] & (1<<(7-(i%8)))) ? + 0xF : 0x0) << 12) | 0xFFF; + break; + case DSPF_ARGB2554: + for (i=0; iwidth; i++) + dst16[i] = (((src[i>>3] & (1<<(7-(i%8)))) ? + 0x3 : 0x0) << 14) | 0x3FFF; + break; + case DSPF_ARGB1555: + for (i=0; iwidth; i++) + dst16[i] = (((src[i>>3] & (1<<(7-(i%8)))) ? + 0x1 : 0x0) << 15) | 0x7FFF; + break; + case DSPF_A8: + for (i=0; iwidth; i++) + dst8[i] = (src[i>>3] & + (1<<(7-(i%8)))) ? 0xFF : 0x00; + break; + case DSPF_A4: + for (i=0, j=0; iwidth; i+=2, j++) + dst8[j] = ((src[i>>3] & + (1<<(7-(i%8)))) ? 0xF0 : 0x00) | + ((src[(i+1)>>3] & + (1<<(7-((i+1)%8)))) ? 0x0F : 0x00); + break; + case DSPF_A1: + direct_memcpy( dst, src, DFB_BYTES_PER_LINE(DSPF_A1, glyph->width) ); + break; + default: + break; + } + break; + + default: + break; + + } + + src += slot->bitmap.pitch; + dst += pitch; + } +} + +static int +do_face( FT_Face face, int size ) +{ + int i, ret; + int align = DFB_PIXELFORMAT_ALIGNMENT( format ); + int num_glyphs = 0; + int num_rows = 1; + int row_index = 0; + int row_offset = 0; + int next_face = sizeof(DGIFFFaceHeader); + int total_height = 0; + FT_ULong code; + FT_UInt index; + DGIFFFaceHeader header; + DGIFFGlyphInfo *glyphs; + DGIFFGlyphRow *rows; + void **row_data; + + D_DEBUG_AT( mkdgiff, "%s( %p, %d ) <- %ld glyphs\n", __FUNCTION__, face, size, face->num_glyphs ); + + /* Clear to not leak any data into file. */ + memset( &header, 0, sizeof(header) ); + + /* Set the desired size. */ + ret = FT_Set_Char_Size( face, 0, size << 6, 0, 0 ); + if (ret) { + D_ERROR( "Could not set pixel size to %d!\n", size ); + return ret; + } + + /* Allocate glyph info array. */ + glyphs = D_CALLOC( face->num_glyphs, sizeof(DGIFFGlyphInfo) ); + rows = D_CALLOC( face->num_glyphs, sizeof(DGIFFGlyphRow) ); /* WORST case :) */ + row_data = D_CALLOC( face->num_glyphs, sizeof(void*) ); /* WORST case :) */ + + for (code = FT_Get_First_Char( face, &index ); + index; + code = FT_Get_Next_Char( face, code, &index )) + { + FT_GlyphSlot slot; + DGIFFGlyphInfo *glyph = &glyphs[num_glyphs]; + DGIFFGlyphRow *row = &rows[num_rows - 1]; + + D_DEBUG_AT( mkdgiff, " -> code %3lu - index %3u\n", code, index ); + + if (num_glyphs == face->num_glyphs) { + D_ERROR( "Actual number of characters is bigger than number of glyphs!\n" ); + break; + } + + ret = FT_Load_Glyph( face, index, FT_LOAD_RENDER ); + if (ret) { + D_ERROR( "Could not render glyph for character index %d!\n", index ); + goto out; + } + + slot = face->glyph; + + glyph->unicode = code; + + glyph->width = slot->bitmap.width; + glyph->height = slot->bitmap.rows; + + glyph->left = slot->bitmap_left; + glyph->top = (face->size->metrics.ascender >> 6) - slot->bitmap_top; + glyph->advance = slot->advance.x >> 6; + + num_glyphs++; + + if (row->width > 0 && row->width + glyph->width > MAX_ROW_WIDTH) { + num_rows++; + row++; + } + + row->width += (glyph->width + align) & ~align; + + if (row->height < glyph->height) + row->height = glyph->height; + } + + for (i=0; i row %d, width %d, height %d\n", i, row->width, row->height ); + + total_height += row->height; + + row->pitch = (DFB_BYTES_PER_LINE( format, row->width ) + 7) & ~7; + + row_data[i] = D_CALLOC( row->height, row->pitch ); + + next_face += row->height * row->pitch; + } + + D_DEBUG_AT( mkdgiff, " -> %d glyphs, %d rows, total height %d\n", num_glyphs, num_rows, total_height ); + + next_face += num_glyphs * sizeof(DGIFFGlyphInfo); + next_face += num_rows * sizeof(DGIFFGlyphRow); + + for (i=0; i reloading character 0x%x (%d)\n", glyph->unicode, i ); + + ret = FT_Load_Char( face, glyph->unicode, FT_LOAD_RENDER ); + if (ret) { + D_ERROR( "Could not render glyph for unicode character 0x%x!\n", glyph->unicode ); + goto out; + } + + if (row_offset > 0 && row_offset + glyph->width > MAX_ROW_WIDTH) { + row_index++; + row_offset = 0; + } + + + D_DEBUG_AT( mkdgiff, " -> row offset %d\n", row_offset ); + + write_glyph( glyph, face->glyph, + row_data[row_index] + DFB_BYTES_PER_LINE( format, row_offset ), + rows[row_index].pitch ); + + glyph->row = row_index; + glyph->offset = row_offset; + + row_offset += (glyph->width + align) & ~align; + } + + D_ASSERT( row_index == num_rows - 1 ); + + header.next_face = next_face; + header.size = size; + + header.ascender = face->size->metrics.ascender >> 6; + header.descender = face->size->metrics.descender >> 6; + header.height = header.ascender - header.descender + 1; + + header.max_advance = face->size->metrics.max_advance >> 6; + + header.pixelformat = format; + + header.num_glyphs = num_glyphs; + header.num_rows = num_rows; + + D_DEBUG_AT( mkdgiff, " -> ascender %d, descender %d\n", header.ascender, header.descender ); + D_DEBUG_AT( mkdgiff, " -> height %d, max advance %d\n", header.height, header.max_advance ); + + fwrite( &header, sizeof(header), 1, stdout ); + + fwrite( glyphs, sizeof(*glyphs), num_glyphs, stdout ); + + for (i=0; ipitch, row->height, stdout ); + } + +out: + for (i=0; idebug = true; + direct_config->debugmem = true; + + /* Parse the command line. */ + if (!parse_command_line( argc, argv )) + return -1; + + if (!size_count) { + fprintf( stderr, "\n\nUsing default sizes 8, 10, 12, 16, 22, 32\n" ); + + size_count = 6; + + face_sizes[0] = 8; + face_sizes[1] = 10; + face_sizes[2] = 12; + face_sizes[3] = 16; + face_sizes[4] = 22; + face_sizes[5] = 32; + } + + header.num_faces = size_count; + + + ret = FT_Init_FreeType( &library ); + if (ret) { + D_ERROR( "Initialization of the FreeType2 library failed!\n" ); + goto out; + } + + ret = FT_New_Face( library, filename, face_index, &face ); + if (ret) { + if (ret == FT_Err_Unknown_File_Format) + D_ERROR( "Unsupported font format in file `%s'!\n", filename ); + else + D_ERROR( "Failed loading face %d from font file `%s'!\n", face_index, filename ); + + goto out; + } + + ret = FT_Select_Charmap( face, ft_encoding_unicode ); + if (ret) { + D_ERROR( "Couldn't select Unicode encoding, falling back to Latin1.\n" ); + + ret = FT_Select_Charmap( face, ft_encoding_latin_1 ); + if (ret) + D_ERROR( "Couldn't even select Latin1 encoding!\n" ); + } + + fwrite( &header, sizeof(header), 1, stdout ); + + for (i=0; i