summaryrefslogtreecommitdiff
path: root/atari/plot
diff options
context:
space:
mode:
Diffstat (limited to 'atari/plot')
-rw-r--r--atari/plot/eddi.h54
-rw-r--r--atari/plot/eddi.s42
-rw-r--r--atari/plot/font_freetype.c512
-rw-r--r--atari/plot/font_freetype.h51
-rw-r--r--atari/plot/font_vdi.c216
-rw-r--r--atari/plot/font_vdi.h23
-rw-r--r--atari/plot/plotter.c723
-rw-r--r--atari/plot/plotter.h293
-rw-r--r--atari/plot/plotter_vdi.c998
-rw-r--r--atari/plot/plotter_vdi.h48
10 files changed, 2960 insertions, 0 deletions
diff --git a/atari/plot/eddi.h b/atari/plot/eddi.h
new file mode 100644
index 000000000..7d6b90d4b
--- /dev/null
+++ b/atari/plot/eddi.h
@@ -0,0 +1,54 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2009 Sam Lantinga
+
+ 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+#ifndef _atari_eddi_h
+#define _atari_eddi_h
+
+/*--- Defines ---*/
+
+/* EdDI versions */
+
+#define EDDI_10 (0x0100)
+#define EDDI_11 (0x0110)
+
+/* Screen format */
+
+enum {
+ VDI_FORMAT_UNKNOWN=-1,
+ VDI_FORMAT_INTER=0, /* Interleaved bitplanes */
+ VDI_FORMAT_VDI=1, /* VDI independent */
+ VDI_FORMAT_PACK=2 /* Packed pixels */
+};
+
+/* CLUT types */
+enum {
+ VDI_CLUT_NONE=0, /* Monochrome mode */
+ VDI_CLUT_HARDWARE, /* <256 colours mode */
+ VDI_CLUT_SOFTWARE /* True colour mode */
+};
+
+
+/*--- Functions ---*/
+
+unsigned long EdDI_version(void *function_pointer);
+
+#endif /* atari_eddi_s_h */
diff --git a/atari/plot/eddi.s b/atari/plot/eddi.s
new file mode 100644
index 000000000..f0ea18a1e
--- /dev/null
+++ b/atari/plot/eddi.s
@@ -0,0 +1,42 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2009 Sam Lantinga
+
+ 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+/*
+ *Read EdDI version
+ *
+ *Patrice Mandin
+ */
+
+.text
+
+.globl _EdDI_version
+
+/*--- Vector installer ---*/
+
+_EdDI_version:
+movel sp@(4),a0 /* Value of EdDI cookie */
+
+/* Call EdDI function #0 */
+clrl d0
+jsr (a0)
+
+rts
diff --git a/atari/plot/font_freetype.c b/atari/plot/font_freetype.c
new file mode 100644
index 000000000..0a1addfdf
--- /dev/null
+++ b/atari/plot/font_freetype.c
@@ -0,0 +1,512 @@
+/*
+ * Copyright 2005 James Bursa <bursa@users.sourceforge.net>
+ * 2008 Vincent Sanders <vince@simtec.co.uk>
+ * 2011 Ole Loots <ole@monochrom.net>
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <math.h>
+#include <assert.h>
+#include <string.h>
+#include <windom.h>
+#include <ft2build.h>
+#include FT_CACHE_H
+
+#include "desktop/plot_style.h"
+#include "image/bitmap.h"
+#include "atari/bitmap.h"
+#include "atari/plot/plotter.h"
+#include "atari/plot/font_freetype.h"
+#include "atari/gui.h"
+#include "atari/font.h"
+#include "atari/options.h"
+#include "atari/findfile.h"
+#include "utils/utf8.h"
+#include "utils/log.h"
+
+#define DEJAVU_PATH "/usr/share/fonts/truetype/ttf-dejavu/"
+
+static FT_Library library;
+static FTC_Manager ft_cmanager;
+static FTC_CMapCache ft_cmap_cache ;
+static FTC_ImageCache ft_image_cache;
+
+int ft_load_type;
+
+/* cache manager faceID data to create freetype faceid on demand */
+typedef struct ftc_faceid_s {
+ char *fontfile; /* path to font */
+ int index; /* index of font */
+ int cidx; /* character map index for unicode */
+} ftc_faceid_t;
+
+static struct bitmap * fontbmp;
+
+static ftc_faceid_t *font_faces[FONT_FACE_COUNT];
+
+static int dtor( FONT_PLOTTER self );
+static int str_width( FONT_PLOTTER self,const plot_font_style_t *fstyle,
+ const char * str, size_t length, int * width );
+static int str_split( FONT_PLOTTER self, const plot_font_style_t *fstyle,
+ const char *string, size_t length,int x,
+ size_t *char_offset, int *actual_x );
+static int pixel_position( FONT_PLOTTER self, const plot_font_style_t *fstyle,
+ const char *string, size_t length,int x,
+ size_t *char_offset, int *actual_x );
+static int text( FONT_PLOTTER self, int x, int y, const char *text,
+ size_t length, const plot_font_style_t *fstyle );
+
+static bool init = false;
+
+
+
+/* map cache manager handle to face id */
+static FT_Error ft_face_requester(FTC_FaceID face_id, FT_Library library, FT_Pointer request_data, FT_Face *face )
+{
+ FT_Error error;
+ ftc_faceid_t *ft_face = (ftc_faceid_t *)face_id;
+ int cidx;
+
+ error = FT_New_Face(library, ft_face->fontfile, ft_face->index, face);
+ if (error) {
+ LOG(("Could not find font (code %d)\n", error));
+ } else {
+ error = FT_Select_Charmap(*face, FT_ENCODING_UNICODE);
+ if (error) {
+ LOG(("Could not select charmap (code %d)\n", error));
+ } else {
+ for (cidx = 0; cidx < (*face)->num_charmaps; cidx++) {
+ if ((*face)->charmap == (*face)->charmaps[cidx]) {
+ ft_face->cidx = cidx;
+ break;
+ }
+ }
+ }
+ }
+ LOG(("Loaded face from %s\n", ft_face->fontfile));
+ return error;
+}
+
+/* create new framebuffer face and cause it to be loaded to check its ok */
+static ftc_faceid_t *
+ft_new_face(const char *option, const char *resname, const char *fontfile)
+{
+ ftc_faceid_t *newf;
+ FT_Error error;
+ FT_Face aface;
+ char buf[PATH_MAX];
+ char resname2[PATH_MAX];
+
+ newf = calloc(1, sizeof(ftc_faceid_t));
+ if (option != NULL) {
+ newf->fontfile = strdup(option);
+ } else {
+ atari_find_resource(buf, resname, fontfile);
+ newf->fontfile = strdup(buf);
+ }
+ error = FTC_Manager_LookupFace(ft_cmanager, (FTC_FaceID)newf, &aface);
+ if (error) {
+ LOG(("Could not find font face %s (code %d)\n", fontfile, error));
+ free(newf);
+ newf = font_faces[FONT_FACE_DEFAULT]; /* use default */
+ }
+ return newf;
+}
+
+static void ft_fill_scalar(const plot_font_style_t *fstyle, FTC_Scaler srec)
+{
+ int selected_face = FONT_FACE_DEFAULT;
+
+ switch (fstyle->family) {
+/*
+ case PLOT_FONT_FAMILY_CURSIVE:
+ break;
+ case PLOT_FONT_FAMILY_FANTASY:
+ break;
+*/
+ case PLOT_FONT_FAMILY_SERIF:
+ if (fstyle->weight >= 700)
+ selected_face = FONT_FACE_SERIF_BOLD;
+ else
+ selected_face = FONT_FACE_SERIF;
+
+ break;
+
+ case PLOT_FONT_FAMILY_MONOSPACE:
+ selected_face = FONT_FACE_MONOSPACE;
+ break;
+
+ case PLOT_FONT_FAMILY_SANS_SERIF:
+ default:
+ if ((fstyle->flags & FONTF_ITALIC) || (fstyle->flags & FONTF_OBLIQUE)) {
+ if (fstyle->weight >= 700)
+ selected_face = FONT_FACE_SANS_SERIF_ITALIC_BOLD;
+ else
+ selected_face = FONT_FACE_SANS_SERIF_ITALIC;
+ } else {
+ if (fstyle->weight >= 700)
+ selected_face = FONT_FACE_SANS_SERIF_BOLD;
+ else
+ selected_face = FONT_FACE_SANS_SERIF;
+ }
+ }
+
+ srec->face_id = (FTC_FaceID)font_faces[selected_face];
+ srec->width = srec->height = (fstyle->size * 64) / FONT_SIZE_SCALE;
+ srec->pixel = 0;
+ srec->x_res = srec->y_res = 72;
+}
+
+static FT_Glyph ft_getglyph(const plot_font_style_t *fstyle, uint32_t ucs4)
+{
+ FT_UInt glyph_index;
+ FTC_ScalerRec srec;
+ FT_Glyph glyph;
+ FT_Error error;
+ ftc_faceid_t *ft_face;
+
+ ft_fill_scalar(fstyle, &srec);
+ ft_face = (ftc_faceid_t *)srec.face_id;
+ glyph_index = FTC_CMapCache_Lookup(ft_cmap_cache, srec.face_id, ft_face->cidx, ucs4);
+ error = FTC_ImageCache_LookupScaler(ft_image_cache,
+ &srec,
+ FT_LOAD_RENDER |
+ FT_LOAD_FORCE_AUTOHINT |
+ ft_load_type,
+ glyph_index,
+ &glyph,
+ NULL);
+
+ return glyph;
+}
+
+
+
+/* initialise font handling */
+static bool ft_font_init(void)
+{
+ FT_Error error;
+ FT_ULong max_cache_size;
+ FT_UInt max_faces = 6;
+
+ /* freetype library initialise */
+ error = FT_Init_FreeType( &library );
+ if (error) {
+ LOG(("Freetype could not initialised (code %d)\n", error));
+ return false;
+ }
+
+ max_cache_size = 2 * 1024 *1024; /* 2MB should be enough */
+
+ /* cache manager initialise */
+ error = FTC_Manager_New(library,
+ max_faces,
+ 0,
+ max_cache_size,
+ ft_face_requester,
+ NULL,
+ &ft_cmanager);
+ if (error) {
+ LOG(("Freetype could not initialise cache manager (code %d)\n", error));
+ FT_Done_FreeType(library);
+ return false;
+ }
+
+ error = FTC_CMapCache_New(ft_cmanager, &ft_cmap_cache);
+ error = FTC_ImageCache_New(ft_cmanager, &ft_image_cache);
+
+ font_faces[FONT_FACE_SANS_SERIF] = NULL;
+ font_faces[FONT_FACE_SANS_SERIF] = ft_new_face(
+ option_atari_face_sans_serif,
+ "fonts/ss.ttf",
+ DEJAVU_PATH"DejaVuSans.ttf"
+ );
+ if (font_faces[FONT_FACE_SANS_SERIF] == NULL) {
+ LOG(("Could not find default font (code %d)\n", error));
+ FTC_Manager_Done(ft_cmanager );
+ FT_Done_FreeType(library);
+ return false;
+ }
+
+ font_faces[FONT_FACE_SANS_SERIF_BOLD] =
+ ft_new_face(option_atari_face_sans_serif_bold,
+ "fonts/ssb.ttf",
+ DEJAVU_PATH"DejaVuSans-Bold.ttf");
+
+ font_faces[FONT_FACE_SANS_SERIF_ITALIC] =
+ ft_new_face(option_atari_face_sans_serif_italic,
+ "fonts/ssi.ttf",
+ DEJAVU_PATH"DejaVuSans-Oblique.ttf");
+
+ font_faces[FONT_FACE_SANS_SERIF_ITALIC_BOLD] =
+ ft_new_face(option_atari_face_sans_serif_italic_bold,
+ "fonts/ssib.ttf",
+ DEJAVU_PATH"DejaVuSans-BoldOblique.ttf");
+
+ font_faces[FONT_FACE_MONOSPACE] =
+ ft_new_face(option_atari_face_monospace,
+ "fonts/mono.ttf",
+ DEJAVU_PATH"DejaVuSansMono.ttf");
+
+ font_faces[FONT_FACE_MONOSPACE_BOLD] =
+ ft_new_face(option_atari_face_monospace_bold,
+ "fonts/monob.ttf",
+ DEJAVU_PATH"DejaVuSansMono-Bold.ttf");
+
+ font_faces[FONT_FACE_SERIF] =
+ ft_new_face(option_atari_face_serif,
+ "fonts/s.ttf",
+ DEJAVU_PATH"DejaVuSerif.ttf");
+
+ font_faces[FONT_FACE_SERIF_BOLD] =
+ ft_new_face(option_atari_face_serif_bold,
+ "fonts/sb.ttf",
+ DEJAVU_PATH"DejaVuSerif-Bold.ttf");
+
+ font_faces[FONT_FACE_CURSIVE] =
+ ft_new_face(option_atari_face_cursive,
+ "fonts/cursive.ttf",
+ DEJAVU_PATH"DejaVuSansMono-Oblique.ttf");
+
+ font_faces[FONT_FACE_FANTASY] =
+ ft_new_face(option_atari_face_fantasy,
+ "fonts/fantasy.ttf",
+ DEJAVU_PATH"DejaVuSerifCondensed-Bold.ttf");
+
+ /* set the default render mode */
+ if (option_atari_font_monochrom == true)
+ ft_load_type = FT_LOAD_MONOCHROME;
+ else
+ ft_load_type = 0;
+
+ return true;
+}
+
+
+static bool ft_font_finalise(void)
+{
+ FTC_Manager_Done(ft_cmanager );
+ FT_Done_FreeType(library);
+ return true;
+}
+
+static int str_width( FONT_PLOTTER self,const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int *width)
+{
+ uint32_t ucs4;
+ size_t nxtchr = 0;
+ FT_Glyph glyph;
+
+ *width = 0;
+ while (nxtchr < length) {
+ ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr);
+ nxtchr = utf8_next(string, length, nxtchr);
+
+ glyph = ft_getglyph(fstyle, ucs4);
+ if (glyph == NULL)
+ continue;
+ *width += glyph->advance.x >> 16;
+ }
+ return(1);
+}
+
+
+static int str_split( FONT_PLOTTER self, const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int x, size_t *char_offset, int *actual_x)
+{
+ uint32_t ucs4;
+ size_t nxtchr = 0;
+ int last_space_x = 0;
+ int last_space_idx = 0;
+ FT_Glyph glyph;
+
+ *actual_x = 0;
+ while (nxtchr < length) {
+ ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr);
+ glyph = ft_getglyph(fstyle, ucs4);
+ if (glyph == NULL)
+ continue;
+ if (ucs4 == 0x20) {
+ last_space_x = *actual_x;
+ last_space_idx = nxtchr;
+ }
+ *actual_x += glyph->advance.x >> 16;
+ if (*actual_x > x) {
+ /* string has exceeded available width return previous space*/
+ *actual_x = last_space_x;
+ *char_offset = last_space_idx;
+ return true;
+ }
+ nxtchr = utf8_next(string, length, nxtchr);
+ }
+ *char_offset = nxtchr;
+ return (1);
+}
+
+
+static int pixel_position( FONT_PLOTTER self, const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int x, size_t *char_offset, int *actual_x)
+{
+ uint32_t ucs4;
+ size_t nxtchr = 0;
+ FT_Glyph glyph;
+
+ *actual_x = 0;
+ while (nxtchr < length) {
+ ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr);
+ glyph = ft_getglyph(fstyle, ucs4);
+ if (glyph == NULL)
+ continue;
+ *actual_x += glyph->advance.x >> 16;
+ if (*actual_x > x)
+ break;
+ nxtchr = utf8_next(string, length, nxtchr);
+ }
+ *char_offset = nxtchr;
+ return ( 1 );
+}
+
+static void draw_glyph8(FONT_PLOTTER self, GRECT * loc, uint8_t * pixdata, int pitch, uint32_t colour)
+{
+ GRECT clip;
+ uint32_t * linebuf;
+ uint32_t fontpix;
+ size_t bmpstride;
+ int xloop,yloop,xoff,yoff;
+ int x,y,w,h;
+
+ x = loc->g_x;
+ y = loc->g_y;
+ w = loc->g_w;
+ h = loc->g_h;
+
+ clip.g_x = self->plotter->clipping.x0;
+ clip.g_y = self->plotter->clipping.y0;
+ clip.g_w = self->plotter->clipping.x1 - self->plotter->clipping.x0;
+ clip.g_h = self->plotter->clipping.y1 - self->plotter->clipping.y0;
+
+ if( !rc_intersect( &clip, loc ) ){
+ return;
+ }
+
+ assert( loc->g_w > 0 );
+ assert( loc->g_h > 0 );
+ xoff = loc->g_x - x;
+ yoff = loc->g_y - y;
+
+ if (h > loc->g_h)
+ h = loc->g_h;
+
+ if (w > loc->g_w)
+ w = loc->g_w;
+ fontbmp = bitmap_realloc( w, h,
+ fontbmp->bpp, w * fontbmp->bpp,
+ BITMAP_GROW, fontbmp );
+ assert( fontbmp );
+ assert( fontbmp->pixdata );
+ bmpstride = bitmap_get_rowstride(fontbmp);
+ for( yloop = 0; yloop < h; yloop++) {
+ linebuf = (uint32_t *)(fontbmp->pixdata + (bmpstride * yloop));
+ for(xloop = 0; xloop < w; xloop++){
+ fontpix = (uint32_t)(pixdata[(( yoff + yloop ) * pitch) + xloop + xoff]);
+ linebuf[xloop] = (uint32_t)(colour | fontpix);
+ }
+ }
+ self->plotter->bitmap( self->plotter, fontbmp, loc->g_x, loc->g_y, 0, 0);
+}
+
+static int text( FONT_PLOTTER self, int x, int y, const char *text, size_t length,
+ const plot_font_style_t *fstyle )
+{
+ uint32_t ucs4;
+ size_t nxtchr = 0;
+ FT_Glyph glyph;
+ FT_BitmapGlyph bglyph;
+ GRECT loc, clip;
+ uint32_t c = fstyle->foreground ;
+ /* in -> BGR */
+ /* out -> ARGB */
+ c = ABGR_TO_RGB(c);
+
+ clip.g_x = self->plotter->clipping.x0;
+ clip.g_y = self->plotter->clipping.y0;
+ clip.g_w = self->plotter->clipping.x1 - self->plotter->clipping.x0;
+ clip.g_h = self->plotter->clipping.y1 - self->plotter->clipping.y0;
+ while (nxtchr < length) {
+ ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr);
+ nxtchr = utf8_next(text, length, nxtchr);
+
+ glyph = ft_getglyph(fstyle, ucs4);
+ if (glyph == NULL)
+ continue;
+
+ if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
+ bglyph = (FT_BitmapGlyph)glyph;
+ loc.g_x = x + bglyph->left;
+ loc.g_y = y - bglyph->top;
+ loc.g_w = bglyph->bitmap.width;
+ loc.g_h = bglyph->bitmap.rows;
+
+ if (bglyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
+ assert( 1 == 0 );
+ } else {
+ if( loc.g_w > 0) {
+ draw_glyph8( self,
+ &loc,
+ bglyph->bitmap.buffer,
+ bglyph->bitmap.pitch,
+ c
+ );
+ }
+ }
+ }
+ x += glyph->advance.x >> 16;
+
+ }
+ return( 0 );
+}
+
+
+int ctor_font_plotter_freetype( FONT_PLOTTER self )
+{
+ self->dtor = dtor;
+ self->str_width = str_width;
+ self->str_split = str_split;
+ self->pixel_position = pixel_position;
+ self->text = text;
+ LOG(("%s: %s\n", (char*)__FILE__, __FUNCTION__));
+ if( !init ) {
+ ft_font_init();
+ fontbmp = bitmap_create(48, 48, 0);
+ fontbmp->opaque = false;
+ init = true;
+ }
+
+ return( 1 );
+}
+
+static int dtor( FONT_PLOTTER self )
+{
+ ft_font_finalise();
+ if( fontbmp == NULL )
+ bitmap_destroy( fontbmp );
+ return( 1 );
+} \ No newline at end of file
diff --git a/atari/plot/font_freetype.h b/atari/plot/font_freetype.h
new file mode 100644
index 000000000..bca6d9956
--- /dev/null
+++ b/atari/plot/font_freetype.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2011 Ole Loots <ole@monochrom.net>
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef FONT_PLOTTER_FREETYPE
+#define FONT_PLOTTER_FREETYPE
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_GLYPH_H
+#include "utils/utf8.h"
+
+/* defines for accesing the faces */
+#define FONT_FACE_DEFAULT 0
+
+#define FONT_FACE_SANS_SERIF 0
+#define FONT_FACE_SANS_SERIF_BOLD 1
+#define FONT_FACE_SANS_SERIF_ITALIC 2
+#define FONT_FACE_SANS_SERIF_ITALIC_BOLD 3
+#define FONT_FACE_MONOSPACE 4
+#define FONT_FACE_MONOSPACE_BOLD 5
+#define FONT_FACE_SERIF 6
+#define FONT_FACE_SERIF_BOLD 7
+#define FONT_FACE_CURSIVE 8
+#define FONT_FACE_FANTASY 9
+
+#define FONT_FACE_COUNT 10
+
+struct font_desc {
+ const char *name;
+ int width, height;
+ const char *encoding;
+};
+
+/* extern int ft_load_type; */
+
+int ctor_font_plotter_freetype( FONT_PLOTTER self );
+#endif \ No newline at end of file
diff --git a/atari/plot/font_vdi.c b/atari/plot/font_vdi.c
new file mode 100644
index 000000000..04a94734e
--- /dev/null
+++ b/atari/plot/font_vdi.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <math.h>
+#include <assert.h>
+#include <string.h>
+#include <windom.h>
+
+#include "desktop/plot_style.h"
+#include "atari/bitmap.h"
+#include "atari/plot/plotter.h"
+#include "atari/plot/font_vdi.h"
+#include "utils/utf8.h"
+#include "utils/log.h"
+
+static char * lstr = NULL;
+
+
+static int dtor( FONT_PLOTTER self );
+static int str_width( FONT_PLOTTER self,const plot_font_style_t *fstyle, const char * str, size_t length, int * width );
+static int str_split( FONT_PLOTTER self, const plot_font_style_t *fstyle,const char *string,
+ size_t length,int x, size_t *char_offset, int *actual_x );
+static int pixel_position( FONT_PLOTTER self, const plot_font_style_t *fstyle,const char *string,
+ size_t length,int x, size_t *char_offset, int *actual_x );
+static int text( FONT_PLOTTER self, int x, int y, const char *text, size_t length, const plot_font_style_t *fstyle );
+
+static bool init = false;
+static int vdih;
+int ctor_font_plotter_vdi( FONT_PLOTTER self )
+{
+ self->dtor = dtor;
+ self->str_width = str_width;
+ self->str_split = str_split;
+ self->pixel_position = pixel_position;
+ self->text = text;
+ LOG(("%s: %s\n", (char*)__FILE__, __FUNCTION__));
+ if( !init ) {
+ vdih = self->vdi_handle;
+ }
+ init = true;
+ return( 1 );
+}
+
+static int dtor( FONT_PLOTTER self )
+{
+ return( 1 );
+}
+
+static int str_width( FONT_PLOTTER self,const plot_font_style_t *fstyle, const char * str,
+ size_t length, int * width )
+{
+ short cw, ch, cellw, cellh;
+ short pxsize;
+ short fx=0;
+ lstr = (char*)str;
+ utf8_to_enc(str, "ATARIST", length, &lstr );
+ assert( lstr != NULL );
+ int slen = strlen(lstr);
+
+ if( fstyle->flags & FONTF_ITALIC )
+ fx |= 4;
+ if( fstyle->flags & FONTF_OBLIQUE )
+ fx |= 16;
+ if( fstyle->weight > 450 )
+ fx |= 1;
+ vst_effects( self->vdi_handle, fx );
+ /* TODO: replace 90 with global dpi setting */
+ pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 / 72 );
+ vst_height( self->vdi_handle, pxsize ,&cw, &ch, &cellw, &cellh);
+ *width = slen * cellw;
+ free( (void*)lstr );
+ lstr = NULL;
+ return( 0 );
+}
+
+static int str_split( FONT_PLOTTER self, const plot_font_style_t * fstyle, const char *string,
+ size_t length,int x, size_t *char_offset, int *actual_x )
+{
+ short cw, ch, cellw, cellh;
+ short pxsize;
+ short fx=0;
+ int i;
+ lstr = (char*)string;
+ int slen = 0;
+ int last_space_x = 0;
+ int last_space_idx = 0;
+
+ utf8_to_enc(string, "ATARIST", length, &lstr );
+ assert( lstr != NULL );
+
+ slen = strlen(lstr);
+ if( fstyle->flags & FONTF_ITALIC )
+ fx |= 4;
+ if( fstyle->flags & FONTF_OBLIQUE )
+ fx |= 16;
+ if( fstyle->weight > 450 )
+ fx |= 1;
+ vst_effects( self->vdi_handle, fx );
+ pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 / 72 );
+ vst_height( self->vdi_handle, pxsize ,&cw, &ch, &cellw, &cellh);
+ *actual_x = 0;
+ *char_offset = 0;
+ int cpos=0;
+ for( i=0; i<slen; i++) {
+ if( lstr[i] == ' ' ) {
+ last_space_x = *actual_x;
+ last_space_idx = cpos;
+ }
+ if( *actual_x > x ) {
+ *actual_x = last_space_x;
+ *char_offset = last_space_idx;
+ return true;
+ }
+ *actual_x += cellw;
+ cpos++;
+ }
+ *char_offset = cpos;
+ free( (void*)lstr );
+ lstr = NULL;
+ return( 0 );
+}
+
+static int pixel_position( FONT_PLOTTER self, const plot_font_style_t * fstyle,const char *string,
+ size_t length,int x, size_t *char_offset, int *actual_x )
+{
+ short cw, ch, cellw, cellh;
+ short pxsize=0;
+ short fx=0;
+
+ lstr = (char*)string;
+ int i=0;
+ int curpx=0;
+ utf8_to_enc(string, "ATRIST", length, &lstr );
+ assert( lstr != NULL );
+ int slen = strlen(lstr);
+ if( fstyle->flags & FONTF_ITALIC )
+ fx |= 4;
+ if( fstyle->flags & FONTF_OBLIQUE )
+ fx |= 16;
+ if( fstyle->weight > 450 )
+ fx |= 1;
+ vst_effects( self->vdi_handle, fx );
+ pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 / 72 );
+ vst_height( self->vdi_handle, pxsize ,&cw, &ch, &cellw, &cellh);
+ *actual_x = 0;
+ *char_offset = 0;
+ for( i=0; i<slen; i++) {
+ *actual_x += cellw;
+ if( *actual_x > x) {
+ *actual_x -= cellw;
+ *char_offset = i;
+ break;
+ }
+ }
+ free( (void*)lstr );
+ lstr = NULL;
+ return( 0 );
+}
+
+static int text( FONT_PLOTTER self, int x, int y, const char *text, size_t length,
+ const plot_font_style_t *fstyle )
+{
+ /* todo: either limit the string to max 80 chars, or use v_ftext instead of v_gtext */
+ short cw, ch, cellw, cellh;
+ short pxsize=8;
+ short fx=0;
+ lstr = (char*)text;
+ utf8_to_enc(text, "ATARIST", length, &lstr );
+ assert( lstr != NULL );
+ int slen = strlen(lstr);
+ size_t mylen = MIN(511, slen );
+ char textcpy[mylen+1];
+
+ textcpy[mylen] = 0;
+ strncpy((char*)&textcpy, lstr, mylen+1 );
+ if( fstyle != NULL){
+ if( fstyle->flags & FONTF_ITALIC )
+ fx |= 4;
+ if( fstyle->flags & FONTF_OBLIQUE )
+ fx |= 4;
+ if( fstyle->weight > 450 )
+ fx |= 1;
+
+ /* TODO: netsurf uses 90 as default dpi ( somewhere defined in libcss), use that value
+ pass it as arg, to reduce netsurf dependency */
+ pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 / 72 );
+ }
+ vst_effects( self->vdi_handle, fx );
+ vst_alignment(vdih, 0, 4, &cw, &ch );
+ vst_height( self->vdi_handle, pxsize ,&cw, &ch, &cellw, &cellh);
+ vswr_mode( self->vdi_handle, MD_TRANS );
+ vst_color( self->vdi_handle, RGB_TO_VDI(fstyle->foreground) );
+ x += CURFB(self->plotter).x;
+ y += CURFB(self->plotter).y;
+ v_ftext( self->vdi_handle, x, y, (char*)&textcpy );
+ free( lstr );
+ return( 0 );
+}
+
diff --git a/atari/plot/font_vdi.h b/atari/plot/font_vdi.h
new file mode 100644
index 000000000..e9f1894b4
--- /dev/null
+++ b/atari/plot/font_vdi.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef FONT_PLOTTER_VDI
+#define FONT_PLOTTER_VDI
+
+int ctor_font_plotter_vdi( FONT_PLOTTER self );
+
+#endif \ No newline at end of file
diff --git a/atari/plot/plotter.c b/atari/plot/plotter.c
new file mode 100644
index 000000000..d21b46540
--- /dev/null
+++ b/atari/plot/plotter.c
@@ -0,0 +1,723 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <windom.h>
+#include <assert.h>
+#include <mint/osbind.h>
+#include <mint/cookie.h>
+#include <Hermes/Hermes.h>
+
+#include "desktop/plot_style.h"
+#include "atari/bitmap.h"
+#include "image/bitmap.h"
+#include "atari/plot/eddi.h"
+#include "atari/plot/plotter.h"
+#include "atari/plot/plotter_vdi.h"
+#include "atari/plot/font_vdi.h"
+#include "atari/plot/font_freetype.h"
+#include "utils/log.h"
+
+
+unsigned char rgb_web_pal[216][3] = {
+ {0x00,0x00,0x00}, {0x33,0x00,0x00}, {0x66,0x00,0x00}, {0x99,0x00,0x00}, {0xcc,0x00,0x00}, {0xff,0x00,0x00},
+ {0x00,0x33,0x00}, {0x33,0x33,0x00}, {0x66,0x33,0x00}, {0x99,0x33,0x00}, {0xcc,0x33,0x00}, {0xff,0x33,0x00},
+ {0x00,0x66,0x00}, {0x33,0x66,0x00}, {0x66,0x66,0x00}, {0x99,0x66,0x00}, {0xcc,0x66,0x00}, {0xff,0x66,0x00},
+ {0x00,0x99,0x00}, {0x33,0x99,0x00}, {0x66,0x99,0x00}, {0x99,0x99,0x00}, {0xcc,0x99,0x00}, {0xff,0x99,0x00},
+ {0x00,0xcc,0x00}, {0x33,0xcc,0x00}, {0x66,0xcc,0x00}, {0x99,0xcc,0x00}, {0xcc,0xcc,0x00}, {0xff,0xcc,0x00},
+ {0x00,0xff,0x00}, {0x33,0xff,0x00}, {0x66,0xff,0x00}, {0x99,0xff,0x00}, {0xcc,0xff,0x00}, {0xff,0xff,0x00},
+ {0x00,0x00,0x33}, {0x33,0x00,0x33}, {0x66,0x00,0x33}, {0x99,0x00,0x33}, {0xcc,0x00,0x33}, {0xff,0x00,0x33},
+ {0x00,0x33,0x33}, {0x33,0x33,0x33}, {0x66,0x33,0x33}, {0x99,0x33,0x33}, {0xcc,0x33,0x33}, {0xff,0x33,0x33},
+ {0x00,0x66,0x33}, {0x33,0x66,0x33}, {0x66,0x66,0x33}, {0x99,0x66,0x33}, {0xcc,0x66,0x33}, {0xff,0x66,0x33},
+ {0x00,0x99,0x33}, {0x33,0x99,0x33}, {0x66,0x99,0x33}, {0x99,0x99,0x33}, {0xcc,0x99,0x33}, {0xff,0x99,0x33},
+ {0x00,0xcc,0x33}, {0x33,0xcc,0x33}, {0x66,0xcc,0x33}, {0x99,0xcc,0x33}, {0xcc,0xcc,0x33}, {0xff,0xcc,0x33},
+ {0x00,0xff,0x33}, {0x33,0xff,0x33}, {0x66,0xff,0x33}, {0x99,0xff,0x33}, {0xcc,0xff,0x33}, {0xff,0xff,0x33},
+ {0x00,0x00,0x66}, {0x33,0x00,0x66}, {0x66,0x00,0x66}, {0x99,0x00,0x66}, {0xcc,0x00,0x66}, {0xff,0x00,0x66},
+ {0x00,0x33,0x66}, {0x33,0x33,0x66}, {0x66,0x33,0x66}, {0x99,0x33,0x66}, {0xcc,0x33,0x66}, {0xff,0x33,0x66},
+ {0x00,0x66,0x66}, {0x33,0x66,0x66}, {0x66,0x66,0x66}, {0x99,0x66,0x66}, {0xcc,0x66,0x66}, {0xff,0x66,0x66},
+ {0x00,0x99,0x66}, {0x33,0x99,0x66}, {0x66,0x99,0x66}, {0x99,0x99,0x66}, {0xcc,0x99,0x66}, {0xff,0x99,0x66},
+ {0x00,0xcc,0x66}, {0x33,0xcc,0x66}, {0x66,0xcc,0x66}, {0x99,0xcc,0x66}, {0xcc,0xcc,0x66}, {0xff,0xcc,0x66},
+ {0x00,0xff,0x66}, {0x33,0xff,0x66}, {0x66,0xff,0x66}, {0x99,0xff,0x66}, {0xcc,0xff,0x66}, {0xff,0xff,0x66},
+ {0x00,0x00,0x99}, {0x33,0x00,0x99}, {0x66,0x00,0x99}, {0x99,0x00,0x99}, {0xcc,0x00,0x99}, {0xff,0x00,0x99},
+ {0x00,0x33,0x99}, {0x33,0x33,0x99}, {0x66,0x33,0x99}, {0x99,0x33,0x99}, {0xcc,0x33,0x99}, {0xff,0x33,0x99},
+ {0x00,0x66,0x99}, {0x33,0x66,0x99}, {0x66,0x66,0x99}, {0x99,0x66,0x99}, {0xcc,0x66,0x99}, {0xff,0x66,0x99},
+ {0x00,0x99,0x99}, {0x33,0x99,0x99}, {0x66,0x99,0x99}, {0x99,0x99,0x99}, {0xcc,0x99,0x99}, {0xff,0x99,0x99},
+ {0x00,0xcc,0x99}, {0x33,0xcc,0x99}, {0x66,0xcc,0x99}, {0x99,0xcc,0x99}, {0xcc,0xcc,0x99}, {0xff,0xcc,0x99},
+ {0x00,0xff,0x99}, {0x33,0xff,0x99}, {0x66,0xff,0x99}, {0x99,0xff,0x99}, {0xcc,0xff,0x99}, {0xff,0xff,0x99},
+ {0x00,0x00,0xcc}, {0x33,0x00,0xcc}, {0x66,0x00,0xcc}, {0x99,0x00,0xcc}, {0xcc,0x00,0xcc}, {0xff,0x00,0xcc},
+ {0x00,0x33,0xcc}, {0x33,0x33,0xcc}, {0x66,0x33,0xcc}, {0x99,0x33,0xcc}, {0xcc,0x33,0xcc}, {0xff,0x33,0xcc},
+ {0x00,0x66,0xcc}, {0x33,0x66,0xcc}, {0x66,0x66,0xcc}, {0x99,0x66,0xcc}, {0xcc,0x66,0xcc}, {0xff,0x66,0xcc},
+ {0x00,0x99,0xcc}, {0x33,0x99,0xcc}, {0x66,0x99,0xcc}, {0x99,0x99,0xcc}, {0xcc,0x99,0xcc}, {0xff,0x99,0xcc},
+ {0x00,0xcc,0xcc}, {0x33,0xcc,0xcc}, {0x66,0xcc,0xcc}, {0x99,0xcc,0xcc}, {0xcc,0xcc,0xcc}, {0xff,0xcc,0xcc},
+ {0x00,0xff,0xcc}, {0x33,0xff,0xcc}, {0x66,0xff,0xcc}, {0x99,0xff,0xcc}, {0xcc,0xff,0xcc}, {0xff,0xff,0xcc},
+ {0x00,0x00,0xff}, {0x33,0x00,0xff}, {0x66,0x00,0xff}, {0x99,0x00,0xff}, {0xcc,0x00,0xff}, {0xff,0x00,0xff},
+ {0x00,0x33,0xff}, {0x33,0x33,0xff}, {0x66,0x33,0xff}, {0x99,0x33,0xff}, {0xcc,0x33,0xff}, {0xff,0x33,0xff},
+ {0x00,0x66,0xff}, {0x33,0x66,0xff}, {0x66,0x66,0xff}, {0x99,0x66,0xff}, {0xcc,0x66,0xff}, {0xff,0x66,0xff},
+ {0x00,0x99,0xff}, {0x33,0x99,0xff}, {0x66,0x99,0xff}, {0x99,0x99,0xff}, {0xcc,0x99,0xff}, {0xff,0x99,0xff},
+ {0x00,0xcc,0xff}, {0x33,0xcc,0xff}, {0x66,0xcc,0xff}, {0x99,0xcc,0xff}, {0xcc,0xcc,0xff}, {0xff,0xcc,0xff},
+ {0x00,0xff,0xff}, {0x33,0xff,0xff}, {0x66,0xff,0xff}, {0x99,0xff,0xff}, {0xcc,0xff,0xff}, {0xff,0xff,0xff}
+};
+
+
+unsigned short vdi_web_pal[216][3] = {
+ {0x000,0x000,0x000}, {0x0c8,0x000,0x000}, {0x190,0x000,0x000}, {0x258,0x000,0x000}, {0x320,0x000,0x000}, {0x3e8,0x000,0x000},
+ {0x000,0x0c8,0x000}, {0x0c8,0x0c8,0x000}, {0x190,0x0c8,0x000}, {0x258,0x0c8,0x000}, {0x320,0x0c8,0x000}, {0x3e8,0x0c8,0x000},
+ {0x000,0x190,0x000}, {0x0c8,0x190,0x000}, {0x190,0x190,0x000}, {0x258,0x190,0x000}, {0x320,0x190,0x000}, {0x3e8,0x190,0x000},
+ {0x000,0x258,0x000}, {0x0c8,0x258,0x000}, {0x190,0x258,0x000}, {0x258,0x258,0x000}, {0x320,0x258,0x000}, {0x3e8,0x258,0x000},
+ {0x000,0x320,0x000}, {0x0c8,0x320,0x000}, {0x190,0x320,0x000}, {0x258,0x320,0x000}, {0x320,0x320,0x000}, {0x3e8,0x320,0x000},
+ {0x000,0x3e8,0x000}, {0x0c8,0x3e8,0x000}, {0x190,0x3e8,0x000}, {0x258,0x3e8,0x000}, {0x320,0x3e8,0x000}, {0x3e8,0x3e8,0x000},
+ {0x000,0x000,0x0c8}, {0x0c8,0x000,0x0c8}, {0x190,0x000,0x0c8}, {0x258,0x000,0x0c8}, {0x320,0x000,0x0c8}, {0x3e8,0x000,0x0c8},
+ {0x000,0x0c8,0x0c8}, {0x0c8,0x0c8,0x0c8}, {0x190,0x0c8,0x0c8}, {0x258,0x0c8,0x0c8}, {0x320,0x0c8,0x0c8}, {0x3e8,0x0c8,0x0c8},
+ {0x000,0x190,0x0c8}, {0x0c8,0x190,0x0c8}, {0x190,0x190,0x0c8}, {0x258,0x190,0x0c8}, {0x320,0x190,0x0c8}, {0x3e8,0x190,0x0c8},
+ {0x000,0x258,0x0c8}, {0x0c8,0x258,0x0c8}, {0x190,0x258,0x0c8}, {0x258,0x258,0x0c8}, {0x320,0x258,0x0c8}, {0x3e8,0x258,0x0c8},
+ {0x000,0x320,0x0c8}, {0x0c8,0x320,0x0c8}, {0x190,0x320,0x0c8}, {0x258,0x320,0x0c8}, {0x320,0x320,0x0c8}, {0x3e8,0x320,0x0c8},
+ {0x000,0x3e8,0x0c8}, {0x0c8,0x3e8,0x0c8}, {0x190,0x3e8,0x0c8}, {0x258,0x3e8,0x0c8}, {0x320,0x3e8,0x0c8}, {0x3e8,0x3e8,0x0c8},
+ {0x000,0x000,0x190}, {0x0c8,0x000,0x190}, {0x190,0x000,0x190}, {0x258,0x000,0x190}, {0x320,0x000,0x190}, {0x3e8,0x000,0x190},
+ {0x000,0x0c8,0x190}, {0x0c8,0x0c8,0x190}, {0x190,0x0c8,0x190}, {0x258,0x0c8,0x190}, {0x320,0x0c8,0x190}, {0x3e8,0x0c8,0x190},
+ {0x000,0x190,0x190}, {0x0c8,0x190,0x190}, {0x190,0x190,0x190}, {0x258,0x190,0x190}, {0x320,0x190,0x190}, {0x3e8,0x190,0x190},
+ {0x000,0x258,0x190}, {0x0c8,0x258,0x190}, {0x190,0x258,0x190}, {0x258,0x258,0x190}, {0x320,0x258,0x190}, {0x3e8,0x258,0x190},
+ {0x000,0x320,0x190}, {0x0c8,0x320,0x190}, {0x190,0x320,0x190}, {0x258,0x320,0x190}, {0x320,0x320,0x190}, {0x3e8,0x320,0x190},
+ {0x000,0x3e8,0x190}, {0x0c8,0x3e8,0x190}, {0x190,0x3e8,0x190}, {0x258,0x3e8,0x190}, {0x320,0x3e8,0x190}, {0x3e8,0x3e8,0x190},
+ {0x000,0x000,0x258}, {0x0c8,0x000,0x258}, {0x190,0x000,0x258}, {0x258,0x000,0x258}, {0x320,0x000,0x258}, {0x3e8,0x000,0x258},
+ {0x000,0x0c8,0x258}, {0x0c8,0x0c8,0x258}, {0x190,0x0c8,0x258}, {0x258,0x0c8,0x258}, {0x320,0x0c8,0x258}, {0x3e8,0x0c8,0x258},
+ {0x000,0x190,0x258}, {0x0c8,0x190,0x258}, {0x190,0x190,0x258}, {0x258,0x190,0x258}, {0x320,0x190,0x258}, {0x3e8,0x190,0x258},
+ {0x000,0x258,0x258}, {0x0c8,0x258,0x258}, {0x190,0x258,0x258}, {0x258,0x258,0x258}, {0x320,0x258,0x258}, {0x3e8,0x258,0x258},
+ {0x000,0x320,0x258}, {0x0c8,0x320,0x258}, {0x190,0x320,0x258}, {0x258,0x320,0x258}, {0x320,0x320,0x258}, {0x3e8,0x320,0x258},
+ {0x000,0x3e8,0x258}, {0x0c8,0x3e8,0x258}, {0x190,0x3e8,0x258}, {0x258,0x3e8,0x258}, {0x320,0x3e8,0x258}, {0x3e8,0x3e8,0x258},
+ {0x000,0x000,0x320}, {0x0c8,0x000,0x320}, {0x190,0x000,0x320}, {0x258,0x000,0x320}, {0x320,0x000,0x320}, {0x3e8,0x000,0x320},
+ {0x000,0x0c8,0x320}, {0x0c8,0x0c8,0x320}, {0x190,0x0c8,0x320}, {0x258,0x0c8,0x320}, {0x320,0x0c8,0x320}, {0x3e8,0x0c8,0x320},
+ {0x000,0x190,0x320}, {0x0c8,0x190,0x320}, {0x190,0x190,0x320}, {0x258,0x190,0x320}, {0x320,0x190,0x320}, {0x3e8,0x190,0x320},
+ {0x000,0x258,0x320}, {0x0c8,0x258,0x320}, {0x190,0x258,0x320}, {0x258,0x258,0x320}, {0x320,0x258,0x320}, {0x3e8,0x258,0x320},
+ {0x000,0x320,0x320}, {0x0c8,0x320,0x320}, {0x190,0x320,0x320}, {0x258,0x320,0x320}, {0x320,0x320,0x320}, {0x3e8,0x320,0x320},
+ {0x000,0x3e8,0x320}, {0x0c8,0x3e8,0x320}, {0x190,0x3e8,0x320}, {0x258,0x3e8,0x320}, {0x320,0x3e8,0x320}, {0x3e8,0x3e8,0x320},
+ {0x000,0x000,0x3e8}, {0x0c8,0x000,0x3e8}, {0x190,0x000,0x3e8}, {0x258,0x000,0x3e8}, {0x320,0x000,0x3e8}, {0x3e8,0x000,0x3e8},
+ {0x000,0x0c8,0x3e8}, {0x0c8,0x0c8,0x3e8}, {0x190,0x0c8,0x3e8}, {0x258,0x0c8,0x3e8}, {0x320,0x0c8,0x3e8}, {0x3e8,0x0c8,0x3e8},
+ {0x000,0x190,0x3e8}, {0x0c8,0x190,0x3e8}, {0x190,0x190,0x3e8}, {0x258,0x190,0x3e8}, {0x320,0x190,0x3e8}, {0x3e8,0x190,0x3e8},
+ {0x000,0x258,0x3e8}, {0x0c8,0x258,0x3e8}, {0x190,0x258,0x3e8}, {0x258,0x258,0x3e8}, {0x320,0x258,0x3e8}, {0x3e8,0x258,0x3e8},
+ {0x000,0x320,0x3e8}, {0x0c8,0x320,0x3e8}, {0x190,0x320,0x3e8}, {0x258,0x320,0x3e8}, {0x320,0x320,0x3e8}, {0x3e8,0x320,0x3e8},
+ {0x000,0x3e8,0x3e8}, {0x0c8,0x3e8,0x3e8}, {0x190,0x3e8,0x3e8}, {0x258,0x3e8,0x3e8}, {0x320,0x3e8,0x3e8}, {0x3e8,0x3e8,0x3e8}
+};
+
+static short prev_vdi_clip[4];
+struct s_vdi_sysinfo vdi_sysinfo;
+
+struct s_driver_table_entry screen_driver_table[] =
+{
+ {(char*)"vdi", ctor_plotter_vdi, 0, 32},
+ {(char*)"screen.ldg", ctor_plotter_vdi, PLOT_FLAG_OFFSCREEN, 32 },
+ {(char*)"vdi_offscreen", ctor_plotter_vdi, PLOT_FLAG_OFFSCREEN, 32},
+ {(char*)NULL, NULL, 0, 0 }
+};
+
+const struct s_font_driver_table_entry font_driver_table[] =
+{
+ {(char*)"vdi", ctor_font_plotter_vdi, 0},
+ {(char*)"freetype", ctor_font_plotter_freetype, 0},
+ {(char*)NULL, NULL, 0}
+};
+
+struct s_vdi_sysinfo * read_vdi_sysinfo( short vdih, struct s_vdi_sysinfo * info ) {
+
+ unsigned long cookie_EdDI=0;
+ short out[300];
+ memset( info, 0, sizeof(struct s_vdi_sysinfo) );
+
+ info->vdi_handle = vdih;
+ if ( Getcookie(C_EdDI, &cookie_EdDI) == C_NOTFOUND ) {
+ info->EdDiVersion = 0;
+ } else {
+ info->EdDiVersion = EdDI_version( (void *)cookie_EdDI );
+ }
+
+ memset( &out, 0, sizeof(short)*300 );
+ vq_extnd( vdih, 0, (short*)&out );
+ info->scr_w = out[0]+1;
+ info->scr_h = out[1]+1;
+ if( out[39] == 2 ) {
+ info->scr_bpp = 1;
+ info->colors = out[39];
+ } else {
+ info->colors = out[39];
+ }
+
+ memset( &out, 0, sizeof(short)*300 );
+ vq_extnd( vdih, 1, (short*)&out );
+ info->scr_bpp = out[4];
+ info->maxpolycoords = out[14];
+ info->maxintin = out[15];
+ if( out[30] & 1 ) {
+ info->rasterscale = true;
+ } else {
+ info->rasterscale = false;
+ }
+
+ switch( info->scr_bpp ) {
+ case 8:
+ info->pixelsize=1;
+ break;
+ case 15:
+ case 16:
+ info->pixelsize=2;
+ break;
+ case 24:
+ info->pixelsize=3;
+ break;
+ case 32:
+ info->pixelsize=4;
+ break;
+ case 64:
+ info->pixelsize=8;
+ break;
+ default:
+ info->pixelsize=0;
+ break;
+
+ }
+ info->pitch = info->scr_w * info->pixelsize;
+ info->vdiformat = ( (info->scr_bpp <= 8) ? VDI_FORMAT_INTER : VDI_FORMAT_PACK);
+ info->screensize = ( info->scr_w * info->pixelsize ) * info->scr_h;
+
+ if( info->EdDiVersion >= EDDI_10 ) {
+ memset( &out, 0, sizeof(short)*300 );
+ vq_scrninfo(vdih, (short*)&out);
+ info->vdiformat = out[0];
+ info->clut = out[1];
+ info->scr_bpp = out[2];
+ info->hicolors = *((unsigned long*) &out[3]);
+ if( info->EdDiVersion >= EDDI_11 ) {
+ info->pitch = out[5];
+ info->screen = (void *) *((unsigned long *) &out[6]);
+ }
+
+ switch( info->clut ) {
+
+ case VDI_CLUT_HARDWARE:
+ {
+
+ int i;
+ unsigned short *tmp_p;
+/* it's possible to store the vdi painters:
+ tmp_p = (unsigned short *)&work_out[16];
+
+ for (i=0;i<256;i++) {
+ vdi_index[*tmp_p++] = i;
+ }
+*/
+ }
+ break;
+
+ case VDI_CLUT_SOFTWARE:
+ {
+ int component; /* red, green, blue, alpha, overlay */
+ int num_bit;
+ unsigned short *tmp_p;
+
+ /* We can build masks with info here */
+ tmp_p = (unsigned short *) &out[16];
+ for (component=0;component<5;component++) {
+ for (num_bit=0;num_bit<16;num_bit++) {
+ unsigned short val;
+
+ val = *tmp_p++;
+
+ if (val == 0xffff) {
+ continue;
+ }
+
+ switch(component) {
+ case 0:
+ info->mask_r |= 1<< val;
+ break;
+ case 1:
+ info->mask_g |= 1<< val;
+ break;
+ case 2:
+ info->mask_b |= 1<< val;
+ break;
+ case 3:
+ info->mask_a |= 1<< val;
+ break;
+ }
+ }
+ }
+ }
+
+ /* Remove lower green bits for Intel endian screen */
+ if ((info->mask_g == ((7<<13)|3)) || (info->mask_g == ((7<<13)|7))) {
+ info->mask_g &= ~(7<<13);
+ }
+ break;
+
+ case VDI_CLUT_NONE:
+ break;
+ }
+ }
+}
+
+
+/*
+ lookup an plotter ID by name
+*/
+static int drvrname_idx( char * name )
+{
+ int i;
+ for( i = 0; ; i++) {
+ if( screen_driver_table[i].name == NULL ) {
+ return( -1 );
+ }
+ else {
+ if( strcmp(name, screen_driver_table[i].name) == 0 ) {
+ return( i );
+ }
+ }
+ }
+}
+
+/*
+ lookup of font plotter ID by name
+*/
+static int font_drvrname_idx( char * name )
+{
+ int i;
+ for( i = 0; ; i++) {
+ if( font_driver_table[i].name == NULL ) {
+ return( -1 );
+ }
+ else {
+ if( strcmp(name, font_driver_table[i].name) == 0 ) {
+ return( i );
+ }
+ }
+ }
+}
+
+/*
+ Get an plotter info entry, the entry contains an pointer to ctor
+*/
+struct s_driver_table_entry * get_screen_driver_entry( char * name )
+{
+ int idx = drvrname_idx( name );
+ if( idx < 0 )
+ return( 0 );
+ else
+ return( &screen_driver_table[idx] );
+}
+
+/*
+ Get an font plotter info entry, the entry contains an pointer to ctor.
+*/
+struct s_font_driver_table_entry * get_font_driver_entry( char * name )
+{
+ int idx = font_drvrname_idx( name );
+ if( idx < 0 )
+ return( 0 );
+ else
+ return( (struct s_font_driver_table_entry *)&font_driver_table[idx] );
+}
+
+
+/*
+ Create an new text plotter object
+*/
+FONT_PLOTTER new_font_plotter( int vdihandle, char * name, unsigned long flags, int * error)
+{
+ int i=0;
+ int res = 0-ERR_PLOTTER_NOT_AVAILABLE;
+ FONT_PLOTTER fplotter = (FONT_PLOTTER)malloc( sizeof(struct s_font_plotter) );
+ if( fplotter == NULL ) {
+ *error = 0-ERR_NO_MEM;
+ return( NULL );
+ }
+ fplotter->vdi_handle = vdihandle;
+ fplotter->name = name;
+ fplotter->flags |= flags;
+ for( i = 0; ; i++) {
+ if( font_driver_table[i].name == NULL ) {
+ res = 0-ERR_PLOTTER_NOT_AVAILABLE;
+ break;
+ } else {
+ if( strcmp(name, font_driver_table[i].name) == 0 ) {
+ if( font_driver_table[i].ctor ) {
+ res = font_driver_table[i].ctor( fplotter );
+ *error = 0;
+ } else {
+ res = 0-ERR_PLOTTER_NOT_AVAILABLE;
+ *error = res;
+ return (NULL);
+ }
+ break;
+ }
+ }
+ }
+ if( res < 0 ) {
+ free( fplotter );
+ *error = res;
+ return( NULL );
+ }
+ fplotter->plotter = NULL;
+ return( fplotter );
+}
+
+static bool init=false;
+static int inst=0;
+
+/*
+ Create an new plotter object
+*/
+GEM_PLOTTER new_plotter(int vdihandle, char * name, GRECT * loc_size,
+ int virt_bpp, unsigned long flags, FONT_PLOTTER fplotter, int * error )
+{
+ int res = 0-ERR_PLOTTER_NOT_AVAILABLE;
+ int i;
+ assert( fplotter != NULL );
+
+ GEM_PLOTTER gemplotter = (GEM_PLOTTER)malloc( sizeof(struct s_gem_plotter) );
+ if( !gemplotter ) {
+ *error = 0-ERR_NO_MEM;
+ return( NULL );
+ }
+ memset( gemplotter, 0, sizeof(struct s_gem_plotter));
+
+ gemplotter->name = name;
+ gemplotter->vdi_handle = vdihandle;
+ gemplotter->flags |= flags;
+ gemplotter->font_plotter = fplotter;
+ gemplotter->bpp_virt = virt_bpp;
+ gemplotter->cfbi = 0;
+ memset(&gemplotter->fbuf, 0, sizeof(struct s_frame_buf) * MAX_FRAMEBUFS );
+ gemplotter->fbuf[0].x = loc_size->g_x;
+ gemplotter->fbuf[0].y = loc_size->g_y;
+ gemplotter->fbuf[0].w = loc_size->g_w;
+ gemplotter->fbuf[0].h = loc_size->g_h;
+
+ /* request vdi info once, so every plotter is able to access the info */
+ if( !init ) {
+ /* vdi_sysinfo */
+ read_vdi_sysinfo( vdihandle, &vdi_sysinfo );
+ init = true;
+ }
+ for( i = 0; ; i++) {
+ if( screen_driver_table[i].name == NULL ) {
+ res = 0-ERR_PLOTTER_NOT_AVAILABLE;
+ break;
+ }
+ else {
+ if( strcmp(name, screen_driver_table[i].name) == 0 ) {
+ if( screen_driver_table[i].ctor ) {
+ gemplotter->flags |= screen_driver_table[i].flags;
+ res = screen_driver_table[i].ctor( gemplotter );
+ *error = 0;
+ } else {
+ res = 0-ERR_PLOTTER_NOT_AVAILABLE;
+ *error = res;
+ return (NULL);
+ }
+ break;
+ }
+ }
+ }
+ if( res < 0 ) {
+ free( gemplotter );
+ *error = res;
+ return( NULL );
+ }
+ inst++;
+ gemplotter->font_plotter->plotter = gemplotter;
+ return( gemplotter );
+}
+
+/*
+ Free an plotter
+*/
+int delete_plotter( GEM_PLOTTER p )
+{
+ if( p ) {
+ p->dtor( p );
+ free( p );
+ p = NULL;
+ inst--;
+ if( inst == 0 ){
+
+ }
+ }
+ else
+ return( -1 );
+ return( 0 );
+}
+
+/*
+ Free an font plotter
+*/
+int delete_font_plotter( FONT_PLOTTER p )
+{
+ if( p ) {
+ p->dtor(p);
+ free( p );
+ p = NULL;
+ }
+ else
+ return( -1 );
+ return( 0 );
+}
+
+/*
+ x - x coord
+ y - y coord
+ stride - stride in bytes
+ bpp - bits per pixel
+*/
+int calc_chunked_buffer_size(int x, int y, int stride, int bpp)
+{
+ return( (x * (bpp >> 3)) * y );
+}
+
+/*
+ x - x coord
+ y - y coord
+ stride - stride in bytes
+ bpp - bits per pixel
+*/
+int get_pixel_offset( int x, int y, int stride, int bpp )
+{
+ LOG(("byte_pp: %d, pure: %d, result: %d\n",(bpp >> 3),(y * stride + x), (y * stride + x) * (bpp >> 3)));
+ return( ( (y * stride) + x) * (bpp >> 3) );
+}
+
+/*
+ 1. calculate visible area of framebuffer in coords relative to framebuffer position
+
+ result:
+ this function should calc offsets into x,y coords of the framebuffer which
+ can be drawn. If the framebuffer coords do not fall within the screen region,
+ all values of visible region are set to zero.
+*/
+void update_visible_rect( GEM_PLOTTER p )
+{
+ GRECT screen;
+ GRECT common;
+ GRECT frame;
+
+ screen.g_x = 0;
+ screen.g_y = 0;
+ screen.g_w = vdi_sysinfo.scr_w;
+ screen.g_h = vdi_sysinfo.scr_h;
+
+ common.g_x = frame.g_x = CURFB(p).x;
+ common.g_y = frame.g_y = CURFB(p).y;
+ common.g_w = frame.g_w = CURFB(p).w;
+ common.g_h = frame.g_h = CURFB(p).h;
+
+ if( rc_intersect( &screen, &common ) ) {
+ CURFB(p).vis_w = common.g_w;
+ CURFB(p).vis_h = common.g_h;
+ if( CURFB(p).x < screen.g_x )
+ CURFB(p).vis_x = frame.g_w - common.g_w;
+ else
+ CURFB(p).vis_x = 0;
+ if( CURFB(p).y <screen.g_y )
+ CURFB(p).vis_y = frame.g_h - common.g_h;
+ else
+ CURFB(p).vis_y = 0;
+ } else {
+ CURFB(p).vis_w = CURFB(p).vis_h = 0;
+ CURFB(p).vis_x = CURFB(p).vis_y = 0;
+ }
+}
+
+/*
+ Returns the visible parts of the box (relative coords within framebuffer),
+ relative to screen coords (normally starting at 0,0 )
+*/
+bool fbrect_to_screen( GEM_PLOTTER self, GRECT box, GRECT * ret )
+{
+ GRECT out, vis, screen;
+
+ screen.g_x = 0;
+ screen.g_y = 0;
+ screen.g_w = vdi_sysinfo.scr_w;
+ screen.g_h = vdi_sysinfo.scr_h;
+
+ /* get visible region: */
+ vis.g_x = CURFB(self).x;
+ vis.g_y = CURFB(self).y;
+ vis.g_w = CURFB(self).w;
+ vis.g_h = CURFB(self).h;
+
+ if ( !rc_intersect( &screen, &vis ) ) {
+ return( false );
+ }
+ vis.g_x = CURFB(self).w - vis.g_w;
+ vis.g_y = CURFB(self).h - vis.g_h;
+
+ /* clip box to visible region: */
+ if( !rc_intersect(&vis, &box) ) {
+ return( false );
+ }
+ out.g_x = box.g_x + CURFB(self).x;
+ out.g_y = box.g_y + CURFB(self).y;
+ out.g_w = box.g_w;
+ out.g_h = box.g_h;
+ *ret = out;
+ return ( true );
+}
+
+const char* plotter_err_str(int i) { return(plot_error_codes[abs(i)]); }
+
+void dump_vdi_info( short vdih )
+{
+ struct s_vdi_sysinfo temp;
+ read_vdi_sysinfo( vdih, &temp );
+ printf("struct s_vdi_sysinfo {\n");
+ printf(" short vdi_handle: %d\n", temp.vdi_handle);
+ printf(" short scr_w: %d \n", temp.scr_w);
+ printf(" short scr_h: %d\n", temp.scr_h);
+ printf(" short scr_bpp: %d\n", temp.scr_bpp);
+ printf(" int colors: %d\n", temp.colors);
+ printf(" ulong hicolors: %d\n", temp.hicolors);
+ printf(" short pixelsize: %d\n", temp.pixelsize);
+ printf(" unsigned short pitch: %d\n", temp.pitch);
+ printf(" unsigned short vdiformat: %d\n", temp.vdiformat);
+ printf(" unsigned short clut: %d\n", temp.clut);
+ printf(" void * screen: 0x0%p\n", temp.screen);
+ printf(" unsigned long screensize: %d\n", temp.screensize);
+ printf(" unsigned long mask_r: 0x0%08x\n", temp.mask_r);
+ printf(" unsigned long mask_g: 0x0%08x\n", temp.mask_g);
+ printf(" unsigned long mask_b: 0x0%08x\n", temp.mask_b);
+ printf(" unsigned long mask_a: 0x0%08x\n", temp.mask_a);
+ printf(" short maxintin: %d\n", temp.maxintin);
+ printf(" short maxpolycoords: %d\n", temp.maxpolycoords);
+ printf(" unsigned long EdDiVersion: 0x0%03x\n", temp.EdDiVersion);
+ printf(" unsigned short rasterscale: 0x%2x\n", temp.rasterscale);
+ printf("};\n");
+}
+
+void dump_plot_drivers(void)
+{
+ int i = 0;
+ while( screen_driver_table[i].name != NULL ) {
+ printf("%s -> max_bpp: %d, flags: %d\n",
+ screen_driver_table[i].name,
+ screen_driver_table[i].max_bpp,
+ screen_driver_table[i].flags
+ );
+ i++;
+ }
+}
+
+void dump_font_drivers(void)
+{
+ int i = 0;
+ while( font_driver_table[i].name != NULL ) {
+ printf("%s -> flags: %d\n",
+ font_driver_table[i].name,
+ font_driver_table[i].flags
+ );
+ i++;
+ }
+}
+
+/*
+ Convert an RGB color to an VDI Color
+*/
+void rgb_to_vdi1000( unsigned char * in, unsigned short * out )
+{
+
+ double r = ((double)in[0]/255); /* prozentsatz red */
+ double g = ((double)in[1]/255); /* prozentsatz green */
+ double b = ((double)in[2]/255); /* prozentsatz blue */
+ out[0] = 1000 * r + 0.5;
+ out[1] = 1000 * g + 0.5;
+ out[2] = 1000 * b + 0.5;
+ return;
+}
+
+
+
+static short web_std_colors[6] = {0, 51, 102, 153, 204, 255};
+
+/*
+ Convert an RGB color into an index into the 216 colors web pallette
+*/
+short rgb_to_666_index(unsigned char r, unsigned char g, unsigned char b)
+{
+ short ret = 0;
+ short i;
+ unsigned char rgb[3] = {r,g,b};
+ unsigned char tval[3];
+ /* convert each 8bit color to 6bit web color: */
+ for( i=0; i<3; i++) {
+ if(0 == rgb[i] % web_std_colors[1] ) {
+ tval[i] = rgb[i] / web_std_colors[1];
+ }
+ else {
+ int pos = ((short)rgb[i] / web_std_colors[1]);
+ if( abs(rgb[i] - web_std_colors[pos]) > abs(rgb[i] - web_std_colors[pos+1]) )
+ tval[i] = pos+1;
+ else
+ tval[i] = pos;
+ }
+ }
+ return( tval[2]*36+tval[1]*6+tval[0] );
+}
+
+/* Shared (static in object oriented slang) plotter functions: */
+int plotter_get_clip( GEM_PLOTTER self, struct s_clipping * out )
+{
+ out->x0 = self->clipping.x0;
+ out->y0 = self->clipping.y0;
+ out->x1 = self->clipping.x1;
+ out->y1 = self->clipping.y1;
+ return( 1 );
+}
+
+int plotter_std_clip(GEM_PLOTTER self,int x0, int y0, int x1, int y1)
+{
+ self->clipping.x0 = x0;
+ self->clipping.y0 = y0;
+ self->clipping.x1 = x1;
+ self->clipping.y1 = y1;
+ return ( 1 );
+}
+
+/* this converts framebuffer clipping to vdi clipping and sets it */
+void plotter_vdi_clip( GEM_PLOTTER self, bool set)
+{
+ return;
+ if( set == true ) {
+ struct s_clipping * c = &self->clipping;
+ short vdiflags[58];
+ short newclip[4];
+ vq_extnd( self->vdi_handle, 1, (short*)&vdiflags);
+ prev_vdi_clip[0] = vdiflags[45];
+ prev_vdi_clip[1] = vdiflags[46];
+ prev_vdi_clip[2] = vdiflags[47];
+ prev_vdi_clip[3] = vdiflags[48];
+ newclip[0] = CURFB(self).x + MAX(c->x0, 0);
+ newclip[1] = CURFB(self).y + MAX(c->y0, 0);
+ newclip[2] = CURFB(self).x + MIN(CURFB(self).vis_w, c->x1 - c->x0)-1;
+ newclip[3] = CURFB(self).y + MIN(CURFB(self).vis_h, c->y1 - c->y0)-1;
+ vs_clip( self->vdi_handle, 1, (short*)&newclip );
+ } else {
+ short set = 1;
+ vs_clip( self->vdi_handle, set, (short *)&prev_vdi_clip );
+ }
+}
+
diff --git a/atari/plot/plotter.h b/atari/plot/plotter.h
new file mode 100644
index 000000000..973b70058
--- /dev/null
+++ b/atari/plot/plotter.h
@@ -0,0 +1,293 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _GEM_PLOTTER_API_H_
+#define _GEM_PLOTTER_API_H_
+#include <windom.h>
+
+
+
+#ifndef ceilf
+#define ceilf(x) (float)ceil((double)x)
+#endif
+
+#ifdef TEST_PLOTTER
+#define verbose_log 1
+#define LOG(x) do { if (verbose_log) (printf(__FILE__ " %s %i: ", __PRETTY_FUNCTION__, __LINE__), printf x, fputc('\n', stdout)); } while (0)
+#endif
+
+#define MAX_FRAMEBUFS 0x010
+#define C2P (1<<0) /* C2P convert buffer 1 to buffer 2 */
+/* TODO: implement offscreen buffer switch */
+/* Plotter Flags: */
+#define PLOT_FLAG_OFFSCREEN 0x01
+#define PLOT_FLAG_LOCKED 0x02
+#define PLOT_FLAG_DITHER 0x04
+#define PLOT_FLAG_TRANS 0x08
+
+/* Error codes: */
+#define ERR_BUFFERSIZE_EXCEEDS_SCREEN 1
+#define ERR_NO_MEM 2
+#define ERR_PLOTTER_NOT_AVAILABLE 3
+
+static const char * plot_error_codes[] =
+{
+ "None",
+ "ERR_BUFFERSIZE_EXCEEDS_SCREEN",
+ "ERR_NO_MEM",
+ "ERR_PLOTTER_NOT_AVAILABLE"
+};
+
+/* Grapics & Font Plotter Objects: */
+typedef struct s_font_plotter * FONT_PLOTTER;
+typedef struct s_gem_plotter * GEM_PLOTTER;
+typedef struct s_font_plotter * GEM_FONT_PLOTTER; /* for public use ... */
+struct s_font_plotter
+{
+ char * name;
+ int flags;
+ int vdi_handle;
+ void * priv_data;
+ GEM_PLOTTER plotter;
+
+ bool (*str_width)(FONT_PLOTTER self, const plot_font_style_t *fstyle,
+ const char * str, size_t length, int * width);
+ bool (*str_split)(FONT_PLOTTER self, const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int x, size_t *char_offset, int *actual_x);
+ bool (*pixel_position)(FONT_PLOTTER self, const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int x, size_t *char_offset, int *actual_x);
+ void (*text)(FONT_PLOTTER self, int x, int y, const char *text, size_t length, const plot_font_style_t *fstyle);
+ void (*dtor)(FONT_PLOTTER self );
+};
+
+
+struct s_clipping {
+ short x0;
+ short y0;
+ short x1;
+ short y1;
+};
+
+struct s_vdi_sysinfo {
+ short vdi_handle; /* vdi handle */
+ short scr_w; /* resolution horz. */
+ short scr_h; /* resolution vert. */
+ short scr_bpp; /* bits per pixel */
+ int colors; /* 0=hiclor, 2=mono */
+ unsigned long hicolors; /* if colors = 0 */
+ short pixelsize; /* bytes per pixel */
+ unsigned short pitch; /* row pitch */
+ unsigned short vdiformat; /* pixel format */
+ unsigned short clut; /* type of clut support */
+ void * screen; /* pointer to screen, or NULL */
+ unsigned long screensize; /* size of screen (in bytes) */
+ unsigned long mask_r; /* color masks */
+ unsigned long mask_g;
+ unsigned long mask_b;
+ unsigned long mask_a;
+ short maxintin; /* maximum pxy items */
+ short maxpolycoords; /* max coords for p_line etc. */
+ unsigned long EdDiVersion; /* EdDi Version or 0 */
+ bool rasterscale; /* raster scaling support */
+};
+
+
+
+struct s_frame_buf
+{
+ short x;
+ short y;
+ short w;
+ short h;
+ short vis_x; /* visible rectangle of the screen buffer */
+ short vis_y; /* coords are relative to framebuffer location */
+ short vis_w;
+ short vis_h;
+ int size;
+ bool swapped;
+ void * mem;
+};
+
+
+struct s_gem_plotter
+{
+ char * name; /* name that identifies the Plotter */
+ unsigned long flags;
+ int vdi_handle;
+ struct s_vdi_sysinfo * scr;
+ void * priv_data;
+ int bpp_virt; /* bit depth of framebuffer */
+ struct s_clipping clipping;
+ struct s_frame_buf fbuf[MAX_FRAMEBUFS];
+ int cfbi; /* current framebuffer index */
+
+ FONT_PLOTTER font_plotter;
+ int (*dtor)(GEM_PLOTTER self);
+ int (*resize)(GEM_PLOTTER self, int w, int h);
+ int (*move)(GEM_PLOTTER self, short x, short y );
+ void * (*lock)(GEM_PLOTTER self);
+ void * (*create_framebuffer)(GEM_PLOTTER self);
+ void * (*switch_to_framebuffer)(GEM_PLOTTER self);
+ int (*unlock)(GEM_PLOTTER self);
+ int (*update_region)(GEM_PLOTTER self, GRECT region);
+ int (*update_screen_region)( GEM_PLOTTER self, GRECT region );
+ int (*update_screen)(GEM_PLOTTER self);
+ int (*put_pixel)(GEM_PLOTTER self, int x, int y, int color );
+ int (*copy_rect)(GEM_PLOTTER self, GRECT src, GRECT dst );
+ int (*clip)(GEM_PLOTTER self, int x0, int y0, int x1, int y1);
+ int (*arc)(GEM_PLOTTER self, int x, int y, int radius, int angle1, int angle2, const plot_style_t * pstyle);
+ int (*disc)(GEM_PLOTTER self, int x, int y, int radius, const plot_style_t * pstyle);
+ int (*line)(GEM_PLOTTER self, int x0, int y0, int x1, int y1, const plot_style_t * pstyle);
+ int (*rectangle)(GEM_PLOTTER self, int x0, int y0, int x1, int y1, const plot_style_t * pstyle);
+ int (*polygon)(GEM_PLOTTER self, const int *p, unsigned int n, const plot_style_t * pstyle);
+ int (*path)(GEM_PLOTTER self, const float *p, unsigned int n, int fill, float width, int c, const float transform[6]);
+ int (*bitmap_resize) ( GEM_PLOTTER self, struct bitmap * bm, int nw, int nh );
+ int (*bitmap)(GEM_PLOTTER self, struct bitmap * bmp, int x, int y,
+ unsigned long bg, unsigned long flags );
+ int (*text)(GEM_PLOTTER self, int x, int y, const char *text, size_t length, const plot_font_style_t *fstyle);
+};
+
+
+struct s_driver_table_entry
+{
+ char * name;
+ int (*ctor)( GEM_PLOTTER self );
+ int flags;
+ int max_bpp;
+};
+
+struct s_font_driver_table_entry
+{
+ char * name;
+ int (*ctor)( FONT_PLOTTER self );
+ int flags;
+};
+
+typedef struct s_driver_table_entry * PLOTTER_INFO;
+typedef struct s_font_driver_table_entry * FONT_PLOTTER_INFO;
+
+/* get index to driver in driver list by name */
+static int drvrname_idx( char * name );
+
+/* get s_driver_table_entry from driver table */
+struct s_driver_table_entry * get_screen_driver_entry(char * name);
+
+/* get s_font_driver_table_entry from driver table */
+struct s_font_driver_table_entry * get_font_driver_entry(char * name);
+
+/* fill screen / sys info */
+struct s_vdi_sysinfo * read_vdi_sysinfo(short vdih, struct s_vdi_sysinfo * info );
+
+/*
+ Create an new plotter object
+ Error Values:
+ -1 no mem
+ -2 error configuring plotter
+ -3 Plotter not available
+*/
+GEM_PLOTTER new_plotter(int vdihandle, char * name,
+ GRECT *, int virt_bpp, unsigned long flags, FONT_PLOTTER font_renderer,
+ int * error);
+
+/*
+ Create an new font plotter object
+ Error Values:
+ -1 no mem
+ -2 error configuring font plotter
+ -3 Font Plotter not available
+*/
+FONT_PLOTTER new_font_plotter(int vdihandle, char * name, unsigned long flags, int * error );
+
+/* free the plotter resources */
+int delete_plotter( GEM_PLOTTER p );
+int delete_font_plotter( FONT_PLOTTER p );
+
+
+/* calculate size of intermediate buffer */
+int calc_chunked_buffer_size(int x, int y, int stride, int bpp);
+
+/* calculates the pixel offset from x,y pos */
+int get_pixel_offset( int x, int y, int stride, int bpp );
+
+/* Recalculate visible parts of the framebuffer */
+void update_visible_rect( GEM_PLOTTER p );
+
+/* resolve possible visible parts of the framebuffer in screen coords */
+bool fbrect_to_screen( GEM_PLOTTER self, GRECT box, GRECT * ret );
+
+/* translate an error number */
+const char* plotter_err_str(int i) ;
+
+void dump_font_drivers(void);
+void dump_plot_drivers(void);
+void dump_vdi_info(short);
+
+/* convert an rgb color to vdi1000 color */
+void rgb_to_vdi1000( unsigned char * in, unsigned short * out );
+
+/* convert an rgb color to an index into the web palette */
+short rgb_to_666_index(unsigned char r, unsigned char g, unsigned char b);
+
+/* shared / static methods ... */
+int plotter_get_clip( GEM_PLOTTER self, struct s_clipping * out );
+int plotter_std_clip(GEM_PLOTTER self,int x0, int y0, int x1, int y1);
+void plotter_vdi_clip( GEM_PLOTTER self, bool set);
+
+#define PLOTTER_IS_LOCKED(plotter) ( plotter->private_flags & PLOTTER_FLAG_LOCKED )
+#define FILL_PLOTTER_VTAB( p ) \
+ p->dtor = dtor;\
+ p->resize= resize;\
+ p->move = move;\
+ p->lock = lock;\
+ p->unlock = unlock;\
+ p->update_region = update_region;\
+ p->update_screen_region = update_screen_region;\
+ p->update_screen = update_screen;\
+ p->put_pixel = put_pixel;\
+ p->copy_rect = copy_rect; \
+ p->clip = clip;\
+ p->arc = arc;\
+ p->disc = disc;\
+ p->line = line;\
+ p->rectangle = rectangle;\
+ p->polygon = polygon;\
+ p->path = path;\
+ p->bitmap = bitmap;\
+ p->text = text;\
+
+
+#define FILL_FONT_PLOTTER_VTAB( p ) \
+ p->dtor = dtor;\
+ p->str_width = str_width;\
+ p->str_split = str_split;\
+ p->pixel_position = pixel_position;\
+ p->text = text;\
+
+#define CURFB( p ) \
+ p->fbuf[p->cfbi]
+
+#define FIRSTFB( p ) \
+ p->fbuf[0]
+
+#define OFFSET_WEB_PAL 16
+#define OFFSET_FONT_PAL 232
+#define RGB_TO_VDI(c) rgb_to_666_index( (c&0xFF),(c&0xFF00)>>8,(c&0xFF0000)>>16)+OFFSET_WEB_PAL
+#define ABGR_TO_RGB(c) ( ((c&0xFF)<<16) | (c&0xFF00) | ((c&0xFF0000)>>16) ) << 8
+
+#endif
diff --git a/atari/plot/plotter_vdi.c b/atari/plot/plotter_vdi.c
new file mode 100644
index 000000000..e825d92d3
--- /dev/null
+++ b/atari/plot/plotter_vdi.c
@@ -0,0 +1,998 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+#include <windom.h>
+#include <Hermes/Hermes.h>
+
+#include "desktop/plot_style.h"
+#include "image/bitmap.h"
+#include "atari/bitmap.h"
+#include "atari/plot/eddi.h"
+#include "atari/plot/plotter.h"
+#include "atari/plot/plotter_vdi.h"
+#include "atari/plot/font_vdi.h"
+#include "atari/bitmap.h"
+#include "utils/log.h"
+
+/* assign vdi line style to dst ( netsurf type ) */
+#define NSLT2VDI(dst, src) \
+ switch( src->stroke_type ) {\
+ case PLOT_OP_TYPE_DOT: \
+ dst = 3; \
+ break;\
+ case PLOT_OP_TYPE_DASH:\
+ dst = 4; \
+ break;\
+ case PLOT_OP_TYPE_SOLID:\
+ case PLOT_OP_TYPE_NONE:\
+ default:\
+ dst = 1;\
+ break;\
+ }\
+
+static int dtor( GEM_PLOTTER self );
+static int resize( GEM_PLOTTER self, int w, int h );
+static int move( GEM_PLOTTER self, short x, short y );
+static void * lock( GEM_PLOTTER self );
+static int unlock( GEM_PLOTTER self );
+static int update_region( GEM_PLOTTER self, GRECT region );
+static int update_screen_region( GEM_PLOTTER self, GRECT region );
+static int update_screen( GEM_PLOTTER self );
+static int put_pixel(GEM_PLOTTER self, int x, int y, int color );
+static int copy_rect( GEM_PLOTTER self, GRECT src, GRECT dst );
+static int arc(GEM_PLOTTER self,int x, int y, int radius, int angle1, int angle2, const plot_style_t * pstyle);
+static int disc(GEM_PLOTTER self,int x, int y, int radius, const plot_style_t * pstyle);
+static int line(GEM_PLOTTER self,int x0, int y0, int x1, int y1, const plot_style_t * pstyle);
+static int rectangle(GEM_PLOTTER self,int x0, int y0, int x1, int y1, const plot_style_t * pstyle);
+static int polygon(GEM_PLOTTER self,const int *p, unsigned int n, const plot_style_t * pstyle);
+static int path(GEM_PLOTTER self,const float *p, unsigned int n, int fill, float width, int c, const float transform[6]);
+static int bitmap_resize( GEM_PLOTTER self, struct bitmap * img, int nw, int nh );
+static int bitmap( GEM_PLOTTER self, struct bitmap * bmp, int x, int y,
+ unsigned long bg, unsigned long flags );
+static int text(GEM_PLOTTER self, int x, int y, const char *text,size_t length, const plot_font_style_t *fstyle);
+
+static unsigned short sys_pal[256][3]; /*RGB*/
+static unsigned short pal[256][3]; /*RGB*/
+
+extern unsigned char rgb_web_pal[126][3];
+extern unsigned short vdi_web_pal[126][3];
+extern struct s_vdi_sysinfo vdi_sysinfo;
+
+static HermesHandle hermes_pal_h; /* hermes palette handle */
+static HermesHandle hermes_cnv_h; /* hermes converter instance handle */
+static HermesHandle hermes_res_h;
+int32 * hermes_pal_p;
+
+int ctor_plotter_vdi(GEM_PLOTTER self )
+{
+ int retval = 0;
+ int i;
+ self->dtor = dtor;
+ self->resize= resize;
+ self->move = move;
+ self->lock = lock;
+ self->unlock = unlock;
+ self->update_region = update_region;
+ self->update_screen_region = update_screen_region;
+ self->update_screen = update_screen;
+ self->put_pixel = put_pixel;
+ self->copy_rect = copy_rect;
+ self->clip = plotter_std_clip;
+ self->arc = arc;
+ self->disc = disc;
+ self->line = line;
+ self->rectangle = rectangle;
+ self->polygon = polygon;
+ self->path = path;
+ self->bitmap = bitmap;
+ self->bitmap_resize = bitmap_resize;
+ self->text = text;
+ LOG(("Screen: x: %d, y: %d\n", vdi_sysinfo.scr_w, vdi_sysinfo.scr_h));
+
+ self->priv_data = malloc( sizeof(struct s_vdi_priv_data) );
+ if( self->priv_data == NULL )
+ return( 0-ERR_NO_MEM );
+ memset( self->priv_data, 0, sizeof(struct s_vdi_priv_data) );
+ DUMMY_PRIV(self)->bufops = 0;
+ DUMMY_PRIV(self)->size_buf_packed = 0;
+ DUMMY_PRIV(self)->size_buf_planar = 0;
+ DUMMY_PRIV(self)->buf_packed = NULL;
+ DUMMY_PRIV(self)->buf_planar = NULL;
+ if( vdi_sysinfo.vdiformat == VDI_FORMAT_PACK ) {
+ self->bpp_virt = vdi_sysinfo.scr_bpp;
+ } else {
+ DUMMY_PRIV(self)->bufops = C2P;
+ self->bpp_virt = 8;
+ }
+ if( FIRSTFB(self).w > vdi_sysinfo.scr_w || FIRSTFB(self).h > vdi_sysinfo.scr_h )
+ return( 0-ERR_BUFFERSIZE_EXCEEDS_SCREEN );
+
+ FIRSTFB(self).size = calc_chunked_buffer_size( FIRSTFB(self).w, FIRSTFB(self).h, FIRSTFB(self).w, self->bpp_virt );
+ /* offscreen: FIRSTFB(self).mem = malloc( FIRSTFB(self).size ); */
+ FIRSTFB(self).mem = NULL;
+ update_visible_rect( self );
+ self->clip( self, 0, 0, FIRSTFB(self).w, FIRSTFB(self).h );
+ /* store system palette & setup the new (web) palette: */
+ i = 0;
+ for( i=0; i<=255; i++ ) {
+ vq_color(self->vdi_handle, i, 1, (unsigned short*)&sys_pal[i][0] );
+ if( i<OFFSET_WEB_PAL ) {
+ pal[i][0] = sys_pal[i][0];
+ pal[i][1] = sys_pal[i][1];
+ pal[i][2] = sys_pal[i][2];
+ } else {
+ if ( i < OFFSET_FONT_PAL ){
+ pal[i][0] = vdi_web_pal[i-OFFSET_WEB_PAL][0];
+ pal[i][1] = vdi_web_pal[i-OFFSET_WEB_PAL][1];
+ pal[i][2] = vdi_web_pal[i-OFFSET_WEB_PAL][2];
+ }
+ if( i >= OFFSET_FONT_PAL ) {
+ /* here we could define some additional colors... */
+ /* rgb_to_vdi1000( &rgb_font_pal[i-OFFSET_FONT_PAL], &pal[i] ); */
+ }
+ vs_color( self->vdi_handle, i, &pal[i][0] );
+ }
+ }
+
+ unsigned char * col;
+ assert( Hermes_Init() );
+ hermes_pal_h = Hermes_PaletteInstance();
+ hermes_pal_p = Hermes_PaletteGet(hermes_pal_h);
+ assert(hermes_pal_p);
+
+ for( i = 0; i<OFFSET_FONT_PAL; i++) {
+ col = (unsigned char *)(hermes_pal_p+i);
+ if( i < OFFSET_WEB_PAL ) {
+ col[0] = sys_pal[i][0];
+ col[1] = sys_pal[i][1];
+ col[2] = sys_pal[i][2];
+ }
+ if( i >= OFFSET_WEB_PAL ) {
+ col[0] = rgb_web_pal[i-OFFSET_WEB_PAL][0];
+ col[1] = rgb_web_pal[i-OFFSET_WEB_PAL][1];
+ col[2] = rgb_web_pal[i-OFFSET_WEB_PAL][2];
+ }
+ /* font colors missing */
+ col[3] = 0;
+ }
+ Hermes_PaletteInvalidateCache(hermes_pal_h);
+
+ unsigned long flags = ( self->flags & PLOT_FLAG_DITHER ) ? HERMES_CONVERT_DITHER : 0;
+ hermes_cnv_h = Hermes_ConverterInstance( flags );
+ assert( hermes_cnv_h );
+ hermes_res_h = Hermes_ConverterInstance( flags );
+ assert( hermes_res_h );
+
+ /* set up the src & dst format: */
+ /* netsurf uses RGBA ... */
+ DUMMY_PRIV(self)->nsfmt.a = 0xFFUL;
+ DUMMY_PRIV(self)->nsfmt.b = 0x0FF00UL;
+ DUMMY_PRIV(self)->nsfmt.g = 0x0FF0000UL;
+ DUMMY_PRIV(self)->nsfmt.r = 0x0FF000000UL;
+ DUMMY_PRIV(self)->nsfmt.bits = 32;
+ DUMMY_PRIV(self)->nsfmt.indexed = false;
+ DUMMY_PRIV(self)->nsfmt.has_colorkey = false;
+
+ DUMMY_PRIV(self)->vfmt.r = vdi_sysinfo.mask_r;
+ DUMMY_PRIV(self)->vfmt.g = vdi_sysinfo.mask_g;
+ DUMMY_PRIV(self)->vfmt.b = vdi_sysinfo.mask_b;
+ DUMMY_PRIV(self)->vfmt.a = vdi_sysinfo.mask_a;
+ DUMMY_PRIV(self)->vfmt.bits = self->bpp_virt;
+ DUMMY_PRIV(self)->vfmt.indexed = false;
+ DUMMY_PRIV(self)->vfmt.has_colorkey = false;
+
+ return( 1 );
+}
+
+static int dtor( GEM_PLOTTER self )
+{
+ int i=0;
+ LOG(("%s: %s\n", (char*)__FILE__, __FUNCTION__));
+ for( i=0; i<MAX_FRAMEBUFS; i++) {
+ if( self->fbuf[i].mem != NULL )
+ free( self->fbuf[i].mem );
+ }
+
+ /* restore system palette */
+ for( i=0; i<=255; i++ ) {
+ vs_color( self->vdi_handle, i, &sys_pal[i][0] );
+ }
+
+ /* close Hermes stuff: */
+ Hermes_ConverterReturn( hermes_cnv_h );
+ Hermes_PaletteReturn( hermes_pal_h );
+ Hermes_Done();
+
+ if( self->priv_data != NULL ){
+ if( DUMMY_PRIV(self)->buf_packed )
+ free( DUMMY_PRIV(self)->buf_packed );
+ if( DUMMY_PRIV(self)->buf_planar )
+ free( DUMMY_PRIV(self)->buf_planar );
+ free( self->priv_data );
+ }
+ return( 1 );
+}
+
+static int resize( GEM_PLOTTER self, int w, int h )
+{
+ if( w == CURFB(self).w && h == CURFB(self).h )
+ return( 1 );
+ int newsize = calc_chunked_buffer_size( w, h, w, self->bpp_virt );
+ LOG(("%s: %s, oldsize: %d\n", (char*)__FILE__, __FUNCTION__, CURFB(self).size ));
+ /* todo: needed when using offscreen buffers...
+ if( newsize > self->screen_buffer_size ) {
+ self->screen_buffer_size = newsize;
+ self->screen_buffer =realloc( self->screen_buffer , self->screen_buffer_size );
+ }
+ */
+ CURFB(self).w = w;
+ CURFB(self).h = h;
+ update_visible_rect( self );
+ LOG(("%s: %s, newsize: %d\n", (char*)__FILE__, (char*)__FUNCTION__, CURFB(self).size ));
+ return( 1 );
+}
+static int move( GEM_PLOTTER self,short x, short y )
+{
+ bool upd;
+ if(x == CURFB(self).x && y == CURFB(self).y ){
+ return 1;
+ }
+ LOG(("%s: x: %d, y: %d\n",(char*)__FUNCTION__, x, y));
+ CURFB(self).x = x;
+ CURFB(self).y = y;
+ update_visible_rect( self );
+
+ /*
+ for offscreen plotters:
+ copy current contents to new pos?
+ we could also copy content of our own screen buffer,
+ but only when it's unlocked
+ ...nono, the user must do this manually. Because window move will already be handled by the OS
+ */
+ /*update_screen( self );*/
+ return( 1 );
+}
+
+
+static void * lock( GEM_PLOTTER self )
+{
+ LOG(("%s: %s\n", (char*)__FILE__, __FUNCTION__));
+ self->flags |= PLOT_FLAG_LOCKED;
+ wind_update(BEG_UPDATE);
+ wind_update(BEG_MCTRL);
+ return( NULL );
+}
+
+static int unlock( GEM_PLOTTER self )
+{
+ LOG(("%s: %s\n", (char*)__FILE__, __FUNCTION__));
+ self->flags &= ~PLOT_FLAG_LOCKED;
+ wind_update(END_MCTRL);
+ wind_update(END_UPDATE);
+ return( 1 );
+}
+
+/*
+ region specifies an rectangle within the framebuffer
+ calculation of screen coords is done automatically.
+*/
+static int update_region( GEM_PLOTTER self, GRECT region )
+{
+ int src_offs;
+ GRECT screen_area, tmp, visible;
+ short pxy[10];
+ visible.g_x = CURFB(self).vis_x;
+ visible.g_y = CURFB(self).vis_y;
+ visible.g_w = CURFB(self).vis_w;
+ visible.g_h = CURFB(self).vis_h;
+
+/*
+ LOG(("%s: %s %d\n", (char*)__FILE__, __FUNCTION__, __LINE__));
+ LOG(("region: x:%d, y:%d, w:%d, h:%d\n", region.g_x, region.g_y, region.g_w, region.g_h ));
+ LOG(("visible: x:%d, y:%d, w:%d, h:%d\n", visible.g_x, visible.g_y, visible.g_w, visible.g_h ));
+*/
+ /* sanitize region: */
+ tmp = region;
+ if( !rc_intersect(&visible, &tmp) )
+ return( 0 );
+/*
+ region is partially out of bottom or left:
+ if( region.g_x < self->visible.g_x )
+ {
+ region.g_w = self->visible.g_x - region.g_x;
+ region.g_x = self->visible.g_x;
+ }
+ if( region.g_y < self->visible.g_y )
+ {
+ region.g_h = self->visible.g_y - region.g_y;
+ region.g_y = self->visible.g_y;
+ }
+ region is partially out of top or right:
+ if( region.g_x + region.g_w > self->visible.g_x + self->visible.g_w )
+ {
+ region.g_w = self->visible.g_w - region.g_x;
+ }
+ if( region.g_y + region.g_h > self->visible.g_y + self->visible.g_h )
+ {
+ region.g_h = self->visible.g_h - region.g_y;
+ }
+ now region contains coords of framebuffer that needs redraw.
+*/
+ if( fbrect_to_screen( self, tmp, &screen_area) ) {
+ pxy[0] = screen_area.g_x;
+ pxy[1] = screen_area.g_y;
+ pxy[2] = screen_area.g_x + screen_area.g_w;
+ pxy[3] = screen_area.g_y;
+ pxy[4] = screen_area.g_x + screen_area.g_w;
+ pxy[5] = screen_area.g_y + screen_area.g_h;
+ pxy[6] = screen_area.g_x;
+ pxy[7] = screen_area.g_y + screen_area.g_h;
+ pxy[8] = screen_area.g_x;
+ pxy[9] = screen_area.g_y;
+ }
+ return( 1 );
+}
+
+/*
+ region specifies an rectangle within the screen,
+ calculation of framebuffer coords is done automatically.
+*/
+static int update_screen_region( GEM_PLOTTER self, GRECT region )
+{
+ LOG(("%s: %s\n", (char*)__FILE__, __FUNCTION__));
+
+ return( 1 );
+}
+
+/* Updates all visible parts of the framebuffer */
+static int update_screen( GEM_PLOTTER self )
+{
+ GRECT target, src;
+ int src_offset;
+ int i,x;
+ LOG(("%s: %s\n", (char*)__FILE__, __FUNCTION__));
+ if( !(PLOT_FLAG_OFFSCREEN & self->flags) )
+ return( 0 );
+ target.g_x = src.g_x = 0;
+ target.g_y = src.g_y = 0;
+ target.g_w = src.g_w = CURFB(self).w;
+ target.g_h = src.g_h = CURFB(self).h;
+ if( !fbrect_to_screen( self, target, &target ) )
+ return( -1 );
+ src_offset = get_pixel_offset( CURFB(self).vis_x, CURFB(self).vis_y, CURFB(self).w, self->bpp_virt );
+ LOG(("area: x:%d ,y:%d ,w:%d ,h:%d, from: %p (offset: %d) \n",
+ target.g_x, target.g_y,
+ target.g_w, target.g_h,
+ ((char*)CURFB(self).mem)+src_offset, src_offset
+ ));
+
+ return( 1 );
+}
+static int put_pixel(GEM_PLOTTER self, int x, int y, int color )
+{
+ LOG(("%s: %s\n", (char*)__FILE__, __FUNCTION__));
+ return( 1 );
+}
+
+static int copy_rect( GEM_PLOTTER self, GRECT src, GRECT dst )
+{
+ MFDB devmf;
+ MFDB scrmf;
+ short pxy[8];
+ GRECT vis;
+
+ /* clip to visible rect, only needed for onscreen renderer: */
+ vis.g_x = CURFB(self).vis_x;
+ vis.g_y = CURFB(self).vis_y;
+ vis.g_w = CURFB(self).vis_w;
+ vis.g_h = CURFB(self).vis_h;
+
+ if( !rc_intersect(&vis, &src) )
+ return 1;
+ if( !rc_intersect(&vis, &dst) )
+ return 1;
+
+ src.g_x = CURFB(self).x + src.g_x;
+ src.g_y = CURFB(self).y + src.g_y;
+ dst.g_x = CURFB(self).x + dst.g_x;
+ dst.g_y = CURFB(self).y + dst.g_y;
+
+ devmf.fd_addr = NULL;
+ devmf.fd_w = src.g_w;
+ devmf.fd_h = src.g_h;
+ devmf.fd_wdwidth = 0;
+ devmf.fd_stand = 0;
+ devmf.fd_nplanes = 0;
+ devmf.fd_r1 = devmf.fd_r2 = devmf.fd_r3 = 0;
+
+ scrmf.fd_addr = NULL;
+ scrmf.fd_w = dst.g_w;
+ scrmf.fd_h = dst.g_h;
+ scrmf.fd_wdwidth = 0 ;
+ scrmf.fd_stand = 0;
+ scrmf.fd_nplanes = 0;
+ scrmf.fd_r1 = scrmf.fd_r2 = scrmf.fd_r3 = 0;
+
+ pxy[0] = src.g_x;
+ pxy[1] = src.g_y;
+ pxy[2] = pxy[0] + src.g_w-1;
+ pxy[3] = pxy[1] + src.g_h-1;
+ pxy[4] = dst.g_x;
+ pxy[5] = dst.g_y;
+ pxy[6] = pxy[4] + dst.g_w-1;
+ pxy[7] = pxy[5] + dst.g_h-1;
+ self->lock( self );
+ vro_cpyfm( self->vdi_handle, S_ONLY, (short*)&pxy, &devmf, &scrmf);
+ self->unlock( self );
+
+ return( 1 );
+}
+
+static int arc(GEM_PLOTTER self,int x, int y, int radius, int angle1, int angle2, const plot_style_t * pstyle)
+{
+ plotter_vdi_clip( self, 1);
+ vswr_mode( self->vdi_handle, MD_REPLACE );
+ if( pstyle->fill_type == PLOT_OP_TYPE_NONE )
+ return 1;
+ if( pstyle->fill_type != PLOT_OP_TYPE_SOLID) {
+ vsl_color( self->vdi_handle, RGB_TO_VDI(pstyle->stroke_colour) );
+ vsf_perimeter( self->vdi_handle, 1);
+ vsf_interior( self->vdi_handle, 1 );
+ v_arc( self->vdi_handle, CURFB(self).x + x, CURFB(self).y + y, radius, angle1*10, angle2*10 );
+ } else {
+ vsl_color( self->vdi_handle, RGB_TO_VDI(pstyle->fill_colour) );
+ vsl_width( self->vdi_handle, 1 );
+ vsf_perimeter( self->vdi_handle, 1);
+ v_arc( self->vdi_handle, CURFB(self).x + x, CURFB(self).y + y, radius, angle1*10, angle2*10 );
+ }
+ plotter_vdi_clip( self, 0);
+ return ( 1 );
+}
+
+static int disc(GEM_PLOTTER self,int x, int y, int radius, const plot_style_t * pstyle)
+{
+ plotter_vdi_clip( self, 1);
+ if( pstyle->fill_type != PLOT_OP_TYPE_SOLID) {
+ vsf_color( self->vdi_handle, RGB_TO_VDI(pstyle->stroke_colour) );
+ vsf_perimeter( self->vdi_handle, 1);
+ vsf_interior( self->vdi_handle, 0 );
+ v_circle( self->vdi_handle, CURFB(self).x + x, CURFB(self).y + y, radius );
+ } else {
+ vsf_color( self->vdi_handle, RGB_TO_VDI(pstyle->fill_colour) );
+ vsf_perimeter( self->vdi_handle, 0);
+ vsf_interior( self->vdi_handle, FIS_SOLID );
+ v_circle( self->vdi_handle, CURFB(self).x + x, CURFB(self).y + y, radius );
+ }
+ plotter_vdi_clip( self, 0);
+ return ( 1 );
+}
+
+static int line(GEM_PLOTTER self,int x0, int y0, int x1, int y1, const plot_style_t * pstyle)
+{
+ short pxy[4];
+ short lt;
+ int sw = pstyle->stroke_width;
+ pxy[0] = CURFB(self).x + x0;
+ pxy[1] = CURFB(self).y + y0;
+ pxy[2] = CURFB(self).x + x1;
+ pxy[3] = CURFB(self).y + y1;
+ /* plotter_vdi_clip( self, 1); */
+ if( sw == 0)
+ sw = 1;
+ NSLT2VDI(lt, pstyle)
+ vsl_type( self->vdi_handle, lt );
+ vsl_width( self->vdi_handle, (short)sw );
+ vsl_color( self->vdi_handle, RGB_TO_VDI(pstyle->stroke_colour) );
+ v_pline(self->vdi_handle, 2, (short *)&pxy );
+ /* plotter_vdi_clip( self, 0); */
+ return ( 1 );
+}
+
+static int rectangle(GEM_PLOTTER self,int x0, int y0, int x1, int y1, const plot_style_t * pstyle)
+{
+ short pxy[10];
+
+ GRECT r, rclip, sclip;
+
+ /* plotter_vdi_clip( self, 1); */
+
+ rclip.g_x = self->clipping.x0;
+ rclip.g_y = self->clipping.y0;
+ rclip.g_w = self->clipping.x1 - self->clipping.x0;
+ rclip.g_h = self->clipping.y1 - self->clipping.y0;
+
+ sclip.g_x = rclip.g_x;
+ sclip.g_y = rclip.g_y;
+ sclip.g_w = CURFB(self).vis_w;
+ sclip.g_h = CURFB(self).vis_h;
+ rc_intersect(&sclip, &rclip);
+ r.g_x = x0;
+ r.g_y = y0;
+ r.g_w = x1 - x0;
+ r.g_h = y1 - y0;
+ if( !rc_intersect( &rclip, &r ) ) {
+ return( 1 );
+ }
+ vsf_color( self->vdi_handle, RGB_TO_VDI(pstyle->fill_colour) );
+ vsf_perimeter( self->vdi_handle, 0);
+ vsf_interior( self->vdi_handle, FIS_SOLID );
+
+ pxy[0] = CURFB(self).x + r.g_x;
+ pxy[1] = CURFB(self).y + r.g_y;
+ pxy[2] = CURFB(self).x + r.g_x + r.g_w -1;
+ pxy[3] = CURFB(self).y + r.g_y + r.g_h -1;
+
+ vsf_style( self->vdi_handle, 1);
+ v_bar( self->vdi_handle, (short*)&pxy );
+
+ /* plotter_vdi_clip( self, 0); */
+ return ( 1 );
+}
+
+static int polygon(GEM_PLOTTER self,const int *p, unsigned int n, const plot_style_t * pstyle)
+{
+ short pxy[n+2];
+ unsigned int i=0;
+ short d[4];
+ if( vdi_sysinfo.maxpolycoords > 0 )
+ assert( n < vdi_sysinfo.maxpolycoords );
+/*
+ Does this double check make sense?
+ else
+ assert( n < vdi_sysinfo.maxintin );
+*/
+ /* test this: */
+ /* plotter_vdi_clip( self, 1); */
+ vsf_interior( self->vdi_handle, FIS_SOLID );
+ vsf_style( self->vdi_handle, 1);
+ for( i = 0; i<n*2; i=i+2 ) {
+ pxy[i] = (short)CURFB(self).x+p[i];
+ pxy[i+1] = (short)CURFB(self).y+p[i+1];
+ }
+ if( pstyle->fill_type == PLOT_OP_TYPE_SOLID){
+ vsf_color( self->vdi_handle, BLACK);
+ v_fillarea(self->vdi_handle, n, (short*)&pxy);
+
+ } else {
+ pxy[n*2]=pxy[0];
+ pxy[n*2+1]=pxy[1];
+ vsl_color( self->vdi_handle, BLACK );
+ v_pline(self->vdi_handle, n+1, (short *)&pxy );
+ }
+ /* plotter_vdi_clip( self, 0); */
+ return ( 1 );
+}
+
+static int path(GEM_PLOTTER self,const float *p, unsigned int n, int fill, float width,
+ int c, const float transform[6])
+{
+ LOG(("%s: %s\n", (char*)__FILE__, __FUNCTION__));
+ return ( 1 );
+}
+
+
+static inline uint32_t ablend(uint32_t pixel, uint32_t scrpixel)
+{
+ int opacity = pixel & 0xFF;
+ int transp = 0x100 - opacity;
+ uint32_t rb, g;
+
+ rb = ((pixel & 0xFF00FF00UL) * opacity +
+ (scrpixel & 0xFF00FF00UL) * transp) >> 8;
+ g = ((pixel & 0x00FF0000UL) * opacity +
+ (scrpixel & 0x00FF0000UL) * transp) >> 8;
+
+ return (rb & 0xFF00FF00) | (g & 0x00FF0000);
+}
+
+static int bitmap_resize( GEM_PLOTTER self, struct bitmap * img, int nw, int nh )
+{
+ HermesFormat fmt;
+ short bpp = bitmap_get_bpp( img );
+ int stride = bitmap_get_rowstride( img );
+ int err;
+
+ if( img->resized != NULL ) {
+ if( img->resized->width != nw || img->resized->height != nh ) {
+ bitmap_destroy( img->resized );
+ img->resized = NULL;
+ } else {
+ return( 0 );
+ }
+ }
+
+ /* allocate the mem for resized bitmap */
+ img->resized = bitmap_create_ex( nw, nh, bpp, nw*bpp, 0, NULL );
+ if( img->resized == NULL ) {
+ assert( img->resized );
+ return ( -ERR_NO_MEM );
+ }
+
+ /* allocate an converter, only for resizing */
+ err = Hermes_ConverterRequest( hermes_res_h,
+ &DUMMY_PRIV(self)->nsfmt,
+ &DUMMY_PRIV(self)->nsfmt
+ );
+ if( err == 0 ) {
+ return( -ERR_PLOTTER_NOT_AVAILABLE );
+ }
+
+ err = Hermes_ConverterCopy( hermes_res_h,
+ img->pixdata,
+ 0, /* x src coord of top left in pixel coords */
+ 0, /* y src coord of top left in pixel coords */
+ bitmap_get_width( img ), bitmap_get_height( img ),
+ stride, /* stride as bytes */
+ img->resized->pixdata,
+ 0, /* x dst coord of top left in pixel coords */
+ 0, /* y dst coord of top left in pixel coords */
+ nw, nh,
+ bitmap_get_rowstride( img->resized ) /* stride as bytes */
+ );
+ if( err == 0 ) {
+ bitmap_destroy( img->resized );
+ img->resized = NULL;
+ return( -2 );
+ }
+
+ return( 0 );
+}
+
+/*
+ fuellt ein mfdb, wenn bpp==null wird angenommen das ein MFDB fr
+ den Bildschirm initialisiert werden soll, der Speicher fuer das Bild
+ wird daher nicht alloziert ( fd_addr == 0 )
+*/
+static int init_mfdb(int bpp, int w, int h, MFDB * out )
+{
+ int pxsize = bpp >> 3;
+ int dststride;
+ dststride = MFDB_STRIDE( w );
+ if( bpp > 0 ) {
+ out->fd_addr = malloc( dststride * pxsize * h );
+ out->fd_stand = 0;
+ out->fd_nplanes = (short)bpp;
+ out->fd_r1 = out->fd_r2 = out->fd_r3 = 0;
+ } else {
+ memset( out, 0, sizeof(MFDB) );
+ }
+ out->fd_w = dststride;
+ out->fd_h = h;
+ out->fd_wdwidth = dststride >> 4;
+ return( 1 );
+}
+
+/*
+* Capture the screen at x,y location
+* param self instance
+* param x absolute screen coords
+* param y absolute screen coords
+* param w width
+* param h height
+*/
+static struct bitmap * snapshot_create(GEM_PLOTTER self, int x, int y, int w, int h)
+{
+ MFDB scr;
+ short pxy[8];
+ int err;
+
+ /* make sure the screen format is pixel packed... */
+ /* no method to convert planar screen to pixel packed ... right now */
+ assert( vdi_sysinfo.vdiformat == VDI_FORMAT_PACK );
+
+ {
+ int pxsize = vdi_sysinfo.scr_bpp >> 3;
+ int scr_stride = MFDB_STRIDE( w );
+ int scr_size = scr_stride * pxsize * h;
+ if( DUMMY_PRIV(self)->size_buf_scr == 0 ){
+ /* init screen mfdb */
+ DUMMY_PRIV(self)->buf_scr.fd_addr = malloc( scr_size );
+ DUMMY_PRIV(self)->size_buf_scr = scr_size;
+ } else {
+ if( scr_size > DUMMY_PRIV(self)->size_buf_scr ) {
+ DUMMY_PRIV(self)->buf_scr.fd_addr = realloc(
+ DUMMY_PRIV(self)->buf_scr.fd_addr, scr_size
+ );
+ DUMMY_PRIV(self)->size_buf_scr = scr_size;
+ }
+ }
+ if( DUMMY_PRIV(self)->buf_scr.fd_addr == NULL ) {
+ DUMMY_PRIV(self)->size_buf_scr = 0;
+ return( NULL );
+ }
+ DUMMY_PRIV(self)->buf_scr.fd_nplanes = vdi_sysinfo.scr_bpp;
+ DUMMY_PRIV(self)->buf_scr.fd_w = scr_stride;
+ DUMMY_PRIV(self)->buf_scr.fd_h = h;
+ DUMMY_PRIV(self)->buf_scr.fd_wdwidth = scr_stride >> 4;
+ assert( DUMMY_PRIV(self)->buf_scr.fd_addr != NULL );
+ }
+
+ init_mfdb( 0, w, h, &scr );
+ pxy[0] = x;
+ pxy[1] = y;
+ pxy[2] = pxy[0] + w-1;
+ pxy[3] = pxy[1] + h-1;
+ pxy[4] = 0;
+ pxy[5] = 0;
+ pxy[6] = pxy[2];
+ pxy[7] = pxy[3];
+ vro_cpyfm( self->vdi_handle, S_ONLY, (short*)&pxy,
+ &scr, &DUMMY_PRIV(self)->buf_scr
+ );
+
+ /* convert screen buffer to ns format: */
+ if( DUMMY_PRIV(self)->buf_scr_compat == NULL ) {
+ DUMMY_PRIV(self)->buf_scr_compat = bitmap_create(w, h, 0);
+ } else {
+ DUMMY_PRIV(self)->buf_scr_compat = bitmap_realloc( w, h,
+ DUMMY_PRIV(self)->buf_scr_compat->bpp,
+ w * DUMMY_PRIV(self)->buf_scr_compat->bpp,
+ BITMAP_GROW,
+ DUMMY_PRIV(self)->buf_scr_compat );
+ }
+ err = Hermes_ConverterRequest( hermes_cnv_h,
+ &DUMMY_PRIV(self)->vfmt,
+ &DUMMY_PRIV(self)->nsfmt
+ );
+ assert( err != 0 );
+ err = Hermes_ConverterCopy( hermes_cnv_h,
+ DUMMY_PRIV(self)->buf_scr.fd_addr,
+ 0, /* x src coord of top left in pixel coords */
+ 0, /* y src coord of top left in pixel coords */
+ w, h,
+ DUMMY_PRIV(self)->buf_scr.fd_w * vdi_sysinfo.pixelsize, /* stride as bytes */
+ DUMMY_PRIV(self)->buf_scr_compat->pixdata,
+ 0, /* x dst coord of top left in pixel coords */
+ 0, /* y dst coord of top left in pixel coords */
+ w, h,
+ bitmap_get_rowstride(DUMMY_PRIV(self)->buf_scr_compat) /* stride as bytes */
+ );
+ assert( err != 0 );
+ return( (struct bitmap * )DUMMY_PRIV(self)->buf_scr_compat );
+}
+
+static void snapshot_suspend(GEM_PLOTTER self )
+{
+ if( DUMMY_PRIV(self)->size_buf_scr > CONV_KEEP_LIMIT ) {
+ DUMMY_PRIV(self)->buf_scr.fd_addr = realloc(
+ DUMMY_PRIV(self)->buf_scr.fd_addr, CONV_KEEP_LIMIT
+ );
+ if( DUMMY_PRIV(self)->buf_scr.fd_addr != NULL ) {
+ DUMMY_PRIV(self)->size_buf_scr = CONV_KEEP_LIMIT;
+ } else {
+ DUMMY_PRIV(self)->size_buf_scr = 0;
+ }
+ }
+
+ if( bitmap_buffer_size( DUMMY_PRIV(self)->buf_scr_compat ) > CONV_KEEP_LIMIT ) {
+ int w = 0;
+ int h = 1;
+ w = (CONV_KEEP_LIMIT / DUMMY_PRIV(self)->buf_scr_compat->bpp);
+ assert( CONV_KEEP_LIMIT == w*DUMMY_PRIV(self)->buf_scr_compat->bpp );
+ DUMMY_PRIV(self)->buf_scr_compat = bitmap_realloc( w, h,
+ DUMMY_PRIV(self)->buf_scr_compat->bpp,
+ CONV_KEEP_LIMIT, BITMAP_SHRINK, DUMMY_PRIV(self)->buf_scr_compat
+ );
+
+ }
+}
+
+static void snapshot_destroy( GEM_PLOTTER self )
+{
+ if( DUMMY_PRIV(self)->buf_scr.fd_addr ) {
+ free( DUMMY_PRIV(self)->buf_scr.fd_addr );
+ DUMMY_PRIV(self)->buf_scr.fd_addr = NULL;
+ }
+
+ if( DUMMY_PRIV(self)->buf_scr_compat ) {
+ bitmap_destroy( DUMMY_PRIV(self)->buf_scr_compat );
+ DUMMY_PRIV(self)->buf_scr_compat = NULL;
+ }
+}
+
+/* convert bitmap to framebuffer format */
+static int convert_bitmap( GEM_PLOTTER self,
+ struct bitmap * img,
+ int x,
+ int y,
+ GRECT * clip,
+ uint32_t bg,
+ MFDB *out )
+{
+ short vpxsize = self->bpp_virt >> 3; /* / 8 */
+ int dststride; /* stride of dest. image */
+ int dstsize; /* size of dest. in byte */
+ int err;
+ int bw;
+ struct bitmap * scrbuf = NULL;
+ struct bitmap * bm;
+
+ assert( clip->g_h > 0 );
+ assert( clip->g_w > 0 );
+
+ bm = img;
+ bw = bitmap_get_width( img );
+
+ /* rem. if eddi xy is installed, we could directly access the screen! */
+ /* apply transparency to the image: */
+ if( (img->opaque == false)
+ && ((self->flags & PLOT_FLAG_TRANS) != 0)
+ && (vdi_sysinfo.vdiformat == VDI_FORMAT_PACK ) ) {
+ uint32_t * imgpixel;
+ uint32_t * screenpixel;
+ int img_x, img_y; /* points into old bitmap */
+ int screen_x, screen_y; /* pointers into new bitmap */
+ /* copy the screen to an temp buffer: */
+ scrbuf = snapshot_create(self, x, y, clip->g_w, clip->g_h );
+ if( scrbuf != NULL ) {
+ /* copy blended pixels the new buffer (which contains screen content): */
+ int img_stride = bitmap_get_rowstride(bm);
+ int screen_stride = bitmap_get_rowstride(scrbuf);
+ for( img_y = clip->g_y, screen_y = 0; screen_y < clip->g_h; screen_y++, img_y++) {
+ imgpixel = (uint32_t *)(bm->pixdata + (img_stride * img_y));
+ screenpixel = (uint32_t *)(scrbuf->pixdata + (screen_stride * screen_y));
+ for( img_x = clip->g_x, screen_x = 0; screen_x < clip->g_w; screen_x++, img_x++ ) {
+ if( (imgpixel[img_x] & 0xFF) != 0xFF ) {
+ if( (imgpixel[img_x] & 0x0FF) != 0 ) {
+ screenpixel[screen_x] = ablend( imgpixel[img_x], screenpixel[screen_x]);
+ }
+ } else {
+ screenpixel[screen_x] = imgpixel[img_x];
+ }
+ }
+ }
+ clip->g_x = 0;
+ clip->g_y = 0;
+ bm = scrbuf;
+ }
+ }
+
+ /* (re)allocate buffer for framebuffer image: */
+ dststride = MFDB_STRIDE( clip->g_w );
+ dstsize = dststride * vpxsize * clip->g_h;
+ if( dstsize > DUMMY_PRIV(self)->size_buf_packed) {
+ int blocks = (dstsize / (CONV_BLOCK_SIZE-1))+1;
+ if( DUMMY_PRIV(self)->buf_packed == NULL )
+ DUMMY_PRIV(self)->buf_packed =(void*)malloc( blocks * CONV_BLOCK_SIZE );
+ else
+ DUMMY_PRIV(self)->buf_packed =(void*)realloc(
+ DUMMY_PRIV(self)->buf_packed,
+ blocks * CONV_BLOCK_SIZE
+ );
+ assert( DUMMY_PRIV(self)->buf_packed );
+ if( DUMMY_PRIV(self)->buf_packed == NULL ) {
+ if( scrbuf != NULL )
+ bitmap_destroy( scrbuf );
+ return( 0-ERR_NO_MEM );
+ }
+ DUMMY_PRIV(self)->size_buf_packed = blocks * CONV_BLOCK_SIZE;
+ }
+ out->fd_addr = DUMMY_PRIV(self)->buf_packed;
+ out->fd_w = dststride;
+ out->fd_h = clip->g_h;
+ out->fd_wdwidth = dststride >> 4;
+ out->fd_stand = 0;
+ out->fd_nplanes = (short)self->bpp_virt;
+ out->fd_r1 = out->fd_r2 = out->fd_r3 = 0;
+
+ err = Hermes_ConverterRequest(
+ hermes_cnv_h,
+ &DUMMY_PRIV(self)->nsfmt,
+ &DUMMY_PRIV(self)->vfmt
+ );
+ assert( err != 0 );
+ /* convert image to virtual format: */
+ err = Hermes_ConverterCopy( hermes_cnv_h,
+ bm->pixdata,
+ clip->g_x, /* x src coord of top left in pixel coords */
+ clip->g_y, /* y src coord of top left in pixel coords */
+ clip->g_w, clip->g_h,
+ bm->rowstride, /* stride as bytes */
+ out->fd_addr,
+ 0, /* x dst coord of top left in pixel coords */
+ 0, /* y dst coord of top left in pixel coords */
+ clip->g_w, clip->g_h,
+ dststride * vpxsize /* stride as bytes */
+ );
+ assert( err != 0 );
+
+ return( 0 );
+
+}
+
+static void convert_bitmap_done( GEM_PLOTTER self )
+{
+ if( DUMMY_PRIV(self)->size_buf_packed > CONV_KEEP_LIMIT ) {
+ /* free the mem if it was an large allocation ... */
+ DUMMY_PRIV(self)->buf_packed = realloc( DUMMY_PRIV(self)->buf_packed, CONV_KEEP_LIMIT );
+ DUMMY_PRIV(self)->size_buf_packed = CONV_KEEP_LIMIT;
+ }
+ snapshot_suspend( self );
+}
+
+
+static int bitmap( GEM_PLOTTER self, struct bitmap * bmp, int x, int y,
+ unsigned long bg, unsigned long flags )
+{
+ MFDB src_mf;
+ MFDB scrmf;
+ short pxy[8];
+ GRECT off, clip, loc, vis;
+
+ src_mf.fd_addr = NULL;
+ scrmf.fd_addr = NULL;
+
+ off.g_x = x;
+ off.g_y = y;
+ off.g_h = bmp->height;
+ off.g_w = bmp->width;
+
+ clip.g_x = self->clipping.x0;
+ clip.g_y = self->clipping.y0;
+ clip.g_w = self->clipping.x1 - self->clipping.x0;
+ clip.g_h = self->clipping.y1 - self->clipping.y0;
+
+ if( !rc_intersect( &clip, &off) ) {
+ return( true );
+ }
+
+ vis.g_x = CURFB(self).vis_x;
+ vis.g_y = CURFB(self).vis_y;
+ vis.g_w = CURFB(self).vis_w;
+ vis.g_h = CURFB(self).vis_h;
+ if( !rc_intersect( &vis, &off) ) {
+ return( true );
+ }
+
+ loc = off;
+ off.g_x = MAX(0, off.g_x - x);
+ off.g_y = MAX(0, off.g_y - y);
+ loc.g_x = MAX(0, loc.g_x);
+ loc.g_y = MAX(0, loc.g_y);
+
+ pxy[0] = 0;
+ pxy[1] = 0;
+ pxy[2] = off.g_w-1;
+ pxy[3] = off.g_h-1;
+ pxy[4] = CURFB(self).x + loc.g_x;
+ pxy[5] = CURFB(self).y + loc.g_y;
+ pxy[6] = CURFB(self).x + loc.g_x + off.g_w-1;
+ pxy[7] = CURFB(self).y + loc.g_y + off.g_h-1;
+ if( convert_bitmap( self, bmp, pxy[4], pxy[5], &off, bg, &src_mf) != 0 ) {
+ return( true );
+ }
+ vro_cpyfm( self->vdi_handle, S_ONLY, (short*)&pxy, &src_mf, &scrmf);
+ convert_bitmap_done( self );
+ return( true );
+}
+
+static int text(GEM_PLOTTER self, int x, int y, const char *text, size_t length, const plot_font_style_t *fstyle)
+{
+ self->font_plotter->text( self->font_plotter,
+ x,
+ y,
+ text, length,
+ fstyle
+ );
+ return ( 1 );
+}
diff --git a/atari/plot/plotter_vdi.h b/atari/plot/plotter_vdi.h
new file mode 100644
index 000000000..8c0a95c9c
--- /dev/null
+++ b/atari/plot/plotter_vdi.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2010 Ole Loots <ole@monochrom.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef GEM_PLOTTER_DUMMY_H_INCLUDED
+#define GEM_PLOTTER_DUMMY_H_INCLUDED
+#include "plotter.h"
+#include <Hermes/Hermes.h>
+
+struct s_vdi_priv_data {
+ short bufops;
+ void * buf_packed; /* temp buffer for bitmap conversion */
+ int size_buf_packed;
+ void * buf_planar; /* temp buffer for bitmap conversion */
+ int size_buf_planar;
+ MFDB buf_scr; /* buffer for native screen capture */
+ int size_buf_scr;
+ struct bitmap * buf_scr_compat;
+ HermesFormat vfmt; /* framebuffer format */
+ /* no screen format here, hermes may not suitable for it */
+ HermesFormat nsfmt; /* netsurf bitmap format */
+};
+
+#define CONV_KEEP_LIMIT 512000 /* how much memory should be kept allocated for temp. conversion bitmaps? */
+#define CONV_BLOCK_SIZE 32000 /* how much memory to allocate if some is needed */
+#define DUMMY_PRIV(self) ((struct s_vdi_priv_data*)self->priv_data)
+
+/* Each driver must export 1 method to create the plotter object: */
+int ctor_plotter_vdi( GEM_PLOTTER p );
+
+static struct bitmap * snapshot_create(GEM_PLOTTER self, int x, int y, int w, int h);
+static void snapshot_suspend(GEM_PLOTTER self );
+static void snapshot_destroy( GEM_PLOTTER self );
+
+#endif