summaryrefslogtreecommitdiff
path: root/Source/DirectFB/interfaces/IDirectFBFont/idirectfbfont_dgiff.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DirectFB/interfaces/IDirectFBFont/idirectfbfont_dgiff.c')
-rwxr-xr-xSource/DirectFB/interfaces/IDirectFBFont/idirectfbfont_dgiff.c364
1 files changed, 364 insertions, 0 deletions
diff --git a/Source/DirectFB/interfaces/IDirectFBFont/idirectfbfont_dgiff.c b/Source/DirectFB/interfaces/IDirectFBFont/idirectfbfont_dgiff.c
new file mode 100755
index 0000000..5e1977c
--- /dev/null
+++ b/Source/DirectFB/interfaces/IDirectFBFont/idirectfbfont_dgiff.c
@@ -0,0 +1,364 @@
+/*
+ (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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <directfb.h>
+
+#include <core/fonts.h>
+#include <core/gfxcard.h>
+#include <core/surface.h>
+#include <core/surface_buffer.h>
+
+#include <gfx/convert.h>
+
+#include <media/idirectfbfont.h>
+
+#include <direct/hash.h>
+
+#include <direct/interface.h>
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+#include <direct/utf8.h>
+
+#include <dgiff.h>
+
+/**********************************************************************************************************************/
+
+static DFBResult
+Probe( IDirectFBFont_ProbeContext *ctx );
+
+static DFBResult
+Construct( IDirectFBFont *thiz,
+ CoreDFB *core,
+ IDirectFBFont_ProbeContext *ctx,
+ DFBFontDescription *desc );
+
+/**********************************************************************************************************************/
+
+#include <direct/interface_implementation.h>
+
+DIRECT_INTERFACE_IMPLEMENTATION( IDirectFBFont, DGIFF )
+
+/**********************************************************************************************************************/
+
+typedef struct {
+ void *map; /* Memory map of the file. */
+ int size; /* Size of the memory map. */
+} DGIFFImplData;
+
+/**********************************************************************************************************************/
+
+static void
+IDirectFBFont_DGIFF_Destruct( IDirectFBFont *thiz )
+{
+ IDirectFBFont_data *data = thiz->priv;
+ CoreFont *font = data->font;
+ DGIFFImplData *impl = font->impl_data;
+
+ munmap( impl->map, impl->size );
+
+ D_FREE( impl );
+
+ IDirectFBFont_Destruct( thiz );
+}
+
+
+static DirectResult
+IDirectFBFont_DGIFF_Release( IDirectFBFont *thiz )
+{
+ DIRECT_INTERFACE_GET_DATA(IDirectFBFont)
+
+ if (--data->ref == 0) {
+ IDirectFBFont_DGIFF_Destruct( thiz );
+ }
+
+ return DFB_OK;
+}
+
+static DFBResult
+Probe( IDirectFBFont_ProbeContext *ctx )
+{
+ DFBResult ret = DFB_OK;
+ int fd;
+ DGIFFHeader header;
+
+ if (!ctx->filename)
+ return DFB_UNSUPPORTED;
+
+ /* Open the file. */
+ fd = open( ctx->filename, O_RDONLY );
+ if (fd < 0) {
+ ret = errno2result( errno );
+ D_PERROR( "Font/DGIFF: Failure during open() of '%s'!\n", ctx->filename );
+ goto out;
+ }
+
+ /* Read the header. */
+ if (read( fd, &header, sizeof(header) ) != sizeof(header)) {
+ ret = errno2result( errno );
+ D_PERROR( "Font/DGIFF: Failure reading %zu bytes from '%s'!\n", sizeof(header), ctx->filename );
+ goto out;
+ }
+
+ /* Check the magic. */
+ if (strncmp( (char*) header.magic, "DGIFF", 5 ))
+ ret = DFB_UNSUPPORTED;
+
+out:
+ if (fd >= 0)
+ close( fd );
+
+ return ret;
+}
+
+static DFBResult
+Construct( IDirectFBFont *thiz,
+ CoreDFB *core,
+ IDirectFBFont_ProbeContext *ctx,
+ DFBFontDescription *desc )
+{
+ DFBResult ret;
+ int i;
+ int fd;
+ struct stat stat;
+ void *ptr = MAP_FAILED;
+ CoreFont *font = NULL;
+ DGIFFHeader *header;
+ DGIFFFaceHeader *face;
+ DGIFFGlyphInfo *glyphs;
+ DGIFFGlyphRow *row;
+ DGIFFImplData *data;
+ char *filename;
+ CoreSurfaceConfig config;
+
+// if (desc->flags & (DFDESC_WIDTH | DFDESC_ATTRIBUTES | DFDESC_FIXEDADVANCE))
+ // return DFB_UNSUPPORTED;
+ /* use the filename for backwards compatibility */
+ filename = ctx->filename;
+
+ if (desc->flags & DFDESC_ROTATION)
+ return DFB_UNSUPPORTED;
+
+ /* Open the file. */
+ fd = open( filename, O_RDONLY );
+ if (fd < 0) {
+ ret = errno2result( errno );
+ D_PERROR( "Font/DGIFF: Failure during open() of '%s'!\n", filename );
+ return ret;
+ }
+
+ /* Query file size etc. */
+ if (fstat( fd, &stat ) < 0) {
+ ret = errno2result( errno );
+ D_PERROR( "Font/DGIFF: Failure during fstat() of '%s'!\n", filename );
+ goto error;
+ }
+
+ /* Memory map the file. */
+ ptr = mmap( NULL, stat.st_size, PROT_READ, MAP_SHARED, fd, 0 );
+ if (ptr == MAP_FAILED) {
+ ret = errno2result( errno );
+ D_PERROR( "Font/DGIFF: Failure during mmap() of '%s'!\n", filename );
+ goto error;
+ }
+
+ /* Keep entry pointers for main header and face. */
+ header = ptr;
+ face = ptr + sizeof(DGIFFHeader);
+
+ /* Lookup requested face, otherwise use first if nothing requested or show error if not found. */
+ if (desc->flags & DFDESC_HEIGHT) {
+ for (i=0; i<header->num_faces; i++) {
+ if (face->size == desc->height)
+ break;
+
+ face = ((void*) face) + face->next_face;
+ }
+
+ if (i == header->num_faces) {
+ ret = DFB_UNSUPPORTED;
+ D_ERROR( "Font/DGIFF: Requested size %d not found in '%s'!\n", desc->height, filename );
+ goto error;
+ }
+ }
+
+ glyphs = (void*)(face + 1);
+ row = (void*)(glyphs + face->num_glyphs);
+
+ /* Create the core object. */
+ ret = dfb_font_create( core, desc, filename, &font );
+ if (ret)
+ goto error;
+
+ /* Fill font information. */
+ font->ascender = face->ascender;
+ font->descender = face->descender;
+ font->height = face->height;
+ font->up_unit_x = 0.0;
+ font->up_unit_y = -1.0;
+
+ font->maxadvance = face->max_advance;
+ font->pixel_format = face->pixelformat;
+ font->surface_caps = DSCAPS_NONE;
+
+ font->num_rows = face->num_rows;
+
+ if (face->blittingflags)
+ font->blittingflags = face->blittingflags;
+
+ /* Allocate array for glyph cache rows. */
+ font->rows = D_CALLOC( face->num_rows, sizeof(void*) );
+ if (!font->rows) {
+ ret = D_OOM();
+ goto error;
+ }
+
+ /* Build glyph cache rows. */
+
+ config.flags = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_PREALLOCATED;
+ config.format = face->pixelformat;
+ config.preallocated[1].addr = NULL;
+ config.preallocated[1].pitch = 0;
+
+ for (i=0; i<face->num_rows; i++) {
+ font->rows[i] = D_CALLOC( 1, sizeof(CoreFontCacheRow) );
+ if (!font->rows[i]) {
+ ret = D_OOM();
+ goto error;
+ }
+
+ config.size.w = row->width;
+ config.size.h = row->height;
+ config.preallocated[0].addr = (void*)(row+1);
+ config.preallocated[0].pitch = row->pitch;
+
+ ret = dfb_surface_create( core, &config, CSTF_PREALLOCATED, 0, NULL,
+ &font->rows[i]->surface );
+
+ if (ret) {
+ D_DERROR( ret, "DGIFF/Font: Could not create preallocated %s %dx%d glyph row surface!\n",
+ dfb_pixelformat_name(face->pixelformat), row->width, row->height );
+ goto error;
+ }
+
+ D_MAGIC_SET( font->rows[i], CoreFontCacheRow );
+
+ /* Jump to next row. */
+ row = (void*)(row + 1) + row->pitch * row->height;
+ }
+
+ /* Build glyph infos. */
+ for (i=0; i<face->num_glyphs; i++) {
+ CoreGlyphData *data;
+ DGIFFGlyphInfo *glyph = &glyphs[i];
+
+ data = D_CALLOC( 1, sizeof(CoreGlyphData) );
+ if (!data) {
+ ret = D_OOM();
+ goto error;
+ }
+
+ data->surface = font->rows[glyph->row]->surface;
+
+ data->start = glyph->offset;
+ data->width = glyph->width;
+ data->height = glyph->height;
+ data->left = glyph->left;
+ data->top = glyph->top;
+ data->xadvance = glyph->advance;
+ data->yadvance = 0;
+
+ D_MAGIC_SET( data, CoreGlyphData );
+
+ direct_hash_insert( font->layers[0].glyph_hash, glyph->unicode, data );
+
+ if (glyph->unicode < 128)
+ font->layers[0].glyph_data[glyph->unicode] = data;
+ }
+
+
+ data = D_CALLOC( 1, sizeof(DGIFFImplData) );
+ if (!data) {
+ ret = D_OOM();
+ goto error;
+ }
+
+ data->map = ptr;
+ data->size = stat.st_size;
+
+ font->impl_data = data;
+
+ /* Already close, we still have the map. */
+ close( fd );
+
+ ret = IDirectFBFont_Construct( thiz, font );
+ D_ASSERT( ret == DFB_OK );
+
+ thiz->Release = IDirectFBFont_DGIFF_Release;
+
+ return DFB_OK;
+
+
+error:
+ if (font) {
+ if (font->rows) {
+ for (i=0; i<font->num_rows; i++) {
+ if (font->rows[i]) {
+ if (font->rows[i]->surface)
+ dfb_surface_unref( font->rows[i]->surface );
+
+ D_FREE( font->rows[i] );
+ }
+ }
+
+ D_FREE( font->rows );
+
+ font->rows = NULL;
+ }
+
+ dfb_font_destroy( font );
+ }
+
+ if (ptr != MAP_FAILED)
+ munmap( ptr, stat.st_size );
+
+ close( fd );
+
+ DIRECT_DEALLOCATE_INTERFACE( thiz );
+
+ return ret;
+}
+